Alexander Ivanin a1b89909ce first commit
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00
2026-07-12 21:17:17 +03:00

Виртуальная машина с инфраструктурой

Terraform создаёт виртуальную машину в Proxmox полным клонированием шаблона Ubuntu 24.04 с VM ID 9000. Ansible устанавливает Docker Engine и Docker Compose, после чего разворачивает Traefik, Gitea, Prometheus, cAdvisor, Grafana и Portainer. На этой же VM настраивается WireGuard для безопасного доступа к локальной сети через VPN.

Базовая настройка VM также включает часовой пояс Europe/Moscow, синхронизацию времени через Chrony и установку QEMU Guest Agent для взаимодействия гостевой системы с Proxmox.

Репозиторий не выполняет terraform apply или запуск Ansible автоматически.

Требования

  • В шаблоне Proxmox 9000 настроен cloud-init, установлен и включён QEMU Guest Agent.
  • Указанный в Terraform публичный SSH-ключ существует на локальной машине.
  • DNS-записи A/AAAA для сервисов указывают на публичный адрес, с которого TCP 80 и 443 перенаправляются на 192.168.1.109.
  • Публичный TCP-порт 80 доступен Traefik для прохождения Let's Encrypt HTTP-01 challenge.
  • Установлены Terraform, Ansible, SOPS и настроен ключ age либо другой поддерживаемый SOPS KMS.

Параметры виртуальной машины по умолчанию:

  • 4 vCPU;
  • 8 ГБ RAM;
  • диск 100 ГБ;
  • адрес 192.168.1.109/24.

Перед использованием проверьте terraform/terraform.tfvars.example, особенно имя узла Proxmox, VM ID новой машины, gateway, datastore, SSH-пользователя и путь к публичному ключу.

Terraform

Создайте локальный файл с параметрами и передайте API token через переменную окружения:

cp terraform/terraform.tfvars.example terraform/terraform.tfvars
export TF_VAR_proxmox_api_token='user@pam!terraform=TOKEN_SECRET'
make tf-init
make tf-plan

Команда применения намеренно не добавлена в Makefile. После проверки плана её нужно выполнить самостоятельно:

terraform -chdir=terraform apply

Файл terraform.tfvars, state-файлы и сохранённые планы добавлены в .gitignore. Не сохраняйте API token или Terraform state в Git.

Секреты SOPS

Скопируйте .sops.yaml.example в .sops.yaml и укажите публичный ключ-получатель age. При использовании KMS настройте соответствующее правило SOPS.

Затем создайте и заполните файл с секретами:

make secrets-init
$EDITOR ansible/inventory/group_vars/all/secrets.sops.yml
make secrets-encrypt
sops ansible/inventory/group_vars/all/secrets.sops.yml

В файле должны быть заданы:

  • gitea_admin_password — пароль администратора Gitea;
  • gitea_db_password — пароль PostgreSQL для Gitea;
  • grafana_admin_password — пароль администратора Grafana.

Каждый пароль должен содержать не менее 12 символов. Playbook остановится до развёртывания сервисов, если файл отсутствует или пароль не прошёл проверку.

Не добавляйте secrets.sops.yml в Git, пока команда sops filestatus не подтверждает, что файл зашифрован. Зашифрованный SOPS-файл можно хранить в Git; secrets.example.yml секретов не содержит.

Ansible

Перед запуском проверьте файл ansible/inventory/group_vars/all/main.yml:

  • замените letsencrypt_email на настоящий адрес;
  • проверьте доменные имена всех сервисов;
  • задайте в admin_allowlist доверенные CIDR-сети;
  • при необходимости обновите закреплённые версии образов контейнеров;
  • проверьте SSH-пользователя ansible_user.
  • при необходимости измените timezone и список ntp_pools.

Версии образов закреплены явно и были сверены с официальными registry 12 июля 2026 года. Для Portainer используется стабильная LTS-ветка, а не более коротко поддерживаемая STS. Образ cAdvisor публикуется в официальном GitHub Container Registry ghcr.io/google/cadvisor.

Установка зависимостей и запуск:

make ansible-deps
make ansible-check
make ansible-run

make ansible-check выполняет Ansible в режиме --check --diff и не должен изменять состояние машины. Некоторые Docker-модули могут сообщать о неполной поддержке check mode, поэтому перед настоящим запуском нужно проверить вывод.

Сеть и открытые порты

Ansible включает UFW с запретом входящих подключений по умолчанию и открывает:

Порт Назначение
22/tcp SSH-доступ к виртуальной машине
80/tcp HTTP и Let's Encrypt HTTP-01 challenge
443/tcp HTTPS через Traefik
2222/tcp Git по SSH в Gitea
51820/udp WireGuard VPN

Web-интерфейс Gitea и встроенный OCI/package registry доступны через https://git.4vkamnyam.ru. Для Git по SSH используется порт 2222.

Самостоятельная регистрация в Gitea отключена. Новых пользователей создаёт только администратор через Site Administration → User Accounts. Анонимный просмотр /explore, репозиториев и API также запрещён: неавторизованные пользователи перенаправляются на страницу входа.

Traefik Dashboard, Grafana, Prometheus и Portainer доступны только с адресов из admin_allowlist. По умолчанию разрешена локальная сеть 192.168.1.0/24.

При первом открытии Portainer предложит создать локального администратора.

WireGuard VPN

WireGuard работает на infra-VM, Proxmox-хост при этом остаётся без дополнительных пакетов и сетевых настроек. Используется следующая схема:

  • публичный endpoint: 78.138.184.244:51820;
  • VPN-подсеть: 10.20.0.0/24;
  • адрес сервера в VPN: 10.20.0.1;
  • доступная через VPN локальная сеть: 192.168.1.0/24;
  • режим split tunnel — обычный интернет клиента не проходит через VPN.

На роутере необходимо создать перенаправление порта:

UDP 51820 → 192.168.1.109:51820

Роль включает IPv4 forwarding и NAT между 10.20.0.0/24 и 192.168.1.0/24. Поэтому добавлять обратный статический маршрут на домашнем роутере не требуется. Устройства локальной сети будут видеть VPN-подключения как трафик от 192.168.1.109.

Первый запуск

При первом запуске роль создаёт приватный ключ сервера непосредственно в /etc/wireguard/server_private.key. Файл имеет права 0600, его нельзя копировать в репозиторий или передавать клиентам. Публичный ключ выводится в результате запуска Ansible и сохраняется здесь:

ssh alexander@192.168.1.109 \
  'sudo cat /etc/wireguard/server_public.key'

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

cd ansible
ansible-playbook site.yml --tags wireguard

Обратите внимание: pre-tasks с загрузкой SOPS-секретов выполняются и при запуске по тегу, поэтому зашифрованный secrets.sops.yml всё равно должен существовать.

Создание ключей клиента

Ключи каждого клиента создаются на его устройстве. На Linux или macOS с установленным WireGuard:

umask 077
wg genkey | tee client-private.key | wg pubkey > client-public.key

Содержимое client-private.key остаётся только у владельца устройства. Содержимое client-public.key добавляется в ansible/inventory/group_vars/all/main.yml:

wireguard_peers:
  - name: alexander-laptop
    address: 10.20.0.10/32
    public_key: "ПУБЛИЧНЫЙ_КЛЮЧ_КЛИЕНТА"

  - name: user-1
    address: 10.20.0.11/32
    public_key: "ПУБЛИЧНЫЙ_КЛЮЧ_КЛИЕНТА"

Адреса клиентов должны быть уникальными, иметь маску /32 и находиться в подсети 10.20.0.0/24.

После добавления или удаления клиента повторно запустите роль WireGuard. Ansible пересоберёт конфигурацию и перезапустит интерфейс.

Конфигурация клиента

[Interface]
PrivateKey = ПРИВАТНЫЙ_КЛЮЧ_КЛИЕНТА
Address = 10.20.0.10/32

[Peer]
PublicKey = ПУБЛИЧНЫЙ_КЛЮЧ_СЕРВЕРА
Endpoint = 78.138.184.244:51820
AllowedIPs = 10.20.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25

После подключения должны быть доступны, например:

https://192.168.1.81:8006   # Proxmox
https://192.168.1.109       # infra-VM

Порт Proxmox 8006 публиковать в интернет не нужно.

Динамические маршруты Traefik

Traefik следит за каталогом /opt/stacks/traefik/dynamic на виртуальной машине. Роль Ansible создаёт в нём security.yml с общими middleware.

В этот каталог можно добавлять отдельные YAML-файлы с динамическими:

  • routers;
  • middlewares;
  • services;
  • TLS options.

Traefik обнаруживает изменения автоматически, перезапуск контейнера не нужен. Для добавляемых вручную маршрутов используйте отдельные имена файлов — тогда Ansible не перезапишет их при следующем запуске.

Адреса сервисов

  • Gitea и registry: https://git.4vkamnyam.ru
  • Traefik Dashboard: https://traefik.4vkamnyam.ru
  • Grafana: https://grafana.4vkamnyam.ru
  • Prometheus: https://prometheus.4vkamnyam.ru
  • Portainer: https://portainer.4vkamnyam.ru
S
Description
No description provided
Readme 46 KiB
Languages
Jinja 65.4%
HCL 23.6%
Makefile 11%