Часть 2: Браузер со звуком и веб-камерой в контейнере

Привет, Хабр!

Это вторая статья о контейнеризации как стиле повседневного использования графических приложений в ОС Линукс. Здесь мы научимся безопасно запускать браузер и менеджер паролей, так как это близкие потребности. Здесь не будут повторяться инструкции и объяснения, данные в первой статье, так как предполагается, что они известны читателю. Посему, без долгих предисловий, ныряем под кат!


Темой изоляции приложений друг от друга я озаботился, когда мне нужно было распаковать свой файл паролей .kbdx приложением KeePass2, чтобы ввести пароль на сайте. И это при том, что в браузере в тот момент было открыто несколько разных вкладок. Ведь браузер представляет собой не только интерпретатор HTML-разметки, но и компилятор JavaScript-кода. Представьте себе, что процесс от имени вашего пользователя, в пространстве имён вашего пользователя, со всеми присущими правами доступа, исполняет присланный сервером код. И это при штатном использовании, без эксплуатации багов.

Историческая справка: Именно таким опасным был выход в Интернет до конца 2008 года. 11 декабря 2008 года, в версии Google Chromium 1.0.154.36 была добавлена песочница, которая изолировала исполняемый браузером код от остальных процессов ОС. По прошествии многих лет развития этой технологии, вроде бы, песочница Chromium закрыла вышеозначенную потребность безопасного открытия менеджера паролей при открытых сайтах. Тем не менее мы знаем, что такие технологии, благодаря несмотря на десятилетия разработки, всё же имеют уязвимости нулевого дня. Тема "побега из песочницы Chromium" все эти годы остаётся актуальной. Так, в одном только 2024м году было обнаружено шесть таких уязвимостей, эксплуатируемых в промышленных масштабах. Поэтому, мы хотим всегда запускать наш браузер в контейнере, без привилегий.

Браузер это мультимедийное приложение, которое мы используем для игр и видеозвонков, поэтому нам потребуются видеокарта, веб-камера, звуковая карта. Качество звука для нас очень важно, поэтому мы также уделим внимание настройке PulseAudio.

Создайте в отдельной папке файл Dockerfile следующего содержания:

FROM --platform=linux/amd64 docker.io/library/debian:latest 

RUN apt update && apt upgrade -y \
    && apt install alsa-oss alsa-utils pulseaudio ca-certificates ffmpeg bluetooth bluez chromium -y \
    && apt clean \
    && rm -rf /var/lib/apt/lists/*

ARG GROUP_ID=9898
ARG USER_ID=9898
ARG USR_NAME=chromeuser

RUN echo "default-sample-format = s32le # Варианты s16le, s32le, float32le" > /etc/pulse/daemon.conf
RUN echo "default-sample-rate = 192000 # как вариант 48000, 96000, 192000, 320000" >> /etc/pulse/daemon.conf
RUN echo "alternate-sample-rate = 44100 # как вариант 44100, 88200" >> /etc/pulse/daemon.conf
RUN echo "default-sample-channels = 2" >> /etc/pulse/daemon.conf
RUN echo "default-channel-map = front-left,front-right" >> /etc/pulse/daemon.conf
RUN echo "default-fragments = 2 # по умолчанию 4" >> /etc/pulse/daemon.conf
RUN echo "default-fragment-size-msec = 125 # по умолчанию 25" >> /etc/pulse/daemon.conf
RUN echo "resample-method = soxr-vhq # Варианты src-sinc-best-quality, soxr-vhq, copy, speex-float-1" >> /etc/pulse/daemon.conf
RUN echo "remixing-produce-lfe=no # yes для 2+1, 5+1 и т.д." >> /etc/pulse/daemon.conf
RUN echo "remixing-consume-lfe=no # yes для 2+1, 5+1 и т.д." >> /etc/pulse/daemon.conf
RUN echo "high-priority = yes" >> /etc/pulse/daemon.conf
RUN echo "nice-level = -11" >> /etc/pulse/daemon.conf
RUN echo "realtime-scheduling = yes" >> /etc/pulse/daemon.conf
RUN echo "realtime-priority = 9 # по умолчанию 5" >> /etc/pulse/daemon.conf
RUN echo "rlimit-rtprio = 9" >> /etc/pulse/daemon.conf
RUN echo "daemonize = no" >> /etc/pulse/daemon.conf
RUN echo "PULSE DAEMON:" && cat /etc/pulse/daemon.conf

RUN echo "autospawn = no" > /etc/pulse/client.conf
RUN echo "daemon-binary = /bin/true" >> /etc/pulse/client.conf
RUN echo "enable-shm = false" >> /etc/pulse/client.conf
RUN echo "default-server = unix:/run/user/$USER_ID/pulse/native" >> /etc/pulse/client.conf
RUN echo "PULSE CLIENT:" && cat /etc/pulse/client.conf

RUN groupadd -g $GROUP_ID --system ${USR_NAME} && \
    useradd -m --gid $GROUP_ID --system -u $USER_ID -G audio,video,bluetooth ${USR_NAME} \
    && mkdir -p /home/${USR_NAME}/reports \
    && mkdir -p /home/${USR_NAME}/.config \
    && mkdir -p /home/${USR_NAME}/.cache \
    && mkdir -p /home/${USR_NAME}/.local/share \
    && chown --recursive ${USR_NAME}:${USR_NAME} /home/${USR_NAME}

USER ${USR_NAME}
RUN mkdir -p /tmp/xdg

CMD "chromium"

Здесь для вас многое должно быть знакомым из предыдущей статьи. Новым является:

  1. Аргумент --platform=linux/amd64 команды FROM позволяет явно задавать архитектуру, для которой был создан образ. Здесь он указан в образовательных целях.

  2. Большое количество слоёв образа - конкатенации конфигурационных файлов звукового сервера PulseAudio.

  3. Добавление пользователя, от имени которого будет запускаться браузер, в группы audio, video и bluetooth.

  4. Вместо ENTRYPOINT можно использовать CMD, что будет интерпретировано как sh -c при запуске контейнера .

Эту конфигурацию звука я смог составить благодаря статье на OpenNet. Заметьте, что данная конфигурация оптимальна для моего оборудования. Вы можете выяснить поддерживаемые форматы передачи звука и и битрейты вашим железом командой aplay --device hw /dev/urandom --dump-hw-params. В тему настройки звука на Линукс далее мы углубляться не будем.

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

sudo apt update && sudo apt upgrade -y && sudo apt install build-essential

В той же папке, где мы создали Dockerfile, создайте файл Makefile следующего содержания:

SHELL=/bin/bash

DOCKER=podman
UUID=$(shell id -u)
GUID=$(shell id -g)
ME=$(shell whoami)
MY_UID=$(shell id -u)
USRNME=chromeuser
IMG_NAME=chromium

build:
	@ echo "Собираем образ Chromium для запуска в ином пространстве имён" && \
    ${DOCKER} build -t ${IMG_NAME} .

build-keep-uid:
	@ echo "Собираем образ Chromium для запуска от имени пользователя ${ME}" && \
    ${DOCKER} build -t ${IMG_NAME}${MY_UID} --build-arg USER_ID=${MY_UID} --build-arg GROUP_ID=${MY_UID} --build-arg USR_NAME=${ME} .

# Запустить образ Chromium в ином пространстве имён
run:
        @ ${DOCKER} run \
        --log-level info \
        --log-driver json-file \
        -it --rm \
        --uidmap=0:7:1 \
        --uidmap=9898:8:1 \
        --gidmap=0:7:1 \
        --gidmap=9898:8:1 \
        --gidmap=29:6:1 \
        --gidmap=44:5:1 \
        --gidmap=108:4:1 \
        --cpus 3.5 \
        --memory 4096m \
        --shm-size 2G \
        -v /opt/${IMG_NAME}/config:/home/${USRNME}/.config:rw \
        -v /opt/${IMG_NAME}/cache:/home/${USRNME}/.cache:rw \
        -v /opt/${IMG_NAME}/reports:/home/${USRNME}/reports:rw \
        -v /opt/${IMG_NAME}/local:/home/${USRNME}/.local:rw \
        -v /home/${ME}/Downloads:/home/${USRNME}/Downloads:rw \
        -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
        -v /run/user/${UUID}/pulse/native:/tmp/xdg/pulse/native:rw \
        --device /dev/dri/card0 \
        --device /dev/snd \
        --device /dev/video0 \
        -e DISPLAY=${DISPLAY} \
        -e PULSE_SERVER=unix:path=/tmp/xdg/pulse/native \
        -e XDG_RUNTIME_DIR=/tmp/xdg \
        ${IMG_NAME}

# Запустить образ Chromium от имени обычного пользователя
run-keep-uid:
        @ ${DOCKER} run \
        --log-level info \
        --log-driver json-file \
        -it --rm \
        --userns=keep-id \
        --cpus 3.5 \
        --memory 4096m \
        -v /opt/${IMG_NAME}${MY_UID}/config:/home/${ME}/.config:rw \
        -v /opt/${IMG_NAME}${MY_UID}/cache:/home/${ME}/.cache:rw \
        -v /opt/${IMG_NAME}${MY_UID}/reports:/home/${ME}/reports:rw \
        -v /opt/${IMG_NAME}${MY_UID}/local:/home/${ME}/.local:rw \
        -v /home/${ME}/Downloads:/home/${ME}/Downloads:rw \
        -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
        -e DISPLAY=${DISPLAY} \
        --device /dev/snd \
        --device /dev/dri/card0 \
        --device /dev/video0 \
        -e XDG_RUNTIME_DIR=/tmp \
        -e PULSE_SERVER=unix:/tmp/pulse/native \
        -v ${XDG_RUNTIME_DIR}/pulse:/tmp/pulse:ro \
        -e DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket \
        -v /run/dbus:/run/dbus:rw \
        ${IMG_NAME}${MY_UID}

# Запустить анонимный агностический браузер в ином пространстве имён
run-anon:
        @ ${DOCKER} run \
        --log-level info \
        --log-driver json-file \
        -it --rm \
        --uidmap=0:7:1 \
        --uidmap=9898:8:1 \
        --gidmap=0:7:1 \
        --gidmap=9898:8:1 \
        --gidmap=29:6:1 \
        --gidmap=44:5:1 \
        --gidmap=108:4:1 \
        --cpus 3.5 \
        --memory 4096m \
        -v /home/${ME}/Downloads:/home/${USRNME}/Downloads:rw \
        -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
        -e DISPLAY=${DISPLAY} \
        ${IMG_NAME}

В этом Makefile мы видим 2 цели для создания контейнеров и 3 цели для запуска.
Рассмотрим цели подробнее:

  • Цель build создаёт образ из нашего Dockerfile, как есть, ничего не меняя.

  • Цель build-keep-uid создаёт образ из нашего Dockerfile, назначая пользователю в контейнере те же имя и uid/gid, которые имеет наш хостовый пользователь.

  • Цель run запускает браузер в ином пространстве имён, со звуком и веб-камерой, который будет сохранять куки, кеши и плагины в папку /opt/chromium.

  • Цель run-keep-uid запускает браузер в пространстве имён хостового пользователя, в котором будет всё то же самое, что и в цели run, плюс вывод звука на bluetooth-устройства. Эта цель собирает контейнер из образа, созданного целью build-keep-uid.

  • Цель run-anon запускает анонимный агностический браузер в отдельном пространстве имён.

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

Обсудим более подробно представленные целями make команды podman run:

  • --log-level info задаёт наименьший приоритет (уровень) логирования, включая который и выше, сообщения от программы журналируются.

  • --log-driver json-file задаёт формат журналирования.

  • Мы дополнительно отображаем группы с gid 29 (audio), 44 (video) и 108 (bluetooth) на uid 100005, 100004 и 100003 хоста, соответственно.

  • Инструкцией --cpus 3.5 мы ограничиваем доступный ресурс ЦПУ для данного контейнера. Например, если процессор 4х-ядерный, то 4.0 означает, что каждое ядро сможет быть задействовано на 100%. Соответственно, 3.5 будет ограничением в 87.5% для каждого ядра. А это значит, что баг на сайте или майнер не смогут перегреть наш ЦП.

  • В Linux есть разные способы организации обмена данными между процессами, и один из них - разделяемая память. Это каталог /dev/shm, содержимое которого находится на плашке ОЗУ, а не на жёстком диске. К сожалению, многие сайты архитектурно зависят от этого механизма, и вообще не работают без него vk.com или работают частично. Ввиду этого, нам придётся выделить контейнеру разделяемую память в объёме 2Гб параметром --shm-size 2G.

Отображение локальных папок в /opt/имя_контейнера, а также папки Downloads и папки с экранами мониторов моей сессии X-сервера /tmp/.X11-unix/ должно быть понятно из предыдущей статьи. Рекомендую их владельцем иметь хостового пользователя, а пользователю с uid 100007 выдавать на них права через ACL командой setfacl -R -m u:100007:rwx /opt/имя_контейнера.
Зато следующее отображение -v /run/user/${UUID}/pulse:/tmp/xdg/pulse:ro и объявления констант окружения -e PULSE_SERVER=unix:path=/tmp/xdg/pulse/native и -e XDG_RUNTIME_DIR=/tmp/xdg требуют пояснения: /run/user/${UUID}/pulse/native это сокет звукового сервера PulseAudio. Константа XDG_RUNTIME_DIR задаёт директорию для сокетов и пайпов времени выполнения пользовательской сессии. Константа PULSE_SERVER объявляет путь к сокету звукового сервера.
Пробросить сокет не является достаточным, требуется проброс устройств:

  • Видеокарта --device /dev/dri/card0

  • Звуковые устройства подключаются так --device /dev/snd, что означает "все символьные I/O устройства в этой папке"

  • Веб-камеру подключаем так --device /dev/video0 Имена ваших файлов типа c, то есть символьных устройств, могут отличаться, поэтому рекомендую изучить содержимое вашей папки /dev/

ВНИМАНИЕ: В Линукс всё является файлом, в том числе и устройства символьного ввода-вывода, как мы видели только что. Однако, эти файлы не хранятся на жёстком диске, а создаются каждый раз при запуске ОС. Для пользования данными файлами-устройствами, пользователь должен иметь соответствующие права доступа. Поэтому, после включения вашего ПК и перед запуском браузера, придётся выполнять с root-правами скрипт следующего содержания:

#!/bin/bash
setfacl -R -m u:100007:rw /dev/snd
setfacl -m u:100007:rw /dev/dri/card0
setfacl -m u:100007:rw /dev/video0

Как видно из определения цели run нашего Makefile, мы выбрали uid/gid 100007 для пользователя дочернего пространства имён suduid/subgid, под которым будет запущен процесс браузера.
Создайте пользователя с uid 100007 для дальнейшего использования с командой xhost, как это было показано в предыдущей статье.
В определении цели run-keep-uid мы видим ранее не встречавшийся параметр --userns=keep-id, что означает "запустить в пространстве имён хостового пользователя", то есть, с сохранением его UID. Обратите внимание, что именно для этого мы создаём отдельный образ make-целью build-keep-uid.

Справедливым вопросом будет: Зачем нам запускать браузер в том же пространстве имён, если от этого мы хотим уйти? Дело в том, что у меня покамест не получилось выводить звук на bluetooth-устройства из-под пользователя в другом пространстве имён. На обычные динамики или гарнитуру, подключенную через мини джек звук идёт, а на bluetooth-устройство - нет. Если у кого-то получится это сделать, дайте знать в комментариях - решим эту задачу вместе.

Если вы, также, как и я, захотите использовать многие приложения исключительно в контейнерах, то подобный Makefile может служить единой точкой запуска всех контейнеризированных приложений, которые вы часто используете.
Доселе, примеры контейнеризированных браузеров, которые я находил в Интернете, скорее вредили пользователю, чем помогали. Например, в Dockerfile отсутствовала смена
пользователя с рутового на обычного, что вынуждало в точке входа запускать Chromium
с флагом --no-sandbox. А это, в свою очередь, отключало описанный в начале статьи механизм изоляции JavaScript-рантайма.

Историческая справка: Дело в том, что в декабре 2017 года произошла ещё одна революция в безопасности браузеров:
В Chrome 63 была добавлена изоляция среды исполнения между вкладками.
До этого, если у вас было открыто две вкладки, на одной из которых вы прошли аутентификацию в почту, а на второй открыли нехороший сайт, то JavaScript с нехорошего сайта мог украсть токен доступа к сессии почтового ящика с первой вкладки и пополнить спам-базу своего неэтичного владельца адресами ваших контактов, к примеру. Как видите, контейнеризация браузера никак не могла бы защитить от такой опасности.
Именно таким опасным было пользование Интернетом до конца 2017 года для пользователей Chromium, а для пользователей Firefox и вовсе вплоть до июня 2021го, когда наконец Project Fisson прошёл стадию бета-тестирования и в Firefox 97 данный механизм изоляции вкладок был уже включен по умолчанию.
Механизм изоляции вкладок в Chromium является составной частью песочницы Chromium.
То есть, отключаем песочницу - отключаем изоляцию вкладок. Уж куда безопаснее будет запускать браузер на хосте, без контейнера, чем в контейнере с флагом --no-sandbox.

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

  • Dockerfile

FROM docker.io/library/debian:bookworm-slim 

RUN apt update && apt upgrade -y \
    && apt install keepass2 -y \
    && rm -rf /var/lib/apt/lists/*

ARG GROUP_ID=9898
ARG USER_ID=9898
ARG USRNME=testpilot

RUN groupadd -g $GROUP_ID --system $USRNME && \
    useradd -m --gid $GROUP_ID --system -u $USER_ID $USRNME \
    && mkdir -p /home/$USRNME/.config \
    && mkdir -p /home/$USRNME/.cache \
    && chown --recursive $USRNME:$USRNME /home/$USRNME

USER $USRNME

CMD ["keepass2"]
  • скрипт запуска:

#!/bin/bash
CONTAINER=$1
podman run \
    --uidmap=0:119:1 \
    --uidmap=9898:120:1 \
    --gidmap=0:119:1 \
    --gidmap=9898:120:1 \
    --rm -it \
    --net=none \
    -v /tmp/.X11-unix:/tmp/.X11-unix:ro \
    -v /opt/keepass:/home/testpilot/:rw \
    -e DISPLAY=$DISPLAY \
    $CONTAINER

Данный скрипт запуска принимает в качестве аргумента имя образа.
Допустим, что у нас есть опасение относительно KeePass2, что по желанию владельца кода, эта программа в один прекрасный день может отправить пароли куда-то в далёкое зарубежье. Чтобы этого не могло произойти, используем параметр --net=none, так что наш контейнер не будет иметь доступа к сети.

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

В завершение:

На этом, я планирую завершить серию статей о запуске графических приложений в контейнерах, ввиду однотипности дальнейших примеров.
Предполагаю, что вам также понадобится контейнер с okular для открытия PDF-документов. Okular желательно также запускать с параметром --net=none, так как PDF-файлы это PostScript-документы, которые похожи на HTML тем, что в них можно добавлять JavaScript код. А JavaScript-вирусы, как правило, докачивают вредоносный код из Интернета.

Важный оффтопик: Советую на хосте задать приложением по умолчанию для открытия PDF-файлов Thunar или другой файловый менеджер, или вовсе текстовый редактор типа gedit. Иначе, риск слишком велик - случайный клик по ярлыку случайно скачанного PDF-файла может оказаться запуском трояна вашими собственными руками.

В Dockerfile для Okular установите попутно KDE, чтобы была доступна тёмная тема Breeze Dark, таким образом:

apt install -y okular kde-plasma-desktop

Чтобы тёмную тему не пришлось настраивать каждый раз после запуска, создайте и отображайте в скрипте запуска домашнюю папку для контейнерного пользователя:

-v /opt/okular:/home/username:rw 

Заметьте, что целиком свою домашнюю папку отображать в контейнер с точки зрения безопасности было бы грубой ошибкой, так как в ~/.local/share/containers хранятся те самые образы контейнеров, на целостность которых мы во многом рассчитываем.
Не забывайте, что UID/GID пользователей для процессов контейнера на хосте ни в коем
случае не должны пересекаться друг с другом. Также, этим пользователям необходимо выдавать права на отрисовку на экране после каждого запуска компьютера. Это делается без повышенных привилегий (в отличие от скрипта sound.sh для выдачи прав на запись в звуковую карту через ACL).
Мой скрипт xhost.sh выглядит примерно так:

#!/bin/bash
xhost +si:localuser:pod_chrom
xhost +si:localuser:pod_kee
xhost +si:localuser:pod_vs
xhost +si:localuser:pod_okular
#... и так далее

Мой скрипт sound.sh выглядит примерно так:

#!/bin/bash

# Дать chromium звук & вебку & GPU
setfacl -R -m u:100007:rw /dev/snd
setfacl -m u:100007:rw /dev/dri/card0
setfacl -m u:100007:rw /dev/video0

# Дать какому-то другому приложению звук & вебку & GPU
setfacl -R -m u:100021:rw /dev/snd
setfacl -m u:100021:rw /dev/dri/card0
setfacl -m u:100021:rw /dev/video0
#... и так далее

В качестве послесловия, отметим, что приведённый в этих двух статьях стиль пользования ОС Линукс является выражением потребности в более современной архитектуре ОС, которая бы делала невозможной столь лёгкую компрометацию системы (как например через открытие PDF-файла). В Линукс всё файл, и доступ любому файлу определяется правами
доступа POSIX или ACL. И такое однообразие в обращении ко всему в системе открывает простор для фантазий на тему эксплойта нецелевого использования. Выражаясь проще, "защита от дурака" это ещё и защита от злоумышленника, а в Линукс она отсутствует. Это и неудивительно, ведь в 1969 году Кен Томпсон и Деннис Ричи вряд ли могли представить себе все эти опасности, которых мы учимся избегать в данных статьях, в частности. Они имплементировали самые лучшие идеи того времени - многопользовательская и многозадачная архитектура.
Тем не менее с годами выявлялись новые потребности, которые оформлялись в пожелания к архитектуре ОС. Так, в начале 2010х годов началась разработка Phantom OS - операционной системы, в которой всё суть объект.
Phantom OS архитектурно, из коробки, закрывает потребности в безопасном, изолированном запуске приложений, а это то, ради чего мы здесь научились делать так много нетривиальных действий. Хочется надеяться на то, что этот проект поскорее станет зрелым и пойдёт в массы, и что мы вскоре сможем пользоваться ОС с современной архитектурой, учитывающей выявленные в последние годы потребности.
Покамест же, запускаем десктопные приложения в контейнерах.

Комментарии (6)


  1. wasd0
    22.12.2024 17:47

    Можете отражать и в заголовках этого цикла, какая это часть по номеру? Например, эта вторая.


    1. vaclav1986 Автор
      22.12.2024 17:47

      Сделал


  1. baldr
    22.12.2024 17:47

    В Ubuntu браузеры Chromium и Firefox по-умолчанию уже ставится через snap, что и есть ещё одна разновидность контейнеров. Они уже настроены и изолированы от хостовой системы. Ещё бывает flatpak.

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

    Очень режет глаз простыня слоёв с RUN echo - почему бы не объединить слои? И вообще - это просто создание двух файлов - создайте их заранее и просто положите через COPY?

    Makefile и build-essentials - это, конечно, на любителя, но, мне кажется, это как из пушки по воробьям. Здесь подойдёт обычный bash-скрипт.

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


    1. vaclav1986 Автор
      22.12.2024 17:47

      Спасибо за конструктивный отзыв. Я сам использовал сначала flatpak, а потом snap на Debian, но вскоре отказался от них. Вот, что меня не устроило:

      • Пакеты flatpak и snap исполняются в том же самом пространстве имён - а это именно тот риск, от которого мы уходили в данном цикле статей.

      • Скачивая приложения из магазина Canonical Snapcraft, мы получаем пакет, настроенный не так, как нам нужно. Например, как в примере с KeePass2 в данной статье, мы могли бы ограничить доступ в сеть `snap disconnect keepass2:network`, но после обновления приложения эта настройка слетит, и нам нужно будет снова исполнять эту команду. А как этот момент на практике не пропустить?

      • Используя snap, мы переходим на автоматические обновления, то есть, не от нас даже зависит, когда пакет обновится. Мы можем влиять на частоту обновлений, но это не меняет того факта, что наша система становится, хотя-бы отчасти, rolling release.

      • Есть общее замечание по безопасности самих пакетов, распространяемых через магазины приложений третьих лиц. Пакеты, которые устанавливаются из репозиториев типа APT, проверяются одной командой, очень надёжной. По сути, у нас никого надёжнее и нет. Образы же snap, напротив, проверяются Canonical не очень тщательно, так как джентельмены верят друг другу на слово.

      • Магазин приложений snapcraft.io это собственность Canonical. Flathub развивается сообществом. В обоих случаях, тут вопрос менеджмента рисков.

      • По поводу размеров образов Podman - слои используются повторно для других образов, которые содержат те же самые слои, с начала до первого отличия. То есть, слой занимает место на диске только один раз. Таким образом, если мы создаём новый образ, основывая его на старом, нам выгоднее что-то приписывать в конце, чем улучшать что-то вначале :-)

      Ещё мне нравится, когда конфигурация прозрачна для меня, как в случае с нашими контейнерами. Это личное предпочтение


  1. greggronix1
    22.12.2024 17:47

    Linux это не OC, а ядро :)


    1. vaclav1986 Автор
      22.12.2024 17:47

      Да, верно. Чтобы не быть мне душным, может просто "Линукс" писать? Просто "ОС семейства Линукс" для глаз долго