Dashboard: add server start dashboard via homepage
Linting / YAML Lint (push) Has been cancelled
Linting / Ansible Lint (push) Has been cancelled

This commit is contained in:
av
2026-07-04 20:45:15 +03:00
parent 5cd66d01bc
commit e57528cef3
10 changed files with 268 additions and 1 deletions
+3 -1
View File
@@ -64,7 +64,8 @@ uv run ansible-galaxy install --role-file requirements.yml
- `playbook-wakapi.yml` — трекинг времени. - `playbook-wakapi.yml` — трекинг времени.
- `playbook-memos.yml` — заметки. - `playbook-memos.yml` — заметки.
- `playbook-outline.yml` — вики/база знаний. - `playbook-outline.yml` — вики/база знаний.
- `playbook-homepage.yml`дашборд (образ из Yandex Registry). - `playbook-homepage.yml`кастомная домашняя страничка на apex `vakhrushev.me` (образ из Yandex Registry).
- `playbook-dashboard.yml` — дашборд со списком сервисов (gethomepage.dev) на `start.vakhrushev.me`, закрыт за Authelia.
- `playbook-rssbridge.yml` — RSS-агрегатор. - `playbook-rssbridge.yml` — RSS-агрегатор.
- `playbook-netdata.yml` — мониторинг. - `playbook-netdata.yml` — мониторинг.
- `playbook-dozzle.yml` — просмотр Docker-логов. - `playbook-dozzle.yml` — просмотр Docker-логов.
@@ -99,6 +100,7 @@ uv run ansible-galaxy install --role-file requirements.yml
- Большинство приложений определяют переменные inline в плейбуке. Отдельные файлы переменных только у homepage и transcriber (`vars/homepage.yml`, `vars/transcriber.yml` + `vars/transcriber.images.yml`). - Большинство приложений определяют переменные inline в плейбуке. Отдельные файлы переменных только у homepage и transcriber (`vars/homepage.yml`, `vars/transcriber.yml` + `vars/transcriber.images.yml`).
- Общие переменные из `vars/secrets.yml`: `application_dir`, `bin_prefix`, `primary_user` и др. - Общие переменные из `vars/secrets.yml`: `application_dir`, `bin_prefix`, `primary_user` и др.
- Каждое приложение: `app_name`, `app_user`, `app_owner_uid`, `app_owner_gid`, `base_dir`, `data_dir`. - Каждое приложение: `app_name`, `app_user`, `app_owner_uid`, `app_owner_gid`, `base_dir`, `data_dir`.
- UID/GID сервисов: новое соглашение — диапазон `11xx`, причём `app_owner_uid == app_owner_gid` (одно число на сервис). Новому приложению берём следующий свободный номер по возрастанию. Старые сервисы ещё сидят на легаси-нумерации `10xx` (часто с разными uid/gid) — их не трогаем, но новые заводим только в `11xx`.
## Линтинг и CI ## Линтинг и CI
@@ -720,6 +720,9 @@ access_control:
rules: rules:
## Rules applied to everyone ## Rules applied to everyone
- domain: "start.vakhrushev.me"
policy: "one_factor"
- domain: "status.vakhrushev.me" - domain: "status.vakhrushev.me"
subject: "group:admins" subject: "group:admins"
policy: "two_factor" policy: "two_factor"
+16
View File
@@ -61,6 +61,22 @@ vakhrushev.me {
} }
# Дашборд со списком сервисов (gethomepage). Закрыт за Authelia. Это отдельный # Дашборд со списком сервисов (gethomepage). Закрыт за Authelia. Это отдельный
# сервис, не путать с кастомной домашней страничкой homepage_app на apex выше.
start.vakhrushev.me {
tls anwinged@ya.ru
import access_log
forward_auth authelia_app:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
reverse_proxy {
to dashboard_app:3000
}
}
matrix.vakhrushev.me {
tls anwinged@ya.ru tls anwinged@ya.ru
import access_log import access_log
@@ -0,0 +1,8 @@
# https://gethomepage.dev/configs/bookmarks/
- Внешнее:
- Yandex Cloud:
- abbr: YC
href: https://console.cloud.yandex.ru/
- Timeweb:
- abbr: TW
href: https://timeweb.cloud/my
@@ -0,0 +1,102 @@
# https://gethomepage.dev/configs/services/
# href — внешний адрес через Caddy (для браузера);
# siteMonitor — внутренний адрес контейнера в web_proxy_network, по нему
# homepage рисует индикатор up/down (быстро, без выхода наружу).
# icon — бренд-логотипы Dashboard Icons (<name>.png, грузятся браузером
# с CDN jsDelivr); где бренда нет — mdi-* из комплекта homepage.
- Работа и знания:
- Gitea:
href: https://git.vakhrushev.me
description: Git-репозитории
icon: gitea.png
siteMonitor: http://gitea_app:3000
- Outline:
href: https://outline.vakhrushev.me
description: База знаний / вики
icon: outline.png
siteMonitor: http://outline_app:3000
- Memos:
href: https://memos.vakhrushev.me
description: Заметки
icon: memos.png
siteMonitor: http://memos_app:5230
- Tududi:
href: https://tududi.vakhrushev.me
description: Планировщик задач
icon: tududi.png
siteMonitor: http://tududi_app:3002
- Wakapi:
href: https://wakapi.vakhrushev.me
description: Трекинг времени в коде
icon: wakapi.png
siteMonitor: http://wakapi_app:3000
- Медиа и хобби:
- Miniflux:
href: https://miniflux.vakhrushev.me
description: RSS-ридер
icon: miniflux.png
siteMonitor: http://miniflux_app:8080
- RSS-Bridge:
href: https://rssbridge.vakhrushev.me
description: Генератор RSS для сайтов без фидов
icon: rss-bridge.png
siteMonitor: http://rssbridge_app:80
- Calibre:
href: https://calibre.vakhrushev.me
description: Электронная библиотека
icon: calibre-web.png
siteMonitor: http://calibre_web_app:8083
- Gramps:
href: https://gramps.vakhrushev.me
description: Генеалогия
icon: gramps-web.png
siteMonitor: http://gramps_app:5000
- Wanderer:
href: https://wanderer.vakhrushev.me
description: Пешие маршруты
icon: wanderer.png
siteMonitor: http://wanderer_web:3000
- Remembos:
href: https://remembos.vakhrushev.me
description: Интервальное повторение
icon: mdi-brain
siteMonitor: http://remembos_app:8080
- Matrix:
href: https://matrix.vakhrushev.me
description: Мессенджер (Tuwunel)
icon: matrix.png
siteMonitor: http://tuwunel_app:6167
- Инфраструктура:
- Netdata:
href: https://status.vakhrushev.me
description: Мониторинг сервера
icon: netdata.png
siteMonitor: http://netdata:19999
- Dozzle:
href: https://dozzle.vakhrushev.me
description: Логи контейнеров
icon: dozzle.png
siteMonitor: http://dozzle_app:8080
- GoAccess:
href: https://goaccess.vakhrushev.me
description: Веб-аналитика логов Caddy
icon: goaccess.png
siteMonitor: http://goaccess_app:8080
- Bifrost:
href: https://bifrost.vakhrushev.me
description: LLM-шлюз (DeepSeek)
icon: mdi-transit-connection-variant
siteMonitor: http://bifrost_app:8080/health
- Authelia:
href: https://auth.vakhrushev.me
description: SSO / аутентификация
icon: authelia.png
siteMonitor: http://authelia_app:9091
- Wanderbase:
href: https://wanderbase.vakhrushev.me
description: PocketBase — бэкенд Wanderer
icon: pocketbase.png
siteMonitor: http://wanderer_db:8090
@@ -0,0 +1,22 @@
# https://gethomepage.dev/configs/settings/
title: Сервер vakhrushev.me
headerStyle: clean
theme: dark
color: slate
# Порядок в layout = порядок групп на странице (сверху вниз). style: row +
# columns: 3 — каждая группа во всю ширину, карточки по 3 в ряд. Блок закладок
# «Внешнее» указан последним, поэтому остаётся внизу.
layout:
Работа и знания:
style: row
columns: 3
Медиа и хобби:
style: row
columns: 3
Инфраструктура:
style: row
columns: 3
Внешнее:
style: row
columns: 3
@@ -0,0 +1,8 @@
# https://gethomepage.dev/configs/info-widgets/
# Метрики хоста homepage читает из /proc внутри контейнера — в docker это
# общий с хостом kernel, поэтому cpu/memory отражают сервер целиком.
- resources:
label: "{{ host_name }}"
cpu: true
memory: true
expanded: true
@@ -0,0 +1,27 @@
# dashboard (gethomepage.dev) — стартовая страница со списком сервисов.
# Контейнер в web_proxy_network, слушает {{ homepage_port }}, наружу НЕ
# публикуется — доступ только через Caddy как https://{{ homepage_domain }}
# (закрыт за Authelia). Это отдельный сервис, не связан с кастомным homepage_app
# на apex vakhrushev.me.
services:
dashboard_app:
image: "{{ homepage_image }}"
container_name: dashboard_app
restart: unless-stopped
user: "{{ app_owner_uid }}:{{ app_owner_gid }}"
networks:
- "web_proxy_network"
volumes:
- "{{ config_dir }}:/app/config"
- "/etc/localtime:/etc/localtime:ro"
- "/etc/timezone:/etc/timezone:ro"
environment:
# homepage 1.x требует явный whitelist Host за реверс-прокси, иначе отдаёт
# «Host validation failed». Пускаем только адрес из Caddy.
- HOMEPAGE_ALLOWED_HOSTS={{ homepage_domain }}
networks:
web_proxy_network:
external: true
+3
View File
@@ -54,6 +54,9 @@
- name: "Configure homepage" - name: "Configure homepage"
ansible.builtin.import_playbook: playbook-homepage.yml ansible.builtin.import_playbook: playbook-homepage.yml
- name: "Configure dashboard"
ansible.builtin.import_playbook: playbook-dashboard.yml
- name: "Configure transcriber" - name: "Configure transcriber"
ansible.builtin.import_playbook: playbook-transcriber.yml ansible.builtin.import_playbook: playbook-transcriber.yml
+76
View File
@@ -0,0 +1,76 @@
---
- name: "Configure dashboard start page"
hosts: all
vars_files:
- vars/secrets.yml
- vars/vars.yml
vars:
app_name: "dashboard"
app_user: "{{ app_name }}"
app_owner_uid: 1109
app_owner_gid: 1109
base_dir: "{{ (application_dir, app_name) | path_join }}"
config_dir: "{{ (base_dir, 'config') | path_join }}"
# gethomepage.dev — проверь актуальный тег перед обновлением.
homepage_image: "ghcr.io/gethomepage/homepage:v1.13.2"
# Внутренний порт контейнера; наружу не публикуется, ходим только через Caddy.
homepage_port: 3000
# Домен, на котором Caddy отдаёт дашборд. homepage 1.x требует явный whitelist
# Host за реверс-прокси, иначе «Host validation failed».
homepage_domain: "start.vakhrushev.me"
config_files:
- "settings"
- "services"
- "widgets"
- "bookmarks"
tasks:
- name: "Create user and environment"
ansible.builtin.import_role:
name: owner
vars:
owner_name: "{{ app_user }}"
owner_uid: "{{ app_owner_uid }}"
owner_gid: "{{ app_owner_gid }}"
owner_extra_groups: ["docker"]
- name: "Create application internal directories"
ansible.builtin.file:
path: "{{ item }}"
state: "directory"
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: "0750"
loop:
- "{{ base_dir }}"
- "{{ config_dir }}"
- name: "Render dashboard config files"
ansible.builtin.template:
src: "./files/{{ app_name }}/config/{{ item }}.template.yaml"
dest: "{{ (config_dir, item ~ '.yaml') | path_join }}"
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: "0640"
loop: "{{ config_files }}"
- name: "Copy docker compose file"
ansible.builtin.template:
src: "./files/{{ app_name }}/docker-compose.template.yml"
dest: "{{ base_dir }}/docker-compose.yml"
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: "0640"
- name: "Run application with docker compose"
community.docker.docker_compose_v2:
project_src: "{{ base_dir }}"
state: "present"
remove_orphans: true
pull: "always"
tags:
- run-app