# 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)