Add Dawarich stack
This commit is contained in:
+2
-1
@@ -6,7 +6,8 @@
|
||||
!**/stack.env.example
|
||||
|
||||
# Secrets and certificate material
|
||||
**/secrets/
|
||||
**/secrets/*
|
||||
!**/secrets/*.example
|
||||
**/letsencrypt/
|
||||
**/acme.json
|
||||
**/*.key
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
COMPOSE_PROJECT_NAME=dawarich
|
||||
|
||||
TZ=Europe/Berlin
|
||||
DAWARICH_HOST=dawarich.kaleschke.info
|
||||
APPLICATION_HOSTS=dawarich.kaleschke.info
|
||||
|
||||
POSTGRES_USER=dawarich
|
||||
POSTGRES_DB=dawarich_production
|
||||
GRAFANA_DB_USER=dawarich_grafana_ro
|
||||
|
||||
METRICS_USERNAME=prometheus
|
||||
BACKGROUND_PROCESSING_CONCURRENCY=5
|
||||
RAILS_MAX_THREADS=10
|
||||
@@ -0,0 +1,152 @@
|
||||
# Dawarich Stack
|
||||
|
||||
Produktionsvorlage fuer Dawarich im KalliLab-Homelab mit GitOps ueber Gitea und Komodo.
|
||||
|
||||
## Gepruefter Stand
|
||||
|
||||
- Dawarich Release: `1.8.1` (GitHub latest am 2026-06-11)
|
||||
- Docker Image: `freikin/dawarich:1.8.1`
|
||||
- Hinweis: `freika/dawarich` existiert auf Docker Hub nicht; das offizielle Image aus dem Upstream-Compose ist `freikin/dawarich`.
|
||||
- Dawarich Tracking-Endpoint fuer OwnTracks: `/api/v1/owntracks/points?api_key=<api-key>`
|
||||
- Dawarich Prometheus ab 1.7.7: `dawarich_app:3000/metrics`; Port `9394` ist intern fuer Sidekiq-Metriken.
|
||||
|
||||
Quellen:
|
||||
|
||||
- https://github.com/Freika/dawarich/releases/tag/1.8.1
|
||||
- https://dawarich.app/docs/getting-started/track-your-location/
|
||||
- https://dawarich.app/docs/self-hosting/monitoring/prometheus/
|
||||
|
||||
## Dateien
|
||||
|
||||
```text
|
||||
apps/dawarich/
|
||||
|-- docker-compose.yml
|
||||
|-- .env.example
|
||||
|-- prometheus-scrape.snippet.yml
|
||||
|-- homeassistant-dawarich.example.yaml
|
||||
|-- grafana/
|
||||
| |-- datasource-dawarich.yml
|
||||
| `-- dashboard-dawarich.json
|
||||
|-- postgres/initdb/20-grafana-readonly.sh
|
||||
`-- secrets/*.txt.example
|
||||
```
|
||||
|
||||
## Setup-Reihenfolge
|
||||
|
||||
1. Stack-Verzeichnis nach Komodo/Gitea uebernehmen: `apps/dawarich`.
|
||||
2. `.env.example` als nicht versionierte Stack-`.env` oder Komodo Stack Environment anlegen.
|
||||
3. Secret-Dateien auf dem Unraid-Host erstellen:
|
||||
|
||||
```bash
|
||||
install -d -m 700 /mnt/user/appdata/secrets
|
||||
openssl rand -base64 48 > /mnt/user/appdata/secrets/dawarich_postgres_password.txt
|
||||
openssl rand -base64 48 | tr -dc 'A-Za-z0-9._~-' | head -c 48 > /mnt/user/appdata/secrets/dawarich_redis_password.txt
|
||||
openssl rand -hex 64 > /mnt/user/appdata/secrets/dawarich_secret_key_base.txt
|
||||
openssl rand -base64 48 > /mnt/user/appdata/secrets/dawarich_metrics_password.txt
|
||||
openssl rand -base64 48 > /mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt
|
||||
chmod 600 /mnt/user/appdata/secrets/dawarich_*.txt
|
||||
```
|
||||
|
||||
4. Bind-Volume-Zielpfade vor dem ersten Deploy anlegen:
|
||||
|
||||
```bash
|
||||
install -d -m 750 \
|
||||
/mnt/user/appdata/dawarich/postgres17 \
|
||||
/mnt/user/appdata/dawarich/redis \
|
||||
/mnt/user/appdata/dawarich/shared \
|
||||
/mnt/user/appdata/dawarich/public \
|
||||
/mnt/user/appdata/dawarich/watched \
|
||||
/mnt/user/appdata/dawarich/storage
|
||||
```
|
||||
|
||||
5. In Komodo als Compose-Stack deployen. `frontend_net` und `backend_net` muessen bereits existieren.
|
||||
6. Ersten Login in Dawarich durchfuehren und den API-Key im Account-Bereich erzeugen.
|
||||
7. Home Assistant `homeassistant-dawarich.example.yaml` in das Smart-Home-Fachrepo uebernehmen und `device_tracker.your_phone` ersetzen.
|
||||
|
||||
## Traefik und Authelia
|
||||
|
||||
Die UI liegt auf `https://dawarich.kaleschke.info` und nutzt `authelia@file,secure-headers@file`.
|
||||
|
||||
Die Tracking-API-Routen fuer OwnTracks, Overland und Traccar sind separat und priorisiert ohne Authelia geroutet, weil diese Clients per Dawarich-API-Key authentifizieren und keine Browser-ForwardAuth-Challenge verarbeiten koennen.
|
||||
|
||||
## Prometheus
|
||||
|
||||
`prometheus-scrape.snippet.yml` ist die dienstnahe Referenz. Produktiv ist der Job bereits in `monitoring/prometheus/prometheus.yml` eingetragen.
|
||||
|
||||
Der Monitoring-Stack ist dafuer bereits vorbereitet:
|
||||
|
||||
- `prometheus` haengt an `backend_net`, damit `dawarich_app` erreichbar ist.
|
||||
- `/mnt/user/appdata/secrets/dawarich_metrics_password.txt` ist als Docker Secret eingebunden.
|
||||
|
||||
Nicht `dawarich_app:9394` scrapen: das ist nach aktueller Dawarich-Doku veraltet. Der Web-Service aggregiert App- und Sidekiq-Metriken unter `dawarich_app:3000/metrics`.
|
||||
|
||||
## Grafana
|
||||
|
||||
Der Read-only-User `dawarich_grafana_ro` wird beim ersten DB-Init durch `postgres/initdb/20-grafana-readonly.sh` angelegt.
|
||||
|
||||
Bei einer bereits initialisierten DB das Script einmal manuell im DB-Container ausfuehren:
|
||||
|
||||
```bash
|
||||
docker exec dawarich_db /docker-entrypoint-initdb.d/20-grafana-readonly.sh
|
||||
```
|
||||
|
||||
Die produktive Provisionierung ist bereits in den vorhandenen Monitoring-Stack integriert:
|
||||
|
||||
- Datasource: `monitoring/grafana/provisioning/datasources/dawarich.yml`
|
||||
- Dashboard: `monitoring/grafana/dashboards/dawarich.json`
|
||||
- Grafana haengt an `backend_net`, damit `dawarich_db:5432` erreichbar ist.
|
||||
- `DAWARICH_GRAFANA_RO_PASSWORD` wird beim Grafana-Start aus `/mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt` exportiert.
|
||||
|
||||
## Home Assistant
|
||||
|
||||
Dawarich akzeptiert OwnTracks-kompatible Location-Punkte per:
|
||||
|
||||
```text
|
||||
https://dawarich.kaleschke.info/api/v1/owntracks/points?api_key=<dawarich-api-key>
|
||||
```
|
||||
|
||||
`homeassistant-dawarich.example.yaml` enthaelt:
|
||||
|
||||
- `rest_command.dawarich_push_owntracks`
|
||||
- Automation fuer `device_tracker`-State-Changes
|
||||
- API-Key aus HA `secrets.yaml` als `dawarich_api_key`
|
||||
|
||||
Alternativ existiert eine HACS-Integration `dawarich-home-assistant`; die YAML-Variante hier bleibt absichtlich transparent und GitOps-lesbar.
|
||||
|
||||
## Backup mit Borg
|
||||
|
||||
Borg-relevante Daten liegen unter:
|
||||
|
||||
```text
|
||||
/mnt/user/appdata/dawarich/postgres17
|
||||
/mnt/user/appdata/dawarich/redis
|
||||
/mnt/user/appdata/dawarich/shared
|
||||
/mnt/user/appdata/dawarich/public
|
||||
/mnt/user/appdata/dawarich/watched
|
||||
/mnt/user/appdata/dawarich/storage
|
||||
/mnt/user/appdata/secrets/dawarich_*.txt
|
||||
```
|
||||
|
||||
Primaerer Restore-Weg fuer die DB sollte ein logischer Dump plus Appdaten sein. Raw-Postgres-Verzeichnisse sind nur fuer gleiches Major/PostGIS-Image und sauberen Shutdown geeignet.
|
||||
|
||||
Empfohlener Dump vor Borg:
|
||||
|
||||
```bash
|
||||
docker exec dawarich_db pg_dump -U dawarich -d dawarich_production -Fc > /mnt/user/backups/borg/dumps/latest/dawarich.dump
|
||||
```
|
||||
|
||||
## Updates
|
||||
|
||||
- Kein `latest` verwenden.
|
||||
- Vor jedem Update Release Notes lesen, besonders bei Dawarich und PostGIS.
|
||||
- Dawarich App und Sidekiq muessen immer dasselbe Image-Tag nutzen.
|
||||
- PostGIS-Major-/Minor-Wechsel getrennt planen und vorher Dump plus Restore-Probe erstellen.
|
||||
- Image-Digests nach Review bewusst aktualisieren.
|
||||
|
||||
## Rollback
|
||||
|
||||
1. Komodo Stack stoppen.
|
||||
2. Vorherigen Git-Commit mit altem Image-Tag/Digest deployen.
|
||||
3. Falls nur App-Code gewechselt wurde: Stack starten und Healthchecks pruefen.
|
||||
4. Falls DB-Migrationen gelaufen sind: DB aus `dawarich.dump` in einen frischen PostGIS-17-Container restoren; kein blindes Zurueckkopieren eines Live-Postgres-Verzeichnisses.
|
||||
5. Dawarich UI, `/api/v1/health`, Prometheus-Scrape und HA-Push testen.
|
||||
@@ -0,0 +1,271 @@
|
||||
name: dawarich
|
||||
|
||||
x-dawarich-image: &dawarich_image freikin/dawarich:1.8.1@sha256:7c70f2169e848ed77ae1cec01dd10ec4a73a70a785d4e4d248db1735c0bc25ed
|
||||
|
||||
services:
|
||||
dawarich_db:
|
||||
image: postgis/postgis:17-3.5-alpine@sha256:fc07e7a034e013d50ada575673b798ca6277e000b8364e39e217f612d94bd9a5
|
||||
container_name: dawarich_db
|
||||
restart: unless-stopped
|
||||
shm_size: 1G
|
||||
environment:
|
||||
TZ: ${TZ}
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/dawarich_postgres_password
|
||||
GRAFANA_DB_USER: ${GRAFANA_DB_USER}
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
volumes:
|
||||
- dawarich_db_data:/var/lib/postgresql/data
|
||||
- dawarich_shared:/var/shared
|
||||
- ./postgres/initdb:/docker-entrypoint-initdb.d:ro
|
||||
networks:
|
||||
- backend_net
|
||||
secrets:
|
||||
- dawarich_postgres_password
|
||||
- dawarich_grafana_ro_password
|
||||
expose:
|
||||
- "5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
dawarich_redis:
|
||||
image: redis:7-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99
|
||||
container_name: dawarich_redis
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- /bin/sh
|
||||
- -lc
|
||||
- |
|
||||
exec redis-server \
|
||||
--save 900 1 \
|
||||
--save 300 10 \
|
||||
--appendonly no \
|
||||
--requirepass "$$(cat /run/secrets/dawarich_redis_password)"
|
||||
volumes:
|
||||
- dawarich_redis_data:/data
|
||||
networks:
|
||||
- backend_net
|
||||
secrets:
|
||||
- dawarich_redis_password
|
||||
expose:
|
||||
- "6379"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli -a \"$$(cat /run/secrets/dawarich_redis_password)\" --raw incr ping >/dev/null"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
dawarich_app:
|
||||
image: *dawarich_image
|
||||
container_name: dawarich_app
|
||||
restart: unless-stopped
|
||||
stdin_open: true
|
||||
tty: true
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -lc
|
||||
command:
|
||||
- |
|
||||
export DATABASE_PASSWORD="$$(cat /run/secrets/dawarich_postgres_password)"
|
||||
export REDIS_URL="redis://:$$(cat /run/secrets/dawarich_redis_password)@dawarich_redis:6379/0"
|
||||
export SECRET_KEY_BASE="$$(cat /run/secrets/dawarich_secret_key_base)"
|
||||
export METRICS_PASSWORD="$$(cat /run/secrets/dawarich_metrics_password)"
|
||||
exec web-entrypoint.sh bin/rails server -p 3000 -b ::
|
||||
environment:
|
||||
TZ: ${TZ}
|
||||
RAILS_ENV: production
|
||||
DATABASE_HOST: dawarich_db
|
||||
DATABASE_PORT: "5432"
|
||||
DATABASE_USERNAME: ${POSTGRES_USER}
|
||||
DATABASE_NAME: ${POSTGRES_DB}
|
||||
APPLICATION_HOSTS: ${APPLICATION_HOSTS}
|
||||
APPLICATION_PROTOCOL: https
|
||||
TIME_ZONE: ${TZ}
|
||||
SELF_HOSTED: "true"
|
||||
STORE_GEODATA: "true"
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
PROMETHEUS_EXPORTER_ENABLED: "true"
|
||||
METRICS_USERNAME: ${METRICS_USERNAME}
|
||||
SIDEKIQ_METRICS_URL: http://dawarich_sidekiq:9394/metrics
|
||||
BACKGROUND_PROCESSING_CONCURRENCY: ${BACKGROUND_PROCESSING_CONCURRENCY}
|
||||
RAILS_MAX_THREADS: ${RAILS_MAX_THREADS}
|
||||
volumes:
|
||||
- dawarich_public:/var/app/public
|
||||
- dawarich_watched:/var/app/tmp/imports/watched
|
||||
- dawarich_storage:/var/app/storage
|
||||
- dawarich_db_data:/dawarich_db_data:ro
|
||||
networks:
|
||||
- frontend_net
|
||||
- backend_net
|
||||
secrets:
|
||||
- dawarich_postgres_password
|
||||
- dawarich_redis_password
|
||||
- dawarich_secret_key_base
|
||||
- dawarich_metrics_password
|
||||
expose:
|
||||
- "3000"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget -qO - http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"[[:space:]]*:[[:space:]]*\"ok\"'"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 30
|
||||
start_period: 30s
|
||||
depends_on:
|
||||
dawarich_db:
|
||||
condition: service_healthy
|
||||
dawarich_redis:
|
||||
condition: service_healthy
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network=frontend_net
|
||||
|
||||
# Public API-key endpoints for mobile apps and Home Assistant pushes.
|
||||
- traefik.http.routers.dawarich-api.rule=Host(`${DAWARICH_HOST}`) && (Path(`/api/v1/owntracks/points`) || Path(`/api/v1/overland/batches`) || Path(`/api/v1/traccar/points`))
|
||||
- traefik.http.routers.dawarich-api.entrypoints=websecure
|
||||
- traefik.http.routers.dawarich-api.tls=true
|
||||
- traefik.http.routers.dawarich-api.tls.certresolver=le
|
||||
- traefik.http.routers.dawarich-api.priority=100
|
||||
- traefik.http.routers.dawarich-api.middlewares=secure-headers@file
|
||||
- traefik.http.routers.dawarich-api.service=dawarich
|
||||
|
||||
# UI and all other routes require Authelia ForwardAuth.
|
||||
- traefik.http.routers.dawarich.rule=Host(`${DAWARICH_HOST}`)
|
||||
- traefik.http.routers.dawarich.entrypoints=websecure
|
||||
- traefik.http.routers.dawarich.tls=true
|
||||
- traefik.http.routers.dawarich.tls.certresolver=le
|
||||
- traefik.http.routers.dawarich.priority=10
|
||||
- traefik.http.routers.dawarich.middlewares=authelia@file,secure-headers@file
|
||||
- traefik.http.routers.dawarich.service=dawarich
|
||||
- traefik.http.services.dawarich.loadbalancer.server.port=3000
|
||||
|
||||
dawarich_sidekiq:
|
||||
image: *dawarich_image
|
||||
container_name: dawarich_sidekiq
|
||||
restart: unless-stopped
|
||||
stdin_open: true
|
||||
tty: true
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -lc
|
||||
command:
|
||||
- |
|
||||
export DATABASE_PASSWORD="$$(cat /run/secrets/dawarich_postgres_password)"
|
||||
export REDIS_URL="redis://:$$(cat /run/secrets/dawarich_redis_password)@dawarich_redis:6379/0"
|
||||
export SECRET_KEY_BASE="$$(cat /run/secrets/dawarich_secret_key_base)"
|
||||
export METRICS_PASSWORD="$$(cat /run/secrets/dawarich_metrics_password)"
|
||||
exec sidekiq-entrypoint.sh sidekiq
|
||||
environment:
|
||||
TZ: ${TZ}
|
||||
RAILS_ENV: production
|
||||
DATABASE_HOST: dawarich_db
|
||||
DATABASE_PORT: "5432"
|
||||
DATABASE_USERNAME: ${POSTGRES_USER}
|
||||
DATABASE_NAME: ${POSTGRES_DB}
|
||||
APPLICATION_HOSTS: ${APPLICATION_HOSTS}
|
||||
APPLICATION_PROTOCOL: https
|
||||
TIME_ZONE: ${TZ}
|
||||
SELF_HOSTED: "true"
|
||||
STORE_GEODATA: "true"
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
PROMETHEUS_EXPORTER_ENABLED: "true"
|
||||
PROMETHEUS_EXPORTER_PORT: "9394"
|
||||
METRICS_USERNAME: ${METRICS_USERNAME}
|
||||
BACKGROUND_PROCESSING_CONCURRENCY: ${BACKGROUND_PROCESSING_CONCURRENCY}
|
||||
RAILS_MAX_THREADS: ${RAILS_MAX_THREADS}
|
||||
volumes:
|
||||
- dawarich_public:/var/app/public
|
||||
- dawarich_watched:/var/app/tmp/imports/watched
|
||||
- dawarich_storage:/var/app/storage
|
||||
networks:
|
||||
- frontend_net
|
||||
- backend_net
|
||||
secrets:
|
||||
- dawarich_postgres_password
|
||||
- dawarich_redis_password
|
||||
- dawarich_secret_key_base
|
||||
- dawarich_metrics_password
|
||||
expose:
|
||||
- "9394"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pgrep -f sidekiq >/dev/null"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 30
|
||||
start_period: 30s
|
||||
depends_on:
|
||||
dawarich_db:
|
||||
condition: service_healthy
|
||||
dawarich_redis:
|
||||
condition: service_healthy
|
||||
dawarich_app:
|
||||
condition: service_healthy
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
networks:
|
||||
frontend_net:
|
||||
external: true
|
||||
backend_net:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
dawarich_db_data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/postgres17
|
||||
dawarich_redis_data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/redis
|
||||
dawarich_shared:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/shared
|
||||
dawarich_public:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/public
|
||||
dawarich_watched:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/watched
|
||||
dawarich_storage:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: /mnt/user/appdata/dawarich/storage
|
||||
|
||||
secrets:
|
||||
dawarich_postgres_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_postgres_password.txt
|
||||
dawarich_redis_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_redis_password.txt
|
||||
dawarich_secret_key_base:
|
||||
file: /mnt/user/appdata/secrets/dawarich_secret_key_base.txt
|
||||
dawarich_metrics_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_metrics_password.txt
|
||||
dawarich_grafana_ro_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt
|
||||
@@ -0,0 +1,355 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": false,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 16,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"basemap": {
|
||||
"config": {},
|
||||
"name": "Layer 0",
|
||||
"type": "default"
|
||||
},
|
||||
"controls": {
|
||||
"mouseWheelZoom": true,
|
||||
"showAttribution": true,
|
||||
"showDebug": false,
|
||||
"showMeasure": false,
|
||||
"showScale": true,
|
||||
"showZoom": true
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"config": {
|
||||
"showLegend": true,
|
||||
"style": {
|
||||
"color": {
|
||||
"fixed": "dark-green"
|
||||
},
|
||||
"opacity": 0.55,
|
||||
"rotation": {
|
||||
"fixed": 0,
|
||||
"max": 360,
|
||||
"min": -360,
|
||||
"mode": "mod"
|
||||
},
|
||||
"size": {
|
||||
"fixed": 4,
|
||||
"max": 15,
|
||||
"min": 2
|
||||
},
|
||||
"symbol": {
|
||||
"fixed": "img/icons/marker/circle.svg",
|
||||
"mode": "fixed"
|
||||
},
|
||||
"textConfig": {
|
||||
"fontSize": 12,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"textAlign": "center",
|
||||
"textBaseline": "middle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"latitude": "latitude",
|
||||
"longitude": "longitude",
|
||||
"mode": "coords"
|
||||
},
|
||||
"name": "Location points",
|
||||
"tooltip": true,
|
||||
"type": "markers"
|
||||
}
|
||||
],
|
||||
"tooltip": {
|
||||
"mode": "details"
|
||||
},
|
||||
"view": {
|
||||
"allLayers": true,
|
||||
"id": "fit",
|
||||
"lat": 51,
|
||||
"lon": 10,
|
||||
"zoom": 5
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n to_timestamp(timestamp) AS \"time\",\n ST_Y(lonlat::geometry) AS latitude,\n ST_X(lonlat::geometry) AS longitude,\n accuracy,\n tracker_id\nFROM points\nWHERE $__unixEpochFilter(timestamp)\n AND lonlat IS NOT NULL\nORDER BY timestamp DESC\nLIMIT 20000;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Location Points",
|
||||
"type": "geomap"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 70,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "km"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"sum"
|
||||
],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "time_series",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n make_date(year, month, 1)::timestamp AS \"time\",\n round((distance::numeric / 1000.0), 2) AS \"km\"\nFROM stats\nWHERE make_date(year, month, 1)::timestamp BETWEEN $__timeFrom() AND $__timeTo()\nORDER BY 1;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Kilometers per Month",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 70,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"sum"
|
||||
],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "time_series",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n date_trunc('day', to_timestamp(timestamp)) AS \"time\",\n count(*) AS \"points\"\nFROM points\nWHERE $__unixEpochFilter(timestamp)\nGROUP BY 1\nORDER BY 1;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Points per Day",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "5m",
|
||||
"schemaVersion": 41,
|
||||
"tags": [
|
||||
"dawarich",
|
||||
"location"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-30d",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Dawarich",
|
||||
"uid": "dawarich",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Dawarich PostgreSQL
|
||||
uid: dawarich-postgres
|
||||
type: postgres
|
||||
access: proxy
|
||||
url: dawarich_db:5432
|
||||
database: dawarich_production
|
||||
user: dawarich_grafana_ro
|
||||
editable: false
|
||||
jsonData:
|
||||
sslmode: disable
|
||||
postgresVersion: 1700
|
||||
timescaledb: false
|
||||
secureJsonData:
|
||||
password: $DAWARICH_GRAFANA_RO_PASSWORD
|
||||
@@ -0,0 +1,47 @@
|
||||
# Add `dawarich_api_key` to Home Assistant `secrets.yaml`.
|
||||
# The endpoint is the current OwnTracks-compatible Dawarich endpoint:
|
||||
# https://<host>/api/v1/owntracks/points?api_key=<api-key>
|
||||
|
||||
rest_command:
|
||||
dawarich_push_owntracks:
|
||||
url: "https://dawarich.kaleschke.info/api/v1/owntracks/points?api_key={{ api_key }}"
|
||||
method: POST
|
||||
content_type: "application/json"
|
||||
payload: >-
|
||||
{
|
||||
"_type": "location",
|
||||
"lat": {{ latitude }},
|
||||
"lon": {{ longitude }},
|
||||
"tst": {{ timestamp }},
|
||||
"acc": {{ accuracy | default(0) }},
|
||||
"alt": {{ altitude | default(0) }},
|
||||
"batt": {{ battery | default(0) }},
|
||||
"tid": "{{ tracker_id[:2] }}"
|
||||
}
|
||||
|
||||
automation:
|
||||
- id: dawarich_push_device_tracker_location
|
||||
alias: Dawarich - push device tracker location
|
||||
mode: queued
|
||||
max: 20
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- device_tracker.your_phone
|
||||
condition:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ trigger.to_state is not none
|
||||
and state_attr(trigger.entity_id, 'latitude') is number
|
||||
and state_attr(trigger.entity_id, 'longitude') is number }}
|
||||
action:
|
||||
- service: rest_command.dawarich_push_owntracks
|
||||
data:
|
||||
api_key: !secret dawarich_api_key
|
||||
tracker_id: "{{ trigger.entity_id.split('.')[1] }}"
|
||||
latitude: "{{ state_attr(trigger.entity_id, 'latitude') }}"
|
||||
longitude: "{{ state_attr(trigger.entity_id, 'longitude') }}"
|
||||
accuracy: "{{ state_attr(trigger.entity_id, 'gps_accuracy') | default(0, true) }}"
|
||||
altitude: "{{ state_attr(trigger.entity_id, 'altitude') | default(0, true) }}"
|
||||
battery: "{{ state_attr(trigger.entity_id, 'battery_level') | default(0, true) }}"
|
||||
timestamp: "{{ as_timestamp(trigger.to_state.last_updated) | int }}"
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
GRAFANA_USER="${GRAFANA_DB_USER:-dawarich_grafana_ro}"
|
||||
GRAFANA_PASSWORD="$(cat /run/secrets/dawarich_grafana_ro_password)"
|
||||
|
||||
sql_ident() {
|
||||
printf '"%s"' "$(printf '%s' "$1" | sed 's/"/""/g')"
|
||||
}
|
||||
|
||||
sql_literal() {
|
||||
printf "'%s'" "$(printf '%s' "$1" | sed "s/'/''/g")"
|
||||
}
|
||||
|
||||
DB_IDENT="$(sql_ident "$POSTGRES_DB")"
|
||||
USER_IDENT="$(sql_ident "$GRAFANA_USER")"
|
||||
USER_LITERAL="$(sql_literal "$GRAFANA_USER")"
|
||||
PASSWORD_LITERAL="$(sql_literal "$GRAFANA_PASSWORD")"
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<EOSQL
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = ${USER_LITERAL}) THEN
|
||||
EXECUTE 'CREATE ROLE ${USER_IDENT} LOGIN PASSWORD ${PASSWORD_LITERAL}';
|
||||
ELSE
|
||||
EXECUTE 'ALTER ROLE ${USER_IDENT} WITH LOGIN PASSWORD ${PASSWORD_LITERAL}';
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
|
||||
GRANT CONNECT ON DATABASE ${DB_IDENT} TO ${USER_IDENT};
|
||||
GRANT USAGE ON SCHEMA public TO ${USER_IDENT};
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO ${USER_IDENT};
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO ${USER_IDENT};
|
||||
EOSQL
|
||||
@@ -0,0 +1,18 @@
|
||||
# Dawarich 1.8.1 serves the Prometheus endpoint on the web service at
|
||||
# /metrics. Port 9394 is the internal Sidekiq metrics endpoint consumed by
|
||||
# dawarich_app via SIDEKIQ_METRICS_URL.
|
||||
#
|
||||
# Prerequisites in monitoring/docker-compose.yml:
|
||||
# - attach service `prometheus` to external `backend_net`
|
||||
# - mount Docker secret/file `/mnt/user/appdata/secrets/dawarich_metrics_password.txt`
|
||||
# into the Prometheus container at `/run/secrets/dawarich_metrics_password`
|
||||
|
||||
- job_name: dawarich
|
||||
metrics_path: /metrics
|
||||
scheme: http
|
||||
basic_auth:
|
||||
username: prometheus
|
||||
password_file: /run/secrets/dawarich_metrics_password
|
||||
static_configs:
|
||||
- targets:
|
||||
- dawarich_app:3000
|
||||
@@ -0,0 +1 @@
|
||||
replace-with-a-long-random-grafana-readonly-password
|
||||
@@ -0,0 +1 @@
|
||||
replace-with-a-long-random-metrics-password
|
||||
@@ -0,0 +1 @@
|
||||
replace-with-a-long-random-postgres-password
|
||||
@@ -0,0 +1 @@
|
||||
replace-with-a-long-random-url-safe-redis-password
|
||||
@@ -0,0 +1 @@
|
||||
replace-with-output-of-openssl-rand-hex-64
|
||||
@@ -60,6 +60,11 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb
|
||||
| Monitoring Grafana -> InfluxDB | Datasource Token | `/mnt/user/appdata/secrets/monitoring_grafana_influxdb_token.txt` -> Docker Secret `/run/secrets/monitoring_grafana_influxdb_token` | aktiv |
|
||||
| Grafana OIDC (Authelia) | Client Secret | `/mnt/user/appdata/secrets/grafana_oidc_client_secret` (Klartext, chmod 600) -> Docker Secret `/run/secrets/grafana_oidc_client_secret` -> `GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET__FILE`. Zugehoeriger pbkdf2-Hash liegt im Authelia-Host-Config-Client `grafana` (kein Wert im Repo) | aktiv (2026-06-06) |
|
||||
| Mealie OIDC (Authelia) | Client Secret | Stack-ENV `${MEALIE_OIDC_CLIENT_SECRET}` in `/mnt/user/services/stacks/mealie/apps/mealie/.env` (Komodo-Stack-ENV); pbkdf2-Hash im Authelia-Host-Config-Client `mealie` (kein Wert im Repo) | aktiv (2026-06-06) |
|
||||
| Dawarich | DB Password | `/mnt/user/appdata/secrets/dawarich_postgres_password.txt` -> Docker Secret `/run/secrets/dawarich_postgres_password`; Postgres nutzt `POSTGRES_PASSWORD_FILE`, App/Sidekiq lesen per Entrypoint-Export | geplant |
|
||||
| Dawarich | Redis Password | `/mnt/user/appdata/secrets/dawarich_redis_password.txt` -> Docker Secret `/run/secrets/dawarich_redis_password`; Redis `--requirepass`, App/Sidekiq `REDIS_URL` | geplant |
|
||||
| Dawarich | Rails `SECRET_KEY_BASE` | `/mnt/user/appdata/secrets/dawarich_secret_key_base.txt` -> Docker Secret `/run/secrets/dawarich_secret_key_base` | geplant |
|
||||
| Dawarich Metrics | Basic-Auth Password | `/mnt/user/appdata/secrets/dawarich_metrics_password.txt` -> Docker Secret `/run/secrets/dawarich_metrics_password`; Prometheus `password_file` | geplant |
|
||||
| Grafana -> Dawarich | Read-only DB Password | `/mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt` -> Docker Secret `/run/secrets/dawarich_grafana_ro_password`; Grafana-Env `DAWARICH_GRAFANA_RO_PASSWORD` | geplant |
|
||||
| Renovate Bot | Gitea Service-Account PAT | `/mnt/user/appdata/secrets/renovate_token.txt` -> Host-Datei (chmod 600), gelesen von `ops/renovate/run-renovate.sh` und an Renovate-Container als `RENOVATE_TOKEN` weitergegeben | aktiv nach Operator-Setup (siehe `docs/RENOVATE.md`) |
|
||||
| n8n | Encryption Key fuer interne Credential-Verschluesselung | `/mnt/user/appdata/secrets/n8n_encryption_key.txt` (chmod 600) -> Komodo Stack ENV `${N8N_ENCRYPTION_KEY}`; kein `_FILE`-Support im Upstream-Image | aktiv |
|
||||
| n8n | GMX IMAP Login (Mail-Trigger Workflow) | n8n Credentials Store (Typ `imap`), nur in `/mnt/user/appdata/n8n/data` mit `N8N_ENCRYPTION_KEY` verschluesselt | aktiv |
|
||||
@@ -108,6 +113,11 @@ Dieses Dokument listet sensible Daten, deren Ablageorte und die vorgesehene Einb
|
||||
|-- ha_token_codex
|
||||
|-- filebrowser_admin_password.txt
|
||||
|-- homelab_smtp_password.txt
|
||||
|-- dawarich_postgres_password.txt
|
||||
|-- dawarich_redis_password.txt
|
||||
|-- dawarich_secret_key_base.txt
|
||||
|-- dawarich_metrics_password.txt
|
||||
|-- dawarich_grafana_ro_password.txt
|
||||
`-- vaultwarden_admin_token.txt
|
||||
```
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
|
||||
| `immich_machine_learning` | Immich ML | `apps/immich/docker-compose.yml` | intern | `immich_default`, `immich_egress` | `model-cache` | rebuildbar | nein | keine Traefik-Route; `immich_egress` (nicht-internal) nur fuer Modell-Download zu huggingface, sonst scheitert Smart Search/Gesichtserkennung an DNS |
|
||||
| `mealie` | Rezeptverwaltung | `apps/mealie/docker-compose.yml` | `https://mealie.kaleschke.info` | `mealie-postgres`, Traefik | `/mnt/user/appdata/mealie/data` | Tier 2, Borg + `mealie.dump` | ja | App + DB in internem Netz getrennt |
|
||||
| `mealie-postgres` | Mealie-Datenbank | `apps/mealie/docker-compose.yml` | intern | `mealie_internal` | `/mnt/user/appdata/mealie/postgres18`, archivierter Rollback-Altstand `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602/mealie-postgres17`, `mealie_postgres_password.txt` | Dump `mealie.dump` | nein | interne DB; PostgreSQL 18 |
|
||||
| `dawarich_app` | Standort-Historie / Google-Timeline-Ersatz | `apps/dawarich/docker-compose.yml` | `https://dawarich.kaleschke.info` | eigene PostGIS-DB, eigene Redis, Traefik + Authelia, optional Home Assistant Push | `/mnt/user/appdata/dawarich/{postgres17,redis,shared,public,watched,storage}`, `dawarich_*.txt` Secrets | Tier 2, Borg + `dawarich.dump` | ja + Authelia | UI hinter Authelia; API-Key-Tracking-Endpunkte fuer OwnTracks/Overland/Traccar ohne ForwardAuth priorisiert. App und Sidekiq nutzen `freikin/dawarich:1.8.1`; Prometheus-Scrape nach aktueller Dawarich-Doku ueber `dawarich_app:3000/metrics`, Sidekiq-Metriken intern ueber `:9394`. |
|
||||
| `dawarich_db` | Dawarich PostGIS-Datenbank | `apps/dawarich/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/dawarich/postgres17`, `dawarich_postgres_password.txt`, `dawarich_grafana_ro_password.txt` | Dump `dawarich.dump`; raw DB nur bei gleichem PG/PostGIS und sauberem Shutdown | nein | PostGIS 17-3.5 Alpine; Grafana-Read-only-User `dawarich_grafana_ro` per Init-Script |
|
||||
| `dawarich_redis` | Dawarich Cache/Queue-Backend | `apps/dawarich/docker-compose.yml` | intern | `backend_net` | `/mnt/user/appdata/dawarich/redis`, `dawarich_redis_password.txt` | Teil von Dawarich-Restore, aber aus DB/Appdaten rekonstruierbar | nein | Redis 7 Alpine, keine Host-Ports |
|
||||
| `mail-archiver` | Mail-Archivierung | `apps/mail-archiver/docker-compose.yml` | `https://mail.kaleschke.info` | PostgreSQL 18, Internet/IMAP, Traefik, Authelia | `/mnt/user/appdata/mailarchiver/data-protection-keys` | Tier 2, `postgresql17-mailarchiver.dump` | ja + Authelia | Hybrid-Dienst: `frontend_net` fuer Internet, `backend_net` fuer DB; App-eigene Auth bleibt zusaetzliche Schutzschicht; Dump-Dateiname behaelt den historischen Cluster-Namen |
|
||||
| `nextcloud` | Datei-/Cloud-Dienst | `apps/nextcloud/docker-compose.yml` | `https://cloud.kaleschke.info` | eigene PostgreSQL, eigene Redis, Traefik | `/mnt/user/appdata/nextcloud/html`, `/mnt/user/documents/nextcloud-data` | Tier 2, `nextcloud.dump` + Share | ja | native App-Auth ohne zentrale ForwardAuth; WebDAV/CardDAV beachten |
|
||||
| `nextcloud-postgres` | Nextcloud-Datenbank | `apps/nextcloud/docker-compose.yml` | intern | `nextcloud_internal` | `/mnt/user/appdata/nextcloud/postgres18`, archivierter Rollback-Altstand `/mnt/user/appdata/_archive/pg18-immich-rollback-volumes-20260602/nextcloud-postgres17`, `nextcloud_postgres_password.txt` | `nextcloud.dump`, raw DB nicht primaerer Restore-Weg | nein | interne DB; PostgreSQL 18 |
|
||||
|
||||
@@ -17,8 +17,11 @@ services:
|
||||
- prometheus_data:/prometheus
|
||||
networks:
|
||||
- monitoring_net
|
||||
- backend_net
|
||||
expose:
|
||||
- "9090"
|
||||
secrets:
|
||||
- dawarich_metrics_password
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
depends_on:
|
||||
@@ -165,6 +168,7 @@ services:
|
||||
- -c
|
||||
- |
|
||||
export GRAFANA_INFLUXDB_TOKEN="$$(cat /run/secrets/monitoring_grafana_influxdb_token)"
|
||||
export DAWARICH_GRAFANA_RO_PASSWORD="$$(cat /run/secrets/dawarich_grafana_ro_password)"
|
||||
exec /run.sh
|
||||
volumes:
|
||||
- grafana_data:/var/lib/grafana
|
||||
@@ -173,10 +177,12 @@ services:
|
||||
networks:
|
||||
- monitoring_net
|
||||
- frontend_net
|
||||
- backend_net
|
||||
secrets:
|
||||
- monitoring_grafana_admin_password
|
||||
- monitoring_grafana_influxdb_token
|
||||
- grafana_oidc_client_secret
|
||||
- dawarich_grafana_ro_password
|
||||
expose:
|
||||
- "3000"
|
||||
security_opt:
|
||||
@@ -390,6 +396,8 @@ networks:
|
||||
driver: bridge
|
||||
frontend_net:
|
||||
external: true
|
||||
backend_net:
|
||||
external: true
|
||||
dns_net:
|
||||
external: true
|
||||
|
||||
@@ -409,3 +417,7 @@ secrets:
|
||||
file: /mnt/user/appdata/secrets/grafana_oidc_client_secret
|
||||
influxdb3_admin_token:
|
||||
file: /mnt/user/appdata/secrets/influxdb3_admin_token.json
|
||||
dawarich_metrics_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_metrics_password.txt
|
||||
dawarich_grafana_ro_password:
|
||||
file: /mnt/user/appdata/secrets/dawarich_grafana_ro_password.txt
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": false,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "none"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 16,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"basemap": {
|
||||
"config": {},
|
||||
"name": "Layer 0",
|
||||
"type": "default"
|
||||
},
|
||||
"controls": {
|
||||
"mouseWheelZoom": true,
|
||||
"showAttribution": true,
|
||||
"showDebug": false,
|
||||
"showMeasure": false,
|
||||
"showScale": true,
|
||||
"showZoom": true
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"config": {
|
||||
"showLegend": true,
|
||||
"style": {
|
||||
"color": {
|
||||
"fixed": "dark-green"
|
||||
},
|
||||
"opacity": 0.55,
|
||||
"rotation": {
|
||||
"fixed": 0,
|
||||
"max": 360,
|
||||
"min": -360,
|
||||
"mode": "mod"
|
||||
},
|
||||
"size": {
|
||||
"fixed": 4,
|
||||
"max": 15,
|
||||
"min": 2
|
||||
},
|
||||
"symbol": {
|
||||
"fixed": "img/icons/marker/circle.svg",
|
||||
"mode": "fixed"
|
||||
},
|
||||
"textConfig": {
|
||||
"fontSize": 12,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"textAlign": "center",
|
||||
"textBaseline": "middle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"latitude": "latitude",
|
||||
"longitude": "longitude",
|
||||
"mode": "coords"
|
||||
},
|
||||
"name": "Location points",
|
||||
"tooltip": true,
|
||||
"type": "markers"
|
||||
}
|
||||
],
|
||||
"tooltip": {
|
||||
"mode": "details"
|
||||
},
|
||||
"view": {
|
||||
"allLayers": true,
|
||||
"id": "fit",
|
||||
"lat": 51,
|
||||
"lon": 10,
|
||||
"zoom": 5
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n to_timestamp(timestamp) AS \"time\",\n ST_Y(lonlat::geometry) AS latitude,\n ST_X(lonlat::geometry) AS longitude,\n accuracy,\n tracker_id\nFROM points\nWHERE $__unixEpochFilter(timestamp)\n AND lonlat IS NOT NULL\nORDER BY timestamp DESC\nLIMIT 20000;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Location Points",
|
||||
"type": "geomap"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 70,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "km"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"sum"
|
||||
],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "time_series",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n make_date(year, month, 1)::timestamp AS \"time\",\n round((distance::numeric / 1000.0), 2) AS \"km\"\nFROM stats\nWHERE make_date(year, month, 1)::timestamp BETWEEN $__timeFrom() AND $__timeTo()\nORDER BY 1;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Kilometers per Month",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 70,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "never",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 8,
|
||||
"x": 16,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [
|
||||
"sum"
|
||||
],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "13.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "postgres",
|
||||
"uid": "dawarich-postgres"
|
||||
},
|
||||
"editorMode": "code",
|
||||
"format": "time_series",
|
||||
"rawQuery": true,
|
||||
"rawSql": "SELECT\n date_trunc('day', to_timestamp(timestamp)) AS \"time\",\n count(*) AS \"points\"\nFROM points\nWHERE $__unixEpochFilter(timestamp)\nGROUP BY 1\nORDER BY 1;",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Points per Day",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"refresh": "5m",
|
||||
"schemaVersion": 41,
|
||||
"tags": [
|
||||
"dawarich",
|
||||
"location"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-30d",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "Dawarich",
|
||||
"uid": "dawarich",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Dawarich PostgreSQL
|
||||
uid: dawarich-postgres
|
||||
type: postgres
|
||||
access: proxy
|
||||
url: dawarich_db:5432
|
||||
database: dawarich_production
|
||||
user: dawarich_grafana_ro
|
||||
editable: false
|
||||
jsonData:
|
||||
sslmode: disable
|
||||
postgresVersion: 1700
|
||||
timescaledb: false
|
||||
secureJsonData:
|
||||
password: $DAWARICH_GRAFANA_RO_PASSWORD
|
||||
@@ -36,6 +36,16 @@ scrape_configs:
|
||||
- targets:
|
||||
- traefik:8082
|
||||
|
||||
- job_name: dawarich
|
||||
metrics_path: /metrics
|
||||
basic_auth:
|
||||
username: prometheus
|
||||
password_file: /run/secrets/dawarich_metrics_password
|
||||
static_configs:
|
||||
# Dawarich >= 1.7.7 serves aggregated web + Sidekiq metrics here.
|
||||
- targets:
|
||||
- dawarich_app:3000
|
||||
|
||||
- job_name: blackbox-http
|
||||
metrics_path: /probe
|
||||
params:
|
||||
|
||||
Reference in New Issue
Block a user