Files
infra/ansible/Makefile
T
DmitryandClaude Opus 5 ef234b17f5 Add Makefile as the entry point for manual operation
Knowing how to run something required reading ansible/README.md and
remembering to source .env first. Provide `make help` instead, with
targets grouped by purpose and pattern rules for the repetitive families:
deploy-%, dry-%, update-% and play-%.

.env is sourced automatically; targets that need Proxmox credentials fail
with an actionable message when it is missing. Destructive targets --
mihomo-harden, which rotates live credentials, the frozen monitoring
stack, and update-all -- require CONFIRM=1.

The interpreter is resolved at runtime rather than hardcoded to .venv:
the repository's venv is currently broken, so the Makefile falls back to
whatever is on PATH, which is what the Nix devshell provides.

gen-inventory-docs.py prints the host and group tables from
ansible-inventory, so documentation can be regenerated instead of being
maintained by hand and drifting.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
2026-08-26 22:10:29 +03:00

242 lines
12 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HomeLab Ansible — единая точка входа для РУЧНОГО управления инфраструктурой.
#
# Запускать из каталога ansible/ (или через `make -C ansible <цель>`):
#
# make список целей
# make check базовая проверка связности
# make deploy-gitea playbooks/pve-gitea.yml с загруженным .env
# make dry-gitea то же самое в режиме --check --diff
# make update-gitea playbooks/gitea-update.yml
# make docs markdown-таблица хостов в stdout
#
# Дополнительные флаги ansible-playbook передаются через EXTRA:
#
# make check EXTRA="--limit pve_nodes -vv"
#
# Интерпретатор определяется автоматически: если рядом есть ./.venv — берётся он,
# иначе бинарь ищется в PATH (nix devshell, системный ansible). Любой путь можно
# переопределить переменной окружения, например:
#
# ANSIBLE_PLAYBOOK=$(which ansible-playbook) make check
SHELL := /bin/sh
.DEFAULT_GOAL := help
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
ANSIBLE_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
VENV_BIN := $(ANSIBLE_DIR)/.venv/bin
# Разрешение бинарей: сначала рабочий локальный venv, иначе PATH (nix devshell,
# системный ansible). VENV_OK проверяет, что интерпретатор venv реально запускается,
# — иначе сломанный .venv (например, после смены системного python) молча ломал бы
# все цели. Переменные окружения имеют приоритет благодаря `?=`.
VENV_OK := $(shell [ -x '$(VENV_BIN)/python3' ] && '$(VENV_BIN)/python3' -c '' >/dev/null 2>&1 && echo yes)
venv_bin = $(if $(VENV_OK),$(if $(wildcard $(VENV_BIN)/$(1)),$(VENV_BIN)/$(1),$(1)),$(1))
ANSIBLE_PLAYBOOK ?= $(call venv_bin,ansible-playbook)
ANSIBLE_INVENTORY_BIN ?= $(call venv_bin,ansible-inventory)
ANSIBLE_GALAXY ?= $(call venv_bin,ansible-galaxy)
ANSIBLE_LINT ?= $(call venv_bin,ansible-lint)
YAMLLINT ?= $(call venv_bin,yamllint)
# scripts/gen-inventory-docs.py обходится стандартной библиотекой, поэтому берём
# python3 из PATH, а не из .venv.
PYTHON ?= python3
ENV_FILE ?= .env
# Дополнительные аргументы ansible-playbook для любой цели.
EXTRA ?=
# Спрашивать sudo-пароль там, где нужен become. `make openvpn ASK_BECOME=` отключает.
ASK_BECOME ?= -K
# Спрашивать пароль Ansible Vault. `make gyro ASK_VAULT=` отключает.
ASK_VAULT ?= --ask-vault-pass
# Строгая загрузка ansible/.env: обязательна для Proxmox API и секретов.
# Каждая строка рецепта make — отдельный шелл, поэтому source и запуск идут одной строкой.
REQUIRE_ENV = if [ ! -f '$(ENV_FILE)' ]; then \
printf 'ОШИБКА: не найден %s/%s\n' '$(ANSIBLE_DIR)' '$(ENV_FILE)' >&2; \
printf 'Создай его и заполни реальными значениями:\n' >&2; \
printf ' cp .env.example .env\n' >&2; \
printf 'Нужны PROXMOX_* (и MONITORING_* / EMERGENCY_* для профильных целей).\n' >&2; \
exit 1; \
fi; \
set -a; . './$(ENV_FILE)'; set +a
# Мягкая загрузка: .env подхватывается если есть, иначе просто предупреждение.
LOAD_ENV = if [ -f '$(ENV_FILE)' ]; then set -a; . './$(ENV_FILE)'; set +a; \
else printf 'ВНИМАНИЕ: %s не найден, продолжаю без него.\n' '$(ENV_FILE)' >&2; fi
# Защита от случайного запуска опасных плейбуков.
REQUIRE_CONFIRM = if [ "$(CONFIRM)" != "1" ]; then \
printf 'ОПАСНАЯ ЦЕЛЬ. Повтори явно: make $@ CONFIRM=1\n' >&2; \
exit 1; \
fi
# host_vars/gyro/vault.yml зашифрован Vault. Для чтения инвентаря он не нужен,
# поэтому vars-плагины отключаются, чтобы make не спрашивал пароль Vault.
INVENTORY_ENV = ANSIBLE_VARS_ENABLED= ANSIBLE_NOCOLOR=1
##@ Справка
.PHONY: help
help: ## Показать этот список целей
@awk 'BEGIN { FS = ":.*##"; \
print ""; \
print "HomeLab Ansible — ручное управление инфраструктурой"; \
print ""; \
print " Использование: make <цель> [EXTRA=\"--limit host -vv\"]"; \
print " Плейбуки Proxmox API сами подхватывают ./.env"; \
} \
/^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5); next } \
/^[a-zA-Z0-9_%.-]+:.*##/ { printf " \033[36m%-24s\033[0m %s\n", $$1, $$2 } \
END { print "" }' $(MAKEFILE_PATH)
##@ Setup
.PHONY: setup
setup: ## Создать .venv, поставить requirements.txt и galaxy-коллекции (не нужно в nix)
$(PYTHON) -m venv $(ANSIBLE_DIR)/.venv
$(VENV_BIN)/pip install --upgrade pip
$(VENV_BIN)/pip install -r requirements.txt
$(VENV_BIN)/ansible-galaxy collection install -r requirements.yml -p collections
.PHONY: collections
collections: ## Доустановить только galaxy-коллекции из requirements.yml
$(ANSIBLE_GALAXY) collection install -r requirements.yml -p collections
.PHONY: env-check
env-check: ## Проверить наличие .env и заполненность ключевых переменных
@$(REQUIRE_ENV); \
rc=0; \
for v in PROXMOX_HOST PROXMOX_USER PROXMOX_TOKEN_ID PROXMOX_TOKEN_SECRET; do \
eval "val=\$$$$v"; \
if [ -z "$$val" ] || [ "$$val" = 'replace-me' ]; then \
printf 'не задано: %s\n' "$$v"; rc=1; \
else printf 'ok: %s\n' "$$v"; fi; \
done; \
exit $$rc
##@ Проверки и диагностика
.PHONY: check
check: ## Проверка связности и ожидаемых IP (playbooks/check.yml)
$(ANSIBLE_PLAYBOOK) playbooks/check.yml $(EXTRA)
.PHONY: status
status: ## Сводный статус инфраструктуры (playbooks/status.yml)
ANSIBLE_CALLBACK_RESULT_FORMAT=yaml $(ANSIBLE_PLAYBOOK) playbooks/status.yml $(EXTRA)
.PHONY: lint
lint: ## Прогнать ansible-lint и yamllint по репозиторию
$(ANSIBLE_LINT)
$(YAMLLINT) .
.PHONY: docs
docs: ## Напечатать markdown-таблицу хостов и групп в stdout
@ANSIBLE_INVENTORY_BIN='$(ANSIBLE_INVENTORY_BIN)' $(PYTHON) scripts/gen-inventory-docs.py
.PHONY: inventory
inventory: ## Показать дерево инвентаря (ansible-inventory --graph)
@$(INVENTORY_ENV) $(ANSIBLE_INVENTORY_BIN) -i inventory/hosts.yml --graph
.PHONY: openvpn-check
openvpn-check: ## Проверить OpenVPN-транспорт ru-vps <-> ovpn-mini
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-check.yml $(EXTRA)
.PHONY: backup-audit
backup-audit: ## Аудит свежести бэкапов PBS и offsite restic
$(ANSIBLE_PLAYBOOK) playbooks/backup-audit.yml $(EXTRA)
dry-%: ## Прогон playbooks/pve-<имя>.yml в режиме --check --diff (пример: make dry-gitea)
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/pve-$*.yml --check --diff $(EXTRA)
##@ Деплой LXC/VM через Proxmox API (требует .env)
deploy-%: ## Применить playbooks/pve-<имя>.yml (пример: make deploy-gitea, deploy-adguard, deploy-monitoring)
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/pve-$*.yml $(EXTRA)
.PHONY: backup-jobs
backup-jobs: ## Настроить PBS backup jobs (playbooks/pve-backup-jobs.yml)
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/pve-backup-jobs.yml $(EXTRA)
.PHONY: bootstrap-pve-token
bootstrap-pve-token: ## Выпустить Proxmox API-токен прямо с ноды (нужен sudo)
$(ANSIBLE_PLAYBOOK) playbooks/bootstrap-pve-api-token.yml $(ASK_BECOME) $(EXTRA)
.PHONY: bootstrap-monitoring-token
bootstrap-monitoring-token: ## Выпустить read-only PVE-токен для мониторинга
$(ANSIBLE_PLAYBOOK) playbooks/bootstrap-monitoring-pve-token.yml $(EXTRA)
.PHONY: bootstrap-ansible-user
bootstrap-ansible-user: ## Завести сервисный аккаунт ansible на shell-хостах (нужен sudo)
$(ANSIBLE_PLAYBOOK) playbooks/bootstrap-ansible-user.yml $(ASK_BECOME) $(EXTRA)
##@ Настройка сервисов
.PHONY: reverse-proxy
reverse-proxy: ## Единый reverse-proxy для gitea/vaultwarden/grimmory
@$(LOAD_ENV); $(ANSIBLE_PLAYBOOK) playbooks/reverse-proxy.yml $(EXTRA)
.PHONY: openvpn
openvpn: ## Поднять OpenVPN-транспорт ru-vps <-> ovpn-mini (нужен sudo)
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-vps-mini.yml $(ASK_BECOME) $(EXTRA)
.PHONY: openvpn-laptop
openvpn-laptop: ## Настроить OpenVPN-профиль ноутбука
$(ANSIBLE_PLAYBOOK) playbooks/openvpn-laptop.yml $(EXTRA)
.PHONY: bash-config
bash-config: ## Раскатать единый bash-конфиг на shell_hosts
$(ANSIBLE_PLAYBOOK) playbooks/bash-config.yml $(EXTRA)
.PHONY: user-ssh-key
user-ssh-key: ## Разложить публичный SSH-ключ пользователя на все хосты
$(ANSIBLE_PLAYBOOK) playbooks/user-ssh-key.yml $(EXTRA)
.PHONY: emergency-access
emergency-access: ## Настроить emergency reverse-SSH и Telegram-бота (нужны EMERGENCY_* в .env)
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/emergency-access.yml $(EXTRA)
.PHONY: gyro
gyro: ## Настроить gyro-аллокатор в CT 150 (спрашивает пароль Vault)
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/gyro.yml $(ASK_VAULT) $(EXTRA)
.PHONY: uptime-kuma
uptime-kuma: ## Развернуть/обновить Uptime Kuma на monitoring LXC
$(ANSIBLE_PLAYBOOK) playbooks/uptime-kuma.yml $(EXTRA)
.PHONY: offsite-restic
offsite-restic: ## Настроить offsite restic-бэкапы на Yandex.Disk
@$(LOAD_ENV); $(ANSIBLE_PLAYBOOK) playbooks/offsite-restic-yadisk.yml $(EXTRA)
play-%: ## Запустить произвольный playbooks/<имя>.yml с загруженным .env (пример: make play-check)
@$(LOAD_ENV); $(ANSIBLE_PLAYBOOK) playbooks/$*.yml $(EXTRA)
##@ Обновления сервисов (сначала свежий бэкап, потом апдейт, потом проверка)
update-%: ## Обновить сервис через playbooks/<имя>-update.yml (gitea, vaultwarden, adguard, mihomo, grimmory)
@$(LOAD_ENV); $(ANSIBLE_PLAYBOOK) playbooks/$*-update.yml $(EXTRA)
.PHONY: update-all
update-all: ## Последовательно обновить gitea, vaultwarden, adguard, mihomo, grimmory (требует CONFIRM=1)
@$(REQUIRE_CONFIRM)
$(MAKE) update-vaultwarden
$(MAKE) update-gitea
$(MAKE) update-adguard
$(MAKE) update-mihomo
$(MAKE) update-grimmory
##@ Опасное (только осознанно, требует CONFIRM=1)
.PHONY: mihomo-harden
mihomo-harden: ## РОТИРУЕТ живые SOCKS-креды Mihomo на ru-vps и убирает публичный доступ
@$(REQUIRE_CONFIRM)
@printf 'Ротация кредов необратима для клиентов без отката бэкапа конфига.\n' >&2
$(ANSIBLE_PLAYBOOK) playbooks/ru-vps-mihomo-harden.yml -e ru_vps_mihomo_harden_confirm=true $(EXTRA)
.PHONY: monitoring
monitoring: ## ЗАМОРОЖЕН: стек Prometheus. Запускать только при восстановлении мониторинга
@$(REQUIRE_CONFIRM)
@printf 'monitoring.yml заморожен, пока используется Uptime Kuma.\n' >&2
@$(REQUIRE_ENV); $(ANSIBLE_PLAYBOOK) playbooks/monitoring.yml $(EXTRA)