Thunderbird, Dovecot и сертификат Let’s Encrypt

Ошибка: «Неустранимая ошибка TLS. Произошла ошибка рукопожатия или, возможно, версия TLS или сертификат, используемые сервером, несовместимы»

Решение: в настройках пролистать до конца, открыть редактор настроек, изменить параметр
security.ssl.enable_ocsp_must_staple = false

Nvidia Optimus: включить ускорение для всего сеанса на постоянку

Долгое время на своем ноуте (Dell Vostro 5470) не мог заставить по-человечески работать  видюху NVIDIA  GK208M [GeForce GT 740M], которая по уму должна включаться по запросу приложений, в остальное время уступая работу по отрисовке графики интегрированной интеловской карточке. Все эти Bumblebee нифига не захотели работать, но на вики дебиана (внезапно) нашлась инструкция — как заставить нвидиевский чип работать постоянно (а почему бы, собственно, и нет — энергосбережение мне нафиг не уперлось).

Коротенько как это сделать при использовании SDDM.

Дрова и xorg

Сначала накатываются дрова

 
 
  1. wajig install  nvidia-driver

Выясняются ID шины для обеих видюх

 
 
  1. lspci
 
 
  1. ...
  2. 00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 09)
  3. ...
  4. 09:00.0 3D controller: NVIDIA Corporation GK208M [GeForce GT 740M] (rev a1)
  5. ...

Теперь создаем файл /etc/X11/xorg.conf (обратите внимание, что запись ID в нем отличается от вывода lspci)

/etc/X11/xorg.conf
 
  1. Section "ServerLayout"
  2.     Identifier "layout"
  3.     Screen 0 "nvidia"
  4.     Inactive "intel"
  5. EndSection
  6. Section "Device"
  7.     Identifier "nvidia"
  8.     Driver "nvidia"
  9.     BusID "PCI:9:0:0"
  10. EndSection
  11. Section "Screen"
  12.     Identifier "nvidia"
  13.     Device "nvidia"
  14.     Option "AllowEmptyInitialConfiguration"
  15. EndSection
  16. Section "Device"
  17.     Identifier "intel"
  18.     Driver "modesetting"
  19.     BusID "PCI:0:2:0"
  20. EndSection
  21. Section "Screen"
  22.     Identifier "intel"
  23.     Device "intel"
  24. EndSection

SDDM

Так как я использую SDDM в качестве дисплей-менеджера, то для него в файл /usr/share/sddm/scripts/Xsetup дописываются строки:

 
 
  1. xrandr --setprovideroutputsource modesetting NVIDIA-0
  2. xrandr --auto
  3. xrandr --dpi 96

Тиринг

Ну и чтобы не было тиринга, в конец файла /etc/modprobe.d/nvidia.conf дописывается строка

 
 
  1. options nvidia-drm modeset=1

после чего выполняется команда

 
 
  1. update-initramfs -u

Теперь после перезагрузки ускорение работает.

Источник: https://wiki.debian.org/NVIDIA%20Optimus#Using_NVIDIA_GPU_as_the_primary_GPU

Отказоустойчивая установка Debian с EFI на зеркало mdadm-рейда

Данный пост возник в результате моей собственной попытки понять, как именно можно добиться отказоустойчивости в конфигурации с EFI-загрузчиком и корнем системы на RAID-массиве. Базовая проблема заключается в том, что разделы с файлами EFI не могут быть расположены на рейде, что приводит к курьезной ситуации, когда сам линукс установлен на рейд, но загрузчик оказывается только на одном диске. Как оказалось, выход конечно есть, но требует дополнительных манипуляций. Я пошел длинным путем и решил описать установку дебиана через Live-CD при помощи debootstrap, что позволяет акцентировать внимание на момент установки загрузчика.

В самом низу будет видео, демонстрирующее все описанные ниже шаги.

Исходная позиция: система с двумя неразмеченными дисками, загруженная с Live-CD

Действия в консоли Live-CD

Размечаем первый диск.
Следующий набор команд создаст на диске GPT-таблицу c двумя разделами: 1 — EFI-раздел на 100 Мб, 2 — раздел под будущее зеркало, размером в 10 Гб

 
 
  1. fdisk /dev/sda
  2. g
  3. n
  4. 1
  5. [default]
  6. +100M
  7. t
  8. 1
  9. n
  10. 2
  11. [default]
  12. +10G
  13. w

Скопируем конфигурацию разделов на второй диск, чтобы они были идентичны

 
 
  1. sfdisk -d /dev/sda | sfdisk /dev/sdb

Отформатируем первые разделы дисков в FAT32

 
 
  1. mkfs.fat -F32 /dev/sda1
  2. mkfs.fat -F32 /dev/sdb1

Создадим зеркало md0 из вторых разделов дисков sda и sdb

 
 
  1. mdadm --create --metadata=0.90 /dev/md0 -l 1 -n 2 /dev/sda2 /dev/sdb2

Форматируем и монтируем рейд

 
 
  1. mkfs.ext4 /dev/md0
  2. mount /dev/md0 /mnt

При помощи утилиты debootstrap скачиваем и разворачиваем на смонтированном рейде основу дебиана

 
 
  1. debootstrap --arch amd64 stable /mnt https://deb.debian.org/debian

Переходим в свежую систему при помощи chroot

 
 
  1. mount --bind /dev /mnt/dev
  2. mount --bind /proc /mnt/proc
  3. mount --bind /sys /mnt/sys
  4. chroot /mnt

Действия в chroot-окружении

Устанавливаем пароль root

 
 
  1. passwd

Создаем директорию под файлы EFI

 
 
  1. mkdir /boot/efi

Выясняем ID рейда и прописываем содержимое fstab

 
 
  1. blkid /dev/md0
  2. vi /etc/fstab
 
 
  1. UUID="..."    /           ext4    errors=remount-ro    1 1
  2. /dev/sda1       /boot/efi       vfat    umask=0077           0 1

Важно: рейд указываем через ID, EFI-раздел — по имени.

Монтируем согласно fstab (рейд уже смонтирован, то есть по факту домонтируем EFI)

 
 
  1. mount -a

Устанавливаем в нашу систему поддержку рейдов, что потребуется в дальнейшем для корректной работы загрузчика.

 
 
  1. apt update
  2. apt install mdadm

Опционально настроим локали и часовой пояс

 
 
  1. apt install locales
  2. dpkg-reconfigure locales
  3. dpkg-reconfigure tzdata

Установим ядро

 
 
  1. apt install linux-image-amd64

Установим и настроим загрузчик

 
 
  1. apt install grub-efi
  2. update-grub2

Проинсталлируем GRUB на диски

 
 
  1. grub-install /dev/sda
  2. grub-install /dev/sdb

В момент инсталляции загрузчика на sda каталог /boot/efi/ заполняется файлами. Для отказоустойчивости необходимо скопировать эти файлы с sda1 на sdb1…

 
 
  1. mkdir /boot/efi2
  2. mount /dev/sdb1 /boot/efi2
  3. cp -RT /boot/efi /boot/efi2

… и добавить второй диск в список UEFI, чтобы система знала, что на нем тоже есть все необходимые файлы

 
 
  1. efibootmgr  -c -g -d /dev/sdb -p 1 -L "debian 2" -l '\EFI\debian\shimx64.efi'

Таким образом у нас оба диска будут в списке загрузчика и при смерти любого из них система будет способна загрузиться.
Используя утилиту efibootmgr в дальнейшем можно удалить из списка замененные диски, а для добавленных дисков нужно будет повторить шаги второго диска:
1. скопировать таблицу разделов,
2. отформатировать первый раздел и скопировать на него файлы EFI,
3. добавить второй раздел в существующий рейд,
4. заинсталлировать на диск grub,
5. добавить этот диск в UEFI.

Выходим из chroot

 
 
  1. exit

Действия в консоли Live-CD

Перезагружаемся

 
 
  1. reboot

Вывод

Обеспечить отказоустойчивость системы на рейд-массиве можно путем создания EFI-раздела на каждом диске, копировании на него файлов EFI и добавлении в список загрузчика при помощи утилиты efibootmgr.

Видео, в котором я последовательно показываю весь процесс с момента создания виртуальной машины:

 

Использованные материалы

См. также

Debian 10 Buster + openbox (установка и настройка)

WordPress: как убрать &nbsp в конце постов.

Совершенно загадочная бага в классическом редакторе вордпресса, выраженная в автоматическом добавлении новой строки и неразрывного пробела в конец поста при каждом его сохранении, лечится следующими путями.

Для лечения уже существующих постов без изменения базы данных, добавляем в functions.php вашей темы следующий код

Загрузчик Загрузка...
Логотип EAD Слишком долго?

Перезагрузка Перезагрузить документ
| Открыть Открыть в новой вкладке

Download

Вторая часть — обработка поста при сохранении. Почти тот же кусок кода

Загрузчик Загрузка...
Логотип EAD Слишком долго?

Перезагрузка Перезагрузить документ
| Открыть Открыть в новой вкладке

Download

Обратите внимание, что смайлик тут используется как символ, заведомо неиспользуемый в постах — в процессе он будет заменен на неразрывный пробел. Это нужно учитывать, если такой символ может появиться в посте «легально».

Чтобы лишний раз не ковырять дефолтный functions.php, можно установить плагин Functionality. Он создаст дополнительный файл с таким же названием и установит его как плагин с именем блога (да, установив этот плагин вы автоматом получите второй — не забудьте активировать и его тоже).

Классный скрипт для конвертации в utf8

Запарило пересохранять субтитры, которые часто выкладывают в вин-кодировке. Нашел клевый скрипт на питоне (а значит и под виндой можно юзать) для конвертации из любой кодировки (исходная автоопределяется) в UTF8. Навесил его как кастомную команду для *.srt в Double Commander, который также юзаю в обеих системах — стало совсем хорошо =)

 
 
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. from chardet import detect
  5. srcfile = sys.argv[1]
  6. tmpfile = sys.argv[1] + '.tmp'
  7. bakfile = sys.argv[1] + '.bak'
  8. # get file encoding type
  9. def get_encoding_type(file):
  10.     with open(file, 'rb') as f:
  11.         rawdata = f.read()
  12.     return detect(rawdata)['encoding']
  13. from_codec = get_encoding_type(srcfile)
  14. # add try: except block for reliability
  15. try:
  16.     with open(srcfile, 'r', encoding=from_codec) as f, open(tmpfile, 'w', encoding='utf-8') as e:
  17.         text = f.read() # for small files, for big use chunks
  18.         e.write(text)
  19.     os.rename(srcfile, bakfile) # backup old encoding file
  20.     os.rename(tmpfile, srcfile) # rename new encoding
  21.    
  22. except UnicodeDecodeError:
  23.     print('Decode Error')
  24. except UnicodeEncodeError:
  25.     print('Encode Error')

Сброс пароля на хосте VMware ESXi

Для сброса пароля хоста ESXi понадобится доступ к серверу (физический, или через iLO-подобные системы управления) и Live CD с каким-нибудь линуксом (я использую GParted Live).

1. Загрузившись с Live CD, проверим какие диски и разделы нам доступны. Скорее всего найдется единственный диск с 9-ю разделами на нем

 
 
  1. ls /dev| grep sd
 
 
  1. sda
  2. sda1
  3. sda2
  4. sda3
  5. sda4
  6. sda5
  7. sda6
  8. sda7
  9. sda8
  10. sda9

2. Пароль находится в архиве в архиве (да, два раза) на разделе sda5. Смонтируем раздел и проверим.

 
 
  1. mkdir /mnt/sda5
  2. mount /dev/sda5 /mnt/sda5
  3. ls -l /mnt/sda5/state.tgz
 
 
  1. -rwxr-xr-x 1 root root 12969 Apr 21 10:42 /mnt/sda5/state.tgz

3. Создадим временную директорию и распакуем в нее этот файл

 
 
  1. mkdir /tmp/state
  2. tar -xf /mnt/sda5/state.tgz -C /tmp/state/
  3. # из архива вылез второй архив, распакуем его сюда же
  4. tar -xf /tmp/state/local.tgz -C /tmp/state/
  5. # удалим этот промежуточный архив
  6. rm /tmp/state/local.tgz

4. Отредактируем файл shadow

 
 
  1. vi /tmp/state/etc/shadow

уберем из первой строки длинный хеш пароля, идущий после «root:», чтобы строка приняла вид

 
 
  1. root::13358:0:99999:7:::

Таким образом пароль для рута будет не установлен. Сохраним файл.

5. Теперь остается запаковать все обратно в архивы и положить на место

 
 
  1. cd /tmp/state
  2. tar -czf local.tgz etc
  3. tar -czf state.tgz local.tgz
  4. mv state.tgz /mnt/sda5/

6. Отмонтируем раздел ESXi и перезагружаемся

 
 
  1. umount /mnt/sda5
  2. reboot

После перезагрузки можно будет зайти в ESXi без пароля и установить его в настройках.

 

Небольшая демонстрация.

mergerfs: прозрачное объединение дисков (файловых систем)

The Perfect Media Server 2016Сегодня хочу рассказать о достаточно нетипичном решении для объединения дисков в один массив. Начну с юзкейса.

У меня есть домашняя файлопомойка, которая построена на классическим RAID5. Инфа на ней хранится, прямо скажем, не критической важности, но все же я предпочитаю ее иногда бэкапить, чтобы хотя бы копия за прошлый год у меня где-то валялась. Разумеется, мне не хочется тратить большие деньги на бэкапные диски, поэтому, как правило, это  старые, относительно небольшого объема, разнокалиберные харды из серии «что было под рукой».

Понятно, что классическим способом получения большого тома из нескольких дисков, является объединение их через LVM, или сборка RAID0. Однако, учитывая,что диски старые и посыпаться могут, например, на этапе восстановления информации с них, мне бы не хотелось рисковать всем таким массивом. Хотелось бы объединить диски в него так, чтобы каждый отдельный диск нес на себе самостоятельную файловую систему, которую можно было бы смонтировать отдельно. Допустим, в массиве из 3х дисков один умер — я смонтировал два оставшихся диска отдельно и спокойно скопировал с них инфу.

Удивительно, но когда я полез гуглить такую хотелку, оказалось, что решение уже придумано и называется mergerfs.

Работает оно ровно так — вы монтируете ваши диски по отдельности, а потом при помощи утилиты mergerfs объединяете их в виртуальную фс.

 
 
  1. mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M  /tmp/backups/vol1:/tmp/backups/vol2 /backup

При этом файлы пишутся то на один диск, то на второй, для балансировки свободного места. При этом любой конкретный файл будет лежать только на одном реальном диске и его можно будет с него прочитать.

 
 
  1. df -h | egrep "Filesystem|backup"
 
 
  1. Filesystem                                      Size  Used Avail Use% Mounted on
  2. /dev/mapper/backup-backup                       3.6T  2.6T  858G  76% /tmp/backups/vol1
  3. /dev/mapper/backup2-backup                      916G   12G  858G   2% /tmp/backups/vol2
  4. vol1:vol2                                       4.5T  2.6T  1.7T  61% /backup
 
 
  1. ls /tmp/backups/vol1/Public/Video/Movies/Qatsi_Trilogy/
 
 
  1. '1. Koyaanisqatsi (1982) 1080p.mkv'
 
 
  1. ls /tmp/backups/vol2/Public/Video/Movies/Qatsi_Trilogy/
 
 
  1. '2. Powaqqatsi (1988) 1080p.mkv'
 
 
  1. ls /backup/Public/Video/Movies/Qatsi_Trilogy/
 
 
  1. '1. Koyaanisqatsi (1982) 1080p.mkv' '2. Powaqqatsi (1988) 1080p.mkv'

Как можно видеть: на одном смонтированном томе виден один файл, на втором — второй, а в точке монтирования mergerfs — оба.

Схема из man mergerfs:

 
 
  1.               A                B        =       C
  2.               /disk1           /disk2           /merged
  3.               |                |                |
  4.                -- /dir1         -- /dir1         -- /dir1
  5.               |   |            |   |            |   |
  6.               |    -- file1    |    -- file2    |    -- file1
  7.               |                |    -- file3    |    -- file2
  8.                -- /dir2        |                |    -- file3
  9.               |   |             -- /dir3        |
  10.               |    -- file4        |             -- /dir2
  11.               |                      -- file5   |   |
  12.                -- file6                         |    -- file4
  13.                                                 |
  14.                                                  -- /dir3
  15.                                                 |   |
  16.                                                 |    -- file5
  17.                                                 |
  18.                                                  -- file6

Конечно, нельзя рекомендовать это решение там, где вы имеете надежное оборудование и вам важна скорость — mergerfs работает через fuse, так что в любом случае это компромисс и не замена RAID0. Но в случае подобном моем — это однозначно лучший вариант, который можно придумать.

PS: К слову, mergerfs не единственная виртуальная ФС такого типа. Изначально я наткнутся на mhddfs, которая даже есть в репозитории debian. Однако, как я понял, ее разработка завяла, а вот тут пишут, что в ней есть баги и лучше таки использовать mergerfs.

Borg Backup: Cache is newer than repository.

Ошибка:
«Cache is newer than repository — do you have multiple, independently updated repos with same ID?»
может возникнуть, если репозиторий был восстановлен из бэкапа.

Лечится выполнением команды (на стороне клиента)

 
 
  1. rm -rf ~/.cache/borg/
  2. mv ~/.config/borg/security{,_bak}

HOW-TO по миграции файловых серверов

Хочу поделиться своим опытом по переносу файловых шар с одного сервера на другой. Такая, казалось бы несложная, процедура осложняется тем, что при достаточно больших объемах данных нужно смигрировать их максимально прозрачно для пользователей и, как минимум, без простоев и потери данных, которые пользователи успели изменить во время переноса.

В моем случае речь ведется о переносе шар с исходного сервера в одном домене на целевой сервер в другом домене, размер шар достигает сотен гигабайт (в некоторых случаях больше терабайта), шара на целевом сервере подключается к серверу DFS.

Итак, первым делом на целевом сервере я создаю папку work, например на диске E:, и расшариваю ее под именем «workE$». Права доступа: полный доступ для SYSTEM, OLDDOMAIN\Domain Admins, NEWDOMAIN\Domain Admins — это позволит копировать конкретные расшареные папки со старого сервера по сети внутрь work с сохранением исходных прав доступа.

Аналогичные права доступа будет очень нелишним добавить и на исходную расшареную папку и ее содержимое, потому что эти права будут копироваться как есть на целевой сервер и возможны ситуации, когда вы, будучи администратором, или не можете получить полные права доступа на файлы на исходном сервере, или, уже скопировав их на целевой, — не имеете прав на изменений атрибутов скопированных файлов. Отдельно нужно следить за папками внутри исходной, на которых отключено наследованием прав — это, к сожалению, вполне распространенная практика в моем случае — на них также нужно проставить полный доступ админам домена(-ов).

Далее, на исходный сервер устанавливается утилита robocopy и изготавливается вот такой скрипт:

rcopy.cmd
 
  1. chcp 1251
  2. robocopy "d:\MyShare" "\\fs-new.local\worke$\MyShare" /MIR /SEC /NS /NC /NDL /R:1 /W:1  /UNILOG:"\\fs-new.local\worke$\MyShare.txt" /TEE
  3. pause

(первая строка нужна на случай, если исходная папка называется по-русски — без этого у меня ломалась кодировка и все файлы копировались с кракозябрами. )

Запускаете cmd с повышенными правами и стартуете скрипт. Он полностью копирует исходную папку на целевой сервер. Что важно — робокопи с этими ключами делает копию директории, а при повторном запуске — актуализирует ее (обновляет измененные файлы, добавляет новые, удаляет те которые были удалены из исходной папки). Поэтому даже если исходная шара была очень большой и копировалась несколько суток, то путем второго-третьего запуска можно уже довольно быстро актуализировать состояние на целевом сервере и пользователи не потеряют те изменения, которые были сделаны во время копирования.
Отдельно замечу что robocopy пишет в лог все ошибки копирования (строго говоря при первом запуске в лог улетают все копируемые файлы, так что лог может быть большим, но при повторном запуске туда попадают только изменения и ошибки, что довольно удобно — как раз видно, например, что на какую-то папку нет прав доступа)

Я так и делаю. Во время копирования или актуализации, пока выполняется скрипт, уже можно на целевом сервере расшарить папку и назначить права доступа к шаре, если они были настроены каким-то специфическим образом. Как только файлы актуализированы (обычно, конечно, актуализацию приходится проводить в нерабочее время) — на старом сервере шара отключается, и поднимается с тем же именем, правами только на чтение, и с двумя файликами: текстовым файлом с содержанием «уважаемые пользователи, файловые ресурс смигрирован на новый адрес: \\новый\адрес, пожалуйста запомните его или скопируйте себе ярлык»,  и ярлыком на новое место, то есть на шару на целевом сервере. Таким образом пользователи, заходя по старому адресу, обнаруживают что ничего не работает, но у них есть подсказка. Из своего опыта могу сказать что даже если у пользователей есть ярлыки куда-то вглубь, то все равно так или иначе они добираются до корня старой шары с подсказкой и вопросов возникает минимум, так что этот метод вполне стрессоустойчив для администратора =)

В моем случае я дополнительно собираю целевые шары на сервере DFS (рекомендую прочитать отдельный пост на тему настройки DFS: Перенастройка DFS для использования DNS-резолвинга), постольку поскольку целевых серверов в моем случае много и хочется дать пользователям единую точку входа. Комментарием тут может быть разве что рекомендация скрывать шару на целевом сервере, то есть реализовывать такую схему:

исходный сервер: \\old-srv\myshare
целевой сервер: \\new-srv\myshare$
dfs-сервер: \\dfs\rootname\myshare

Это позволяет минимизировать риск, что любопытный пользователь через сетевое окружение или как-то иначе найдет шару на целевом сервере и сохранит ярлык на нее, поделится потом с кем-то, и в итоге люди столкнутся с  проблемами если вы захотите переместить шару куда-то еще, переименовать сервер и т.п.

Всё вышеописанное есть изложение моего личного опыта, возможно есть какие-то лучшие пути, но описанный вариант является вполне рабочим — могу его с чистой совестью рекомендовать.

Заполнение mp3-тегов скриптом

Довелось скачать саундтрек к игре в виде кучи файлов без тегов вообще.

Захотелось на скорую руку заполнить хотя бы названия и номера треков (альбом/год/жанр — одинаковые для всех, с этим все сильно проще).

Для начала из имени каждого файла нужно вычленить название трека. Используем sed в однострочном цикле для разделения имени файла на три блока. Блоки в sed выделяются экранированными скобками: начало — \(, конец — \)

 
 
  1.                                                        вычленяем блок №2
  2.                                                         |             |
 
 
  1. for file in *.mp3; do name=$(sed "s/\(^.*_.\{1,3\}_\)\(.*\)\(\.mp3\)/\2/" <<< $file); echo $name ; done;
 
 
  1.                                           |                     |    
  2.            блок №1: начало строки, любые символы,          блок №3: .mp3
  3.                     подчеркивание, 1-3 любых символа,
  4.                     подчеркивание

Вывод:

 
 
  1. chat_thiscouldbeAWESOME
  2. lab sewers
  3. chat_downthe
  4. ...

(да, если вы решаете проблему с помощью регулярных выражений — у вас уже 2 проблемы, но в данном случае это отличное решение).

Убедившись что имена получаются корректные, меняем echo $name на редактор тегов mid3v2

 
 
  1. for file in *.mp3; do name=$(sed "s/\(^.*_.\{1,3\}_\)\(.*\)\(\.mp3\)/\2/" <<< $file); mid3v2 -t "$name" "$file" ; done;

Самое сложное сделано. Теперь номера треков (всего их 46, так что это число я подставляю вручную):

 
 
  1. i=1; for file in *.mp3; do mid3v2 -T  "${i}/46" "$file" ; ((i+=1)); done;

Все одинаковые для треков теги заполняются совсем просто, например год:

 
 
  1. for file in *.mp3; do mid3v2 -y 2010  "$file" ; done;

PS: утилита mid3v2 (рекомендуется как полностью поддерживающая v2/utf8-теги) входит в питоновский пакет mutagen и ставится примерно так (для debian/ubuntu)

 
 
  1. apt install python3-mutagen

или так (установка в пользовательский профиль из репозитория pypi)

 
 
  1. pip3 install --user mutagen