Adds initial repo structure for the internal network configuration
This commit is contained in:
parent
19e7194fa2
commit
375fddaab0
9 changed files with 445 additions and 0 deletions
10
README.md
10
README.md
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Infrastructure
|
||||||
|
|
||||||
|
Homelab network overhaul and homeserver setup — Omada-based networking, VLANs,
|
||||||
|
and Docker/Ansible-managed services.
|
||||||
|
|
||||||
|
- [docs/status.md](docs/status.md) — decisions and status
|
||||||
|
- [docs/todo.md](docs/todo.md) — live TODO checklist
|
||||||
|
- [docs/er605-firmware-update.md](docs/er605-firmware-update.md) — ER605 firmware update steps
|
||||||
|
- [docker/omada-controller/](docker/omada-controller/) — self-hosted Omada Software Controller (Docker)
|
||||||
|
- [docs/omada-controller-migration.md](docs/omada-controller-migration.md) — moving the controller from desktop to the NUC later
|
||||||
33
docker/npm/README.md
Normal file
33
docker/npm/README.md
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Nginx Proxy Manager (temporary, on the Synology)
|
||||||
|
|
||||||
|
Running here until the NUC homeserver exists — see
|
||||||
|
[../../docs/todo.md](../../docs/todo.md) for the full local-DNS + reverse-proxy
|
||||||
|
plan (Pi-hole/LAN DNS points internal hostnames at this box's IP; NPM routes
|
||||||
|
each hostname to the right backend service/port).
|
||||||
|
|
||||||
|
Deploy via Container Manager's **Project** feature (paste/import this
|
||||||
|
compose file — same as however Pi-hole was set up there) or over SSH with
|
||||||
|
`docker compose up -d` from this directory.
|
||||||
|
|
||||||
|
## Port note
|
||||||
|
|
||||||
|
Ports 80/443 are already taken on this Synology by DSM's own internal nginx
|
||||||
|
(`netstat -tulpn | grep :443` showed `nginx: worker` — likely Web Station or
|
||||||
|
the Login Portal's HTTP→HTTPS redirect feature); 8080/8443/81 turned out to
|
||||||
|
also already be in use by other running packages. Rather than chase down and
|
||||||
|
touch existing DSM config for a temporary deployment, NPM is remapped to
|
||||||
|
host ports **9080/9443/9081** instead — meaning proxied HTTPS URLs need an
|
||||||
|
explicit `:9443` and the admin UI is at `http://<synology-ip>:9081` until
|
||||||
|
this moves to the NUC, where a clean `80:80`/`443:443`/`81:81` mapping will
|
||||||
|
work with no conflict. Revert the compose file's `ports:` section at that
|
||||||
|
point.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- No MariaDB container — NPM's built-in SQLite database is enough for this
|
||||||
|
scale and keeps the footprint light on the DS223j's 1GB RAM.
|
||||||
|
- Admin UI: `http://<synology-ip>:81` — default login is `admin@example.com`
|
||||||
|
/ `changeme` on first run; change both immediately.
|
||||||
|
- TLS certs: plan is Let's Encrypt via DNS-01 using INWX's API (an `acme.sh`
|
||||||
|
plugin exists for this) once that part of the plan is implemented — see
|
||||||
|
[../../docs/todo.md](../../docs/todo.md).
|
||||||
24
docker/npm/docker-compose.yml
Normal file
24
docker/npm/docker-compose.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: nginx-proxy-manager
|
||||||
|
# Multi-arch tag — auto-selects the arm64 build on the Synology DS223j.
|
||||||
|
# Never set the DB_MYSQL_* / DB_SQLITE_* env vars unless you specifically
|
||||||
|
# want MariaDB — omitting them keeps NPM on its lightweight built-in
|
||||||
|
# SQLite database, no separate DB container needed.
|
||||||
|
image: 'jc21/nginx-proxy-manager:latest'
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
# Remapped off 80/443/81 — all three were already claimed on this
|
||||||
|
# Synology (DSM's own internal nginx plus other running packages).
|
||||||
|
# Temporary deployment only; revert to a clean 80:80/443:443/81:81
|
||||||
|
# once this moves to the NUC, which won't have that conflict.
|
||||||
|
- '9080:80' # HTTP, proxied traffic
|
||||||
|
- '9443:443' # HTTPS, proxied traffic
|
||||||
|
- '9081:81' # Admin UI
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
letsencrypt:
|
||||||
51
docker/omada-controller/README.md
Normal file
51
docker/omada-controller/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Omada Software Controller (temporary, on David's desktop)
|
||||||
|
|
||||||
|
Runs the self-hosted Omada Software Controller via the community-maintained
|
||||||
|
[`mbentley/omada-controller`](https://github.com/mbentley/docker-omada-controller)
|
||||||
|
image, avoiding TP-Link's cloud controller.
|
||||||
|
|
||||||
|
This instance is meant to be **temporary**: it runs on David's Linux desktop just
|
||||||
|
long enough to adopt the ER605 (and later the switch/AP) instead of leaving them
|
||||||
|
in standalone mode, then gets migrated to the NUC once that's provisioned — see
|
||||||
|
[../../docs/omada-controller-migration.md](../../docs/omada-controller-migration.md).
|
||||||
|
|
||||||
|
The desktop does not need to run 24/7. The ER605 keeps forwarding traffic on its
|
||||||
|
last-known config even if the controller is offline — you only lose live
|
||||||
|
management/statistics visibility while it's down.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker + Docker Compose installed on the desktop.
|
||||||
|
- ER605 firmware already updated — see [../../docs/er605-firmware-update.md](../../docs/er605-firmware-update.md). Do this first; it's harder once the device is controller-managed.
|
||||||
|
- Desktop and ER605 on the same L2 network segment (needed for adoption's broadcast discovery).
|
||||||
|
|
||||||
|
## Bring it up
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open `https://<desktop-ip>:8043` and walk through the initial setup wizard
|
||||||
|
(create the controller admin account, name the site, etc).
|
||||||
|
|
||||||
|
## Adopt the ER605
|
||||||
|
|
||||||
|
1. In the controller UI, go to the site's **Devices** view — the ER605 should
|
||||||
|
appear as "Pending" once discovery finds it on the network.
|
||||||
|
2. Click **Adopt** and enter the router's current admin credentials when
|
||||||
|
prompted.
|
||||||
|
3. Wait for adoption to finish and the device to show **Connected**.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Image tag is pinned to a `major.minor` version (currently `6.3`) — check
|
||||||
|
[Docker Hub tags](https://hub.docker.com/r/mbentley/omada-controller/tags)
|
||||||
|
before bumping it, and never move backwards to an older version once the
|
||||||
|
Mongo database has been touched by a newer one.
|
||||||
|
- `network_mode: host` is used because Omada discovery/adoption depends on a
|
||||||
|
wide range of UDP/TCP ports and broadcast traffic; bridging those
|
||||||
|
individually is more fragile than just sharing the host network.
|
||||||
|
- Controller data lives in the `omada-data` / `omada-logs` named Docker
|
||||||
|
volumes, not bind mounts — back them up via the controller's own
|
||||||
|
**Settings → Maintenance → Backup** feature (see the migration guide),
|
||||||
|
not by copying the volume directly.
|
||||||
45
docker/omada-controller/docker-compose.yml
Normal file
45
docker/omada-controller/docker-compose.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
services:
|
||||||
|
omada-controller:
|
||||||
|
container_name: omada-controller
|
||||||
|
# Pin major.minor — never use `latest`, a version bump can break the Mongo schema mid-upgrade.
|
||||||
|
# Check https://hub.docker.com/r/mbentley/omada-controller/tags for the current recommended tag.
|
||||||
|
image: mbentley/omada-controller:6.3
|
||||||
|
restart: unless-stopped
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 4096
|
||||||
|
hard: 8192
|
||||||
|
stop_grace_period: 60s
|
||||||
|
# Host networking: Omada device discovery/adoption relies on broadcast + a wide range of
|
||||||
|
# UDP/TCP ports below. Simplest to just share the desktop's network stack directly.
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
- PUID=508
|
||||||
|
- PGID=508
|
||||||
|
- TZ=Europe/Vienna
|
||||||
|
- MANAGE_HTTP_PORT=8088
|
||||||
|
- MANAGE_HTTPS_PORT=8043
|
||||||
|
- PORTAL_HTTP_PORT=8088
|
||||||
|
- PORTAL_HTTPS_PORT=8843
|
||||||
|
- UPGRADE_HTTPS_PORT=8044
|
||||||
|
- PORT_APP_DISCOVERY=27001
|
||||||
|
- PORT_DISCOVERY=29810
|
||||||
|
- PORT_MANAGER_V1=29811
|
||||||
|
- PORT_ADOPT_V1=29812
|
||||||
|
- PORT_UPGRADE_V1=29813
|
||||||
|
- PORT_MANAGER_V2=29814
|
||||||
|
- PORT_TRANSFER_V2=29815
|
||||||
|
- PORT_RTTY=29816
|
||||||
|
- PORT_DEVICE_MONITOR=29817
|
||||||
|
- WEB_CONFIG_OVERRIDE=false
|
||||||
|
- SHOW_SERVER_LOGS=true
|
||||||
|
- SHOW_MONGODB_LOGS=false
|
||||||
|
- SSL_CERT_NAME=tls.crt
|
||||||
|
- SSL_KEY_NAME=tls.key
|
||||||
|
volumes:
|
||||||
|
- omada-data:/opt/tplink/EAPController/data
|
||||||
|
- omada-logs:/opt/tplink/EAPController/logs
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
omada-data:
|
||||||
|
omada-logs:
|
||||||
44
docs/er605-firmware-update.md
Normal file
44
docs/er605-firmware-update.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# ER605: Firmware Update (Standalone Mode)
|
||||||
|
|
||||||
|
Do this **before** installing the Omada Software Controller or adopting the router — it's much easier to upgrade a device while it's still in standalone/local mode than after it's controller-managed, and you want to start the VLAN/ACL/WireGuard build on current firmware.
|
||||||
|
|
||||||
|
## 1. Identify your hardware version
|
||||||
|
|
||||||
|
TP-Link ships multiple hardware revisions of the ER605 (v1, v2, v3, ...) with different firmware trains — the wrong file won't install cleanly. Check the sticker on the bottom/back of the unit for something like `Ver: 2.0`.
|
||||||
|
|
||||||
|
## 2. Download the firmware
|
||||||
|
|
||||||
|
- Official download page: https://www.tp-link.com/us/support/download/er605/ (also mirrored at https://support.omadanetworks.com/us/download/firmware/er605/v2/ for the v2 hardware line)
|
||||||
|
- Select the page for **your exact hardware version**, then the "Firmware" tab.
|
||||||
|
- As of writing, the latest ER605 firmware is around **2.4.5** — but check the download page for what's current, and note the changelog in case anything is relevant (e.g. the LAN DNS feature referenced in [status.md](status.md) needs 2.3.0+).
|
||||||
|
- Download is a `.zip` — extract it to get the actual `.bin` firmware file.
|
||||||
|
|
||||||
|
## 3. Back up current config first
|
||||||
|
|
||||||
|
Do this even though the router is barely configured yet — it's a 30-second safety net.
|
||||||
|
|
||||||
|
1. Log into the router's web UI (default `https://192.168.0.1`, or whatever IP it's currently reachable at; default credentials are `admin`/`admin` unless already changed).
|
||||||
|
2. Go to **System Tools / Settings → Backup & Restore** (exact path varies slightly by firmware version).
|
||||||
|
3. Download the current config backup somewhere safe (e.g. `docker/omada-controller/` is *not* the place — keep router backups out of git, or in a private/untracked location).
|
||||||
|
|
||||||
|
## 4. Upload the new firmware
|
||||||
|
|
||||||
|
1. Same web UI → **System Tools → Firmware Upgrade** (naming may vary; some firmwares call it **Administration → Firmware**).
|
||||||
|
2. Select the `.bin` file you extracted in step 2.
|
||||||
|
3. Start the upgrade.
|
||||||
|
4. **Do not power off the router or disconnect the Ethernet cable during the upgrade.** It reboots itself when done — this can take a few minutes.
|
||||||
|
|
||||||
|
## 5. Verify
|
||||||
|
|
||||||
|
- Log back into the web UI and confirm the firmware version shown matches what you just installed.
|
||||||
|
- Confirm basic connectivity (internet still works through the router) before moving on to controller adoption.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Once firmware is current, move on to standing up the Omada Software Controller: [../docker/omada-controller/](../docker/omada-controller/).
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [How do I upgrade firmware of Omada Gateway in Standalone web UI? (TP-Link FAQ)](https://www.tp-link.com/us/support/faq/4020/)
|
||||||
|
- [How to upgrade firmware of Omada Gateway in controller mode (TP-Link FAQ)](https://www.tp-link.com/us/support/faq/4644/) — for later reference, once the router is adopted
|
||||||
|
- [ER605 firmware downloads (Omada Networks support)](https://support.omadanetworks.com/us/download/firmware/er605/v2/)
|
||||||
33
docs/omada-controller-migration.md
Normal file
33
docs/omada-controller-migration.md
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Migrating the Omada Controller: desktop → NUC
|
||||||
|
|
||||||
|
Once the NUC homeserver is provisioned and set up with Docker (via Ansible),
|
||||||
|
move the Omada Software Controller there permanently so it doesn't depend on
|
||||||
|
the desktop being on. This is a **backup/restore** move, not a live migration —
|
||||||
|
plan for a few minutes of controller downtime (the ER605 itself keeps routing
|
||||||
|
traffic the whole time; only controller management is briefly unavailable).
|
||||||
|
|
||||||
|
## Before you start
|
||||||
|
|
||||||
|
- **Note the exact controller version** running on the desktop (`Settings → About` or the version shown in the container image tag, e.g. `mbentley/omada-controller:6.3.0.x`).
|
||||||
|
- The NUC's Compose setup **must run the same major.minor(.patch) version** as the desktop at restore time. TP-Link's controller cannot restore a backup taken by a newer version into an older one — it corrupts the database. If you want to upgrade, upgrade *after* the restore succeeds on matching versions, not before.
|
||||||
|
- The NUC needs to be reachable from the ER605 for adoption to keep working post-migration — either on the same L2 segment, or with the gateway's controller "inform URL" pointed at the NUC's address (Omada gateways support setting this manually under the standalone/local management settings if they're ever on different segments).
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
1. **On the desktop controller:** `Settings → Maintenance → Backup` → create a manual backup (or use Auto Backup if one's already scheduled) and download the backup file.
|
||||||
|
2. **On the NUC:** copy [`../docker/omada-controller/docker-compose.yml`](../docker/omada-controller/docker-compose.yml) over via the Ansible-managed Docker setup, keeping the **image tag identical** to what the desktop was running.
|
||||||
|
3. Bring the container up on the NUC (`docker compose up -d`), open its controller UI, and go through the setup wizard just far enough to reach the option to restore from a backup instead of creating a new site — this is usually offered right at first login (`Restore` alongside `Create New Controller`).
|
||||||
|
4. Upload the backup file from step 1 and let it restore. The controller restarts once done.
|
||||||
|
5. Confirm the ER605 (and anything else already adopted) shows up and reconnects on the NUC controller. Give discovery a minute — devices need to re-inform to the new controller address.
|
||||||
|
6. Once confirmed working, stop and remove the desktop instance (`docker compose down`, and clean up the `omada-data`/`omada-logs` volumes there if you're done with them) — don't leave two controllers able to fight over the same devices.
|
||||||
|
7. If you *do* want to move to a newer controller version, do that now, as a separate step, against the NUC instance only — bump the image tag, `docker compose up -d`, and let it run its own internal DB migration.
|
||||||
|
|
||||||
|
## If versions don't match
|
||||||
|
|
||||||
|
If the desktop somehow ended up ahead of what you initially deploy on the NUC:
|
||||||
|
|
||||||
|
1. Deploy the **exact matching version** on the NUC first (adjust the image tag).
|
||||||
|
2. Restore the backup — this will succeed since versions match.
|
||||||
|
3. *Then* bump the NUC's image tag to the newer version and let it self-upgrade the database in place.
|
||||||
|
|
||||||
|
Never try to restore a newer-version backup directly into an older controller — see the note in [status.md](status.md#omada-controller).
|
||||||
153
docs/status.md
Normal file
153
docs/status.md
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
# Homelab Network Overhaul — Status & Decisions
|
||||||
|
|
||||||
|
Living document. Update checkboxes and tables as things change instead of re-deriving this from scratch each time.
|
||||||
|
|
||||||
|
Location: Linz, Austria. ISP: LIWEST (cable). Modem: Technicolor CGA4233-EU.
|
||||||
|
|
||||||
|
## Current TODO
|
||||||
|
|
||||||
|
See [todo.md](todo.md) for the live checklist. Quick status (as of 2026-09-26): bridge mode, controller adoption, firmware update, VLANs, ACLs, WireGuard VPN + INWX DynDNS, the SG2016P switch, all three SSIDs, NAS on Servers with QuickConnect disabled, and NPM/Pi-hole local naming are all done. In progress: the first Hyper Backup of the NAS. Next: second AP + living-room switch (purchase decided), office AP ceiling mount + Wi-Fi re-measure, partner's Synology app logins, hardware shopping list. Everything else is waiting on the NUC.
|
||||||
|
|
||||||
|
## Hardware decisions
|
||||||
|
|
||||||
|
### Network core
|
||||||
|
|
||||||
|
| Item | Model | Status |
|
||||||
|
|---|---|---|
|
||||||
|
| Router | TP-Link Omada ER605 v2.30, firmware 2.4.5 | Received, adopted, updated |
|
||||||
|
| Main switch | TP-Link Omada SG2016P (16-port, 8×PoE+, 120W budget) | Received, adopted, wired in; powers the office AP via PoE (make sure the AP is in an actual **PoE** port — only 8 of the 16 are) |
|
||||||
|
| Access point #1 | TP-Link Omada EAP650 | Received — mounting in the **office** first, powered via its own DC adapter until the switch's PoE+ is available |
|
||||||
|
| Access point #2 | TP-Link Omada EAP650 (same model as AP #1) | **Decided to buy** — chosen over the EAP610 (AX1800, no 160 MHz on 5 GHz) so both APs are identical; the peak-speed difference is irrelevant to the actual couch problem, which is signal quality. Living-room/dining-area coverage, mounted above the TV (see Wi-Fi section) |
|
||||||
|
| Living-room switch | TP-Link Omada **ES205GP** (5-port, 4× PoE+ 802.3at/af, 65W budget) | **Decided to buy** — note the **P**: the plain ES205G in earlier notes has no PoE. Easy Managed tier, but supports 802.1Q VLANs (up to 32 groups) via Omada Controller, adopted like the other devices. 3 devices need ports (AP, TV, streaming Pi), so 5 ports is plenty — no need for an 8-port unit |
|
||||||
|
|
||||||
|
### Homeserver
|
||||||
|
|
||||||
|
- **Used Intel NUC** (8th-gen Core i3, 16GB DDR4, 128GB SSD), bought via Willhaben for ~€155 — replaced the original new-Beelink-EQ14 plan.
|
||||||
|
- OS: plain Debian/Ubuntu + Docker Compose. **No Proxmox/hypervisor.**
|
||||||
|
- Home Assistant via the official **"Home Assistant Container"** image (not Home Assistant OS) — matches running everything else as plain Docker.
|
||||||
|
- Config management: **Ansible**, run from David's own machine over SSH (no footprint on the server itself).
|
||||||
|
- **Kubernetes explicitly rejected for home services** (no benefit on a single node). Will build a separate **k3s learning cluster** later on already-owned Raspberry Pis (RPi4 and older), kept fully separate from production services — motivated by wanting K8s reps for work, not by home-service needs.
|
||||||
|
|
||||||
|
### Living room
|
||||||
|
|
||||||
|
- Single existing Ethernet cable feeds this area from the wall. **Plan: run that connection to a spot above the TV**, and put the new ES205GP switch + second AP (EAP650) there, so the TV and streaming Pi are each only a short patch cable away. (Alternative considered and rejected: switch + AP at the wall outlet above the cabinet, which would need two ~5 m runs to the TV and Pi instead of one longer run.)
|
||||||
|
- Connected there: the second AP (EAP650, **PoE-powered** from the ES205GP — no separate adapter), the TV (wired, on **IoT**), and the Raspberry Pi for game streaming (on **Trusted**).
|
||||||
|
- VLAN plumbing this needs: the ES205GP uplink port and the AP's port are **trunks** carrying Trusted (10) / IoT (20) / Guest (40) tagged; TV port = access port on IoT; Pi port = access port on Trusted. The SG2016P port feeding this cable must be a matching trunk (remember the lesson from the first AP: every VLAN needs to be tagged on **every** hop between the AP and the ER605, or clients associate but never get an IP).
|
||||||
|
- Streaming Steam games to the TV: try the already-owned **RPi4 with Moonlight** first (well-proven, hardware-decode, zero cost) before buying anything. Fallback if insufficient: new RPi5 (~€150) or a cheap N100 mini PC (similar price, more flexible, slightly higher latency/idle power).
|
||||||
|
- Streaming Pi should sit on the **Trusted VLAN** (same as the gaming PC) to avoid an unnecessary routing hop.
|
||||||
|
|
||||||
|
### Full wired device list (needs a switch port)
|
||||||
|
|
||||||
|
Linux PC · Windows gaming PC · partner's PC · printer (optional) · Synology NAS · homeserver (NUC) · OctoPrint Pi · AP (via living-room switch) · streaming Pi (via living-room switch)
|
||||||
|
|
||||||
|
## Network architecture
|
||||||
|
|
||||||
|
### VLAN plan
|
||||||
|
|
||||||
|
| VLAN | Subnet | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| 10 — Trusted | `192.168.10.0/24` | Personal devices, PCs, streaming Pi (avoids an extra routing hop for game streaming) |
|
||||||
|
| 20 — IoT / Home Automation | `192.168.20.0/24` | OctoPrint + webcam, sensors, light bulbs, camera, robot vacuum, TV — internet allowed (needed for TV streaming apps + vacuum's cloud control), LAN access denied by ACL |
|
||||||
|
| 30 — Servers / Homelab | `192.168.30.0/24` | NAS, homeserver (NUC) |
|
||||||
|
| 40 — Guest | `192.168.40.0/24` | Isolated (Omada "Isolate Network" flag), internet-only |
|
||||||
|
| 99 — Management | `192.168.99.0/24` | Switch/AP/controller control plane |
|
||||||
|
|
||||||
|
- Window/door/temperature sensors are **Zigbee via a USB coordinator on the homeserver**, not IP devices — they never touch VLAN 20's network; Home Assistant talks to them over the local Zigbee radio directly.
|
||||||
|
- **Default-deny between VLANs is not automatic on Omada** — inter-VLAN routing is allow-all by default; ACL rules must be built manually (e.g., Home Assistant → IoT devices).
|
||||||
|
- ACL direction for alerts/control is **Servers → IoT** (Home Assistant reaching in to poll/control devices), not the reverse — IoT devices never need to initiate connections out to notify anyone.
|
||||||
|
- TV casting only needs **Trusted → IoT** allowed (the casting source connects out to the TV); return traffic flows back automatically as part of that established connection, no reverse rule needed. Discovery is handled by the ER605's mDNS repeater.
|
||||||
|
- **ACL rules built** (Omada ACL types: `Network` = exact match, `!Network` = any network except the one picked; Direction `LAN-LAN` vs `LAN-WAN` vs `WAN-IN` are separate scopes — a `LAN-LAN` rule has zero effect on internet access):
|
||||||
|
- `Network: IoT` → `!Network: IoT`, Direction `LAN-LAN`, **Deny** — one rule blocks IoT from reaching every other VLAN (Trusted/Servers/Management/Guest) at once; internet access for IoT is untouched since WAN isn't in scope for a `LAN-LAN` rule.
|
||||||
|
- `Network: Servers` → `Network: Management`, Direction `LAN-LAN`, **Deny**.
|
||||||
|
- `Network: Guest` → `Network: Management`, Direction `LAN-LAN`, **Deny** (defense-in-depth alongside Guest's Isolate Network flag).
|
||||||
|
- Everything else (Trusted↔Servers, Trusted→Management, Servers→IoT, Trusted→IoT, all internet access) relies on Omada's allow-all-by-default behavior — no rule needed.
|
||||||
|
- **WAN-IN rules generally aren't needed** — NAT already blocks all unsolicited inbound traffic by default; WAN-IN only matters for scoping something you've already port-forwarded (e.g. the VPN port).
|
||||||
|
- ER605 supports full per-port 802.1Q tagging/untagging/PVID; no practical VLAN-count limit for this setup.
|
||||||
|
- ER605's built-in **mDNS repeater** bridges Bonjour/mDNS discovery across VLANs (relevant for reaching OctoPrint/HA by local hostname).
|
||||||
|
- ER605's **LAN DNS** feature (firmware 2.3.0+) allows manual local hostname → IP entries — but like all DNS, it cannot encode a port number. Non-standard-port services (OctoPrint:5000, HA:8123, Omada Controller:8043, Spoolman:7912, Portainer:9000, etc.) still need a reverse proxy for clean no-port URLs.
|
||||||
|
|
||||||
|
### Wi-Fi
|
||||||
|
|
||||||
|
- Router is headless by design (lives in a cupboard — its own Wi-Fi radio would be useless there anyway).
|
||||||
|
- First AP (EAP650) is in the **office**. Measured signal (interim position, AP on top of a closet — not yet at its final ceiling mount): office desk **-42 dBm**, office at the 3D printer **-39**, master bedroom **-42**, kitchen **-57**, storage room (door closed) **-59**, living-room couch **-70** (matches a measured drop from ~50 to 10-20 Mbit there). Coverage is good everywhere except the couch nook, which sits behind the bathroom and hallway walls relative to the office. Rough thresholds: better than -60 good, to about -67 reliable for streaming/calls, -70 marginal, worse than -75 weak.
|
||||||
|
- **Decision: add a second AP (EAP650) in the living/dining area, mounted above the TV** — a single weak spot alone wouldn't have justified it (phone use at -70 is fine, and the TV/streaming Pi are wired), but David wants to keep working from the couch or dining table on a laptop, where -70 dBm is genuinely marginal. Wired backhaul, so no mesh needed.
|
||||||
|
- A ping to an idle phone is **not** a valid coverage test — phones in Wi-Fi power-save routinely show 100-500 ms round trips with a strong signal. Use the AP's own reading (Controller → Clients → the device's signal/link rate), a screen-on ping, or a throughput test instead.
|
||||||
|
- Worth re-measuring the couch once the office AP is at its real ceiling position and again after the second AP is up, for a before/after comparison.
|
||||||
|
|
||||||
|
### VPN
|
||||||
|
|
||||||
|
- **WireGuard runs on the ER605 itself**, not on the homeserver — avoids extra port-forwarding + static routing that a NUC-hosted VPN would need. **Working as of firmware 2.4.5.**
|
||||||
|
- **ER605 firmware must be at least 2.4.5 for WireGuard VPN Server to appear as an option in the Controller at all** — on the pre-update firmware (2.3.3), WireGuard wasn't listed, and the OpenVPN server that *was* available silently never actually started (config looked correct in the Controller — enabled, user linked, no errors in Audit Logs — but the daemon never bound to its port, confirmed via `ECONNREFUSED` on local, WAN-direct, and external tests). Updating firmware fixed both.
|
||||||
|
- **Local Networks scoped to Servers (30) + IoT (20)** — remote access to the NAS/self-hosted services and things like OctoPrint, not to personal devices on Trusted. (Was briefly set to Trusted-only, then discovered to actually have *every* network selected — same "field silently left on all networks" class of bug hit earlier with OpenVPN's Local Networks. Corrected to the minimal actual-need scope: Servers + IoT, explicitly excluding Management for now — no current need for it, easy to widen later.) Tunnel Mode **Split** (only the selected networks' traffic goes through the tunnel, not general browsing).
|
||||||
|
- VPN client IP pool: `192.168.66.0/24` — deliberately outside all VLAN subnets, no fixed convention requirement (doesn't have to be a `10.x` range).
|
||||||
|
- Needs its own port-forward rule (Settings → Transmission → NAT → Port Forwarding) separate from any VLAN/ACL config: WAN1, external+internal port `51820`, internal IP `192.168.0.1` (the gateway's own Default-network address, since the VPN terminates on the gateway itself), protocol UDP or All — **not TCP only** (a real bug hit during OpenVPN testing: the port-forward was accidentally set to TCP-only while OpenVPN used UDP, causing a silent timeout that looked identical to "nothing is running" until diagnosed via matching local vs. external `ECONNREFUSED` signals).
|
||||||
|
- No additional WAN-IN ACL rule was needed on top of the port-forward — confirmed via the external test returning an active `ECONNREFUSED` rather than a silent timeout, which proves traffic was already reaching the gateway.
|
||||||
|
- Android: WireGuard/OpenVPN aren't part of Android's built-in VPN framework (that only covers IKEv2/IPsec and L2TP natively) — use the official **WireGuard** app (supports QR-code import — zoom the browser in if the phone camera won't scan it off a monitor) or **OpenVPN Connect** app.
|
||||||
|
- **DynDNS instead of paying LIWEST for a static IP** — real annual cost difference (~€200+/year for static IP vs. free DynDNS), and cable IPs don't change often in practice anyway. **Decided against DuckDNS** — David already owns a domain via **INWX**, which has its own DynDNS2-compatible service, so used that instead (no shared `duckdns.org` domain, and INWX's DomRobot API has a ready-made `acme.sh` plugin for future Let's Encrypt DNS-01 certs on NPM).
|
||||||
|
- Set up an INWX **DynDNS account** (their control panel's dedicated DynDNS section, not general domain/DNS management) — this single step both creates the DNS record for the chosen hostname and generates a **separate DynDNS-scoped username/password** (not the main INWX account login — narrower blast radius if it ever leaked).
|
||||||
|
- Configured on the ER605 via **Device Config → Gateway → DNS → Dynamic DNS**, Service Provider **Custom**:
|
||||||
|
- Update-URL: `https://[USERNAME]:[PASSWORD]@dyndns.inwx.com/nic/update?hostname=[DOMAIN]&myip=[IP]` (Omada's Custom DDNS placeholders — substituted from the Username/Password/Domain Name fields, not typed literally into the URL)
|
||||||
|
- The actual filled-in URL/credentials are **not** written anywhere in this repo — keep them out of anything committed.
|
||||||
|
- **Working** — verified via `dig +short <hostname>` returning the ER605's current public IP.
|
||||||
|
- WireGuard client `Endpoint` doesn't auto-update to a hostname from the Controller UI (it always embeds the raw WAN IP in exported configs) — WireGuard's config format supports hostnames in `Endpoint` natively though, so just manually edit the line (in the downloaded `.conf` or directly in the WireGuard app's peer settings) to `Endpoint = <hostname>:51820` after generating a client config.
|
||||||
|
- **General WireGuard gotcha, same shape as the Endpoint one above**: fields set on the *server* config (e.g. Primary DNS Server) do **not** retroactively apply to peers whose config was already generated/imported before the change — WireGuard bakes settings into the client's config at generation time, it isn't pushed live the way DHCP options are. After changing a server-side field, either regenerate and re-import the client config, or edit the existing peer directly in the WireGuard app (same trick as the Endpoint fix).
|
||||||
|
- Bridge mode confirmed active on the modem — ER605 WAN gets the public IP directly (see TODO above).
|
||||||
|
|
||||||
|
### Local DNS & naming
|
||||||
|
|
||||||
|
- Naming scheme settled on: **`<name>.home.staffenberger.at`** — a subdomain of David's own already-owned INWX domain, not `.local` (reserved for mDNS/Bonjour, RFC 6762 — using it for manual DNS records risks conflicting with automatic mDNS resolution) and not `.home` or `.home.arpa` (the latter is the IETF-correct reserved suffix per RFC 8375, but rejected as too unfriendly for the partner to read/type). These records exist only in Pi-hole's local DNS — never published to INWX's real public DNS, so nothing is internet-exposed by using a real owned domain for the naming.
|
||||||
|
- Records added so far as individual **Local DNS Records** in Pi-hole (not yet the wildcard approach — see TODO): `pihole.home.staffenberger.at`, `nas.home.staffenberger.at`, both pointing at the NAS's Servers-VLAN IP (`192.168.30.10`).
|
||||||
|
- **Gotcha: a secondary/fallback DNS server on a VLAN's DHCP config causes intermittent resolution failures for internal-only names.** Trusted's DHCP had Pi-hole as Primary DNS but `8.8.8.8` (Google public DNS) as Secondary — client OS resolvers don't reliably always-prefer-primary (can race/round-robin), so any query that happened to hit `8.8.8.8` for an internal `.home.staffenberger.at` name failed immediately, since a public resolver has no knowledge of it. Symptom looked like "works for me, not for my partner" / inconsistent across devices. Fix: don't set a secondary DNS pointing outside Pi-hole at all — Pi-hole already forwards normal internet lookups upstream itself.
|
||||||
|
- Same **stale-DHCP-lease pattern hit all week applies to DNS server changes too** — a device won't pick up a newly-configured DNS server until it renews its lease (Wi-Fi toggle, `ipconfig /release`+`/renew`, etc.), same as VLAN reassignment.
|
||||||
|
|
||||||
|
### Omada Controller
|
||||||
|
|
||||||
|
- Self-hosted **Omada Software Controller** (Docker) instead of TP-Link's cloud controller — avoids a vendor cloud relay, in line with the general "no cloud relay" networking principle.
|
||||||
|
- Plan: run it temporarily on David's own Linux desktop now, adopt the ER605 immediately, then migrate to the NUC later via Omada's **Controller Migration** (backup/restore) feature once the NUC is set up.
|
||||||
|
- Watch for controller version mismatches between export and import — TP-Link/Omada requires matching major.minor(.patch) versions for restore; fallback is installing a specific matching version first, restoring, then upgrading.
|
||||||
|
|
||||||
|
### Reverse proxy
|
||||||
|
|
||||||
|
- **Chosen: Nginx Proxy Manager (NPM)** — single GUI, single source of truth for all proxy configs, works uniformly whether the target is a Docker container on the NUC or a bare-metal service elsewhere (e.g. OctoPrint on the Pi).
|
||||||
|
- Traefik considered and rejected for home use (label-based config fights against wanting one central place to look); will get real Traefik exposure anyway via the k3s learning cluster, where it's the default ingress controller.
|
||||||
|
|
||||||
|
### Switch port configuration (SG2016P)
|
||||||
|
|
||||||
|
- **Access port** = one VLAN, untagged — for every VLAN-unaware end device (PCs, NAS, printer, Pis, TV). Set the port's Native/Untagged network to the device's VLAN and leave Tagged empty; don't leave Default involved. **Trunk** = several VLANs tagged over one cable — only for infrastructure links (switch↔router, switch↔AP).
|
||||||
|
- **Every VLAN must be tagged on every hop** between an AP and the ER605, or clients associate to the SSID but never get an IP ("IP configuration failure"). Hit this twice: the first AP's port, then the switch's uplink to the ER605 (missing VLAN 10). The per-Network "Select Device Port" step and the per-port VLAN config are two views of the same thing; editing the **port** directly avoids the "cannot deselect the interface which selects the LAN as PVID" error.
|
||||||
|
- The AP's port native/untagged VLAN and the switch/AP management traffic deliberately stay on **Default** for now (same L2 segment as the Controller on David's desktop) — migrate management to VLAN 99 together with the Controller move to the NUC, at which point Default can be retired.
|
||||||
|
- Extra safety net: Guest VLAN also enabled on the currently-used ports so anything unexpectedly plugged in lands isolated.
|
||||||
|
- After any port/VLAN or DHCP-scope change, a device keeps its old lease until it renews: toggle the port off/on in the Controller (equivalent to unplugging), `ipconfig /release`+`/renew` on Windows, or Wi-Fi off/on on phones.
|
||||||
|
- The `Network` column in the Controller's Clients list is blank for wireless clients — cosmetic; the client's IP range is the real check of which VLAN it landed in.
|
||||||
|
- Switch PoE is only on 8 of the 16 ports; a "dead" AP was just plugged into a non-PoE port (and then needed a minute to boot).
|
||||||
|
|
||||||
|
## Backups
|
||||||
|
|
||||||
|
- **Omada Controller**: auto-backup enabled, **daily** for now (config is changing a lot; switch to weekly later). Local only on the Controller host for now — backups live in the container's data volume, so `docker compose down -v` deletes them. Off-machine rsync copy to a dedicated, quota-limited Synology user is deferred until the NUC migration (see todo.md). Backups contain secrets (Device Account, WireGuard keys, DDNS settings) — never commit them.
|
||||||
|
- **Synology NAS → 6TB USB drive via Hyper Backup**, deliberately **manually connected** (offline drive also guards against ransomware/accidental deletion), cadence **every two weeks**, recurring calendar reminder. Drive arrived as **exFAT** (DSM 7.3 mounts exFAT natively — the "exFAT Access" package no longer appears in Package Center — but exFAT has no journal, so an unclean unplug leaves a dirty flag and DSM reports "not ejected safely"); reformatted to **ext4** via DSM (Control Panel → External Devices → Format — select the device row and Eject first if Format is greyed out). Hyper Backup has no plug-in trigger on DSM 7, so it's "plug in → Back up now → **eject in DSM** → unplug".
|
||||||
|
- Wizard order is **destination first, then sources**. Backup type **Multiple versions**, **Folders and Packages** (not LUNs).
|
||||||
|
- Sources: all shared folders (incl. `photo`, Drive team folders, `docker`) + `homes` (~200 GB) + all applications (Synology Drive Server and Photos matter most — they carry the version history / albums / metadata that plain file copies lose), config backup on, **client-side encryption on** (password in Enpass), no schedule, Smart Recycle retention.
|
||||||
|
- `homes` is a reserved system share: its permissions can't be edited ("homes is reserved for the system"), and only Administrators-group accounts see it in Hyper Backup — neither is a problem.
|
||||||
|
- Entire-system backup (restorable NAS image) isn't available to a local USB destination, only to a remote NAS / C2 — restoring means reinstalling DSM and packages and restoring data + config from the backup.
|
||||||
|
- **Still to confirm after the first run finishes: a test restore** of a personal Drive file and a personal photo (both users) to prove the application backup really covers personal data. Later: occasional off-site copy (3-2-1).
|
||||||
|
- Hyper Backup vs Hyper Backup Vault: Vault is only the *receiving* side on a second Synology (relevant for a future off-site copy), not needed for a local USB drive.
|
||||||
|
|
||||||
|
## Cabling & power
|
||||||
|
|
||||||
|
- **Cupboard patch cables**: flat Cat6 is fine for short (2-3 m or less) **data-only** links — buy pure copper (CCA and very thin conductors are the risk), from a reputable maker (deleyCON flat U/UTP is AWG 27 stranded copper, unshielded, 1.5 mm thick, sold as 5-packs in white and individually in white/black, down to 25 cm; Goobay, InLine, Digitus/Delock are comparable). Unshielded is fine — twisted-pair geometry does the noise rejection. Flat cables are fragile where the cable meets the plug: no pull or sharp bend there. **PoE runs (to the APs) and longer runs (e.g. to above the TV) should be round pure-copper cable, not flat.** Verify each link shows 1000 Mbps in the Controller after swapping; a link that negotiates 100 Mbps or shows errors = swap the cable. (The TV port showed 100 Mbps earlier — probably the TV's own NIC, but unconfirmed.) Measure the real cable path with string and add 20-30 cm before choosing 2 m vs 3 m. Color-by-length coding isn't available in flat cables (only white/black) — use labels/Velcro, and a colored round multi-length set for loose spares.
|
||||||
|
- **Socket strips** (Austria: Schuko/Type F): a strip adds sockets, not capacity — plug two strips into *different* wall outlets, no daisy-chaining. Look for VDE/GS/ÖVE mark, 16 A, 3×1.5 mm² cable, surge protection for the PC/desk strip, and **no switch (or a guarded one) for the router/switch/NAS strip**. Mount with **screws** (keyhole slots/mounting plate), sockets facing sideways/down, never adhesive. The workshop-style metal strip David likes is bracket-mounted (Brennenstuhl Premium-Alu-Line is the closest wall-mountable match found; the AJ Produkte MOTION and Manutan ones are for their own workbench frames and only list CE, not VDE/GS).
|
||||||
|
|
||||||
|
## Home automation plans
|
||||||
|
|
||||||
|
- Sensors: temperature/humidity, window-open monitoring, light bulb monitoring — via Zigbee-style sensors + a USB coordinator dongle (e.g. Sonoff Zigbee 3.0, ~€15–20) plugged into the homeserver.
|
||||||
|
- Camera to check on the cat: casual live viewing is computationally free. If smart detection (Frigate) is wanted later, add a Coral USB accelerator (~€70) rather than upgrading the CPU.
|
||||||
|
|
||||||
|
## Planned services on the homeserver (NUC)
|
||||||
|
|
||||||
|
- Home Assistant (Container image)
|
||||||
|
- Pi-hole
|
||||||
|
- Filament spool manager (Docker)
|
||||||
|
- Omada Software Controller (Docker — migrated from the temporary desktop instance)
|
||||||
|
- Nginx Proxy Manager
|
||||||
|
- Self-written Docker tools (future)
|
||||||
|
- All managed via Ansible playbooks
|
||||||
52
docs/todo.md
Normal file
52
docs/todo.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Homelab Network Overhaul — TODO
|
||||||
|
|
||||||
|
Living checklist. See [status.md](status.md) for the full decisions/context behind each item.
|
||||||
|
|
||||||
|
## Switch wiring — in progress
|
||||||
|
|
||||||
|
- [x] SG2016P wired in and adopted; AP moved over to it (PoE-powered).
|
||||||
|
- [x] SSID plan implemented: Trusted (10), Guest (40), IoT (20, hidden) all working on their correct VLAN subnets. Root cause of the initial "Trusted Wi-Fi won't get an IP" bug: the switch's uplink port to the ER605 was missing VLAN 10 from its tagged list — same bug independently blocked the partner's PC from getting onto Trusted directly. Fixed by adding all VLANs to that uplink port's tagged list.
|
||||||
|
- [x] OctoPrint Pi wired to IoT, confirmed reachable.
|
||||||
|
- [x] Printer moved to IoT (after fixing its port — was left as untagged-Default with IoT only tagged, which a VLAN-unaware printer could never actually reach; fixed to native/untagged = IoT).
|
||||||
|
- [x] DHCP reservations done for devices with stable MACs.
|
||||||
|
- [x] Guest VLAN enabled as a safety net on currently-in-use switch ports, so anything unexpectedly plugged in lands isolated by default.
|
||||||
|
- [x] **Synology NAS** → Servers (30), DHCP-reserved.
|
||||||
|
- [x] **Windows gaming PC** and **partner's PC** both on Trusted (the uplink-port VLAN bug above was what had blocked them).
|
||||||
|
- [ ] Still to wire/move: homeserver (NUC), blocked until the NUC itself is provisioned. David's own Linux desktop deliberately stays on Default for now (it hosts the Omada Controller) — moves to Trusted once the Controller moves to the NUC, which is also when the Default network can finally be retired.
|
||||||
|
|
||||||
|
## Next up
|
||||||
|
|
||||||
|
- [ ] **Hardware shopping list**: **EAP650** (2nd AP) + **ES205GP** (living-room PoE switch); **flat Cat6 patch cables** for the cupboard (deleyCON flat U/UTP, pure copper — 25 cm 5-pack for short links, plus 0.5 m / 1 m / 2 m, and a **3 m** for the PC runs *if* a string measurement of the real path is over ~1.7 m; verify on each listing that it says copper and is the flat U/UTP version); optionally a colored multi-length **round** Cat6 set for grab-and-go spares (flat only matters for the permanent cupboard cables); **socket strips** — two, each plugged into a *different* wall outlet, no daisy-chaining, wall-mountable metal-housing (screws, no adhesive), VDE/GS/ÖVE mark, 3×1.5 mm² cable, surge-protected for the desk/PC strip, and no switch (or a guarded one) for the strip carrying router/switch/NAS. **PoE-powered cables (to the APs) should be round pure-copper cable, not flat/thin ones.**
|
||||||
|
- [ ] **Living-room second AP + switch** (decided — see status.md Wi-Fi and Living room sections): buy an **EAP650** (same as the first AP) and an **ES205GP** (the PoE+ variant, not the plain ES205G). Mount both above the TV, one cable run from the wall to there. Then: adopt both, set the ES205GP uplink + AP ports as trunks (Trusted/IoT/Guest tagged) and the SG2016P port feeding it likewise, TV port → access on IoT, Pi port → access on Trusted. Re-measure the couch afterward (baseline was **-70 dBm**).
|
||||||
|
- [ ] **Mount the office AP at its final ceiling position**, then re-measure the couch and the other rooms (baseline readings recorded in status.md) — cheap to do first, and useful as the before/after reference for the second AP.
|
||||||
|
- [x] **Omada Controller auto-backup enabled, set to daily** (config is changing a lot right now). Weekly switch tracked separately in Backlog. Original notes: top priority, cheap insurance for all the VLAN/ACL/VPN config already built. **Scope for now: local only** — backups stay on the machine running the Controller (accepted for now); also download a manual copy occasionally. The off-machine copy to the Synology is deferred, see "Later". Note auto-backups live in the container's data volume, so `docker compose down -v` deletes them along with everything else.
|
||||||
|
- [x] **Robot vacuum** and **cat feeder** connected to the IoT Wi-Fi SSID, named in the Controller for easy recognition. No DHCP reservation — not needed for devices only reached via their own cloud apps.
|
||||||
|
- [x] **Synology NAS access**: QuickConnect **disabled** — NAS is now only reachable via the WireGuard VPN, confirmed working. Synology Drive/Photos apps switched from QuickConnect ID to manual local-address login (David's phone done; **partner's accounts still to do — planned for tomorrow**).
|
||||||
|
- [ ] **Decide whether IoT devices should use Pi-hole for DNS**: the NAS (running Pi-hole as a Docker container) sits on Servers (30), same as always planned. The existing `IoT → !IoT deny` ACL rule currently blocks IoT from reaching Pi-hole too — meaning any IoT device pointed at it for DNS would fail to resolve. **Left as-is for now** (IoT just uses ER605/ISP DNS directly, no ad-blocking there). If wanted later: add a narrow exception, `Network: IoT → Network: Servers`, port 53 only, Direction `LAN-LAN`, Allow — evaluated before the broader IoT deny-all rule.
|
||||||
|
- [ ] **Backup strategy for the NUC/homeserver's own data** — Home Assistant config, Docker volumes, Omada Controller data, etc. Not addressed anywhere yet; the Synology's own backups don't cover this.
|
||||||
|
- [ ] **▶ Synology NAS backup — first run in progress (2026-09-26, overnight).** Task is created (Multiple versions, Folders and Packages, all shared folders + `homes` + all applications, config backup + encryption on, key in Enpass, no schedule). **Next: (1)** check the run finished without per-folder/per-app errors, **(2) test-restore** a personal Drive file and a personal photo for both users to confirm the Drive Server / Photos application backups really cover personal data, **(3) eject in DSM and unplug**, **(4) set the every-two-weeks reminder**, then tick this item. Full setup notes are in status.md's Backups section. Original notes: (currently no backup existed at all — top data-safety item): 6TB USB drive on hand, but the **USB 3.0 Micro-B cable is misplaced** (find it, or buy a replacement). Chosen workflow: **manually connected, not permanently attached** — the offline drive also protects against ransomware/accidental deletion. Steps: format the drive as **ext4** in DSM (Control Panel → External Devices → Format; erases it — check for existing data first), install **Hyper Backup**, create a Data backup task ("Local folder & USB") covering the important shared folders + Applications, **encryption on** (password in Enpass), version retention (Smart Recycle) + periodic integrity check, DSM notifications on failure, and **test-restore one folder**. To run: plug in, "Back up now", **eject in DSM** (Control Panel → External Devices → Eject) before unplugging, store the drive away from the NAS. DSM 7 has no plug-in-triggered backup, so the habit needs a **recurring calendar reminder** — chosen cadence: **every two weeks** (see how it goes; also run one before big photo imports or major DSM updates). Drive was exFAT out of the box (DSM couldn't cleanly mount it and reported "not ejected safely" — exFAT has no journal); reformatted to ext4 in DSM. The first full backup will be slow on the DS223j's 1 GB RAM — run it overnight. Later: an occasional off-site copy (3-2-1 rule) since one drive at home doesn't cover fire/theft.
|
||||||
|
|
||||||
|
- [ ] **Real (non-self-signed) certificate for the NAS's own DSM access** — not crucial, DSM's cert warning is just cosmetic for local access. Leaning toward **`mkcert`** (local CA, install its root cert as trusted on your own devices once, zero external credentials/services involved) over Let's Encrypt DNS-01 through INWX — the latter would need either a scoped INWX API key (check if INWX offers one) or `acme.sh`'s manual mode (no credentials, but manual renewal every ~90 days); full INWX account credentials handed to a script was correctly ruled out as too broad a permission grant for this.
|
||||||
|
|
||||||
|
## Backlog / lower priority
|
||||||
|
|
||||||
|
- [ ] **Change the Omada Controller auto-backup from daily to weekly** — daily is deliberate for now because so much config is changing; revisit once the switch/AP/VLAN work has settled and changes become infrequent.
|
||||||
|
- [ ] UPS/power protection for the always-on gear (router/switch/homeserver/NAS) — optional cost/complexity tradeoff, not urgent.
|
||||||
|
- [ ] Basic uptime/service monitoring (e.g. Uptime Kuma) once the NUC exists — nice-to-have, not essential.
|
||||||
|
|
||||||
|
## Later
|
||||||
|
|
||||||
|
- [x] **Local DNS + reverse proxy plan**: implemented ahead of schedule, running temporarily on the Synology rather than waiting for the NUC. NPM deployed (SQLite-based), remapped to ports **9080/9443/9081** since DSM's own internal nginx already held 80/443/81 — proxied HTTPS URLs need an explicit `:9443` until this moves to the NUC, where a clean 80/443/81 mapping will work with no conflict (revert `docker/npm/docker-compose.yml`'s `ports:` at that point). Pi-hole Local DNS Records in use (e.g. `pihole.home.staffenberger.at`, `nas.home.staffenberger.at`) rather than the wildcard approach so far — worth switching to the wildcard dnsmasq config later to stop needing a new record per service.
|
||||||
|
- [ ] **TLS certs for NPM**: same decision as the NAS's own cert (see above) — leaning `mkcert` over Let's Encrypt DNS-01/INWX for the same credential-scope reasons. Decide once NPM proxy hosts are actually being used for more than testing.
|
||||||
|
- [ ] **Off-machine Omada Controller backups to the Synology** — set this up on the NUC after the migration rather than on the desktop. Decided approach: a scheduled **rsync** job on the Controller host copying the Controller's autobackup folder (believed to be `/opt/tplink/EAPController/data/autobackup` inside the container — verify with `docker exec omada-controller ls` once a backup has run) to the NAS. **Not** a NAS folder mounted into the container (avoids the container's startup depending on the NAS, and keeps a failed copy from affecting the Controller). Use a **dedicated Synology user with a small storage quota** and key-based auth, so the credential on the Controller host can only touch that one backup folder — check that the DS223j's volume filesystem supports user quotas, and how DSM allows a non-admin user to do rsync/SFTP (SSH is admin-only by default). Backups contain secrets (Device Account, WireGuard keys, DDNS settings), so restrict the folder to that user and keep the files out of this Git repo. Once the Synology's own Hyper Backup to the 6TB drive exists, these are covered there too.
|
||||||
|
- [ ] Migrate Omada Controller from the desktop to the NUC once the NUC is provisioned — see [omada-controller-migration.md](omada-controller-migration.md).
|
||||||
|
|
||||||
|
## Future ideas
|
||||||
|
|
||||||
|
- [ ] **Parents' network overhaul**: plan refined after discussion — not a site-to-site link, not adopting their hardware into this Omada Controller (TP-Link **Deco is a separate, incompatible ecosystem** — can't be adopted into Omada Controller under any configuration; a "workaround" of switching Deco to AP mode just makes it a dumber Wi-Fi extender still managed by the Deco app, doesn't add controller compatibility).
|
||||||
|
- Buy a **second ER605** to replace their current limited ISP-provided modem/router — get their modem into bridge mode (same pattern as home), ER605 becomes their real router.
|
||||||
|
- Switch their existing **Deco units into Access Point Mode** (a supported Deco app toggle) so they stop doing their own NAT/DHCP behind the new ER605 — otherwise double-NAT. Note: even in AP mode, Deco can't map SSIDs to VLANs like the EAP650 can — it just bridges onto whatever single network the port it's plugged into carries. Since they don't need segmentation (confirmed — no IoT/multi-trust-tier need there), this doesn't matter: **one flat subnet** is enough, no VLANs needed on their side.
|
||||||
|
- Pick a subnet clearly distinct from home's (`192.168.10/20/30/40/66/99.0/24`) — e.g. `10.50.0.0/24`, using a different address family entirely so it's visually obvious which network you're on.
|
||||||
|
- Set up an **independent WireGuard VPN server** on that second ER605 (own DynDNS entry via INWX, same pattern as home) with its own client IP pool distinct from home's `192.168.66.0/24` — **not** a site-to-site link. Connect to it only on-demand from your own devices when help is actually needed; no persistent link between the two networks, no changes/risk to your own network at all.
|
||||||
|
- Doesn't remove the Deco mesh's own reliance on TP-Link's cloud for its own management (that's inherent to Deco) — separate, optional concern from the remote-access goal, not solved by any of the above.
|
||||||
|
- Next actual step: investigate their current ISP/modem situation (does it support bridge mode? which ISP?) before buying anything.
|
||||||
Loading…
Reference in a new issue