Кукловодим через OpenVox. Часть 1. Установка сервера
Первая часть цикла про то, как я приручил парк серверов через OpenVox — форк Puppet, который живёт и развивается, пока сам Puppet потихоньку закрывается. В этой части поднимаем сервер управления на Debian 13, кладём весь код под git и настраиваем автоматическую раскатку через r10k.
Идея простая: ни одной настройки руками на боевых серверах. Всё, что делает инфраструктуру такой, какая она есть, лежит в git, проходит через ревью в виде коммита и раскатывается одной командой. Хочешь понять, почему сервер настроен именно так — смотришь историю. Хочешь откатить — git revert. Вот к этому и идём.
Все команды выполняются от root на сервере.
Ставим OpenVox Server
Подключаем репозиторий OpenVox и ставим сервер:
wget https://apt.voxpupuli.org/openvox8-release-debian13.deb
dpkg -i openvox8-release-debian13.deb
apt update
apt install -y openvox-server
Запускаем и включаем автозапуск. Обратите внимание: исторически сервис называется puppetserver, а не openvoxserver — форк сохранил совместимость:
systemctl enable --now puppetserver
/opt/puppetlabs/bin/puppetserver --version
Добавляем бинарники OpenVox в PATH, чтобы не писать полный путь каждый раз:
echo 'export PATH=$PATH:/opt/puppetlabs/bin' > /etc/profile.d/openvox.sh
Три грабли, на которые я наступил на Debian 13
Свежий trixie преподнёс пару сюрпризов — сохраняю, чтобы вы их обошли.
Ошибка про openjdk при установке. В середине 2025-го пакет openvox-server на trixie тянул несуществующие openjdk-17 и openjdk-11. Если словили такую ошибку — поставьте openjdk-21-jre-headless руками и повторите установку сервера.
puppetserver не сразу слушает порт 8140. Это JVM, холодный старт занимает 30–90 секунд. Если systemctl status puppetserver показывает active, а порта всё ещё нет — не паникуйте, просто подождите. Проверка:
ss -tlnp | grep 8140
Память. По умолчанию heap 2 ГБ (-Xms2g -Xmx2g). Для 10–50 нод хватает с запасом. Если RAM в обрез, правьте JAVA_ARGS в /etc/default/puppetserver и перезапускайте сервис.
Финальная проверка, что сервер жив и слушает порт:
systemctl status puppetserver # active (running)
ss -tlnp | grep 8140 # java слушает 8140
Кладём код в control-repo
Теперь самое важное архитектурное решение. Весь код — манифесты, Hiera, профили — живёт в git-репозитории /root/control-repo. А r10k раскатывает его в рабочее окружение /etc/puppetlabs/code/environments/production/.
Здесь есть одна вещь, которую надо усвоить сразу, иначе потом будет больно.
Ветка git = окружение Puppet. Ветка
productionсоответствует окружениюproduction. И r10k затирает содержимое окружения тем, что лежит в git. Поэтому весь код обязан быть закоммичен, а рабочая ветка обязана называтьсяproduction, а неmain. Забудете — r10k молча снесёт незакоммиченное.
Структура кода
control-repo/
├── environment.conf # modulepath (обязательно с site-modules)
├── hiera.yaml # иерархия данных
├── Puppetfile # внешние модули с Forge (stdlib и т.п.)
├── .gitignore # /modules/ (наполняется r10k)
├── data/ # данные Hiera
│ ├── common.yaml # дефолты для всех нод
│ └── nodes/ # переопределения по конкретной ноде
├── manifests/
│ └── site.pp # классификация нод
└── site-modules/ # локальный код (не трогается r10k)
├── role/manifests/ # роли (чем является сервер)
└── profile/ # профили (технологические кусочки)
├── manifests/
└── templates/
Разделение site-modules/ и modules/ — принципиальное. r10k управляет каталогом modules/ целиком и сносит оттуда всё, чего нет в Puppetfile. А ваш локальный код — роли и профили — живёт в site-modules/ и r10k не трогается. Перепутаете каталоги — потеряете свои модули при первом же деплое.
Собираем репозиторий из текущего кода
Если на сервере уже есть код в окружении production, берём его как основу:
cp -a /etc/puppetlabs/code/environments/production /root/control-repo
cd /root/control-repo
Если начинаем с чистого листа — создаём каталоги вручную:
mkdir -p /root/control-repo/{manifests,data/nodes,site-modules/role/manifests,site-modules/profile/manifests,site-modules/profile/templates}
cd /root/control-repo
Ключевые файлы
environment.conf — обязательно с site-modules в modulepath, иначе Puppet не найдёт ваши роли:
cat > environment.conf <<'EOF'
modulepath = site-modules:modules:$basemodulepath
EOF
hiera.yaml — иерархия данных, от частного к общему: сначала ищем настройки конкретной ноды, потом общие:
cat > hiera.yaml <<'EOF'
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: 'Per-node'
path: 'nodes/%{trusted.certname}.yaml'
- name: 'Common'
path: 'common.yaml'
EOF
Puppetfile — внешние модули с Forge. stdlib нужен почти всем модулям, так что ставим сразу:
cat > Puppetfile <<'EOF'
forge 'https://forge.puppet.com'
# базовый модуль; держим на 9.x до осознанного перехода на 10.x
mod 'puppetlabs-stdlib', '9.7.0'
EOF
.gitignore — каталог modules/ наполняет r10k, в git его не держим:
cat > .gitignore <<'EOF'
# modules/ наполняет r10k из Puppetfile — в git не держим
/modules/
EOF
manifests/site.pp — базовая классификация. Пока все ноды получают role::base:
cat > manifests/site.pp <<'EOF'
node default {
include role::base
}
EOF
Инициализируем git — и не забываем про ветку
git init -b production
git config user.name 'puppet admin'
git config user.email 'root@puppet.example.com'
git add -A
git commit -m 'Initial control repo import'
git branch # ПРОВЕРЬ: активна ветка production
Если по какой-то причине ветка называется иначе — переименуйте:
git branch -m production
Bare-репозиторий как origin
r10k тянет код из git-remote. Простейший рабочий вариант — локальный bare-репозиторий прямо на сервере:
git init --bare /srv/puppet/control-repo.git
git remote add origin /srv/puppet/control-repo.git
git push origin production
Про бэкап честно. Bare-репозиторий на том же сервере спасает от ошибок в коде — есть история, есть откат. Но он не переживёт смерть диска. Для настоящего бэкапа заведите приватный репозиторий на GitHub или GitLab и добавьте его вторым remote:
git remote set-url --add origin git@github.com:youruser/control-repo.git
Ставим и настраиваем r10k
r10k ставим как ruby-gem внутрь AIO-Ruby от OpenVox — чтобы не мешать системному Ruby:
/opt/puppetlabs/puppet/bin/gem install r10k
/opt/puppetlabs/puppet/bin/r10k version
Конфиг r10k — указываем, откуда брать код и куда его раскатывать:
mkdir -p /etc/puppetlabs/r10k
cat > /etc/puppetlabs/r10k/r10k.yaml <<'EOF'
---
sources:
main:
remote: '/srv/puppet/control-repo.git'
basedir: '/etc/puppetlabs/code/environments'
EOF
Первый деплой. Флаг -p — ставить модули из Puppetfile, -v — подробный вывод. Перед этим на всякий случай бэкапим текущее окружение, потому что r10k его перезапишет:
cp -a /etc/puppetlabs/code/environments/production /root/production-backup-$(date +%F)
/opt/puppetlabs/puppet/bin/r10k deploy environment -pv
Проверяем, что код на месте и внешние модули подтянулись:
ls /etc/puppetlabs/code/environments/production # код на месте
ls /etc/puppetlabs/code/environments/production/modules # появился stdlib
Рабочий цикл — то, ради чего всё затевалось
С этого момента /etc/puppetlabs/code — только для чтения. Его наполняет r10k, и лезть туда руками нельзя. Любая правка манифеста, Hiera или шаблона идёт через git:
cd /root/control-repo
# ... правите манифесты / Hiera / шаблоны ...
git add -A
git commit -m 'что изменил'
git push origin production
/opt/puppetlabs/puppet/bin/r10k deploy environment production -pv
Отредактировал → закоммитил → запушил → задеплоил. Четыре шага, которые быстро уходят в мышечную память. Взамен вы получаете историю всех изменений, откат через git revert и бэкап кода как побочный эффект.
И последнее правило, нарушать которое дорого: внешние модули с Forge теперь добавляются только через Puppetfile. Никаких puppet module install — r10k снесёт всё установленное вручную при следующем же деплое.
Что в итоге
После этих шагов у вас есть:
- OpenVox Server на Debian 13, слушает порт 8140;
- весь код инфраструктуры под git — с историей и откатом;
- r10k как механизм раскатки, где ветка
productionсоответствует окружению; - доступ ко всему Puppet Forge через Puppetfile;
- отлаженный рабочий цикл правок без ручных вмешательств в прод.
В следующей части подключим к серверу первых клиентов и разберёмся с подписью сертификатов. А дальше — начнём собственно кукловодить: писать роли и профили, которые превращают голый сервер в то, чем он должен быть.