Collect the facts about all 14 services -- VMID, node, address, ports,
domain, pinned images, resources, backup and monitoring participation --
into group_vars/all/services.yml. Values are taken from the existing
playbooks; gaps are marked null rather than invented.
Replace reverse-proxy-{gitea,vaultwarden,grimmory}.yml with a single
playbook iterating over registry entries that declare a domain. It keeps
every check the three had, preserves grimmory's richer Caddy block
byte-for-byte, and restarts Caddy once when any site changed instead of
up to three times. Verified with --check --diff against ru-vps: ok=6
changed=0, so it reproduces the current Caddyfile exactly.
Add two roles factoring out the skeleton duplicated across the pve-*
playbooks: lxc_docker_host (packages, /dev/fuse assertion, fuse-overlayfs
storage driver, UFW baseline) and compose_service (compose file, systemd
unit, config validation, health check). They are not wired into any
playbook yet -- migrating a live service is a separate, per-service step;
compose_service/README.md shows the Gitea example and spells out what
actually changes on the host.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
lxc_docker_host
Приводит непривилегированный Proxmox LXC в состояние «здесь можно запускать
Docker»: пакеты, проверка /dev/fuse, storage-driver: fuse-overlayfs,
запуск демона и базовый UFW.
Роль вынесена из повторяющихся блоков playbooks/pve-*.yml
(gitea, vaultwarden, mihomo, adguard, memoir-bot, docker-test, grimmory,
hermes-ai) — суммарно около 350 строк копипасты.
Что делает
- Ставит
ca-certificates,curl,docker.io,fuse-overlayfs(+lxc_docker_host_extra_packages,ufwпри управлении фаерволом). stat+assertна/dev/fuse: без символьного устройства fuse-overlayfs не работает, и Docker молча деградирует доvfs. Сообщение об ошибке подсказывает, какие строки добавить в/etc/pve/lxc/<vmid>.confна узле PVE.- Пишет
/etc/docker/daemon.jsonсоstorage-driver: fuse-overlayfs. systemd: docker—enabled: true,restartedпри смене daemon.json, иначеstarted.- UFW: SSH из
homelab_lan_cidrиopenvpn_network_cidr, node-exporter 9100/tcp с хоста мониторинга (192.168.1.30), произвольные порты сервиса изlxc_docker_host_ufw_service_rules, затемpolicy deny incoming. Разрешающие правила ставятся ДО включения политики — иначе прогон обрывает собственную SSH-сессию. - Проверяет
docker info --format '{{.Driver}}'и падает при расхождении.
Переменные
Полный список с комментариями — в defaults/main.yml. Ключевые:
| Переменная | По умолчанию | Назначение |
|---|---|---|
lxc_docker_host_extra_packages |
[] |
доп. пакеты сервиса |
lxc_docker_host_require_fuse |
true |
проверять /dev/fuse |
lxc_docker_host_storage_driver |
fuse-overlayfs |
драйвер хранилища |
lxc_docker_host_manage_ufw |
true |
трогать ли UFW вообще |
lxc_docker_host_ssh_sources |
LAN + OpenVPN | откуда разрешён SSH |
lxc_docker_host_allow_node_exporter |
true |
9100 с хоста мониторинга |
lxc_docker_host_ufw_service_rules |
[] |
порты сервиса |
lxc_docker_host_ufw_enable |
true |
включать deny incoming |
lxc_docker_host_verify_storage_driver |
true |
финальная проверка |
Пример: как выглядела бы подготовка хоста Grimmory
- name: Prepare the Grimmory Docker host
hosts: grimmory
gather_facts: true
vars:
ansible_become: false
roles:
- role: lxc_docker_host
lxc_docker_host_extra_packages:
- mariadb-client
- openssl
lxc_docker_host_install_node_exporter: true
lxc_docker_host_ufw_service_rules:
- port: "{{ homelab_services.grimmory.ports[0].port }}"
proto: tcp
comment: Grimmory HTTP
sources:
- "{{ homelab_lan_cidr }}"
- "{{ openvpn_network_cidr }}"
Эти 12 строк заменяют 86 строк из playbooks/pve-grimmory.yml.
Чего роль НЕ делает
- Не создаёт LXC и не правит
/etc/pve/lxc/<vmid>.conf— это рольpve_lxcи соответствующийpve-*.yml. Роль только проверяет результат. - Не публикует порты Docker в обход UFW. Помните:
-pв Docker обходит UFW, поэтому для публикуемых портов нужны правила в цепочкеDOCKER-USER(см.grimmory-docker-firewallвplaybooks/pve-grimmory.yml). - Не ставит node-exporter по умолчанию — этим занимается
monitoring_exporter.
Handlers
Их нет намеренно. Docker перезапускается прямо в задаче через
state: restarted if changed else started: handler отработал бы в конце
play, уже после того как compose-стек стартовал на старом драйвере хранилища.