Запуск snap в LXC в Ubuntu 22.04 Jammy

Ранее я писал статью о том, как запустить snap под Ubuntu 18.04 Bionic, однако сейчас всё усложнилось и потребовалось искать и изучать актуальную информацию.

На данный момент, актуальный список действий таков:

  1. Подгружаем модуль fuse на хосте (modprobe fuse), делаем его автозагрузку;
  2. В конфигурационный файл конейнера (/var/lib/lxc/containername/config) прописываем следующие параметры:
    • lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,optional
    • lxc.apparmor.profile = unconfined
    • lxc.cap.drop =
    • lxc.cap.drop = mac_override sys_time sys_module sys_rawio
  3. Запускаем контейнер, устанавливаем snap: apt install snapd -y
  4. Проверяем работу: snap install hello-world и получаем ошибки

Выполняем snap install hello-world ещё раз и магическим образом всё начинает работать.

Почему snap такой кривой и требует гору костылей — вопрос остаётся открытым.

Кстати говоря, под LXD всё работает «из коробки», то есть просто создаём контейнер lxc launch images:ubuntu/jammy test и всё в нём сразу запускается.

Правильная установка GRUB UEFI на USB флешку

Предположим, раздел fat32 флешки примонтирован в директорию /mnt, следовательно команда выглядит следующим образом:

grub-install —removable —target=x86_64-efi —boot-directory=/mnt/boot —efi-directory=/mnt

Как мы видим, указывать в —efi-directory нужно именно корень флешки, а не ./boot/EFI или ./EFI.

Как запустить OpenWRT под lxc и настроить маршрутизацию

Использование программного роутера — довольно недорогое и одновременно высокопроизводительное решение, но использование ОС внутри виртуальной машины с аппаратной виртуализацией создаёт дополнительные задержки и повышенную нагрузку на железо. Лучшим решением является использование виртуальных машин с программной виртуализацией, в данном случае я использую LXC.

В качестве «роутерной» ОС будет выступать свободная операционная система OpenWRT.

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

Сперва, нам необходимо скачать образ корневой ФС, она имеет имя в роде rootfs-squashfs.img.gz, например https://downloads.openwrt.org/releases/19.07.3/targets/x86/64/openwrt-19.07.3-x86-64-rootfs-squashfs.img.gz

Переходим в /var/lib/lxc, создаём директорию с именем машины и копируем ФС в vm/rootfs

  1. cd /var/lib/lxc
  2. wget https://downloads.openwrt.org/releases/19.07.3/targets/x86/64/openwrt-19.07.3-x86-64-rootfs-squashfs.img.gz
  3. gzip -d openwrt-19.07.3-x86-64-rootfs-squashfs.img.gz
  4. mkdir mount
  5. mount openwrt-19.07.3-x86-64-rootfs-squashfs.img mount -o loop
  6. mkdir -p router/rootfs
  7. cp -a mount/* router/rootfs/
  8. umout mount
  9. rm openwrt-19.07.3-x86-64-rootfs-squashfs.img

Приступаем к написанию конфига router/config. Общий вид такой:

lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/userns.conf
lxc.arch = linux64
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.rootfs.path = dir:/var/lib/lxc/router/rootfs
lxc.cgroup.devices.allow = c 108:0 rwm
lxc.mount.entry = /dev/ppp dev/ppp none bind,optional,create=file

lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 52:a4:00:d3:4e:ea
lxc.net.0.name = eth0

Касательно опций

lxc.cgroup.devices.allow = c 108:0 rwm
lxc.mount.entry = /dev/ppp dev/ppp none bind,optional,create=file

Они необходимы для работы PPP (PPPoE), если это не требуется, необходимо удалить эти строчки.

108:0 определяется таким образом:

На хост-машине: ls -ls /dev/ppp

0 crw——- 1 root root 108, 0 May 21 13:05 /dev/ppp

108, 0 и есть нужные нам значения.

После того, как настроили сеть и зашли на роутер либо через luCI, либо через консоль, необходимо прописать кастомное правило для фаерволла, для этого заходим в Network — Firewall — Custom rules и прописываем iptables -t nat -A POSTROUTING -o pppoe-inet -j MASQUERADE

Или же прописать в /etc/firewall.user

где pppoe-inet имя вашего интерфейса «с интернетом». Да, это костыль, почему-то по дефолту маршрутизация с lxc версией не работает.

Не работает сканер на Ubuntu 18.04 Bionic, Brother (DCP-7057R): scanimage: open of device brother4:net1;dev0 failed: Invalid argument

Предполагается, что вы уже установили драйвера brscan(2,3,4 — в зависимости от модели), а пользователь присутствует в нужной группе (scanner) и заданы правила для устройства, но sane ни в какую не хочет начать сканировать.

Дело в том, что необходимые библиотеки (драйвера) для работы сканера в пакетах находятся в /usr/lib64 и /usr/lib64/sane, в то время как sane «ищет» их в папке /usr/lib и /usr/lib/sane.

Поэтому, делаем следующее:

  1. mkdir /usr/lib/sane
  2. ln -s /usr/lib64/sane/libsane-brother* /usr/lib/sane
  3. ln -s /usr/lib64/libbrscandec* /usr/lib
  4. ln -s /usr/lib64/libbrcolm* /usr/lib

Важно! По какой-то причине, после установки sane, пользователь saned (от имени которого работает собственно сам sane, не добавлен в группу lp и scanner. Его необходимо добавить, иначе будут проблемы с правами, сделать это можно так: sudo usermod -aG scanner,lp sane

После этого сканер должен заработать. Не забывайте задать параметры разрешения, иначе scanimage —test не определяет корректные параметры.

Первоисточник: https://askubuntu.com/questions/564059/ubuntu-14-04-scanimage-invalid-argument (немного доделано).

Использование менеджера пакетов Snappy (snap) в контейнерах LXC на примере Ubuntu Bionic

При стандартной установке контейнера вы непременно столкнётесь с кучей ошибок в процессе попытки установить/запустить ПО через snap.


Для решения этой проблемы необходимо сделать следующее:


0.1) Первым делом, необходимо остановить работу контейнера (lxc-stop -n rc)


1) Откройте конфигурационный файл контейнера (/var/lib/lxc/rc/config) и допишите в него две строчки:


lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,optional

lxc.mount.auto=cgroup:rw

0.2) Запустите контейнер (lxc-start -n rc) и подключитесь к нему (lxc-attach -n rc)

2) В контейнер установите squashfuse и fuse (и snapd, если вы этого ещё не сделали) — apt update; apt install squashfuse fuse snapd

3) Проверьте работоспособность.
snap install hello-world; snap run hello-world

Важно! После установки первого пакета вы получите кучу ошибок:

Это изображение имеет пустой атрибут alt; его имя файла - image-3.png

Просто остановите и запустите контейнер снова (lxc-stop и lxc-start)

Параллельное выполнение команд с одного читаемого файла

Задача: допустим, при создании тяжелого бэкапа или вообще дампа диска, необходимо параллельно к созданию сжатого файла еще и создать контрольную сумму исходного файла.

Сделать это можно с помощью утилиты pee, входящей в состав пакета программ moreutils. Для установки в Ubuntu используем apt install moreutils.

Сделать это можно так:

dd if=test | pee «dd of=newtest» «sha512sum».

Результаты следующие:

Последовательное выполнение

Тут пришлось делать скрипт, т.к. time не хотел никак выполнять несколько команд. 
cat ./sc
#!/bin/bash
if=test of=newtest
sha512sum test

time ./sc 678d36fc5a1d14b23dcd04740604a643f2d3159167af1211ab779ac10394ac443a06feabee9d826fd715bce84e0d13ea75bc85fe990e340e775c1d9521c8dac9 test

real 0m24.453s
user 0m23.885s
sys 0m0.548s

[свернуть]

Параллельное выполнение

time dd if=test | pee «dd of=newtest» «sha512sum»
1228276+0 records in
1228276+0 records out
628877312 bytes (629 MB, 600 MiB) copied, 14.766 s, 42.6 MB/s
1228276+0 records in
1228276+0 records out
628877312 bytes (629 MB, 600 MiB) copied, 14.4783 s, 43.4 MB/s
678d36fc5a1d14b23dcd04740604a643f2d3159167af1211ab779ac10394ac443a06feabee9d826fd715bce84e0d13ea75bc85fe990e340e775c1d9521c8dac9 —

real 0m14.779s
user 0m12.009s
sys 0m22.671s

[свернуть]

Также можно сделать и с архивом:

tar cf — test | cat | pee «dd of=archive.tar» «sha512sum»

выведет контрольную сумму sha512 конечного архива, и, собственно говоря, сам архив будет создан.

где:

test — имя архивируемого файла/директории

archive.tar — имя конечного архива

Для создания сжатого архива, например, lz4:

tar cf — test | lz4 -z| cat | pee «dd of=archive.tar.lz4» «sha512sum»

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

Как установить браузер Tor на Ubuntu 17.10 Artful

При попытке установить браузер тор через torbrowser-launcher выплёвывается куча ошибок:

Текст ошибки

Unhandled Error Traceback (most recent call last): File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 929, in dispatcher return func(*args, **kwargs) File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 1497, in _finishResponse_WAITING self._giveUp(Failure(reason)) File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 1550, in _giveUp self._disconnectParser(reason) File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 1538, in _disconnectParser parser.connectionLost(reason) -— —- File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 550, in connectionLost self.response._bodyDataFinished() File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 929, in dispatcher return func(*args, **kwargs) File «/usr/lib/python2.7/dist-packages/twisted/web/_newclient.py», line 1185, in _bodyDataFinished_CONNECTED self._bodyProtocol.connectionLost(reason) File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 329, in connectionLost self.all_done(reason) File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 346, in response_finished self.run_task() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 276, in run_task self.run_task() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 282, in run_task self.verify() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 491, in verify self.run_task() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 286, in run_task self.extract() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 531, in extract self.run_task() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 290, in run_task self.run() File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 547, in run if not self.check_min_version(): File «/usr/lib/python2.7/dist-packages/torbrowser_launcher/launcher.py», line 535, in check_min_version for line in open(self.common.paths[‘tbb’][‘versions’]).readlines(): exceptions.IOError: [Errno 2] No such file or directory: ‘/home/user/.local/share/torbrowser/tbb/x86_64/tor-browser_en-US/Browser/TorBrowser/Docs/sources/versions

[свернуть]

Но и при попытке добавить репозиторий

add-apt-repository ppa:webupd8team/tor-browser

вываливается ошибка 404. Это происходит потому, что в данном репозитории ещё нет пакетов для нашей свежей версии убунты, поэтому смотрим, для каких наиболее свежих релизов есть пакеты:

Ага, zesty есть, следовательно, делаем следующее:

    1. Добавляем сам репозиторий sudo add-apt-repository ppa:webupd8team/tor-browser
    2. Редактируем файл /etc/apt/sources.list.d/webupd8team-ubuntu-tor-browser-artful.list и меняем artful на zesty
    3. Обновляем индексы пакетов apt update
    4. Устанавливаем сам браузер тор apt install tor-browser

Готово! Тор запускается и прекрасно работает!

Настройка nut в Ubuntu 14.04 на автоотключение сервера и нюансы

В интернете полно инфы по настройке nut, но не рассказаны одни из важных нюансов, что да как происходит, о них я распишу по ходу установки и настройки на примере ИБП Ippon Back Power Pro 600 через USB. Перейдем. Все команды выполняется под root’ом.

1) Устанавливаем сам nut. apt install nut

Важно: в Ubuntu 14.04 (Trusty) сервис nut называется как nut-server, поэтому работать нужно с этим именем.

2) Настраиваем конфиги. Советую не смотреть и просто копировать, а то глаза на лоб вылезут, если вы никогда этого не делали 🙂

2.05) /etc/nut/nut.conf

MODE=none заменить на MODE=standalone

2.1) /etc/nut/ups.conf

Переходим в конец файла и прописываем:

[ups]
driver = blazer_usb
port = auto
offdelay = 100
ondelay = 1
desc = «Ippon 600W» — тут важно использовать простые двойные кавычки.

[ups] — название ИБП (можно писать любое, главное английскими буквами и важно его запомнить)

driver = blazer_usb и port = auto — их не трогаем, это драйвер, который нужно использовать и порт (заранее узнаем нужный драйвер по этой ссылке).

offdelay = 100 и
ondelay = 1 — о них я расскажу в конце

2.2) /etc/nut/upsd.conf

Найдем здесь линию LISTEN 127.0.0.1 3493 и раскомментируем её (или можно вставить в конец файла). Это настройка указывает, где и на каком порту nut сервер будет «слушать». Рекомендую разрешать доступ только с локалхоста.

2.3) /etc/nut/upsd.users

Настройка юзера. Прописываем:

[upsmon]
password = pass
actions = SET
instcmds = ALL
upsmon master

[upsmon] — имя юзера, password — его пароль. На остальное внимание не обращаем, при желании, можете погуглить.

2.4) /etc/nut/upsmon.conf

MONITOR ups@127.0.0.1 1 upsmon pass master
MINSUPPLIES 1
NOTIFYCMD /sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/nut/killpower
NOTIFYMSG ONLINE «UPS %s on line power»
NOTIFYMSG ONBATT «UPS %s on battery»
NOTIFYMSG LOWBATT «UPS %s battery is low»
NOTIFYMSG FSD «UPS %s: forced shutdown in progress»
NOTIFYMSG COMMOK «Communications with UPS %s established»
NOTIFYMSG COMMBAD «Communications with UPS %s lost»
NOTIFYMSG SHUTDOWN «Auto logout and shutdown proceeding»
NOTIFYMSG REPLBATT «UPS %s battery needs to be replaced»
NOTIFYMSG NOCOMM «UPS %s is unavailable»
NOTIFYMSG NOPARENT «upsmon parent process died — shutdown impossible»
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

Тут MONITOR ups@127.0.0.1 1 upsmon pass master

где

ups@127.0.0.1 — ups — имя бесперебойника (из пункта 2.1), 127.0.0.1 — адрес сервера (из пункта 2.2).

upsmon — имя юзера, pass — пароль юзера (из пункта 2.3)

2.4) /etc/nut/upssched.conf

CMDSCRIPT /etc/nut/cmd.sh
PIPEFN /tmp/upspipe
LOCKFN /tmp/upslock
AT COMMBAD * EXECUTE commbad
AT COMMOK * EXECUTE commok
AT NOCOMM * EXECUTE nocomm
AT ONBATT * EXECUTE powerout
AT ONBATT * START-TIMER shutdownnow 90
AT LOWBATT * EXECUTE shutdowncritical
AT ONLINE * CANCEL-TIMER shutdownnow
AT ONLINE * EXECUTE powerup

где AT ONBATT * START-TIMER shutdownnow 90 — запускаем таймер и ждем 90 секунд, если в течении 90-а секунд не появится питание в сети, то посылается сигнал завершения работы. Об этом чуть далее.

2.5) /etc/nut/cmd.sh

Открываем файл и пишем:

#!/bin/sh
case $1 in
commbad)
logger «UPS communications failure»
;;
commok)
logger «UPS communications restored»
;;
nocomm)
logger «UPS communications cannot be established»
;;
powerout)
logger «UPS on battery. Shutdown in 90 seconds….»
upscmd -u upsmon -p pass ups@127.0.0.1 shutdown.return
;;
shutdownnow)
logger «UPS has been on battery for 120 seconds. Starting orderly shutdown»
sudo poweroff
;;
shutdowncritical)
logger «UPS battery level CRITICAL. Shutting down NOW!!!!»
upsmon -c fsd
;;
powerup)
logger «UPS on line. Shutdown aborted.»
upscmd -u upsmon -p pass ups@127.0.0.1 shutdown.stop
;;
*)
logger «Unrecognized command: $1»
;;
esac

где

logger «UPS on battery. Shutdown in 90 seconds….»
upscmd -u upsmon -p pass ups@127.0.0.1 shutdown.return
;;

где -u и -p — имя и пароль юзера (из пункта 2.3)

ups@127.0.0.1 — об этом было сказано в пункте 2.4.

logger «UPS on line. Shutdown aborted.»
upscmd -u upsmon -p pass ups@127.0.0.1 shutdown.stop
;;

тут также

shutdown.return — запуск таймера, настроенного в пункте 2.4

shutdown.stop — соответственно, остановка таймера (при подачи напряжения, если время таймера не истекло).

2.5) chmod 777 /etc/nut/cmd.sh

2.6) Нюанс по поводу того, что сервер не выключался при подачи команды shutdownnow — у юзера nut просто нет прав на завершение работы, решаем это быстрым костылем (заранее я прописал в конфиге выше команду sudo poweroff). Открываем /etc/sudoers (sudo должен быть установлен заранее! apt install sudo) и прописываем:

nut ALL=(ALL:ALL) NOPASSWD: ALL

2.7) Перезапускаем демон и получаем инфу:

upsc ups@127.0.0.1

Получить должны примерно это:

Теперь перезагружаем сервер и тестируем работу.

Нюансы касательно принципа работы автоотключения ИБП:

1) При отключении электричества (пропадание напряжения на входе ИБП) nut получает информацию и запускает таймер, (в нашем случае это 90 секунд) и если в течении этого времени напряжение не появится, то выполняется команда sudo poweroff от пользователя nut, которая безопасно отключает питание сервера.

2) Теперь касательно offdelay = 100 и ondelay = 1.

offdelay — время в секундах, через которое ИБП отключается (в т.ч. отключает питание от батареи). Если в течении 100 секунд (в данном случае) не появится напряжение, то ИБП отключается.

ondelay — время в минутах, через которое ИБП включится после отключения (после offdelay). Как работает — если отключится ИБП и через 5 секунд появится напряжение в сети, то ИБП будет отключен и будет ждать 1 минуту (в данном случае), через минуту он включится (будет заметен характерный «щелк» реле) при этом, если: напряжение в сети все еще отсутствует, то питание от батареи возобновлено не будет. Если напряжение появится в сети, то ИБП автоматически включится (будет характерный длинный «писк») и подаст напряжение на сервер.

На этом всё, конфиги и настройка взяты отсюда, однако, о важных нюансах выше не было ничего сказано в интернете, как и что работает. Вообще, настройка nut слишком усложнена и явно не стоит такого заморачивания.