SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-21

Установка Incus системных контейнеров на VPS

Узнайте, как развернуть Incus на VPS для запуска полноценных системных контейнеров. Руководство охватывает настройку хранилища, сети, проверку виртуализации и типичные ошибки.

What an Incus system container is

Incus system containers on a VPS give you a whole machine with its own init system and its own user accounts, not a single process with a filesystem attached. The container boots, runs an init as PID 1, and answers systemctl. It shares the host's kernel, so it is not a virtual machine. Everything above the kernel behaves like one.

Incus is the community fork of LXD, maintained under the Linux Containers project. The client command is incus. It also runs real virtual machines through QEMU when you pass --vm, but the system container is the reason most people install it, and it is what the rest of this guide covers.

Почему сравнение с Docker вводит людей в заблуждение

Docker упаковывает один процесс. Incus упаковывает одну операционную систему. Документация Incus прямо указывает на это различие: «Контейнеры приложений (как, например, в Docker) упаковывают один процесс или приложение. Системные контейнеры, напротив, имитируют полноценную операционную систему, подобную той, что вы запускаете на хосте или в виртуальной машине».

Это различие меняет повседневную работу с инструментом.

  • В образе Docker нет init, поэтому systemctl внутри него не работает. В контейнере Incus работает система инициализации, поэтому службы и таймеры функционируют так же, как на обычном сервере.
  • Контейнер Docker предназначен для удаления и пересборки из Dockerfile. Контейнер Incus предназначен для длительного использования, обновления и создания снимков состояния.
  • Образ Docker — это артефакт сборки, который вы отправляете в реестр. Экземпляр Incus — это состояние на диске в пуле хранилища, которое вы перемещаете с помощью incus export.
  • Docker изолирует рабочую нагрузку. Incus изолирует машину, поэтому один контейнер может содержать несколько рабочих нагрузок и несколько учетных записей пользователей.

Вы можете запустить Docker внутри системного контейнера Incus. Вы не сможете запустить Incus внутри контейнера приложений Docker. Если вам действительно нужен один процесс на контейнер с этапом сборки образа, сначала ознакомьтесь со статьей Podman и Docker на VPS. Если вам нужно отдельное ядро для каждой рабочей нагрузки вместо общего, статья Микро-ВМ Firecracker на VPS описывает альтернативный подход.

Будет ли Incus работать внутри VPS?

Это зависит от типа виртуализации вашего VPS и версии ядра, поэтому проверьте оба параметра перед установкой. Не полагайтесь на рекламные страницы провайдера. Выполните эти четыре команды на сервере.

systemd-detect-virt
uname -r
stat -fc %T /sys/fs/cgroup
cat /sys/fs/cgroup/cgroup.controllers

systemd-detect-virt вывод kvm или qemu означает, что ваш VPS является виртуальной машиной с собственным ядром. Это простой случай, так как Incus будет работать так же, как на физическом оборудовании. Вывод lxc, lxc-libvirt или openvz означает, что ваш VPS сам является контейнером, использующим ядро хоста провайдера. Контейнеры Incus внутри него будут вложенными, и вложенность работает только в том случае, если провайдер включил её для вашего контейнера. Вы не можете включить её изнутри, так как эта настройка находится на хосте, к которому у вас нет доступа.

stat -fc %T /sys/fs/cgroup должен выводить cgroup2fs. Любой другой результат означает, что система использует cgroup (control group) v1 или гибридную схему, которые текущая версия Incus не поддерживает.

cat /sys/fs/cgroup/cgroup.controllers перечисляет контроллеры control-group, делегированные вам. Incus требует наличия blkio, cpuset, devices, freezer, memory и pids. На вложенном VPS этот список часто короче, чем на KVM, так как провайдер сам определяет, какие ресурсы предоставить. Отсутствие контроллера в этом файле означает, что Incus не сможет его использовать, поэтому лимиты экземпляров, зависящие от этого контроллера, будут недоступны.

Версия ядра сейчас важнее, чем раньше. По состоянию на август 2026 года документация Incus указывает два разных минимума для двух веток, поддерживаемых разработчиками. Для ветки 6.0 LTS (long term support) указано: «Минимально поддерживаемая версия ядра — 5.4». Для текущей стабильной ветки указано: «Минимально поддерживаемая версия ядра — 6.12». Ubuntu 24.04 включает серию 6.0 LTS в свой репозиторий и использует ядро 6.8, что является поддерживаемой комбинацией. Установка текущей стабильной сборки из официального репозитория на то же ядро 6.8 опускает вас ниже документированного минимума, поэтому прочитайте uname -r перед выбором репозитория.

Если ваша цель — полноценные виртуальные машины, а не контейнеры, ограничения будут другими и более строгими. См. вложенная виртуализация на VPS, чтобы узнать, может ли ваш VPS вообще предоставлять /dev/kvm, и Proxmox на арендованном VPS для случаев, когда вы владеете оборудованием.

Установка Incus в Ubuntu или Debian

В Debian 13, Ubuntu 24.04 и более новых версиях Incus входит в состав официальных репозиториев.

sudo apt update
sudo apt install -y incus

В Debian команда incus-base устанавливает поддержку контейнеров без компонентов для виртуальных машин. В Ubuntu добавьте qemu-system, если вам также нужны экземпляры --vm.

Если вам требуется более свежий релиз, чем тот, что доступен в вашем дистрибутиве, используйте официальные пакеты из репозитория проекта по адресу pkgs.zabbly.com. Эти команды взяты из файла README в репозитории проекта.

sudo apt update && sudo apt install -y curl
sudo mkdir -p /etc/apt/keyrings/
sudo curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
sudo sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/stable
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
sudo apt-get update
sudo apt-get install -y incus

Затем предоставьте вашему пользователю доступ к сокету демона.

sudo usermod -aG incus-admin "$USER"
newgrp incus-admin
incus info

incus info выводит конфигурацию сервера, что подтверждает работоспособность сокета. Ошибка прав доступа означает, что изменения группы еще не применились к вашей оболочке; это исправляется командой newgrp incus-admin для текущего сеанса или полным перезаходом в систему. Учитывайте, что членство в группе incus-admin равносильно правам root на хосте, так как доступ к этому сокету дает полный контроль над демоном, работающим от имени root. Некоторые дистрибутивы также создают группу incus для ограниченного доступа пользователей.

Теперь инициализируйте демон.

sudo incus admin init

Отвечайте на вопросы интерактивно, вместо использования incus admin init --minimal. Минимальный путь настройки выбирает драйвер хранилища dir; в следующем разделе объясняется, почему этот выбор важен в дальнейшем.

Запустите что-нибудь и убедитесь, что всё работает.

incus launch images:debian/13 web
incus list
incus exec web -- bash

incus list должен показать web в статусе RUNNING с IPv4-адресом в подсети incusbr0. Отсутствие адреса означает, что DHCP (протокол динамической настройки узла) не завершил работу; это рассматривается в разделе о сети. Если контейнер не запускается, причина выводится в incus info web --show-log, а ошибки уровня демона попадают в sudo journalctl -u incus -n 50. На VPS, где systemd-detect-virt вернул lxc или openvz, этот запуск является проверкой того, доступна ли вам вложенная виртуализация.

Почему важен выбор бэкенда хранилища

Бэкенд хранилища определяет, будет ли создание снимка (snapshot) мгновенным или потребует полного копирования диска контейнера. Это единственный параметр, который нельзя легко изменить после установки.

Incus поддерживает dir, btrfs, lvm, zfs, Ceph и несколько удаленных драйверов. На VPS с одним диском реальный выбор стоит между dir и btrfs.

Драйвер dir хранит каждый контейнер в виде обычных файлов и директорий в /var/lib/incus. В документации Incus он описан как «значительно медленнее всех остальных драйверов», так как ему приходится распаковывать каждый образ и создавать полные копии вместо использования ссылок на общие блоки. Снимок контейнера объемом 4 GiB требует записи 4 GiB данных и занимает столько же времени, сколько cp -a. Дисковые квоты работают только на ext4 или XFS с включенными на уровне файловой системы project quotas, что по умолчанию отсутствует в большинстве образов VPS, поэтому ограничение диска в пуле dir часто не работает.

btrfs и zfs используют технологию copy-on-write, поэтому снимок записывает только те блоки, которые изменились после его создания. Incus рекомендует именно эти два бэкенда. Снимки создаются практически мгновенно. Дисковые квоты работают через встроенную поддержку квот файловой системы.

Большинство тарифных планов VPS предоставляют один диск без свободного раздела, поэтому размещайте пул в loop-файле. Incus сделает это за вас, если вы не укажете source=.

sudo apt install -y btrfs-progs
incus storage create fast btrfs size=30GiB
incus profile device set default root pool=fast
incus launch images:debian/13 web2 -s fast

Без size= пул на основе loop-файла занимает 20% свободного дискового пространства, с минимальным порогом 5 GiB и максимальным 30 GiB. Устанавливайте размер осознанно. Loop-файл находится на вашей корневой файловой системе, поэтому пул и хост используют общее свободное пространство: заполнение пула приведет к заполнению диска хоста.

ZFS в Debian и Ubuntu является DKMS-модулем, а не частью ядра, поэтому он пересобирается при каждом обновлении ядра и может не собраться после него. На сервере, за которым вы не следите ежедневно, btrfs требует меньше обслуживания, чем ZFS.

Три сетевых режима и то, что каждый из них открывает

incus admin init создает управляемый мост под названием incusbr0 и помещает в него каждый новый экземпляр. Это один из трех способов подключения контейнера; остальные два существуют потому, что первый скрывает ваши контейнеры за NAT (network address translation).

Управляемый мост. incusbr0 получает частную подсеть. Хост занимает в ней первый адрес и выступает в роли шлюза, Incus запускает на нем DHCP и DNS (domain name system), а исходящий трафик уходит через публичный адрес хоста с применением source NAT. Ничто извне не попадет в контейнер, пока вы не разрешите это явно. Перенаправьте порт с помощью устройства proxy.

incus config device add web http proxy listen=tcp:0.0.0.0:8080 connect=tcp:127.0.0.1:80 nat=true

nat=true выполняет пересылку с помощью правил netfilter вместо проксирования через отдельное соединение в пространстве пользователя, поэтому реальный адрес клиента сохраняется в логах контейнера. Incus поддерживает этот режим только тогда, когда хост является шлюзом для экземпляра, что в точности соответствует случаю incusbr0.

macvlan. Контейнер получает собственный MAC-адрес (media access control) в физической сети хоста. На большинстве VPS-платформ это не работает, так как порт виртуального коммутатора привязан к MAC-адресу вашей виртуальной машины и отбрасывает кадры с любыми другими адресами. Существует второе ограничение, с которым сталкиваются пользователи даже там, где это работает. В документации Incus указано, что «устройства macvlan, будучи способными обмениваться данными между собой и с внешним миром, не могут взаимодействовать с родительским устройством. Это означает, что вы не сможете использовать macvlan, если вам когда-либо потребуется, чтобы экземпляры взаимодействовали с самим хостом».

Routed. Это режим, который обычно работает на VPS с дополнительными адресами. В документации Incus это устройство описывается как такое, которое «создает пару виртуальных устройств для соединения хоста с экземпляром и настраивает статические маршруты и записи proxy ARP/NDP, позволяя экземпляру присоединиться к сети назначенного родительского интерфейса». ARP — это протокол разрешения адресов (address resolution protocol). Контейнер сохраняет публичный адрес. Хост отвечает на ARP-запросы для него, поэтому провайдер по-прежнему видит только MAC-адрес хоста.

incus config device add web eth0 nic nictype=routed parent=enp1s0 ipv4.address=203.0.113.20

Узнайте имя родительского интерфейса с помощью ip route show default. В современных образах используются имена вроде enp1s0 или ens3, реже eth0. Указание имени устройства eth0 переопределяет то, что задано в профиле default, поэтому контейнер оказывается в маршрутизируемом интерфейсе вместо моста. Проверьте результат изнутри с помощью ip a и ip route.

Почему контейнер получил доступ к сервису на хосте

Контейнер в incusbr0 имеет собственное сетевое пространство имен. У него нет межсетевого экрана, отделяющего его от хоста. Хост находится в той же сети моста по адресу шлюза, поэтому изнутри контейнера хост является напрямую доступным соседом, и любой сервис хоста, привязанный к 0.0.0.0, будет отвечать на запросы.

Проверьте это самостоятельно. На хосте выведите список слушающих портов.

sudo ss -tlnp

Затем изнутри контейнера обратитесь к шлюзу, который сообщает ip route.

ip route show default
nc -zv 10.0.0.1 6379

Если база данных, эндпоинт метрик или панель администратора на хосте привязаны к 0.0.0.0, эта проверка пройдет успешно. Сетевой экран вашего провайдера никогда не увидит этот пакет, так как пакет не покидал пределы машины. В этом кроется причина большинства вопросов «как он получил доступ»: контейнер изолирован от интернета через NAT, но от хоста он не изолирован ничем.

Привязывайте сервисы хоста к 127.0.0.1 везде, где это возможно. Затем настройте фильтрацию моста на хосте. В системах с ufw политика по умолчанию deny уже блокирует трафик от контейнеров к хосту, что нарушает работу DNS и DHCP в Incus, и решение, предлагаемое в документации Incus, — это sudo ufw allow in on incusbr0. Эта единственная команда открывает все порты хоста для всех контейнеров. Вместо этого разрешайте только то, что действительно необходимо контейнерам.

sudo ufw allow in on incusbr0 to any port 53 proto udp
sudo ufw allow in on incusbr0 to any port 53 proto tcp
sudo ufw allow in on incusbr0 to any port 67 proto udp
sudo ufw route allow in on incusbr0
sudo ufw route allow out on incusbr0

Два правила ufw route позволяют трафику экземпляров проходить через хост в интернет. Без них политика маршрутизации ufw отбрасывает пересылаемые пакеты, поэтому контейнеры получают адрес, но не имеют доступа к сети.

Снимки и профили

Снимок (snapshot) — это копия состояния экземпляра (instance) в конкретный момент времени, хранящаяся внутри пула хранения.

incus snapshot create web pre-upgrade
incus info web
incus snapshot restore web pre-upgrade
incus snapshot delete web pre-upgrade

incus info web выводит список снимков, принадлежащих экземпляру. Настраивайте расписание снимков для каждого экземпляра отдельно.

incus config set web snapshots.schedule=@daily
incus config set web snapshots.expiry=4w

Снимок находится в том же пуле, на том же диске и на том же сервере. Он защищает от последствий неудачного обновления. Снимок не защищает от выхода диска из строя или удаления экземпляра. Резервной копией является incus export, при этом файл должен быть выгружен за пределы сервера.

incus export web /root/web-backup.tar.gz
incus import /root/web-backup.tar.gz

Профиль — это именованный набор ключей конфигурации и устройств, применяемый к экземплярам. Каждый экземпляр получает профиль default, если не указано иное; именно этот профиль определяет корневой диск и сетевой интерфейс. Изменение default затрагивает все использующие его экземпляры. Это полезно, например, для одновременного отключения сети у двадцати контейнеров.

incus profile create small
incus profile set small limits.memory=512MiB
incus profile set small limits.cpu=1
incus launch images:debian/13 api -p default -p small

Профили применяются последовательно, поэтому приоритет имеет ключ, установленный в последнем указанном профиле. Проверить итоговую конфигурацию экземпляра можно с помощью incus config show api --expanded.

Запуск Docker внутри контейнера Incus

Для работы Docker внутри системного контейнера Incus необходимо включить вложенность (nesting), так как Docker создает собственные пространства имен и точки монтирования, которые по умолчанию запрещены для контейнера.

incus config set web security.nesting=true
incus restart web

Документация Incus описывает security.nesting как «разрешение вложенности внутри экземпляра», и по умолчанию для контейнеров установлено значение false. Еще два важных момента следуют из FAQ Incus. Контейнер не может загружать модули ядра, поэтому все необходимые для Docker модули должны быть загружены на хосте и указаны в incus config set web linux.kernel_modules overlay,br_netfilter. Кроме того, создание файла /.dockerenv внутри контейнера позволяет Docker пропустить некоторые проверки, которые завершаются ошибкой во вложенной среде.

На хостах с Ubuntu 24.04 ограничения AppArmor на пространства имен непривилегированных пользователей могут блокировать pivot_root, выполняемый runc. Docker внутри контейнера выводит следующее сообщение:

failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error jailing process inside rootfs: pivot_root .: permission denied

а в dmesg на хосте появляется строка, содержащая apparmor="DENIED" operation="pivotroot" class="mount". Настройка, к которой часто прибегают — kernel.apparmor_restrict_unprivileged_userns. Отключение этой опции не является надежным решением: в официальном отчете об ошибке Incus для данного случая указано, что установка значения 0 не решила проблему. Сначала изучите dmesg, чтобы убедиться, что причиной является именно AppArmor, прежде чем изменять настройки безопасности по умолчанию.

Если вы предпочитаете запускать контейнеры напрямую на VPS, исключив лишний уровень абстракции, в разделе запуск Docker на VPS описана соответствующая настройка.

Типичные сбои и сообщения об ошибках

Экземпляры теряют сеть после установки Docker на хосте. В документации Incus указана причина: «Docker устанавливает глобальную политику FORWARD в drop, что мешает Incus пересылать трафик, из-за чего экземпляры теряют сетевое подключение». Экземпляры сохраняют свои IP-адреса, но не могут ничего передать. Установите ip-forward-no-drop в значение true в файле /etc/docker/daemon.json, затем обеспечьте постоянную работу пересылки и разрешите прохождение трафика через цепочку Docker.

echo "net.ipv4.conf.all.forwarding=1" | sudo tee /etc/sysctl.d/99-forwarding.conf
sudo systemctl restart systemd-sysctl
sudo iptables -I DOCKER-USER -i incusbr0 -j ACCEPT
sudo iptables -I DOCKER-USER -o incusbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Эти правила iptables не сохраняются автоматически после перезагрузки. Настройте их постоянное применение.

Контейнеры перестают запускаться с ошибкой cgroup. Об этом говорится в FAQ Incus. Сообщение о Failed to mount "/sys/fs/cgroup" обычно означает, что VPN-клиент на хосте примонтировал контроллер cgroup v1 по пути net_cls поверх cgroup v2, который использует Incus. Команда sudo umount /sys/fs/cgroup/net_cls исправляет это.

Экземпляр не получает IPv4-адрес. Команда incus list показывает, что экземпляр запущен, но столбец адреса пуст. Ответы DHCP от хоста отбрасываются, чаще всего межсетевым экраном хоста, который не знает о мосте. В ufw команда sudo ufw allow in on incusbr0 to any port 67 proto udp восстанавливает работу. Отслеживайте поступление запросов с помощью sudo tcpdump -ni incusbr0 port 67.

Экземпляр отказывается запускаться на вложенном VPS. Сначала ознакомьтесь с incus info <name> --show-log, затем с sudo journalctl -u incus -n 50. Если systemd-detect-virt выдает lxc или openvz, значит, проблема на стороне провайдера, и никакие настройки внутри вашего VPS её не решат.

Снимки (snapshots) создаются медленно, а диск постоянно переполняется. Вы используете пул dir. Команда incus storage list выводит драйвер для каждого пула. Переход на пул с поддержкой copy-on-write подразумевает создание нового пула, копирование экземпляров в него с помощью incus copy web web-new -s fast и последующее удаление оригиналов после того, как вы убедитесь, что копии запускаются корректно.

FAQ

Является ли контейнер Incus тем же самым, что и контейнер Docker?

Нет. Docker упаковывает один процесс или приложение. Системный контейнер Incus имитирует полноценную операционную систему со своим init-процессом, пользователями, службами и менеджером пакетов. Контейнер Incus обслуживается и обновляется как обычный сервер. Контейнер Docker при обновлении удаляется и пересобирается из образа. Вы можете запустить Docker внутри контейнера Incus, установив security.nesting=true для этого контейнера. Обратное невозможно.

Могу ли я запустить Incus на VPS?

На KVM VPS — да. Если systemd-detect-virt выводит kvm или qemu, значит, у вас собственное ядро, и Incus работает так же, как на физическом оборудовании. Если выводится lxc, lxc-libvirt или openvz, ваш VPS сам является контейнером. В этом случае контейнеры Incus будут вложенными и заработают только при условии, что провайдер разрешил вложенность (nesting) для вашего контейнера. Также проверьте uname -r, поскольку по состоянию на август 2026 года текущая стабильная ветка Incus требует ядро версии не ниже 6.12, в то время как для ветки 6.0 LTS минимальным является 5.4.

Какой бэкенд хранилища выбрать для Incus на VPS?

Используйте btrfs на loop-файле, если у вас нет свободного блочного устройства. Драйвер dir работает значительно медленнее остальных, так как он копирует файлы вместо использования copy-on-write, из-за чего каждый снапшот приводит к полной перезаписи контейнера. Команда incus admin init --minimal выбирает dir, поэтому стоит потратить две минуты на ответы в интерактивном режиме. Создайте пул с помощью incus storage create fast btrfs size=30GiB.

Почему мой контейнер Incus может получить доступ к службе, запущенной на хосте?

Потому что мост incusbr0 по умолчанию помещает хост в ту же подсеть, что и контейнер, назначая его шлюзом, и между ними нет фильтрации. Любая служба хоста, привязанная к 0.0.0.0, будет отвечать на запросы, а сетевой экран провайдера не увидит эти пакеты, так как они не покидают пределы машины. Привязывайте службы хоста к 127.0.0.1, а на хостах с ufw разрешайте только DNS и DHCP на интерфейсе incusbr0 вместо использования общего правила sudo ufw allow in on incusbr0.

Как сделать резервную копию контейнера Incus?

Команда incus export web /root/web-backup.tar.gz записывает экземпляр и его снапшоты в один файл, а incus import восстанавливает его на том же или другом сервере. Снапшоты, созданные через incus snapshot create, не являются резервными копиями: они хранятся в том же пуле на том же диске, поэтому они помогут при неудачном обновлении, но не при выходе сервера из строя. Планируйте создание бэкапов с помощью incus config set web snapshots.schedule=@daily и копируйте полученные файлы за пределы сервера.

#incus#lxd#system-containers#virtualization#vps