Files
DmitryandClaude Sonnet 5 05d8c748ab
lint / yamllint + ansible-lint + syntax-check (push) Canceled after 0s
feat: infrastructure dashboard (Homepage) generated from the service registry
playbooks/dashboard.yml deploys Homepage as a second compose stack on the
monitoring LXC (CT 155) next to Uptime Kuma and renders its config from
homelab_services: one tile per service, link to its UI, grouped by Proxmox
node. Adding a service to the registry is enough — no second service list.

- new registry consumer: playbooks/dashboard.yml + playbooks/templates/homepage-*.j2
- homelab_dashboard_* vars in group_vars/all/services.yml (top-level, like
  homelab_reverse_proxy_*); image pinned by digest, floating tag needs an
  explicit -e dashboard_allow_floating_tag=true
- bootstrap-dashboard-pve-token.yml: read-only homepage@pve!dashboard token
  (PVEAuditor) for the Proxmox widget, secret in the root .env as DASHBOARD_PVE_*
- Makefile: dashboard, dry-dashboard, bootstrap-dashboard-token
- container binds the LAN address only (192.168.1.30:8082), not published via Caddy
- docs: architecture.md Monitoring section, plan.md active task, consumer lists

Deployed to CT 155 on 2026-09-03: container healthy, http://192.168.1.30:8082/
returns 200, `make dashboard` idempotent, `make validate` and `make lint` green.
Pending operator steps: `make bootstrap-dashboard-token` (blocked in the agent
session as credential creation) and an Uptime Kuma status page with slug homelab.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbuZrUoevfBgCpf5DCF4DG
2026-09-03 09:17:16 +03:00

132 lines
6.8 KiB
YAML
Raw Permalink 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 (Homepage, gethomepage.dev).
#
# ОБЛАСТЬ ОТВЕТСТВЕННОСТИ
# Разворачивает compose-стек Homepage на LXC monitoring (рядом с Uptime
# Kuma) и ГЕНЕРИРУЕТ его конфиги из реестра homelab_services: одна плитка
# на сервис, ссылка на его UI, группировка по узлу Proxmox. Добавили
# сервис в реестр -> плитка появилась сама, второй список вести не нужно.
#
# Наружу дашборд НЕ публикуется: контейнер слушает только LAN-адрес CT 155,
# доступ из локальной сети или по OpenVPN. Внутренняя топология (IP, VMID,
# раскладка по нодам) на публичный периметр не выносится.
#
# ГРАНИЦА С reverse-proxy.yml
# Никакой общей области. Дашборд — отдельный стек на другом хосте, Caddyfile
# он не трогает.
#
# ЗАПУСК
# make dashboard (ansible-playbook playbooks/dashboard.yml)
# make dry-dashboard (--check --diff)
# Первый прогон, пока образ не закреплён по digest:
# ansible-playbook playbooks/dashboard.yml -e dashboard_allow_floating_tag=true
#
# СЕКРЕТЫ
# Виджет proxmox требует read-only токен homepage@pve!dashboard (роль
# PVEAuditor). Выпускается playbooks/bootstrap-dashboard-pve-token.yml,
# секрет кладётся в корневой .env как DASHBOARD_PVE_API_USER /
# DASHBOARD_PVE_API_TOKEN_ID / DASHBOARD_PVE_API_TOKEN_SECRET и подхватывается
# отсюда через lookup('env', ...). Без него дашборд работает — просто плитка
# "Proxmox кластер" показывает ошибку виджета, это не блокер.
#
# ТАРГЕТ
# По умолчанию homelab_dashboard_host (monitoring). Переопределяется ради
# blue-green: `-e dashboard_config_target=monitoring-new --limit monitoring-new`
# (голый --limit play не перенацеливает, а обнуляет — см. uptime-kuma.yml).
# ============================================================================
- name: Deploy the HomeLab infrastructure dashboard (Homepage) on the monitoring LXC
hosts: "{{ dashboard_config_target | default(homelab_dashboard_host | default('monitoring')) }}"
gather_facts: true
vars:
dash_root: "{{ homelab_dashboard_dir | default('/opt/homepage') }}"
dash_config_dir: "{{ (homelab_dashboard_dir | default('/opt/homepage')) ~ '/config' }}"
dash_bind: "{{ homelab_dashboard_bind_ip | default(expected_lan_ip) }}"
dash_port: "{{ homelab_dashboard_port | default(8082) }}"
dash_image: "{{ homelab_dashboard_image | default('') }}"
dash_allowed_hosts: >-
{{ homelab_dashboard_allowed_hosts | default(dash_bind ~ ':' ~ dash_port) }}
# Список узлов Proxmox, встречающихся в реестре, — по нему строятся группы.
dashboard_nodes: >-
{{ homelab_services | dict2items | map(attribute='value.node')
| unique | sort | list }}
# Секрет Proxmox-виджета из окружения (make load .env). Пусто -> плитка
# рендерится без данных. no_log на задаче, которая это пишет.
dash_pve_user: "{{ lookup('ansible.builtin.env', 'DASHBOARD_PVE_API_USER') }}"
dash_pve_token_id: "{{ lookup('ansible.builtin.env', 'DASHBOARD_PVE_API_TOKEN_ID') }}"
dash_pve_token_secret: "{{ lookup('ansible.builtin.env', 'DASHBOARD_PVE_API_TOKEN_SECRET') }}"
pre_tasks:
- name: Require the dashboard registry variables
ansible.builtin.assert:
that:
- dash_image | length > 0
- dash_bind | length > 0
fail_msg: >-
Не заданы homelab_dashboard_* в
inventory/group_vars/all/services.yml.
- name: Require the Homepage image to be pinned by digest
ansible.builtin.assert:
that:
- "'@sha256:' in dash_image or dashboard_allow_floating_tag | default(false) | bool"
fail_msg: >-
{{ dash_image }} не закреплён по digest. Выполни на
{{ inventory_hostname }}:
docker pull {{ dash_image }}
docker inspect --format '{{ '{{' }} index .RepoDigests 0 {{ '}}' }}' {{ dash_image }}
и пропиши tag@sha256 в homelab_dashboard_image. Разовый обход для
первого прогона: -e dashboard_allow_floating_tag=true
- name: Ensure the Homepage config directory exists
ansible.builtin.file:
path: "{{ dash_config_dir }}"
state: directory
owner: root
group: root
mode: "0755"
- name: Render Homepage configuration files from the registry
ansible.builtin.template:
src: "{{ item.src }}"
dest: "{{ dash_config_dir }}/{{ item.dest }}"
owner: root
group: root
mode: "0644"
loop:
- {src: homepage-settings.yaml.j2, dest: settings.yaml}
- {src: homepage-services.yaml.j2, dest: services.yaml}
- {src: homepage-widgets.yaml.j2, dest: widgets.yaml}
- {src: homepage-bookmarks.yaml.j2, dest: bookmarks.yaml}
loop_control:
label: "{{ item.dest }}"
register: dash_config_files
- name: Render the Homepage widget secrets file
ansible.builtin.template:
src: homepage.env.j2
dest: "{{ dash_root }}/homepage.env"
owner: root
group: root
mode: "0600"
register: dash_env_file
no_log: true
roles:
- role: compose_service
compose_service_name: homelab-homepage
compose_service_description: HomeLab infrastructure dashboard (Homepage)
compose_service_root: "{{ dash_root }}"
compose_service_root_mode: "0755"
compose_service_compose_file: docker-compose.yml
compose_service_compose_template: homepage-compose.yml.j2
# | bool обязателен: роль фильтрует триггеры по truthiness, а строка
# "False" из "{{ ... is changed }}" тоже истинна.
compose_service_restart_triggers:
- "{{ (dash_config_files is changed) | bool }}"
- "{{ (dash_env_file is changed) | bool }}"
compose_service_health_url: "http://{{ dash_bind }}:{{ dash_port }}/"
compose_service_health_status: [200]
compose_service_health_follow_redirects: none