Hardware per locatie Netwerk
📦 Meterkast
| Apparaat | Functie | VLAN | IP | Voeding |
| KPN Glasvezelkast | ISP modem/ONT | — | — | 230V |
| UCG-Ultra | Router, firewall, UniFi controller | Mgmt | 10.2.1.1 | 230V |
| USW Lite 8 PoE | Meterkast hoofdswitch | Trunk | 10.2.1.2 | 230V |
| HA NUC (primair) | Home Assistant primair | VLAN 21 | 10.2.21.10 | 230V |
| HA Yellow (failover) | HA warm-standby | VLAN 21 | 10.2.21.11 | USB-C |
| SLZB-06 #1 (Zigbee/Thread) | Zigbee2MQTT coordinator #1 | VLAN 21 | 10.2.21.12 | USB-C |
| SLZB-06 #2 (Zigbee/Thread) | Zigbee2MQTT coordinator #2 | VLAN 21 | 10.2.21.13 | USB-C |
| Hue Hub Pro | Philips Hue verlichting | VLAN 107 | 10.2.107.10 | 230V |
| Somfy TaHoma Switch | Rolluiken & zonwering | VLAN 107 | 10.2.107.14 | 230V |
| Aqara Hub M2 | Zigbee + IR hub | VLAN 107 | 10.2.107.15 | 230V |
| G400 Doorbell (PoE) | UniFi deurbel camera | VLAN 40 | 10.2.40.10 | PoE |
| USW Flex Mini (sub-switch) | Extra poorten voor hubs | Trunk | 10.2.1.5 | PoE |
🛋️ Woonkamer
| Apparaat | Functie | VLAN | IP | Voeding |
| U7 Pro WiFi 7 | Access point tri-band | Trunk | 10.2.1.4 | PoE+ |
| Samsung TV | Smart TV, Plex client | VLAN 30 | 10.2.30.20 | 230V |
| Google Hub(s) | HA passief dashboard | VLAN 107 | 10.2.107.11/12 | 230V |
🔧 Hobbykamer
| Apparaat | Functie | VLAN | IP | Voeding |
| Switch Ultra 42W | Hobbykamer switch + PoE | Trunk | 10.2.1.3 | 230V |
| Minisforum UM890 Pro (HumLab) | Docker stack, Plex, Frigate | VLAN 30 | 10.2.30.10 | 230V |
| Buitencamera (outdoor) | Achtertuin / zijkant | VLAN 40 | 10.2.40.11 | PoE |
VLAN schema
| VLAN | Naam | Subnet | DHCP pool | DNS | WiFi SSID |
| 1 | Mgmt | 10.2.1.0/24 | geen DHCP | — | — |
| 21 | Trusted | 10.2.21.0/24 | .100–.199 | 10.2.30.10 | WiFi4Home |
| 30 | Media | 10.2.30.0/24 | .100–.199 | 10.2.30.10 | WiFi4Media |
| 40 | Camera | 10.2.40.0/24 | .100–.129 | 1.1.1.1 | — |
| 107 | IoT | 10.2.107.0/24 | .100–.250 | 10.2.30.10 | IoT-Net |
| 161 | Gasten | 10.2.161.0/24 | .100–.250 | 1.1.1.1 | Gasten |
VLAN 1 (Management) heeft geen DHCP. UniFi-apparaten krijgen hun management-IP automatisch via het UniFi Inform-mechanisme.
Switch configuratie — USW Lite 8 PoE (Meterkast)
| Poort | Aangesloten | VLAN profiel | PoE | Opmerking |
| P1 | UCG-Ultra (uplink) | Trunk — alle VLANs | UIT | Uplink naar router |
| P2 | U7 Pro WiFi 7 | Trunk — alle WiFi VLANs | PoE+ (~13W) | AP woonkamer |
| P3 | Switch Ultra 42W (hobbykamer) | Trunk | UIT | Cascade naar hobbykamer |
| P4 | HA NUC (primair) | VLAN 21 untagged | UIT | Vaste IP 10.2.21.10 |
| P5 | HA Yellow (failover) | VLAN 21 untagged | UIT! | USB-C voeding — PoE ALTIJD UIT |
| P6 | G400 Doorbell Camera | VLAN 40 untagged | PoE+ (~15W) | Deurbel camera voordeur |
| P7 | USW Flex Mini (sub-switch hubs) | Trunk | PoE (~5W) | Hue Pro + Somfy + Aqara + SLZB |
| P8 | Reserve | — | — | PoE beschikbaar |
PoE budget: P2 13W + P6 15W + P7 5W = 33W van 52W totaal ✓
USW Flex Mini poortindeling (aan P7)
| Poort | Aangesloten | VLAN | Opmerking |
| FM-P1 | SLZB-06 #1 | VLAN 21 untagged | USB-C gevoed, data via eth |
| FM-P2 | SLZB-06 #2 | VLAN 21 untagged | USB-C gevoed |
| FM-P3 | Hue Hub Pro | VLAN 107 untagged | Smart verlichting |
| FM-P4 | Somfy TaHoma Switch | VLAN 107 untagged | Rolluiken |
| FM-P5 | Aqara Hub M2 | VLAN 107 untagged | Zigbee + IR |
HA Yellow: PoE ALTIJD uitschakelen op P5. De Yellow heeft geen 802.3af/at bescherming op de ethernet poort — PoE spanning beschadigt het apparaat.
Switch configuratie — Switch Ultra 42W (Hobbykamer)
| Poort | Aangesloten | VLAN profiel | PoE | Opmerking |
| P1 | USW Lite 8 PoE (uplink) | Trunk | UIT | Uplink naar meterkast |
| P2 | HumLab Minisforum UM890 Pro | VLAN 30 untagged | UIT | 2.5 GbE — vaste IP 10.2.30.10 |
| P3 | Buitencamera (outdoor) | VLAN 40 untagged | PoE (~15W) | Achtertuin/zijkant camera |
| P4–P8 | Reserve | — | PoE beschikbaar | Max 42W totaal |
Switch Ultra 42W heeft 8 PoE-poorten maar max 42W totaal budget. Met de buitencamera op ~15W blijft er 27W over voor eventuele toekomstige PoE-apparaten in de hobbykamer.
DHCP pools instellen in UniFi
Ga naar Settings → Networks → [VLAN naam] → DHCP
| VLAN | Start IP | End IP | Lease | DNS server | Opmerking |
| VLAN 21 Trusted | 10.2.21.100 | 10.2.21.199 | 24u | 10.2.30.10 | AdGuard DNS |
| VLAN 30 Media | 10.2.30.100 | 10.2.30.199 | 24u | 10.2.30.10 | AdGuard DNS |
| VLAN 40 Camera | 10.2.40.100 | 10.2.40.129 | 12u | 1.1.1.1 | Geen AdGuard nodig |
| VLAN 107 IoT | 10.2.107.100 | 10.2.107.250 | 12u | 10.2.30.10 | AdGuard filtert telemetrie |
| VLAN 161 Gasten | 10.2.161.100 | 10.2.161.250 | 2u | 1.1.1.1 | Nooit intern DNS! |
Gasten (VLAN 161) krijgen NOOIT 10.2.30.10 als DNS. Ze zouden anders interne hostnamen kunnen queryen. Gebruik altijd 1.1.1.1 of 8.8.8.8.
IP Reserveringen (MAC binding in UniFi)
Ga naar UniFi → Clients → [apparaat] → Fixed IP
VLAN 21 — Trusted
| IP | Apparaat | Prioriteit |
| 10.2.21.10 | HA NUC (primair) | 🔴 Kritiek |
| 10.2.21.11 | HA Yellow (failover) | 🔴 Kritiek |
| 10.2.21.12 | SLZB-06 #1 | 🟡 Aanbevolen |
| 10.2.21.13 | SLZB-06 #2 | 🟡 Aanbevolen |
| 10.2.21.20 | HA Voice PE | 🟡 Aanbevolen |
| 10.2.21.30 | Laptop Alwin | Optioneel |
VLAN 30 — Media
| IP | Apparaat | Prioriteit |
| 10.2.30.10 | HumLab Minisforum UM890 Pro | 🔴 Kritiek — nooit wijzigen |
| 10.2.30.20 | Samsung TV | 🟡 Aanbevolen (Wake-on-LAN) |
VLAN 40 — Camera
| IP | Apparaat | Prioriteit |
| 10.2.40.10 | G400 Doorbell Camera | 🔴 Kritiek (Frigate RTSP) |
| 10.2.40.11 | Buitencamera (outdoor) | 🔴 Kritiek (Frigate RTSP) |
VLAN 107 — IoT
| IP | Apparaat | Prioriteit |
| 10.2.107.10 | Hue Hub Pro | 🟡 Aanbevolen |
| 10.2.107.11 | Google Hub Keuken | 🟡 Aanbevolen |
| 10.2.107.12 | Google Hub Woonkamer | 🟡 Aanbevolen |
| 10.2.107.14 | Somfy TaHoma Switch | 🟡 Aanbevolen |
| 10.2.107.15 | Aqara Hub M2 | 🟡 Aanbevolen |
VLAN 1 — Management
| IP | Apparaat |
| 10.2.1.1 | UCG-Ultra (gateway) |
| 10.2.1.2 | USW Lite 8 PoE (meterkast) |
| 10.2.1.3 | Switch Ultra 42W (hobbykamer) |
| 10.2.1.4 | U7 Pro WiFi 7 |
| 10.2.1.5 | USW Flex Mini |
Firewall rules (LAN-In, volgorde belangrijk)
| # | Actie | Bron | Doel | Poort |
| 1 | ALLOW | Alle VLANs | — | established/related |
| 2 | ALLOW | 10.2.21.10 (HA NUC) | 10.2.30.10 (HumLab) | 1883 (MQTT) |
| 3 | ALLOW | 10.2.21.10 (HA NUC) | 10.2.30.10 (HumLab) | 5000 (Frigate) |
| 4 | ALLOW | 10.2.21.10 (HA NUC) | VLAN 107 (IoT) | 8008–8009 (Cast) |
| 5 | ALLOW | 10.2.21.10 (HA NUC) | 10.2.107.10 (Hue Pro) | 80/443 |
| 6 | ALLOW | 10.2.21.12/13 (SLZB) | 10.2.21.10 (HA NUC) | 8123 |
| 7 | ALLOW | 10.2.30.10 (Frigate) | VLAN 40 (Camera) | 554 (RTSP) |
| 8 | ALLOW | VLAN 21 | 10.2.30.10 | 32400 (Plex) |
| 9 | DROP | VLAN 107 (IoT) | 10.2.1.0/24 + 10.2.21.0/24 | Alles |
| 10 | DROP | VLAN 40 (Camera) | 10.2.21.0/24 | Alles |
| 11 | DROP | VLAN 161 (Gasten) | 10.2.0.0/16 | Alles |
mDNS inschakelen: Settings → Security → Advanced → Multicast DNS → AAN voor alle VLANs. Hierdoor werkt Google Cast over VLAN-grenzen.
Smart Home Hubs overzicht Hubs
| Hub | Protocol | VLAN | IP | HA integratie |
| Hue Hub Pro | Zigbee (Hue) | 107 | 10.2.107.10 | Philips Hue (native) |
| SLZB-06 #1 | Zigbee / Thread over Ethernet | 21 | 10.2.21.12 | Zigbee2MQTT of ZHA |
| SLZB-06 #2 | Zigbee / Thread over Ethernet | 21 | 10.2.21.13 | Zigbee2MQTT of ZHA |
| Somfy TaHoma Switch | RTS/io-homecontrol | 107 | 10.2.107.14 | Overkiz / TaHoma (HACS) |
| Aqara Hub M2 | Zigbee + IR | 107 | 10.2.107.15 | Xiaomi Miot (HACS) |
SMLIGHT SLZB-06 configuratie
De SLZB-06 is een Zigbee/Thread coordinator die via ethernet communiceert. Verbind met het webinterface op het toegewezen IP.
Stap 1 — Webinterface openen
http://10.2.21.12 # SLZB-06 #1
http://10.2.21.13 # SLZB-06 #2
Stap 2 — Zigbee2MQTT toevoegen aan docker-compose.yml
zigbee2mqtt:
image: koenkk/zigbee2mqtt:latest
container_name: zigbee2mqtt
restart: unless-stopped
ports:
- "8099:8080"
volumes:
- /opt/humlab/zigbee2mqtt:/app/data
environment:
- TZ=Europe/Amsterdam
Stap 3 — Zigbee2MQTT configuratie
homeassistant: true
permit_join: false
mqtt:
base_topic: zigbee2mqtt
server: mqtt://10.2.30.10:1883
serial:
port: tcp://10.2.21.12:6638 # SLZB-06 #1
adapter: ember # voor Thread/Matter
frontend:
port: 8080
advanced:
log_level: info
Gebruik poort 6638 voor Zigbee en 6639 voor Thread op de SLZB-06. Check de exacte poort in het SLZB-06 webinterface onder "Serial settings".
HA Yellow — Failover setup
PoE ALTIJD uitgeschakeld op de switchpoort van de HA Yellow! Gebruik uitsluitend de meegeleverde USB-C voedingsadapter.
Failover workflow
- HA NUC (10.2.21.10) valt uit
- Open browser → ga naar http://10.2.21.11:8123
- HA Yellow heeft identieke config (gesynchroniseerd via backup)
- Herstel indien nodig de laatste backup van de NUC op de Yellow
Wekelijkse backup synchronisatie (cron op NUC)
# In Home Assistant: Settings → Add-ons → Google Drive Backup
# Of via de ingebouwde backup-scheduler:
# Settings → System → Backups → Schedule: dagelijks
# Bewaar: 7 kopieën
🚀 Script installatie HumLab
Twee methodes: handmatig stap-voor-stap (de secties hieronder) of via een GitHub-script dat alles doet en alleen vraagt wat jij uniek hebt (UUIDs, wachtwoorden, claim-token).
Optie A — Handmatig (cut & paste)
Volg de secties hieronder één voor één. Elke codeblok heeft een kopieerknop. Meest controle, geschikt voor eerste kennismaking of gedeeltelijke herinstallatie.
Optie B — GitHub installatiescript (alles-in-één)
Voer dit uit op een verse Ubuntu Server installatie als root of met sudo. Het script vraagt interactief om jouw specifieke gegevens en past alles aan voor je uitvoert.
bash <(curl -fsSL https://raw.githubusercontent.com/AlwinHummels/humlab/main/setup/humlab-setup.sh)
Het script vraagt om de volgende gegevens — houd ze bij de hand:
| Gegeven | Voorbeeld | Waar te vinden |
| Ubuntu gebruikersnaam | alwin | Ingesteld tijdens OS-installatie |
| UUID schijf 1 | a1b2c3d4-... | sudo blkid na schijven aansluiten |
| UUID schijf 2 | e5f6g7h8-... | idem |
| UUID schijf 3 | i9j0k1l2-... | idem |
| Plex claim token | claim-XXXXXXX | plex.tv/claim (geldig 4 min) |
| MQTT wachtwoord | MqttGeheim123 | Zelf kiezen — ook invoeren in HA |
| Frigate RTSP camera URL | rtsp://10.2.40.x:554/stream | Camera-configuratiepagina |
Wat het script doet
| Stap | Actie |
| 1 | Systeem updaten + headless tools installeren (mesa-va-drivers, vainfo, ssh) |
| 2 | Slaapstand permanent uitschakelen via systemctl mask |
| 3 | SSH activeren + Docker installeren + autostart inschakelen |
| 4 | Coral TPU drivers installeren |
| 5 | MergerFS installeren + fstab schrijven met ingevoerde UUIDs |
| 6 | Directory structuur aanmaken (/opt/humlab, /mnt/storage/...) |
| 7 | docker-compose.yml genereren met jouw Plex claim + MQTT wachtwoord |
| 8 | Mosquitto config schrijven |
| 9 | docker compose up -d starten |
| 10 | Samenvatting met alle service-URLs printen |
Partial run mogelijk: het script detecteert al uitgevoerde stappen en slaat ze over. Je kunt het dus opnieuw draaien na een onderbreking.
Ubuntu Server — Basisinstallatie HumLab
HumLab (Minisforum UM890 Pro) staat in de hobbykamer. Verbonden via Switch Ultra 42W poort P2, bedraad 2.5 GbE, VLAN 30, IP 10.2.30.10. Draait Ubuntu Server — geen desktop nodig, alles via SSH + web UIs. VAAPI/GPU werkt headless via kernel-drivers.
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git htop usbutils lm-sensors \
mesa-va-drivers libva-drm2 vainfo
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
# Verificatie — verwacht: "masked" voor elk target
sudo systemctl status sleep.target | grep -i masked
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
# Kopieer je SSH-key vanaf je laptop (eenmalig):
# ssh-copy-id alwin@10.2.30.10
# Verificatie:
sudo systemctl status ssh | grep -i active
sudo systemctl enable docker
sudo systemctl enable containerd
# Docker start nu automatisch na herstart — zonder GUI of inlogprompt
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | \
sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt update && sudo apt install -y libedgetpu1-std
# Verificatie:
lsusb | grep -i google # verwacht: "Global Unichip" of "Google LLC"
vainfo 2>&1 | grep VAProfile # verwacht: H264, HEVC, AV1
ls /dev/dri/ # verwacht: card0, renderD128
VAAPI werkt volledig headless — de AMD Radeon 780M drijft op kernel-drivers (amdgpu), niet op de desktopstack. Mesa + libva-drm2 zijn voldoende voor Frigate en Plex transcoding.
MergerFS opslag (3× 4TB USB-C SSD = 12TB)
Gebruik ALTIJD UUID= in fstab voor USB-schijven. /dev/sdb etc. kunnen wisselen bij herstart en dan mount je verkeerde schijven!
sudo apt install -y mergerfs
sudo mkdir -p /mnt/disk1 /mnt/disk2 /mnt/disk3 /mnt/storage
sudo mkdir -p /mnt/storage/{media/{films,series},downloads/{complete,incomplete},backups,frigate}
sudo blkid | grep -E "sd[b-z]"
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /mnt/disk1 ext4 defaults,nofail,x-systemd.device-timeout=30 0 2
UUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY /mnt/disk2 ext4 defaults,nofail,x-systemd.device-timeout=30 0 2
UUID=ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ /mnt/disk3 ext4 defaults,nofail,x-systemd.device-timeout=30 0 2
/mnt/disk1:/mnt/disk2:/mnt/disk3 /mnt/storage fuse.mergerfs defaults,allow_other,use_ino,cache.files=off,moveonenospc=true,dropcacheonclose=true,category.create=mfs,nofail 0 0
sudo mount -a && df -h /mnt/storage # verwacht: ~12TB zichtbaar
Docker Engine installeren
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER && newgrp docker
sudo mkdir -p /opt/humlab/{adguard/{work,conf},mosquitto/{config,data,log},frigate/{config,media},zigbee2mqtt,plex/{config,transcode},prowlarr,sabnzbd,sonarr,radarr,bazarr,npm/{data,letsencrypt},homarr/{configs,data,icons},uptime-kuma,kavita,mealie,immich/{upload,model-cache},syncthing,paperless/{data,media,export,consume},scrutiny,ntfy,glances,restic/{config,cache}}
sudo chown -R $USER:$USER /opt/humlab
Docker Compose — volledige stack
Geen "version:" veld in docker-compose.yml — dit is deprecated in Docker Compose v2 (Docker 25+) en geeft een waarschuwing.
# /opt/humlab/docker-compose.yml
# Geen "version:" field — deprecated in Docker Compose v2
services:
adguard:
image: adguard/adguardhome:latest
container_name: adguard
restart: unless-stopped
network_mode: host
volumes:
- /opt/humlab/adguard/work:/opt/adguardhome/work
- /opt/humlab/adguard/conf:/opt/adguardhome/conf
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
- "9001:9001"
volumes:
- /opt/humlab/mosquitto/config:/mosquitto/config
- /opt/humlab/mosquitto/data:/mosquitto/data
- /opt/humlab/mosquitto/log:/mosquitto/log
zigbee2mqtt:
image: koenkk/zigbee2mqtt:latest
container_name: zigbee2mqtt
restart: unless-stopped
ports:
- "8099:8080"
volumes:
- /opt/humlab/zigbee2mqtt:/app/data
environment:
- TZ=Europe/Amsterdam
frigate:
image: ghcr.io/blakeblackshear/frigate:stable
container_name: frigate
privileged: true
restart: unless-stopped
shm_size: "256mb"
devices:
- /dev/dri/renderD128:/dev/dri/renderD128 # AMD VAAPI
- /dev/bus/usb:/dev/bus/usb # Coral USB TPU
volumes:
- /opt/humlab/frigate/config:/config
- /opt/humlab/frigate/media:/media/frigate
- /mnt/storage/frigate:/media/storage
- type: tmpfs
target: /tmp/cache
tmpfs:
size: 1000000000
ports:
- "5000:5000" # web UI
- "8554:8554" # RTSP
- "8555:8555/tcp"
- "8555:8555/udp"
environment:
FRIGATE_RTSP_PASSWORD: "jouw_rtsp_wachtwoord"
labels:
- "com.centurylinklabs.watchtower.enable=false"
plex:
image: lscr.io/linuxserver/plex:latest
container_name: plex
restart: unless-stopped
network_mode: host
devices:
- /dev/dri:/dev/dri # AMD VAAPI hardware transcoding
environment:
- PUID=1000
- PGID=1000
- VERSION=docker
- PLEX_CLAIM=claim-XXXXXX # éénmalig via plex.tv/claim
volumes:
- /opt/humlab/plex/config:/config
- /opt/humlab/plex/transcode:/transcode
- /mnt/storage/media:/data/media
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
restart: unless-stopped
ports:
- "9696:9696"
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/humlab/prowlarr:/config
sabnzbd:
image: lscr.io/linuxserver/sabnzbd:latest
container_name: sabnzbd
restart: unless-stopped
ports:
- "8080:8080"
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/humlab/sabnzbd:/config
- /mnt/storage/downloads:/downloads
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
restart: unless-stopped
ports:
- "8989:8989"
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/humlab/sonarr:/config
- /mnt/storage:/data
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
restart: unless-stopped
ports:
- "7878:7878"
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/humlab/radarr:/config
- /mnt/storage:/data
bazarr:
image: lscr.io/linuxserver/bazarr:latest
container_name: bazarr
restart: unless-stopped
ports:
- "6767:6767"
environment:
- PUID=1000
- PGID=1000
volumes:
- /opt/humlab/bazarr:/config
- /mnt/storage/media:/data/media
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
volumes:
- /opt/humlab/npm/data:/data
- /opt/humlab/npm/letsencrypt:/etc/letsencrypt
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 0 4 * * *
homarr:
image: ghcr.io/ajnart/homarr:latest
container_name: homarr
restart: unless-stopped
ports:
- "7575:7575"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/humlab/homarr/configs:/app/data/configs
- /opt/humlab/homarr/data:/data
- /opt/humlab/homarr/icons:/app/public/icons
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
restart: unless-stopped
ports:
- "3001:3001"
volumes:
- /opt/humlab/uptime-kuma:/app/data
# ── Kavita (ebooks + comics) ──────────────────────────────────
kavita:
image: jvmilazz0/kavita:latest
container_name: kavita
restart: unless-stopped
environment:
- TZ=Europe/Amsterdam
volumes:
- /opt/humlab/kavita:/kavita/config
- /mnt/storage/books:/books
ports:
- "8083:5000"
# ── Mealie (receptenbeheer) ───────────────────────────────────
mealie:
image: ghcr.io/mealie-recipes/mealie:latest
container_name: mealie
restart: unless-stopped
environment:
- TZ=Europe/Amsterdam
- PUID=1000
- PGID=1000
- MAX_WORKERS=1
- WEB_CONCURRENCY=1
volumes:
- /opt/humlab/mealie:/app/data
ports:
- "9000:9000"
# ── Immich (foto-opslag) ──────────────────────────────────────
immich-server:
image: ghcr.io/immich-app/immich-server:release
container_name: immich-server
restart: unless-stopped
environment:
- TZ=Europe/Amsterdam
- DB_HOSTNAME=immich-postgres
- DB_USERNAME=immich
- DB_PASSWORD=${IMMICH_DB_PASS}
- DB_DATABASE_NAME=immich
- REDIS_HOSTNAME=immich-redis
volumes:
- /opt/humlab/immich/upload:/usr/src/app/upload
ports:
- "2283:3001"
depends_on:
- immich-postgres
- immich-redis
immich-machine-learning:
image: ghcr.io/immich-app/immich-machine-learning:release
container_name: immich-ml
restart: unless-stopped
volumes:
- /opt/humlab/immich/model-cache:/cache
immich-postgres:
image: tensorchord/pgvecto-rs:pg14-v0.2.0
container_name: immich-postgres
restart: unless-stopped
environment:
- POSTGRES_USER=immich
- POSTGRES_PASSWORD=${IMMICH_DB_PASS}
- POSTGRES_DB=immich
volumes:
- /opt/humlab/immich/db:/var/lib/postgresql/data
immich-redis:
image: redis:6.2-alpine
container_name: immich-redis
restart: unless-stopped
# ── Syncthing (lokale bestandssync) ──────────────────────────
syncthing:
image: lscr.io/linuxserver/syncthing:latest
container_name: syncthing
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Amsterdam
volumes:
- /opt/humlab/syncthing:/config
- /mnt/storage/syncthing:/data
ports:
- "8384:8384"
- "22000:22000/tcp"
- "22000:22000/udp"
- "21027:21027/udp"
# ── Paperless-ngx (documentarchief) ──────────────────────────
paperless-broker:
image: redis:7-alpine
container_name: paperless-broker
restart: unless-stopped
volumes:
- /opt/humlab/paperless/redis:/data
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
depends_on:
- paperless-broker
environment:
- PAPERLESS_REDIS=redis://paperless-broker:6379
- PAPERLESS_OCR_LANGUAGE=nld+eng
- PAPERLESS_TIME_ZONE=Europe/Amsterdam
- PAPERLESS_SECRET_KEY=${PAPERLESS_SECRET}
volumes:
- /opt/humlab/paperless/data:/usr/src/paperless/data
- /opt/humlab/paperless/media:/usr/src/paperless/media
- /opt/humlab/paperless/export:/usr/src/paperless/export
- /opt/humlab/paperless/consume:/usr/src/paperless/consume
ports:
- "8000:8000"
# ── Scrutiny (SMART schijfmonitoring) ────────────────────────
scrutiny:
image: ghcr.io/analogj/scrutiny:master-omnibus
container_name: scrutiny
restart: unless-stopped
cap_add:
- SYS_RAWIO
privileged: true
volumes:
- /run/udev:/run/udev:ro
- /opt/humlab/scrutiny:/opt/scrutiny/config
ports:
- "8088:8080"
# ── Ntfy (push notificaties) ──────────────────────────────────
ntfy:
image: binwiederhier/ntfy:latest
container_name: ntfy
restart: unless-stopped
command: serve
environment:
- TZ=Europe/Amsterdam
volumes:
- /opt/humlab/ntfy:/var/lib/ntfy
ports:
- "8090:80"
# ── Glances (server monitoring) ──────────────────────────────
glances:
image: nicolargo/glances:latest
container_name: glances
restart: unless-stopped
pid: host
network_mode: host
environment:
- GLANCES_OPT=-w
- TZ=Europe/Amsterdam
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# ── Seerr (media request management) ────────────────────────
seerr:
image: ghcr.io/seerr-team/seerr:latest
container_name: seerr
restart: unless-stopped
environment:
- TZ=Europe/Amsterdam
- LOG_LEVEL=info
volumes:
- /opt/humlab/seerr:/app/config
ports:
- "5056:5055" # 5055 is bezet door ha-failover
cd /opt/humlab && docker compose up -d
docker compose ps # alles should show "running"
Lokale hostnamen — AdGuard + Nginx Proxy Manager
Met een wildcard DNS-rewrite in AdGuard en proxy hosts in NPM bereik je elke service op een nette hostnaam in plaats van IP:poort.
Stap 1 — AdGuard wildcard DNS rewrite
AdGuard Home → Filters → DNS rewrites → Add DNS rewrite:
| Domain | Answer | Opmerking |
*.humlab.local | 10.2.30.10 | Wildcard — dekt alle subdomains in één regel |
Apparaten moeten AdGuard als DNS-server gebruiken (via DHCP al ingesteld). De wildcard stuurt elk *.humlab.local verzoek naar de HumLab server, NPM handelt de rest af.
Stap 2 — Nginx Proxy Manager proxy hosts
NPM → http://10.2.30.10:81 → Proxy Hosts → Add Proxy Host. Gebruik onderstaande tabel. SSL niet nodig voor lokaal verkeer.
| Hostname | Forward Hostname | Forward Port | Opmerking |
adguard.humlab.local | 10.2.30.10 | 3000 | Host-network container |
plex.humlab.local | 10.2.30.10 | 32400 | Host-network container |
glances.humlab.local | 10.2.30.10 | 61208 | Host-network container |
frigate.humlab.local | frigate | 5000 | |
sonarr.humlab.local | sonarr | 8989 | |
radarr.humlab.local | radarr | 7878 | |
prowlarr.humlab.local | prowlarr | 9696 | |
bazarr.humlab.local | bazarr | 6767 | |
sabnzbd.humlab.local | sabnzbd | 8080 | |
homarr.humlab.local | homarr | 7575 | |
uptime.humlab.local | uptime-kuma | 3001 | |
seerr.humlab.local | seerr | 5055 | |
kavita.humlab.local | kavita | 5000 | |
mealie.humlab.local | mealie | 9000 | |
immich.humlab.local | immich-server | 3001 | |
syncthing.humlab.local | syncthing | 8384 | |
paperless.humlab.local | paperless | 8000 | |
scrutiny.humlab.local | scrutiny | 8080 | |
ntfy.humlab.local | ntfy | 80 | |
ha.humlab.local | 10.2.21.10 | 8123 | Beheerd door ha-failover (DNS rewrite) |
NPM draait in Docker bridge-mode en kan container-namen gebruiken als forward hostname — behalve voor host-network containers (AdGuard, Plex, Glances). Gebruik daarvoor het host-IP 10.2.30.10.
AdGuard Home — DNS blokkering
Doe dit EERST vóór je AdGuard start. Ubuntu gebruikt systemd-resolved op poort 53 — dat conflicteert met AdGuard.
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf
sudo chattr -i /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
sudo chattr +i /etc/resolv.conf
Setup: open http://10.2.30.10:3000 → wizard → listening interface: eth0, DNS poort: 53, upstream: 1.1.1.1 + 9.9.9.9
Aanbevolen blocklists (AdGuard → Filters → DNS blocklists)
| Naam | URL (plak in AdGuard) |
| AdGuard DNS filter | https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt |
| OISD (groot) | https://big.oisd.nl/domainswild |
| Steven Black hosts | https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts |
VPN — WireGuard via UCG-Ultra
De UCG-Ultra heeft ingebouwde WireGuard VPN-ondersteuning. Geen extra container nodig — alles wordt beheerd via de UniFi interface. Via VPN bereik je alle lokale services alsof je thuis bent.
WireGuard is sneller en lichter dan OpenVPN. De UCG-Ultra implementatie ondersteunt meerdere clients (telefoon, laptop, tablet) via QR-code of config-bestand.
VPN server instellen op de UCG-Ultra
| Stap | Actie |
| 1 | UniFi Network → Settings → Teleport & VPN → VPN Server |
| 2 | Klik Create New → kies WireGuard |
| 3 | Naam: HumLab VPN — poort: 51820 (UDP) |
| 4 | VPN subnet: 10.9.0.0/24 (apart van je VLANs) |
| 5 | DNS server: 10.2.30.10 (AdGuard — zodat *.humlab.local ook via VPN werkt) |
| 6 | Sla op → UniFi genereert automatisch server keys |
VPN client toevoegen (per apparaat)
| Stap | Actie |
| 1 | VPN Server → Add Client → naam bijv. Alwin iPhone |
| 2 | Klik op de client → QR-code verschijnt |
| 3 | Open WireGuard-app op telefoon/laptop → scan QR-code |
| 4 | Verbinding testen: schakel WiFi uit → activeer VPN → open http://adguard.humlab.local |
Firewall — poort 51820 UDP openzetten
UniFi doet dit automatisch bij het aanmaken van de VPN server. Controleer wel of je router/modem van je ISP poort 51820 UDP doorstuurt naar het WAN-IP van de UCG-Ultra — dit is nodig als de UCG-Ultra achter een modem zit (dubbel NAT).
# Op je telefoon/laptop met actieve VPN:
ping 10.2.30.10 # HumLab server bereikbaar?
curl http://10.2.30.10:3000 # AdGuard bereikbaar?
curl http://adguard.humlab.local # DNS via AdGuard werkend?
Dynamisch IP (geen vast WAN-IP)?
Gebruik DDNS zodat je VPN-client altijd het juiste adres heeft. UniFi Network → Settings → Internet → Dynamic DNS → provider bijv. dyndns of noip. Of gebruik de gratis Duck DNS dienst.
Mosquitto MQTT configuratie
Een lege mosquitto.conf start NIET — je moet minimaal listener en allow_anonymous definiëren.
listener 1883
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
mosquitto_sub -h 10.2.30.10 -t "#" -v & # subscribe op alles
mosquitto_pub -h 10.2.30.10 -t test -m "hallo" # publish test
Frigate NVR — config.yml
mqtt:
host: 10.2.30.10
port: 1883
detectors:
coral:
type: edgetpu
device: usb
ffmpeg:
hwaccel_args: preset-vaapi # AMD Radeon 780M
cameras:
voordeur:
ffmpeg:
inputs:
- path: rtsp://10.2.40.10:554/stream # G400 deurbel
roles: [detect, record]
detect:
width: 1920
height: 1080
fps: 5
record:
enabled: true
retain:
days: 14
mode: motion
achtertuin:
ffmpeg:
inputs:
- path: rtsp://10.2.40.11:554/stream # outdoor camera
roles: [detect, record]
detect:
width: 1920
height: 1080
fps: 5
record:
enabled: true
retain:
days: 7
mode: motion
lsusb | grep -i google # verwacht: "Google Inc. Coral USB"
docker logs frigate 2>&1 | grep -i "coral\|detector"
Plex Media Server — hardware transcoding
# In Plex Web UI (http://10.2.30.10:32400/web):
# Settings → Troubleshooting → Hardware-Accelerated Transcoding: AAN
# Settings → Transcoder → Hardware transcoding: enable
docker exec plex vainfo 2>&1 | head -20 # verwacht: VAProfileH264, HEVC
Backup strategie
#!/bin/bash
DATUM=$(date +%Y-%m-%d)
DEST="/mnt/storage/backups/humlab-$DATUM.tar.gz"
tar -czf "$DEST" /opt/humlab --exclude /opt/humlab/plex/transcode
# Verwijder backups ouder dan 7 dagen
find /mnt/storage/backups -name "humlab-*.tar.gz" -mtime +7 -delete
echo "Backup klaar: $DEST"
chmod +x /opt/humlab/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/humlab/backup.sh") | crontab -
SSID strategie & WiFi instellingen WiFi
| SSID | VLAN | Band | Beveiliging | Zichtbaar | Gebruik |
| WiFi4Home | 21 | 2.4 + 5 + 6 GHz | WPA3 | ✅ Ja | Telefoons, laptops, HA-apparaten |
| WiFi4Media | 30 | 2.4 + 5 GHz | WPA2/3 | 🔒 Verborgen | Chromecast, Smart TV |
| IoT-Net | 107 | 2.4 GHz only | WPA2 | 🔒 Verborgen | Google Hubs, sensoren, IoT |
| Gasten | 161 | 2.4 + 5 GHz | WPA2 | ✅ Ja | Bezoekers |
SSID verbergen: Settings → WiFi → [SSID] → Advanced → Hide SSID. Apparaten die al verbonden waren blijven verbonden — ze onthouden het netwerk.
IoT-Net: Fast Roaming UIT zetten! Veel IoT-apparaten (incl. Google Hubs) hebben problemen met 802.11r. DTIM period: 3 voor batterijbesparing.
mDNS & Cross-VLAN casting
Inschakelen: UniFi → Settings → Security → Advanced → Multicast DNS → AAN voor alle VLANs.
Google Cast benodigde poorten (firewall rule)
| Protocol | Poort(en) | Richting |
| TCP | 8008, 8009 | HA (VLAN 21) → Google Hub (VLAN 107) |
| UDP | 32768–61000 | Beide richtingen |
| UDP Multicast | 5353 | mDNS (verwerkt door UniFi proxy) |
Home Assistant automatisering — Google Hub dashboard HA
alias: "Google Hub Keuken: Permanent Dashboard"
description: "Houdt HA dashboard actief — herstart elke 9 min"
trigger:
- platform: time_pattern
minutes: "/9"
- platform: state
entity_id: media_player.google_hub_keuken
to: "idle"
- platform: homeassistant
event: start
condition: []
action:
- action: cast.show_lovelace_view
data:
dashboard_path: dashboard-hub
view_path: home
entity_id: media_player.google_hub_keuken
mode: restart
action:
- repeat:
for_each:
- media_player.google_hub_keuken
- media_player.google_hub_woonkamer
sequence:
- action: cast.show_lovelace_view
data:
dashboard_path: dashboard-hub
view_path: home
entity_id: "{{ repeat.item }}"
Filmmodus automatisering
alias: "Filmmodus activeren"
trigger:
- platform: conversation
command: "filmmodus"
action:
- service: media_player.turn_on
target:
entity_id: media_player.samsung_tv
- service: media_player.select_source
data:
source: "HDMI 1"
target:
entity_id: media_player.samsung_tv
- service: light.turn_off
target:
area_id: woonkamer
Frigate ↔ Home Assistant MQTT integratie
Stap 1 — MQTT integratie in HA
- Settings → Integrations → MQTT → Broker:
10.2.30.10, Poort: 1883
- Test verbinding → Save
- Frigate HACS integratie installeren: HACS → Integrations → "Frigate NVR Integration"
- Herstart HA → Settings → Integrations → Frigate → Host:
http://10.2.30.10:5000
alias: "Frigate: Persoon bij voordeur"
trigger:
- platform: mqtt
topic: frigate/voordeur/person
payload: "1"
action:
- service: notify.mobile_app_alwin
data:
title: "Beweging gedetecteerd"
message: "Persoon gezien bij de voordeur"
data:
url: /lovelace/cameras
image: /api/frigate/notifications/{{trigger.payload_json.id}}/snapshot.jpg
- service: notify.mobile_app_renate
data:
title: "Beweging voordeur"
message: "Iemand bij de voordeur"
Frigate MQTT topics overzicht
| Topic | Payload | Beschrijving |
frigate/events | JSON | Alle detectie-events |
frigate/voordeur/person | 0/1 | Persoon bij voordeur |
frigate/achtertuin/person | 0/1 | Persoon achtertuin |
frigate/stats | JSON | FPS, detectie statistieken |
Poorten & services quickref Referentie
| Service | Poort | IP | URL |
| UCG-Ultra (UniFi) | 443 | 10.2.1.1 | https://10.2.1.1 |
| Home Assistant (primair) | 8123 | 10.2.21.10 | http://10.2.21.10:8123 |
| Home Assistant (failover) | 8123 | 10.2.21.11 | http://10.2.21.11:8123 |
| SLZB-06 #1 (webUI) | 80 | 10.2.21.12 | http://10.2.21.12 |
| SLZB-06 #2 (webUI) | 80 | 10.2.21.13 | http://10.2.21.13 |
| AdGuard Home | 3000 | 10.2.30.10 | http://10.2.30.10:3000 |
| Mosquitto MQTT | 1883 | 10.2.30.10 | mqtt://10.2.30.10:1883 |
| Zigbee2MQTT | 8099 | 10.2.30.10 | http://10.2.30.10:8099 |
| Frigate NVR | 5000 | 10.2.30.10 | http://10.2.30.10:5000 |
| Plex Media Server | 32400 | 10.2.30.10 | http://10.2.30.10:32400/web |
| SABnzbd | 8080 | 10.2.30.10 | http://10.2.30.10:8080 |
| Sonarr | 8989 | 10.2.30.10 | http://10.2.30.10:8989 |
| Radarr | 7878 | 10.2.30.10 | http://10.2.30.10:7878 |
| Prowlarr | 9696 | 10.2.30.10 | http://10.2.30.10:9696 |
| Bazarr | 6767 | 10.2.30.10 | http://10.2.30.10:6767 |
| Nginx Proxy Manager | 81 | 10.2.30.10 | http://10.2.30.10:81 |
| Homarr dashboard | 7575 | 10.2.30.10 | http://10.2.30.10:7575 |
| Uptime Kuma | 3001 | 10.2.30.10 | http://10.2.30.10:3001 |
| Kavita | 8083 | 10.2.30.10 | http://10.2.30.10:8083 |
| Mealie | 9000 | 10.2.30.10 | http://10.2.30.10:9000 |
| Immich | 2283 | 10.2.30.10 | http://10.2.30.10:2283 |
| Syncthing | 8384 | 10.2.30.10 | http://10.2.30.10:8384 |
| Paperless-ngx | 8000 | 10.2.30.10 | http://10.2.30.10:8000 |
| Scrutiny | 8088 | 10.2.30.10 | http://10.2.30.10:8088 |
| Ntfy | 8090 | 10.2.30.10 | http://10.2.30.10:8090 |
| Glances | 61208 | 10.2.30.10 | http://10.2.30.10:61208 |
| Seerr | 5056 | 10.2.30.10 | http://10.2.30.10:5056 |
| Hue Hub Pro | 80/443 | 10.2.107.10 | http://10.2.107.10 |
| Somfy TaHoma Switch | 80 | 10.2.107.14 | http://10.2.107.14 |
| Aqara Hub M2 | 80 | 10.2.107.15 | http://10.2.107.15 |
Docker commando's quickref
cd /opt/humlab
docker compose up -d # start alle containers
docker compose down # stop alle containers
docker compose pull && docker compose up -d # update alle images
docker compose ps # status overzicht
docker compose logs -f frigate # live logs van één service
docker restart plex # herstart één container
docker image prune -f # verwijder ongebruikte images
docker stats # live CPU/geheugen gebruik
Systeemcommando's quickref
df -h /mnt/storage && df -h / # schijfruimte
mount | grep mergerfs # MergerFS status
lsusb | grep -i google # Coral TPU detectie
vainfo 2>&1 | grep VAProfile # GPU VAAPI check
sensors | grep -E "Tctl|Tdie|edge" # temperaturen
sudo blkid | grep -E "sd[b-z]" # USB-schijf UUIDs
sudo systemctl status sleep.target # slaapstand status