--- # ============================================================================ # Дашборд-обзор всей инфраструктуры 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