Add full NAS service catalog for disaster recovery.

Compose files and configs for postgres, adguard, duckdns, homarr, neo4j,
portainer, remotely, and monitoring; RESTORE.md and sync-from-nas script.
Sanitize pgAdmin secrets; document homelab-command as separate repo.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mo
2026-05-17 13:15:24 +02:00
parent b315f593ec
commit 21dbee4b53
32 changed files with 6567 additions and 32 deletions
+18
View File
@@ -0,0 +1,18 @@
# Globale referentie — per service staat een eigen .env.example in docker/<service>/
NAS_IP=192.168.1.211
POSTGRES_USER=mo
POSTGRES_PASSWORD=changeme
POSTGRES_DB=homelab
PG_HOST_PORT=5433
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=changeme_grafana
GRAFANA_ROOT_URL=http://192.168.1.211:3002
PGADMIN_PASSWORD=changeme
PGADMIN_EMAIL=mo@el-kadi.nl
NEO4J_AUTH=neo4j/changeme
DUCKDNS_SUBDOMAINS=mohome020
DUCKDNS_TOKEN=your-token
+3
View File
@@ -2,6 +2,9 @@
.DS_Store .DS_Store
Thumbs.db Thumbs.db
*.bak *.bak
.env
.env.*
!.env.example
# Runtime data (niet in git) # Runtime data (niet in git)
*.db *.db
+44 -28
View File
@@ -1,37 +1,53 @@
# Homelab Infrastructure Configuration # Homelab Infrastructure Configuration
Docker compose, application configs, nginx, deploy scripts, en Proxmox configs voor Synology NAS (192.168.1.211). Docker compose, applicatie-configs, nginx en deploy-scripts voor Synology NAS (`192.168.1.211`).
## Repos **Snel herstellen:** zie [RESTORE.md](RESTORE.md)
| Service | Repo |
|---|---| ## Repos op Gitea
| HA Voice Control MCP | [ha-voice-control-mcp](http://192.168.1.211:3000/mo/ha-voice-control-mcp) |
| Homelab Configs | [homelab-configs](http://192.168.1.211:3000/mo/homelab-configs) (dit repo) | | Repo | Inhoud |
|------|--------|
| [homelab-configs](http://192.168.1.211:3000/mo/homelab-configs) | Dit repo — infra, compose, configs |
| [homelab-command](http://192.168.1.211:3000/mo/homelab-command) | Dashboard-app + Grafana-build + mesh |
| [ha-voice-control-mcp](http://192.168.1.211:3000/mo/ha-voice-control-mcp) | Home Assistant voice MCP |
## Structuur ## Structuur
``` ```
docker/ docker/
gitea/ # Gitea self-hosted Git (poort 3000) postgres/ # PostgreSQL homelab (5433)
ha-voice-control/ # HA Voice Control MCP server (poort 8765) postgres-web/ # pgAdmin (5434)
guacamole/ # Guacamole remote desktop (poort 8348) gitea/ # Git server (3000)
excalidraw/ # Excalidraw whiteboard (poort 3765) adguard/ # DNS/filter (host network)
wazuh/ # Wazuh SIEM security monitoring duckdns/ # Dynamische DNS
nginx/ # Reverse proxy configs (ha.el-kadi.nl) homarr/ # Dashboard (4755)
configs/ # Application configs neo4j/ # Graph DB
home-assistant/ # Home Assistant (192.168.1.235:8123) portainer/ # Docker UI (9000)
prowlarr/ # Torrent indexer management remotely/ # Remote support (8080)
sonarr/ # TV series management excalidraw/ # Whiteboard (3765)
radarr/ # Movie management guacamole/ # Remote desktop (8348)
qbittorrent/ # Torrent client wazuh/ # SIEM
sabnzbd/ # Usenet client ha-voice-control/ # HA MCP (8765)
unifi/ # UniFi Controller (192.168.1.24) monitoring/ # Prometheus + refs naar homelab-command
proxmox/ # Proxmox VE configs homelab-command/ # README → aparte repo
pve/ # Node "pve" (192.168.1.216, PVE 9.1.6, RTX 3090) configs/
qemu-server/ # 2 VMs: W11, Syno-latest adguard/ # AdGuardHome.yaml
lxc/ # 18 LXCs (100-119) homarr/ # Dashboard JSON
proxmox/ # Node "proxmox" (192.168.1.56, PVE 8.4.14, Dell) home-assistant/
qemu-server/ # 5 VMs prowlarr/ sonarr/ radarr/ qbittorrent/ sabnzbd/
lxc/ # 12 LXCs proxmox/
scripts/ # Deploy en setup scripts nginx/
scripts/
sync-from-nas.sh # NAS → git vóór commit
``` ```
## Workflow
1. Wijziging op NAS → `sh scripts/sync-from-nas.sh`
2. `git add -A && git commit && git push`
3. Bij disaster → [RESTORE.md](RESTORE.md)
## Poorten
Zie RESTORE.md tabel.
+72
View File
@@ -0,0 +1,72 @@
# Snel herstellen na NAS-reset of nieuwe host
**NAS:** `192.168.1.211` · **Gitea:** http://192.168.1.211:3000
## 1. Clone repos
```bash
mkdir -p /volume1/docker /volume1/homes/mo
git clone http://192.168.1.211:3000/mo/homelab-configs.git /volume1/docker/homelab-configs
git clone http://192.168.1.211:3000/mo/homelab-command.git /volume1/homes/mo/homelab-command
```
## 2. Secrets
Kopieer per service `.env.example``.env` en vul wachtwoorden in.
**Nooit** echte `.env` committen.
## 3. Startvolgorde (Docker)
| Stap | Service | Commando |
|------|---------|----------|
| 1 | Netwerk monitoring | `docker network create homelab-monitor` |
| 2 | PostgreSQL | `cd /volume1/docker/homelab-configs/docker/postgres && docker compose up -d` |
| 3 | Gitea | `cd .../docker/gitea && docker compose up -d` |
| 4 | AdGuard | Zet `configs/adguard/AdGuardHome.yaml` op NAS, dan `docker/adguard` |
| 5 | DuckDNS | `docker/duckdns` met `.env` |
| 6 | Neo4j | `docker/neo4j` |
| 7 | pgAdmin | `docker/postgres-web` |
| 8 | Monitoring | Zie `docker/monitoring/README.md` + homelab-command build |
| 9 | Homelab Command | `homelab-command`: `docker compose -f docker-compose.homelab.yml up -d --build` |
| 10 | Mesh (NATS) | `homelab-command`: `docker compose -f docker-compose.mesh.yml up -d` |
| 11 | Homarr, Portainer, Remotely, Excalidraw | elk in `docker/<naam>/` |
| 12 | Overige | Guacamole, Wazuh, HA-voice — zie `docker/` submappen |
Na stap 8: verbind containers op `homelab-monitor`:
```bash
for c in postgres-homelab neo4j prometheus-homelab postgres-exporter-homelab grafana-homelab; do
docker network connect homelab-monitor "$c" 2>/dev/null || true
done
```
## 4. Config terugzetten
| Wat | Bron in git | NAS-pad |
|-----|-------------|---------|
| Homarr | `configs/homarr/*.json` | `/volume1/docker/homarr/` |
| AdGuard | `configs/adguard/AdGuardHome.yaml` | `/volume1/docker/Configs/adguard/` |
| pgAdmin servers | `docker/postgres-web/servers.json` | naast compose |
| *arr / HA / Proxmox | `configs/` | zie README.md structuur |
## 5. Sync vóór commit
```bash
sh /volume1/docker/homelab-configs/scripts/sync-from-nas.sh
cd /volume1/docker/homelab-configs && git add -A && git status
```
## Poorten (referentie)
| Poort | Service |
|-------|---------|
| 3000 | Gitea |
| 3002 | Grafana |
| 4222 | NATS |
| 4755 | Homarr |
| 5433 | PostgreSQL |
| 5434 | pgAdmin |
| 8080 | Remotely |
| 8765 | Homelab Command |
| 9090 | Prometheus |
| 9000 | Portainer |
+344
View File
@@ -0,0 +1,344 @@
http:
pprof:
port: 6060
enabled: false
address: 192.168.1.211:3001
session_ttl: 720h
users:
- name: mo
password: $2a$10$hTko3Z04gyjeG1PwE1AIDObRmamgNOGzH9b66G/FRK75HIhVjhILO
auth_attempts: 5
block_auth_min: 15
http_proxy: ""
language: ""
theme: auto
dns:
bind_hosts:
- 0.0.0.0
port: 53
anonymize_client_ip: false
ratelimit: 20
ratelimit_subnet_len_ipv4: 24
ratelimit_subnet_len_ipv6: 56
ratelimit_whitelist: []
refuse_any: true
upstream_dns:
- https://dns10.quad9.net/dns-query
upstream_dns_file: ""
bootstrap_dns:
- 9.9.9.10
- 149.112.112.10
- 2620:fe::10
- 2620:fe::fe:10
fallback_dns: []
upstream_mode: load_balance
fastest_timeout: 1s
allowed_clients: []
disallowed_clients: []
blocked_hosts:
- version.bind
- id.server
- hostname.bind
trusted_proxies:
- 127.0.0.0/8
- ::1/128
cache_enabled: true
cache_size: 4194304
cache_ttl_min: 0
cache_ttl_max: 0
cache_optimistic: false
cache_optimistic_answer_ttl: 30s
cache_optimistic_max_age: 12h
bogus_nxdomain: []
aaaa_disabled: false
enable_dnssec: false
edns_client_subnet:
custom_ip: ""
enabled: false
use_custom: false
max_goroutines: 300
handle_ddr: true
ipset: []
ipset_file: ""
bootstrap_prefer_ipv6: false
upstream_timeout: 10s
private_networks: []
use_private_ptr_resolvers: true
local_ptr_upstreams: []
use_dns64: false
dns64_prefixes: []
serve_http3: false
use_http3_upstreams: false
serve_plain_dns: true
hostsfile_enabled: true
pending_requests:
enabled: true
tls:
enabled: false
server_name: ""
force_https: false
port_https: 443
port_dns_over_tls: 853
port_dns_over_quic: 853
port_dnscrypt: 0
dnscrypt_config_file: ""
allow_unencrypted_doh: false
certificate_chain: ""
private_key: ""
certificate_path: ""
private_key_path: ""
strict_sni_check: false
querylog:
dir_path: ""
ignored: []
interval: 2160h
size_memory: 1000
enabled: true
ignored_enabled: false
file_enabled: true
statistics:
dir_path: ""
ignored: []
interval: 24h
enabled: true
ignored_enabled: false
filters:
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt
name: AdGuard DNS filter
id: 1
- enabled: false
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt
name: AdAway Default Blocklist
id: 2
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_34.txt
name: HaGeZi's Normal Blocklist
id: 1771582373
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_48.txt
name: HaGeZi's Pro Blocklist
id: 1771582374
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_51.txt
name: HaGeZi's Pro++ Blocklist
id: 1771582375
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_29.txt
name: 'CHN: AdRules DNS List'
id: 1771582376
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_21.txt
name: 'CHN: anti-AD'
id: 1771582377
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_35.txt
name: 'HUN: Hufilter'
id: 1771582378
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_22.txt
name: 'IDN: ABPindo'
id: 1771582379
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_19.txt
name: 'IRN: PersianBlocker list'
id: 1771582380
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_43.txt
name: 'ISR: EasyList Hebrew'
id: 1771582381
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_25.txt
name: 'KOR: List-KR DNS'
id: 1771582382
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_15.txt
name: 'KOR: YousList'
id: 1771582383
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_36.txt
name: 'LIT: EasyList Lithuania'
id: 1771582384
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_20.txt
name: 'MKD: Macedonian Pi-hole Blocklist'
id: 1771582385
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_13.txt
name: 'NOR: Dandelion Sprouts nordiske filtre'
id: 1771582386
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_41.txt
name: 'POL: CERT Polska List of malicious domains'
id: 1771582387
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_14.txt
name: 'POL: Polish filters for Pi-hole'
id: 1771582388
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_17.txt
name: 'SWE: Frellwit''s Swedish Hosts File'
id: 1771582389
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_26.txt
name: 'TUR: turk-adlist'
id: 1771582390
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_40.txt
name: 'TUR: Turkish Ad Hosts'
id: 1771582391
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_16.txt
name: 'VNM: ABPVN List'
id: 1771582392
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_30.txt
name: Phishing URL Blocklist (PhishTank and OpenPhish)
id: 1771582393
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_18.txt
name: Phishing Army
id: 1771582394
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt
name: The Big List of Hacked Malware Web Sites
id: 1771582395
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_50.txt
name: uBlock₀ filters Badware risks
id: 1771582396
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt
name: Malicious URL Blocklist (URLHaus)
id: 1771582397
- enabled: true
url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_47.txt
name: HaGeZi's Gambling Blocklist
id: 1771582398
whitelist_filters: []
user_rules:
- '@@||g.live.com^$important'
- '@@||ashemaletube.com^$client=''192.168.1.235'''
- '@@||o540343.ingest.sentry.io^$important'
- '@@||console.bce.baidu.com^$important'
- ""
dhcp:
enabled: false
interface_name: ""
local_domain_name: lan
dhcpv4:
gateway_ip: ""
subnet_mask: ""
range_start: ""
range_end: ""
lease_duration: 86400
icmp_timeout_msec: 1000
options: []
dhcpv6:
range_start: ""
lease_duration: 86400
ra_slaac_only: false
ra_allow_slaac: false
filtering:
blocking_ipv4: ""
blocking_ipv6: ""
blocked_services:
schedule:
time_zone: UTC
ids:
- 4chan
- 500px
- 9gag
- activision_blizzard
- amino
- battle_net
- betano
- betfair
- betway
- blaze
- blizzard_entertainment
- bluesky
- douban
- electronic_arts
- epic_games
- facebook
- gog
- instagram
- io_interactive
- kook
- leagueoflegends
- line
- mail_ru
- minecraft
- nintendo
- odysee
- ok
- onlyfans
- origin
- playstation
- plenty_of_fish
- qq
- riot_games
- rockstar_games
- snapchat
- steam
- tiktok
- tinder
- tumblr
- ubisoft
- valorant
- vk
- wargaming
- warnerbrosgames
- wizz
- xboxlive
- zhihu
protection_disabled_until: null
safe_search:
enabled: true
bing: true
duckduckgo: true
ecosia: true
google: true
pixabay: true
yandex: true
youtube: true
blocking_mode: default
parental_block_host: family-block.dns.adguard.com
safebrowsing_block_host: standard-block.dns.adguard.com
rewrites: []
safe_fs_patterns:
- /opt/adguardhome/work/userfilters/*
safebrowsing_cache_size: 1048576
safesearch_cache_size: 1048576
parental_cache_size: 1048576
cache_time: 30
filters_update_interval: 24
blocked_response_ttl: 10
filtering_enabled: true
rewrites_enabled: true
parental_enabled: false
safebrowsing_enabled: true
protection_enabled: true
clients:
runtime_sources:
whois: true
arp: true
rdns: true
dhcp: true
hosts: true
persistent: []
log:
enabled: true
file: ""
max_backups: 0
max_size: 100
max_age: 3
compress: false
local_time: false
verbose: false
os:
group: ""
user: ""
rlimit_nofile: 0
schema_version: 33
+61
View File
@@ -0,0 +1,61 @@
{
"schemaVersion": 1,
"configProperties": {
"name": "Fatima"
},
"categories": [
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f",
"position": 1,
"name": "Welcome to Homarr 🎉"
}
],
"wrappers": [
{
"id": "default",
"position": 0
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a326",
"position": 1
}
],
"apps": [],
"widgets": [],
"settings": {
"common": {
"searchEngine": {
"type": "google",
"properties": {}
}
},
"customization": {
"layout": {
"enabledLeftSidebar": false,
"enabledRightSidebar": false,
"enabledDocker": false,
"enabledPing": false,
"enabledSearchbar": true
},
"pageTitle": "Homarr ⭐️",
"logoImageUrl": "/imgs/logo/logo.png",
"faviconUrl": "/imgs/favicon/favicon-squared.png",
"backgroundImageUrl": "",
"customCss": "",
"colors": {
"primary": "red",
"secondary": "yellow",
"shade": 7
},
"appOpacity": 100,
"gridstack": {
"columnCountSmall": 3,
"columnCountMedium": 6,
"columnCountLarge": 10
}
},
"access": {
"allowGuests": false
}
}
}
+61
View File
@@ -0,0 +1,61 @@
{
"schemaVersion": 1,
"configProperties": {
"name": "Hodeifa"
},
"categories": [
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f",
"position": 1,
"name": "Welcome to Homarr 🎉"
}
],
"wrappers": [
{
"id": "default",
"position": 0
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a326",
"position": 1
}
],
"apps": [],
"widgets": [],
"settings": {
"common": {
"searchEngine": {
"type": "google",
"properties": {}
}
},
"customization": {
"layout": {
"enabledLeftSidebar": false,
"enabledRightSidebar": false,
"enabledDocker": false,
"enabledPing": false,
"enabledSearchbar": true
},
"pageTitle": "Homarr ⭐️",
"logoImageUrl": "/imgs/logo/logo.png",
"faviconUrl": "/imgs/favicon/favicon-squared.png",
"backgroundImageUrl": "",
"customCss": "",
"colors": {
"primary": "red",
"secondary": "yellow",
"shade": 7
},
"appOpacity": 100,
"gridstack": {
"columnCountSmall": 3,
"columnCountMedium": 6,
"columnCountLarge": 10
}
},
"access": {
"allowGuests": false
}
}
}
File diff suppressed because it is too large Load Diff
+61
View File
@@ -0,0 +1,61 @@
{
"schemaVersion": 1,
"configProperties": {
"name": "isra"
},
"categories": [
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f",
"position": 1,
"name": "Welcome to Homarr 🎉"
}
],
"wrappers": [
{
"id": "default",
"position": 0
},
{
"id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a326",
"position": 1
}
],
"apps": [],
"widgets": [],
"settings": {
"common": {
"searchEngine": {
"type": "google",
"properties": {}
}
},
"customization": {
"layout": {
"enabledLeftSidebar": false,
"enabledRightSidebar": false,
"enabledDocker": false,
"enabledPing": false,
"enabledSearchbar": true
},
"pageTitle": "Homarr ⭐️",
"logoImageUrl": "/imgs/logo/logo.png",
"faviconUrl": "/imgs/favicon/favicon-squared.png",
"backgroundImageUrl": "",
"customCss": "",
"colors": {
"primary": "red",
"secondary": "yellow",
"shade": 7
},
"appOpacity": 100,
"gridstack": {
"columnCountSmall": 3,
"columnCountMedium": 6,
"columnCountLarge": 10
}
},
"access": {
"allowGuests": false
}
}
}
+21
View File
@@ -0,0 +1,21 @@
# AdGuard Home — DNS + filtering (host network, poort 53 + web UI).
# Config: configs/adguard/AdGuardHome.yaml → mount naar /opt/adguardhome/conf
services:
adguard:
image: adguard/adguardhome:latest
container_name: Adguard
restart: always
network_mode: host
volumes:
- ${ADGUARD_CONFIG_DIR:-/volume1/docker/Configs/adguard}:/opt/adguardhome/conf
- adguard-work:/opt/adguardhome/work
command:
- --no-check-update
- -c
- /opt/adguardhome/conf/AdGuardHome.yaml
- -w
- /opt/adguardhome/work
volumes:
adguard-work:
+7
View File
@@ -0,0 +1,7 @@
PUID=1026
PGID=100
TZ=Europe/Brussels
DUCKDNS_SUBDOMAINS=mohome020
DUCKDNS_TOKEN=your-duckdns-token
DUCKDNS_UPDATE_IP=true
DUCKDNS_INTERVAL=300
+16
View File
@@ -0,0 +1,16 @@
# DuckDNS — dynamisch DNS voor mohome020.duckdns.org
# Start: cp .env.example .env && docker compose up -d
services:
duckdns:
image: linuxserver/duckdns:latest
container_name: duckdns
restart: unless-stopped
environment:
PUID: ${PUID:-1026}
PGID: ${PGID:-100}
TZ: ${TZ:-Europe/Brussels}
SUBDOMAINS: ${DUCKDNS_SUBDOMAINS:?}
TOKEN: ${DUCKDNS_TOKEN:?}
UPDATE_IP: ${DUCKDNS_UPDATE_IP:-true}
INTERVAL: ${DUCKDNS_INTERVAL:-300}
+2 -2
View File
@@ -25,11 +25,11 @@ services:
- PG_HOST=localhost - PG_HOST=localhost
- PG_PORT=5433 - PG_PORT=5433
- PG_USER=mo - PG_USER=mo
- PG_PASSWORD=${PG_PASSWORD:-WaQTUw2t} - PG_PASSWORD=${PG_PASSWORD:?}
- PG_DATABASE=homelab - PG_DATABASE=homelab
- NEO4J_URI=neo4j://localhost:49153 - NEO4J_URI=neo4j://localhost:49153
- NEO4J_USER=neo4j - NEO4J_USER=neo4j
- NEO4J_PASSWORD=${NEO4J_PASSWORD:-WaQTUw2t} - NEO4J_PASSWORD=${NEO4J_PASSWORD:-}
volumes: volumes:
- whisper-cache:/root/.cache/huggingface - whisper-cache:/root/.cache/huggingface
+17
View File
@@ -0,0 +1,17 @@
# Homarr — startdashboard (poort 4755).
# Configs: configs/homarr/ → /app/data/configs
services:
homarr:
image: ghcr.io/ajnart/homarr:latest
container_name: homarr
restart: always
ports:
- "${HOMARR_PORT:-4755}:7575"
environment:
TZ: ${TZ:-Europe/Brussels}
volumes:
- ${HOMARR_CONFIG_DIR:-/volume1/docker/homarr}:/app/data/configs
- ${HOMARR_ICONS_DIR:-/volume1/docker/homarr/icons}:/app/public/icons
- ${HOMARR_DATA_DIR:-/volume1/docker/homarr/data}:/data
- /var/run/docker.sock:/var/run/docker.sock
+15
View File
@@ -0,0 +1,15 @@
# Homelab Command
Applicatiecode en monitoring-build staan in een aparte repo:
- **Gitea:** http://192.168.1.211:3000/mo/homelab-command
- **NAS-pad:** `/volume1/homes/mo/homelab-command`
```bash
git clone http://192.168.1.211:3000/mo/homelab-command.git /volume1/homes/mo/homelab-command
cd /volume1/homes/mo/homelab-command
cp .env.example .env # vul in
docker compose -f docker-compose.homelab.yml up -d --build
```
Zie ook `docker/monitoring/` in homelab-configs voor Prometheus/Grafana compose.
+16
View File
@@ -0,0 +1,16 @@
# Monitoring (Prometheus + Grafana + postgres-exporter)
Prometheus-config staat in deze map. **Grafana-image** en dashboards bouw je vanuit [homelab-command](http://192.168.1.211:3000/mo/homelab-command):
```bash
cd /volume1/homes/mo/homelab-command
export PG_PASSWORD='...'
export GRAFANA_ADMIN_PASSWORD='...'
docker build -f Dockerfile.grafana -t grafana-homelab:latest .
docker compose -f docker-compose.grafana.yml up -d
# of: sh scripts/recreate_monitoring_docker.sh
```
Na start: `docker network create homelab-monitor` en verbind postgres-homelab, neo4j, prometheus, exporter, grafana.
Mesh (NATS + normalizer): `docker compose -f docker-compose.mesh.yml --env-file .env up -d` in homelab-command.
@@ -0,0 +1,77 @@
# Grafana — aparte stack (projectmap: homelab-command).
#
# Start (vanuit deze map):
# export PG_PASSWORD='jouw_postgres_wachtwoord'
# docker compose -f docker-compose.grafana.yml up -d --build
#
# UI: http://<NAS-IP>:3002 (standaard host-poort; 3001 was bezet op deze host)
# login: admin / GRAFANA_ADMIN_PASSWORD
#
# Vereist: postgres container heet postgres-homelab en luistert intern op 5432.
# Eénmalig (DNS tussen Prometheus en postgres-exporter op Synology bridge):
# sh scripts/docker_monitoring_join.sh homelab-monitor
# Daarna: docker network connect homelab-monitor postgres-homelab # als exporter DB niet bereikt
#
# Dashboards (Grafana.com IDs): PostgreSQL 9628, Proxmox 10347, Neo4j 10371,
# Synology overview 14364, Node Exporter 1860 — onder folder "Infrastructure".
# Prometheus scrape: postgres-exporter + optioneel Neo4j :2004 / Proxmox via targets/extra.yml.
services:
prometheus:
image: prom/prometheus:v2.53.2
container_name: prometheus-homelab
restart: unless-stopped
ports:
- "${PROMETHEUS_PORT:-9090}:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/targets:/etc/prometheus/targets:ro
- prometheus-homelab-data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --web.enable-lifecycle
networks:
- homelab-monitor
postgres-exporter:
image: prometheuscommunity/postgres-exporter:latest
container_name: postgres-exporter-homelab
restart: unless-stopped
ports:
- "${POSTGRES_EXPORTER_PORT:-9187}:9187"
environment:
DATA_SOURCE_NAME: "postgresql://${PG_USER:-mo}:${PG_PASSWORD}@postgres-homelab:5432/${PG_DATABASE:-homelab}?sslmode=disable"
networks:
- homelab-monitor
grafana:
# Bouw image vanuit homelab-command repo (zie docker/monitoring/README.md)
image: grafana-homelab:latest
container_name: grafana-homelab
restart: unless-stopped
ports:
- "${GRAFANA_PORT:-3002}:3000"
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-changeme_grafana}
GF_USERS_DEFAULT_THEME: dark
GF_SERVER_ROOT_URL: ${GRAFANA_ROOT_URL:-http://localhost:3002}
PG_USER: ${PG_USER:-mo}
PG_DATABASE: ${PG_DATABASE:-homelab}
HOMELAB_PG_PASSWORD: ${PG_PASSWORD:-}
volumes:
- grafana-homelab-data:/var/lib/grafana
# Grafana provisioning/dashboards: clone homelab-command en mount paden daar
depends_on:
- prometheus
networks:
- homelab-monitor
volumes:
grafana-homelab-data:
prometheus-homelab-data:
networks:
homelab-monitor:
driver: bridge
+31
View File
@@ -0,0 +1,31 @@
# Security Mesh stack — NATS + Go-normalizer (Zeek/Suricata JSON → Postgres).
# Start vanuit homelab-command: docker compose -f docker-compose.mesh.yml --env-file .env.mesh up -d
# Stop bestaande NATS op poort 4222 of wijzig poorten hieronder.
services:
nats:
image: nats:2.10-alpine
command: ["-js", "-m", "8222"]
ports:
- "${NATS_CLIENT_PORT:-4222}:4222"
- "${NATS_HTTP_PORT:-8222}:8222"
restart: unless-stopped
mesh-normalizer:
image: mesh-normalizer:local
build:
context: ./mesh-ingest
dockerfile: Dockerfile
environment:
NATS_URL: nats://nats:4222
MESH_DEFAULT_TENANT_ID: ${MESH_DEFAULT_TENANT_ID:-00000000-0000-4000-8000-000000000001}
PG_HOST: ${PG_HOST:-172.17.0.1}
PG_PORT: ${PG_PORT:-5433}
PG_USER: ${PG_USER:-mo}
PG_PASSWORD: ${PG_PASSWORD:-}
PG_DATABASE: ${PG_DATABASE:-homelab}
depends_on:
- nats
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
+44
View File
@@ -0,0 +1,44 @@
# Prometheus — scrape targets op Docker bridge (naast postgres-homelab, neo4j, …).
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
- job_name: postgres-exporter
static_configs:
- targets: ["postgres-exporter-homelab:9187"]
labels:
instance: postgres-homelab
# Neo4j 4.4+ enterprise metrics.prometheus.enabled → endpoint op poort 2004
- job_name: neo4j
scrape_interval: 30s
metrics_path: /metrics
static_configs:
- targets: ["neo4j:2004"]
labels:
instance: neo4j
# Proxmox VE — prometheus-pve-exporter; vul monitoring/prometheus/targets/extra.yml
- job_name: proxmox-pve
scrape_interval: 30s
file_sd_configs:
- files:
- /etc/prometheus/targets/extra.yml
refresh_interval: 1m
# Synology / SNMP: zet targets in monitoring/prometheus/targets/snmp.yml en uncomment hieronder.
# - job_name: snmp
# scrape_interval: 60s
# metrics_path: /snmp
# params:
# module: [synology]
# static_configs:
# - targets:
# - 192.168.1.211
# labels:
# job: snmp-nas
@@ -0,0 +1,9 @@
# Voeg hier scrape-targets toe (YAML array van scrape_configs entries wordt NIET ondersteund —
# dit bestand is voor **file_sd** formaat: lijst van static_configs targets).
#
# Voorbeeld Proxmox (prometheus-pve-exporter op host of VM):
# - targets:
# - '192.168.1.10:9221'
# labels:
# instance: pve
[]
@@ -0,0 +1,7 @@
# Hernoem naar extra.yml of merge handmatig. Formaat: lijst van static config groepen.
#
# Proxmox VE exporter (github.com/prometheus-pve/prometheus-pve-exporter):
- targets:
- "192.168.1.50:9221"
labels:
instance: proxmox
@@ -0,0 +1,2 @@
# SNMP exporter targets (Synology via snmp_exporter). Leeg = geen scrapes.
[]
@@ -0,0 +1,5 @@
# snmp_exporter (poort 9116) die naar je Synology SNMP wijst.
- targets:
- "snmp-exporter:9116"
labels:
job: synology
+16
View File
@@ -0,0 +1,16 @@
# Neo4j — graph database (bolt 49153, browser 49154/49155).
# Data: /volume1/docker/neo4j
services:
neo4j:
image: neo4j:latest
container_name: neo4j
restart: unless-stopped
ports:
- "${NEO4J_BOLT_PORT:-49153}:7687"
- "${NEO4J_HTTP_PORT:-49154}:7474"
- "${NEO4J_HTTPS_PORT:-49155}:7473"
environment:
NEO4J_AUTH: ${NEO4J_AUTH:-neo4j/changeme}
volumes:
- ${NEO4J_DATA_DIR:-/volume1/docker/neo4j}:/data
+13
View File
@@ -0,0 +1,13 @@
# Portainer CE — Docker UI (poorten 8000, 9000).
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
ports:
- "${PORTAINER_EDGE:-8000}:8000"
- "${PORTAINER_HTTP:-9000}:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${PORTAINER_DATA_DIR:-/volume1/docker/portainer}:/data
+1 -1
View File
@@ -18,7 +18,7 @@ services:
environment: environment:
# Standaard inlog voor de web UI # Standaard inlog voor de web UI
- PGADMIN_DEFAULT_EMAIL=mo@el-kadi.nl - PGADMIN_DEFAULT_EMAIL=mo@el-kadi.nl
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD:-WaQTUw2t} - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD:?Zet PGADMIN_PASSWORD in .env}
# Masquerade root URL voor nginx reverse proxy # Masquerade root URL voor nginx reverse proxy
- PGADMIN_CONFIG_SERVER_MODE=True - PGADMIN_CONFIG_SERVER_MODE=True
- PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False
+1 -1
View File
@@ -7,7 +7,7 @@
"Port": 5433, "Port": 5433,
"MaintenanceDB": "homelab", "MaintenanceDB": "homelab",
"Username": "mo", "Username": "mo",
"Password": "WaQTUw2t", "Password": "",
"SSLMode": "prefer", "SSLMode": "prefer",
"PassFile": "", "PassFile": "",
"SSLCert": "", "SSLCert": "",
+15
View File
@@ -0,0 +1,15 @@
{
"Servers": {
"1": {
"Name": "Homelab PostgreSQL",
"Group": "Servers",
"Host": "192.168.1.211",
"Port": 5433,
"MaintenanceDB": "homelab",
"Username": "mo",
"Password": "VUL_IN_PGADMIN_UI",
"SSLMode": "prefer",
"Comment": "Synology NAS — Homelab dashboard database"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
POSTGRES_USER=mo
POSTGRES_PASSWORD=changeme
POSTGRES_DB=homelab
PG_HOST_PORT=5433
PG_DATA_DIR=/volume1/docker/postgres/data
+17
View File
@@ -0,0 +1,17 @@
# PostgreSQL — centrale homelab-database (poort 5433 op host).
# NAS-pad: /volume1/docker/postgres/
# Start: cp .env.example .env && docker compose up -d
services:
postgres-homelab:
image: postgres:16-alpine
container_name: postgres-homelab
restart: unless-stopped
ports:
- "${PG_HOST_PORT:-5433}:5432"
environment:
POSTGRES_USER: ${POSTGRES_USER:-mo}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Zet POSTGRES_PASSWORD in .env}
POSTGRES_DB: ${POSTGRES_DB:-homelab}
volumes:
- ${PG_DATA_DIR:-/volume1/docker/postgres/data}:/var/lib/postgresql/data
+11
View File
@@ -0,0 +1,11 @@
# Remotely — remote support (poort 8080).
services:
remotely:
image: immybot/remotely:latest
container_name: remotely
restart: always
ports:
- "${REMOTELY_PORT:-8080}:8080"
volumes:
- ${REMOTELY_CONFIG_DIR:-/volume1/docker/remotely}:/config
+38
View File
@@ -0,0 +1,38 @@
#!/bin/sh
# Kopieer actuele NAS-configs naar deze git-repo (draai vóór commit).
set -e
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
NAS_DOCKER="${NAS_DOCKER:-/volume1/docker}"
NAS_HOMELAB="${NAS_HOMELAB:-/volume1/homes/mo/homelab-command}"
echo "Sync → $ROOT"
# Homarr dashboards
mkdir -p "$ROOT/configs/homarr"
cp -f "$NAS_DOCKER/homarr"/*.json "$ROOT/configs/homarr/" 2>/dev/null || true
# AdGuard (config zit vaak in container; export als map leeg is)
mkdir -p "$ROOT/configs/adguard"
if docker ps --format '{{.Names}}' | grep -qx Adguard; then
docker cp Adguard:/opt/adguardhome/conf/AdGuardHome.yaml "$ROOT/configs/adguard/AdGuardHome.yaml"
fi
# Prometheus targets + compose bron
if [ -d "$NAS_HOMELAB/monitoring" ]; then
cp -f "$NAS_HOMELAB/monitoring/prometheus.yml" "$ROOT/docker/monitoring/"
cp -rf "$NAS_HOMELAB/monitoring/prometheus/targets/"* "$ROOT/docker/monitoring/prometheus/targets/" 2>/dev/null || true
cp -f "$NAS_HOMELAB/docker-compose.grafana.yml" "$ROOT/docker/monitoring/"
cp -f "$NAS_HOMELAB/docker-compose.mesh.yml" "$ROOT/docker/monitoring/"
fi
# Live compose uit docker-mappen (bron van waarheid op NAS)
for svc in gitea postgres-web excalidraw guacamole wazuh ha-voice-control; do
src="$NAS_DOCKER/$svc/docker-compose.yml"
dst="$ROOT/docker/$svc/docker-compose.yml"
if [ -f "$src" ]; then
mkdir -p "$(dirname "$dst")"
cp -f "$src" "$dst"
fi
done
echo "Klaar. Controleer: git status && git diff"