Compare commits

...

42 Commits

Author SHA1 Message Date
Kaloyan Danchev
6320c0f8d9 Docs: Claude Code tooling setup on Unraid — Cooperator, glab, skills, MCP prep
Installed Cooperator CLI, glab, uv+Python 3.12, 6 custom skills,
and built MCP servers (shortcut, mikrotik, unraid). MCP registration
via `claude mcp add` still pending as TODO.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:13:44 +02:00
jazzymc
8aef54992a Docker audit: migrate all containers to Dockge, clean up Traefik config
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-28 20:39:16 +02:00
Kaloyan Danchev
7867b5c950 WiFi VLAN fixes, CAP bridge filtering, AdGuard IP conflicts, channel optimization
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Enable bridge VLAN filtering on CAP for proper per-client VLAN assignment
- Fix AdGuard container IP conflicts (.2→.10, .3→.11) with static IPs
- Fix 2.4GHz co-channel interference (both APs were on ch 1, CAP now ch 6)
- Fix 5GHz overlap (HAP ch 36/5180, CAP moved to ch 52/5260)
- Update WiFi access-list: VLAN assignment now active with per-device VLAN IDs
- Add Xiaomi Air Purifier MC1 to VLAN 30 access-list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:40:29 +02:00
Kaloyan Danchev
cdb961f943 Post-migration container cleanup: fix broken services, remove obsolete containers
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fixed Traefik networking (stale Docker bridge), adguardhome-sync config,
diode stack (Hydra DB + OAuth2 bootstrap), diode-agent auth. Removed 5
deprecated/duplicate containers. Started unmarr + rustfs stacks. 53
containers now running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:30:15 +02:00
Kaloyan Danchev
877aa71d3e Update docs: motherboard swap, NVMe cache pool, Docker migration
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- New motherboard installed, MAC/DHCP updated
- 3x Samsung 990 EVO Plus 1TB NVMe cache pool (ZFS RAIDZ1)
- Docker migrated from HDD loopback to NVMe ZFS storage driver
- disk1 confirmed dead (clicking heads), still on parity emulation
- Hardware inventory, changelog, and incident report updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:47:07 +02:00
Kaloyan Danchev
bf6a62a275 Add incident report: disk1 hardware failure (clicking/head crash)
HGST Ultrastar 10TB drive (serial 2TKK3K1D) failed on Feb 18.
Array running degraded on parity emulation. Recovery plan documented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:54:23 +02:00
Kaloyan Danchev
0119c4d4d8 docs: add Minecraft server, WiFi DHCP fix to changelog
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Added Minecraft Java server section to 03-SERVICES-OTHER.md
- Documented WiFi DHCP fix (VLAN 40 tagged→untagged on wifi1/wifi2)
- Documented Minecraft deployment and hairpin NAT setup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:16:32 +02:00
Kaloyan Danchev
2a522d56d2 docs: update configs after CAP recovery and roms share setup
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 07-WIFI-CAPSMAN: CAP both radios working, access list no VLAN assignment
- 01-NETWORK-MAP: fix CAP IP .6→.2, add Nobara and SMB shares section
- 04-HARDWARE-INVENTORY: CAP SSH/version details, add Recalbox device
- 06-VLAN-DEVICE-ASSIGNMENT: add Nobara (VLAN 10), Recalbox (VLAN 25)
- 03-SERVICES-OTHER: add Roms SMB share section with mount details
- CHANGELOG: add 2026-02-14 entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:50:01 +02:00
Kaloyan Danchev
4e726a4963 Add cross-VLAN casting docs, update device assignments
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- New doc: 11-CROSS-VLAN-CASTING.md with full MikroTik config
  (firewall rules, FastTrack exclusion, mDNS, IGMP proxy,
  AirPlay/Chromecast troubleshooting)
- Update device IPs: LG TV .40/.41, Chromecast .42
- Move HP printer from VLAN 40 to VLAN 30 at .30

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:28:55 +02:00
Kaloyan Danchev
ecbce1ca94 Add VRRP failover infrastructure documentation (Nobara)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Deployed automatic failover for critical services (Traefik, Vaultwarden,
Authentik, AdGuard) from Unraid to Nobara workstation via Keepalived VRRP
with VIP 192.168.10.250. ~4 second failover time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:03:26 +02:00
Kaloyan Danchev
d2f49e9130 Add Vaultwarden sync script for MikroTik cold standby
Syncs the Vaultwarden database, RSA key, and config from Unraid
to the MikroTik container standby instance via a temporary PHP
HTTP server. Designed for manual daily runs before maintenance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 11:21:24 +02:00
Kaloyan Danchev
4305657ad0 Add Bosch Home Connect integration to HA setup docs
Oven (HRG7784B1) and Washing Machine (WGB24400BY) added via OAuth2.
Both dashboards updated with Bosch appliance sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 19:23:46 +02:00
Kaloyan Danchev
5af3c9478b Add Home Assistant setup documentation
Covers HAOS VM setup, Xiaomi/Gree/Tuya integrations, visionOS theme,
Mushroom Cards dashboards (mobile + desktop), and known issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 11:30:17 +02:00
Kaloyan Danchev
c93f7da733 Add Unraid flash drive migration procedure
Flash drive on XTRM-U is failing. Created incident doc with complete
step-by-step procedure: backup retrieval (4 options), new USB prep via
Flash Creator, license transfer via Tools→Registration, post-migration
verification checklist, and prevention measures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:14:43 +02:00
Kaloyan Danchev
ec9659d0cb Restructure docs: archive VLAN migration, update IPs to VLAN 10
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Major documentation cleanup after VLAN migration completion:
- Archive 12 VLAN project docs to archive/vlan-migration/
- Archive 5 done WIP docs (VLAN proposals, AI stack, Fossorial, DNS backup)
- Create standing reference docs 08-DNS-ARCHITECTURE and 09-TAILSCALE-VPN
- Renumber docs to clean 01-09 sequence with merged CHANGELOG
- Update all active docs from stale 192.168.31.x to current VLAN 10 IPs
- Fix CSS1 (.10.9→.10.3) and ZX1 (.10.7→.10.4) IPs in hardware inventory
- Clean 06-VLAN-DEVICE-ASSIGNMENT: remove migration columns/sections, fix VLAN 25 subnet

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 12:45:16 +02:00
Kaloyan Danchev
81f2f03400 Replace Portainer with Dockge for container management
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Remove Portainer, add Dockge on port 5001
- Add project-specific CLAUDE.md with infrastructure instructions
- Update services documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 08:01:42 +02:00
Kaloyan Danchev
60369e6f43 Add Settop Box to VLAN 30 device list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- LAN MAC: FC:D5:D9:EB:6A:82 → 192.168.30.50 (CSS326 Port 23)
- WiFi MAC: 08:FB:EA:61:9D:3A → 192.168.30.51 (XTRM2 2.4GHz)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 15:56:12 +02:00
Kaloyan Danchev
740170a164 Add Roborock S7 to WPA+TKIP device list
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fixed XTRM2 WiFi by enabling WPA-PSK + WPA2-PSK and setting
fixed channel 2412 MHz (channel 1) with 20MHz width.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:52:52 +02:00
Kaloyan Danchev
c1ab68f499 Update CSS326 switch configuration with port labels
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Configured VLANs 10, 20, 25, 30 on CSS326 via SwOS API
- Added port labels: HAP-Trunk, KVM-V10, Kids-B1/B2/G1, Main-M1/M2/M3, LR-L1/L2/L3, ZX1-10G
- Updated port assignments table with detailed per-port configuration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:39:16 +02:00
Kaloyan Danchev
5b8c8b72ec Add CSS326 port assignments with VLAN mapping
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Port 1: HAP Uplink (Trunk)
- Port 2: KVM (VLAN 10)
- Ports 16-18: Kids Rooms (VLAN 25)
- Ports 19-21: Main Bedroom (VLAN 20)
- Ports 22-24: Living Room (VLAN 30, includes settop box)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 12:14:36 +02:00
Kaloyan Danchev
76106664a7 Update HAP ax³ port assignments documentation
- ether1: ISP Gateway (WAN)
- ether2: CAP XL ac
- ether3: CSS326-24G-2S+
- ether4: XTRM-U (Unraid)
- ether5: Dell Monitor LAN

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 11:27:18 +02:00
Kaloyan Danchev
6ba0f4c14f Add Kaloyan's device MAC addresses
- USB Hub: 34:0A:33:2C:1E:28
- MacBook Pro WiFi 5GHz: BE:A7:95:87:19:4A
- MacBook Pro WiFi 2.4GHz: CE:B8:11:EA:8D:55

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 09:19:38 +02:00
Kaloyan Danchev
7e03532700 Identify Tuya Smart Gateway (JMWZG1) MAC address
- 38:1F:8D:04:6F:E4 is the Tuya Smart Gateway, not Xiaomi
- New IP: 192.168.30.5
- Requires WPA+TKIP for connectivity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 09:14:16 +02:00
Kaloyan Danchev
b7c998121e Reorganize VLAN 20/25 device assignments
- VLAN 20 (Trusted): Kaloyan's devices only (S25, MacBook, Gaming PC, USB Hub)
- VLAN 25 (Family): All other family members (Nora, Dancho, Kimi, Compusbg)
- Dell Monitor LAN moved to VLAN 10 (connected to HAP ether5)
- Added TBD section for USB Hub and Gaming PC WiFi MACs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 09:05:02 +02:00
Kaloyan Danchev
5608c45e05 Update Dell Monitor LAN device with new VLAN assignment
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Renamed MacBook Pro LAN to Dell Monitor LAN
- Assigned to VLAN 10 (Management) with IP 192.168.20.100

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:51:47 +02:00
Kaloyan Danchev
9a6b725a14 Add device migration worksheet with all devices by VLAN
Includes columns for new VLAN and new IP planning:
- 36 devices across 7 VLANs
- Organized by VLAN section and flat list views
- Ready for migration planning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:28:28 +02:00
Kaloyan Danchev
0c492d016c Add WiFi/CAPsMAN config and fix Xiaomi OUI misidentification
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Created docs/19-WIFI-CAPSMAN-CONFIG.md documenting working WiFi settings
- Fixed 38:1F:8D:04:6F:E4 OUI - was incorrectly labeled as Tuya, is actually Xiaomi
- XTRM2 (2.4GHz) requires WPA+WPA2 with TKIP for legacy device compatibility
- CAPsMAN working with CAP XL ac on 2.4GHz

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 20:14:44 +02:00
546adad373 Restore HID++ for Nobara->Mac, keep Mac->Nobara monitor-only 2026-02-01 18:31:49 +02:00
663542ff17 Simplify KVM scripts - monitor only, manual peripheral switch
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-01 16:42:04 +02:00
Kaloyan Danchev
2a3bdb9934 Fix KVM switch: working Nobara → Mac with correct HID++ commands
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Discovered correct HID++ feature indices per device
- Updated to_mac.sh with working hidapitester commands
- Updated docs with complete setup instructions
- Mac → Nobara direction still needs work (TODO)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 13:38:17 +02:00
2d67ba5cb5 Add KVM scripts for Mac/Nobara switching
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- to_mac.sh: Switch from Nobara to Mac (monitor USB-C, peripherals Ch3)
- to_nobara.sh: Switch from Mac to Nobara (monitor HDMI2, peripherals Ch2)
- README.md: Setup instructions for both machines

Uses DDC/CI for monitor and HID++ for Logitech Bolt peripherals.
2026-02-01 11:46:24 +02:00
0c50f7088c Update changelog: KVM switch documentation added
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 09:44:36 +02:00
0d0131d2b2 Add KVM switch documentation for Mac/Nobara setup
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- DDC/CI monitor switching (Dell U3821DW)
- HID++ Logitech peripheral switching (MX Keys S, MX Master 3S)
- Scripts for bidirectional switching
- Troubleshooting guide and reference

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 09:44:20 +02:00
b95ba0f444 fix: resolve DNS issues - update DHCP to use gateway as DNS 2026-01-31 23:25:56 +02:00
886f46bd77 docs: log network connectivity issue
docs: add Docker cleanup changelog + log network issue (2026-01-31)
2026-01-31 23:11:05 +02:00
Kaloyan Danchev
7470d3f502 Update documentation with correct VLAN IPs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Hardware Inventory:
- Unraid server: 192.168.10.20
- Unraid AdGuard (macvlan): 192.168.10.10
- Router: 192.168.10.1
- CSS326 switch: 192.168.10.9
- ZX switch: 192.168.10.7
- cAP XL: 192.168.10.6

Critical Services:
- Updated DNS section with correct container IPs
- Added failover details and Web UI URLs
- Updated routing to reflect VLAN structure
- Updated DHCP pools for all VLANs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 22:22:10 +02:00
Kaloyan Danchev
f56a43741d Update DNS failover with dual health check
- Added DNS resolution Netwatch monitor (type=dns) alongside ping
- Ping check: Fast container crash detection (10s interval)
- DNS check: Actual DNS functionality verification (30s interval)
- Either monitor failing triggers failover to Unraid
- Documented /32 routing fix for multi-container ECMP issue
- Updated troubleshooting section with routing checks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:52:49 +02:00
Kaloyan Danchev
d34cea9df6 Add MikroTik Tailscale container documentation
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Documents the Tailscale container setup on MikroTik hAP ax³:
- Userspace networking mode (TS_USERSPACE=true) required for RouterOS containers
- Container network configuration (172.17.0.0/24)
- NAT masquerade for internet access
- Environment variables and mount configuration
- Troubleshooting guide for common issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 18:43:27 +02:00
Kaloyan Danchev
4b766145b4 Add AdGuard DNS setup with automatic failover documentation
- docs/16-ADGUARD-VLAN-PLAN.md: Implementation plan for AdGuard on VLANs
- docs/17-DNS-ADGUARD-FAILOVER.md: Complete DNS architecture with:
  - Dual AdGuard setup (MikroTik primary, Unraid secondary)
  - Automatic failover via Netwatch monitoring
  - NAT redirect rules for all VLANs
  - Sync configuration between instances
- docs/wip/CONSOLE-PORT-ETHER5.md: WIP plan for dedicated console port

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 17:22:18 +02:00
Kaloyan Danchev
70fa8c0654 Update port forwards and IPs for VLAN 10 setup
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Updated NAT port forwards to use 192.168.10.20 (Unraid on VLAN 10)
- Added hairpin NAT rules for internal access to WAN IP
- Updated SSH connection commands
- AdGuard DNS rules pending (not configured yet)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:06:02 +02:00
Kaloyan Danchev
0c27218091 Update NanoKVM IP to 192.168.10.200
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:06:02 +02:00
Kaloyan Danchev
e9572ae166 Add VLAN setup documentation - complete implementation
- docs/12-VLAN-SETUP-PROGRESS.md: Progress tracking during setup
- docs/13-VLAN-SETUP-PLAN-V2.md: Initial VLAN plan
- docs/14-VLAN-SETUP-PLAN-V3-SAFE-MODE.md: Safe mode approach
- docs/15-VLAN-SETUP-COMPLETE-2026-01-31.md: Final session summary

VLANs implemented:
- VLAN 10: Management (192.168.10.0/24) - port-based
- VLAN 20: Trusted (192.168.20.0/24) - WiFi MAC-based
- VLAN 25: Kids (192.168.25.0/24) - WiFi MAC-based
- VLAN 30: IoT (192.168.30.0/24) - WiFi MAC-based
- VLAN 40: Catch-All (192.168.1.0/24) - default

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:05:33 +02:00
49 changed files with 6751 additions and 630 deletions

135
CLAUDE.md Normal file
View File

@@ -0,0 +1,135 @@
# Home Network - Unraid Server
## Connect to Unraid
When user says "connect unraid", use this command:
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422
```
## Connect to Nobara (Failover Node)
```bash
ssh nobara
# or: ssh -i ~/.ssh/id_ed25519_nobara jazzymc@192.168.10.103
# sudo password: (same as SSH login)
```
Failover stack: `/home/failover/docker-compose.yml`
Keepalived: `systemctl status keepalived`
## Connect to MikroTik HAP ax³
SSH port is **2222** (not 22):
From Mac (user **xtrm**):
```bash
ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.1
```
From Unraid (user **unraid**):
```bash
ssh -p 2222 unraid@192.168.10.1
```
Alternative IPs (depending on your VLAN):
- VLAN 10 (Management): 192.168.10.1
- VLAN 20 (Trusted): 192.168.20.1
- VLAN 40 (Catch-All): 192.168.1.1
WinBox (port 8291) and WebFig (port 80) also available.
## Key Paths on Unraid Server
| Item | Path |
|------|------|
| Claude binary | `/root/.local/bin/claude` |
| Claude data | `/mnt/user/appdata/claude-code/` |
| Infrastructure repo | `/tmp/infrastructure` (git clone) |
## Infrastructure Documentation (Git-Managed)
**Repository:** https://git.xtrm-lab.org/jazzymc/infrastructure
All infrastructure documentation is version-controlled in Gitea:
```
infrastructure/
├── README.md
├── CLAUDE.md
└── docs/
├── 01-NETWORK-MAP.md # Network topology
├── 02-SERVICES-CRITICAL.md # P0/P1 services (DNS, Auth, Proxy)
├── 03-SERVICES-OTHER.md # Non-critical services
├── 04-HARDWARE-INVENTORY.md # Hardware list
├── 05-PORT-UTILIZATION.md # Device port assignments
├── 06-VLAN-DEVICE-ASSIGNMENT.md # VLAN device mapping
├── 07-WIFI-CAPSMAN-CONFIG.md # WiFi and CAPsMAN settings
├── 08-DNS-ARCHITECTURE.md # DNS failover architecture
├── 09-TAILSCALE-VPN.md # Tailscale VPN setup
├── 10-FAILOVER-NOBARA.md # VRRP failover to Nobara
├── CHANGELOG.md # Change history
├── archive/ # Completed/legacy docs
│ └── vlan-migration/ # VLAN migration project artifacts
├── incidents/ # Incident reports
└── wip/ # Work in progress
```
## On Connect - Clone/Pull Docs First
Always ensure you have the latest infrastructure documentation:
```bash
# Clone if not exists, or pull latest
cd /tmp && \
([ -d infrastructure ] && cd infrastructure && git pull || \
git clone 'https://jazzymc:zRuHTu%5D7Q3LC%2Bq%3F@git.xtrm-lab.org/jazzymc/infrastructure.git')
```
## Documentation Update Routine (Git-Based)
**IMPORTANT:** After any infrastructure change, commit to Git:
### When to Update
- Service added/removed/changed
- Container started/stopped/crashed
- NAT rules changed on MikroTik
- Network configuration changed
- Phase task completed or status changed
### Update Process
1. **Pull latest:** `cd /tmp/infrastructure && git pull`
2. **Check current state:** `docker ps -a` on Unraid
3. **Update docs:** Edit files in `/tmp/infrastructure/docs/`
4. **Commit & push:**
```bash
cd /tmp/infrastructure
git add docs/
git commit -m "Description of changes"
git push
```
### Changelog Format (docs/CHANGELOG.md)
```markdown
## YYYY-MM-DD
- [PHASE X] Task description - COMPLETED/FIXED/ISSUE
- [SERVICE] service-name: status change or config change
```
### Quick Status Check Command
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422 "docker ps -a --format 'table {{.Names}}\t{{.Status}}' | grep -vE '^NAMES'"
```
## GitOps Services
| Service | URL | Purpose |
|---------|-----|---------|
| Gitea | https://git.xtrm-lab.org | Git repository hosting |
| Woodpecker CI | https://ci.xtrm-lab.org | CI/CD pipelines |
| Dockge | http://192.168.10.20:5001 | Docker Compose stack management |
## Git Credentials (for automation)
- **Username:** jazzymc
- **Repo URL (with auth):** `https://jazzymc:zRuHTu%5D7Q3LC%2Bq%3F@git.xtrm-lab.org/jazzymc/infrastructure.git`

View File

@@ -1,6 +1,6 @@
# XTRM Home Lab Infrastructure
**Domain:** xtrm-lab.org
**Domain:** xtrm-lab.org
**Repository:** https://git.xtrm-lab.org/jazzymc/infrastructure
---
@@ -15,6 +15,7 @@
| **CI/CD** | https://ci.xtrm-lab.org |
| **DNS Primary** | dns.xtrm-lab.org |
| **DNS Secondary** | dns2.xtrm-lab.org |
| **Failover VIP** | 192.168.10.250 |
---
@@ -22,15 +23,21 @@
```
docs/
├── 01-NETWORK-MAP.md # Network topology, IPs, Docker networks
├── 02-SERVICES-CRITICAL.md # DNS, Auth, Routing - must stay up
├── 03-SERVICES-OTHER.md # All other services
├── 04-HARDWARE-INVENTORY.md # Physical devices, specs, serials
├── 00-CHANGELOG.md # Major events only
├── wip/ # Planned changes & ideas
│ ├── UPGRADE-2026-HARDWARE.md
│ └── GITOPS-CONTAINERS.md
── archive/ # Legacy docs (read-only)
├── 01-NETWORK-MAP.md # Network topology, IPs, Docker networks
├── 02-SERVICES-CRITICAL.md # DNS, Auth, Routing - must stay up
├── 03-SERVICES-OTHER.md # All other services
├── 04-HARDWARE-INVENTORY.md # Physical devices, specs, serials
├── 05-PORT-UTILIZATION.md # Device port assignments
├── 06-VLAN-DEVICE-ASSIGNMENT.md # VLAN device mapping
├── 07-WIFI-CAPSMAN-CONFIG.md # WiFi and CAPsMAN settings
├── 08-DNS-ARCHITECTURE.md # DNS failover architecture
── 09-TAILSCALE-VPN.md # Tailscale VPN setup
├── 10-FAILOVER-NOBARA.md # VRRP failover to Nobara workstation
├── CHANGELOG.md # Change history
├── archive/ # Completed/legacy docs
│ └── vlan-migration/ # VLAN migration project artifacts
├── incidents/ # Incident reports
└── wip/ # Work in progress
```
---
@@ -39,11 +46,12 @@ docs/
| Device | IP | Role |
|--------|-----|------|
| HAP1 | 192.168.31.1 | Router, DNS, WiFi Controller |
| XTRM-U | 192.168.31.2 | Production Server (Unraid) |
| CSS1 | 192.168.31.9 | Distribution Switch |
| ZX1 | 192.168.31.7 | Core Switch (2.5G) |
| CAP | 192.168.31.6 | Wireless Access Point |
| HAP1 | 192.168.10.1 | Router, DNS, WiFi Controller |
| XTRM-U | 192.168.10.20 | Production Server (Unraid) |
| XTRM-Nobara | 192.168.10.103 | Failover Node (Nobara Linux) |
| CSS1 | 192.168.10.3 | Distribution Switch |
| ZX1 | 192.168.10.4 | Core Switch (2.5G) |
| CAP | 192.168.10.6 | Wireless Access Point |
---
@@ -51,26 +59,30 @@ docs/
```bash
# Unraid
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.31.2 -p 422
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422
# MikroTik Router
ssh -i ~/.ssh/mikrotik_key -p 2222 unraid@192.168.31.1
ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.1
# Nobara (failover node)
ssh nobara
```
---
## Emergency Recovery
1. **DNS down?**Clients fallback to 192.168.31.4 (secondary)
2. **Internet down?** → Check HAP1 at 192.168.31.1
3. **Services down?** → Check Unraid at 192.168.31.2
4. **Full outage?** → See `02-SERVICES-CRITICAL.md` startup order
1. **DNS down?**Automatic failover to 192.168.10.10 (secondary), see `08-DNS-ARCHITECTURE.md`
2. **Internet down?** → Check HAP1 at 192.168.10.1
3. **Services down?** → Check Unraid at 192.168.10.20
4. **Unraid maintenance?** → VRRP failover to Nobara (192.168.10.250 VIP), see `10-FAILOVER-NOBARA.md`
5. **Full outage?** → See `02-SERVICES-CRITICAL.md` startup order
---
## Change Management
- **Major changes:** Document in `00-CHANGELOG.md`
- **Major changes:** Document in `CHANGELOG.md`
- **Minor changes:** Git commit messages only
- **Planned work:** Create doc in `wip/` folder

BIN
docs/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,118 +0,0 @@
# Infrastructure Changelog
**Purpose:** Major infrastructure events only. Minor changes are in git commit messages.
---
## 2026-01
### 2026-01-25
- **[INCIDENT]** DNS outage after MikroTik restart - multiple root causes fixed:
- NAT rules blocking AdGuard outbound DNS (added exception rules)
- DHCP pushing wrong DNS (8.8.8.8 → 192.168.31.1)
- NAT redirect pointing to wrong IP/port (172.17.0.5:5355 → 192.168.31.4:53)
- Asymmetric routing (added srcnat masquerade for DNS redirect)
- **[SERVICE]** Removed MikroTik AdGuard Home container (storage/overlay errors)
- **[SERVICE]** Removed MikroTik Tailscale container (root directory missing)
- **[SERVICE]** Removed Pi-hole/Unbound leftovers from MikroTik (veth, mounts, envs)
- **[NETWORK]** Consolidated DNS architecture: MikroTik → Unraid AdGuard (192.168.31.4) only
- **[DOCS]** Created incident reports in docs/incidents/
- **[DOCS]** Restructured documentation - consolidated into 5 core docs + archive
- **[NETBOX]** Added shelf devices for rack organization (U9, U7, U3)
### 2026-01-24
- **[NETBOX]** Standardized device names to NetBox convention (HAP1, CSS1, ZX1)
- **[DOCS]** Created NETWORK-PHYSICAL-MAP.md with complete port maps
### 2026-01-23
- **[SERVICE]** Deployed Diode network discovery stack
- **[SERVICE]** Removed Slurp'it (replaced by Diode + NetDisco)
- **[SERVICE]** Consolidated NetBox Redis to shared instance
- **[SERVICE]** Removed redundant DNS services (Unbound, DoH-Server, stunnel-dot)
### 2026-01-22
- **[SERVICE]** Migrated NetBox to shared PostgreSQL 17
- **[SERVICE]** Deployed AdGuard Home on MikroTik (primary DNS)
- **[SERVICE]** Deployed AdGuard Home on Unraid (secondary DNS)
- **[SERVICE]** Removed Pi-hole (replaced by AdGuard Home)
- **[DOCS]** Created INFRASTRUCTURE-DIAGRAM.md
### 2026-01-21
- **[BACKUP]** Configured Rclone sync to Google Drive
### 2026-01-19
- **[SERVICE]** Deployed NetBox IPAM/DCIM
- **[SERVICE]** Deployed NetDisco network discovery
- **[NETWORK]** Enabled SNMP on all MikroTik devices
### 2026-01-18
- **[SERVICE]** Deployed Gitea git server
- **[SERVICE]** Deployed Woodpecker CI
- **[NETWORK]** Configured CAPsMAN on HAP1
- **[WIRELESS]** CAP added to CAPsMAN management
### 2026-01-17
- **[SERVICE]** Deployed Portainer CE
---
## Format Guide
```markdown
### YYYY-MM-DD
- **[CATEGORY]** Brief description
Categories:
- [DEVICE] - Hardware added/removed/changed
- [SERVICE] - Container/service deployed/removed
- [NETWORK] - Network topology/config changes
- [WIRELESS] - WiFi/CAPsMAN changes
- [BACKUP] - Backup configuration
- [DOCS] - Major documentation changes
- [INCIDENT] - Outages and fixes
```
---
## Previous History
For detailed history before 2026-01-17, see archived changelogs:
- `archive/06-CHANGELOG.md`
- `archive/07-CHANGELOG.md`
- `archive/00-CHANGELOG.md`
## 2026-01-25
- [PHASE DNS] MikroTik AdGuard Home container installed - COMPLETED
- Container: adguardhome v0.107.71 on veth-adguard (172.17.0.2/24)
- Upstreams: 192.168.31.4 (Unraid AdGuard), 8.8.8.8, 1.1.1.1
- TLS enabled with Let's Encrypt cert for dns.xtrm-lab.org
- DoT on port 853, DoH on port 8443 (external)
- LAN DNS redirect updated to use MikroTik AdGuard
- Old docker-bridge removed (routing conflict)
- Web UI at http://192.168.31.1:3000
- [ISSUE] Container failed after restart with 'could not load config json'
- Fix: Removed and recreated container, added mountlists, restarted
- AdGuard config preserved (on separate mount)
- Documented fix in 09-MIKROTIK-ADGUARD-DOT-DOH.md
- [CONTAINERS] Created container bridge (containers-br) for shared networking
- Both AdGuard and Tailscale containers now use the same bridge
- Added NAT masquerade for container outbound traffic
- [SERVICE] Tailscale container installed and running
- Image: tailscale/tailscale:latest
- IP: 172.17.0.3/24 on veth-tailscale
- State persisted to usb1/tailscale/state
- Userspace mode enabled
## 2026-01-25 (VLAN Implementation)
- [VLAN] Created VLAN interfaces on bridge:
- VLAN 10: Management (192.168.10.0/24)
- VLAN 20: Trusted (192.168.20.0/24)
- VLAN 30: IoT (192.168.30.0/24)
- VLAN 35: Cameras (192.168.35.0/24)
- VLAN 40: Servers (192.168.40.0/24)
- VLAN 50: Guest (192.168.50.0/24)
- [VLAN] DHCP servers configured for all VLANs
- [VLAN] Inter-VLAN firewall rules created
- [VLAN] WiFi SSIDs created: Home-Trusted, Home-IoT, Home-Guest
- [STATUS] VLAN filtering NOT yet enabled (Phase 1 complete)
- [NOTE] Legacy 192.168.31.0/24 still active for transition

View File

@@ -1,6 +1,6 @@
# Network Map - xtrm-lab.org
**Last Updated:** 2026-01-25
**Last Updated:** 2026-02-14
**Domain:** xtrm-lab.org
**WAN IP:** 62.73.120.142
@@ -13,8 +13,8 @@
| **Dashboard** | https://xtrm-lab.org |
| **DNS Primary** | dns.xtrm-lab.org (HAP1) |
| **DNS Secondary** | dns2.xtrm-lab.org (XTRM-U) |
| **Unraid SSH** | `ssh -i ~/.ssh/id_ed25519_unraid root@192.168.31.2 -p 422` |
| **MikroTik SSH** | `ssh -i ~/.ssh/mikrotik_key -p 2222 unraid@192.168.31.1` |
| **Unraid SSH** | `ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422` |
| **MikroTik SSH** | `ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.1` |
---
@@ -27,27 +27,27 @@ flowchart TB
end
subgraph Rack19["19&quot; Rack (3U)"]
HAP1["HAP1 | hAP ax³<br/>192.168.31.1"]
HAP1["HAP1 | hAP ax³<br/>192.168.10.1"]
PP1["PP1 | 24-port"]
CSS1["CSS1 | CSS326-24G-2S+<br/>192.168.31.9"]
CSS1["CSS1 | CSS326-24G-2S+<br/>192.168.10.3"]
end
subgraph Rack10["10&quot; Rack (9U)"]
ZX1["ZX1 | ZX-SWTGW218AS<br/>192.168.31.22"]
ZX1["ZX1 | ZX-SWTGW218AS<br/>192.168.10.4"]
PP2["PP2 | 12-port"]
XTRMU["XTRM-U<br/>192.168.31.2"]
XTRMU["XTRM-U<br/>192.168.10.20"]
end
subgraph Wireless["WiFi"]
CAP["CAP | cAP XL ac<br/>192.168.31.6"]
CAP["CAP | cAP XL ac<br/>192.168.10.2"]
end
ISP -->|"H-1 WAN"| HAP1
HAP1 -->|"H-4 → ZX1-1"| ZX1
HAP1 -->|"H-3 → CSS1-1"| CSS1
ISP -->|"ether1 WAN"| HAP1
HAP1 -->|"ether2"| CAP
HAP1 -->|"ether3"| CSS1
HAP1 -->|"ether4"| XTRMU
HAP1 -->|"ether5"| DELL["Dell Monitor<br/>192.168.10.100"]
ZX1 <-->|"⚡ 10G SFP+ ⚡"| CSS1
ZX1 -->|"ZX1-2/3 via PP2"| XTRMU
HAP1 -->|"H-2 via PP1"| CAP
CSS1 -->|"Ports 16-24"| PP1
```
@@ -63,58 +63,66 @@ flowchart TB
|---|--------|-------|-----|-------|
| U9 | Shelf + ISP Gateway | Vivacom ONT | 62.73.120.2 | WAN |
| U8 | PP2 | 10" 12-port Cat6a | - | Patch panel |
| U7 | Shelf + ZX1 | ZX-SWTGW218AS | 192.168.31.22 | 8x2.5G + 2x10G SFP+ |
| U7 | Shelf + ZX1 | ZX-SWTGW218AS | 192.168.10.4 | 8x2.5G + 2x10G SFP+ |
| U6 | (empty) | - | - | Reserved for XTRM-N1 |
| U1-U4 | XTRM-U | NAS Server | 192.168.31.2 | 4x 2.5GbE bond |
| U1-U4 | XTRM-U | NAS Server | 192.168.10.20 | 4x 2.5GbE bond |
#### 19" Rack (3U)
| U | Device | Model | IP | Notes |
|---|--------|-------|-----|-------|
| U3 | Shelf + HAP1 | hAP ax³ | 192.168.31.1 | Router + WiFi controller |
| U3 | Shelf + HAP1 | hAP ax³ | 192.168.10.1 | Router + WiFi controller |
| U2.5 | PP1 | 19" 24-port Cat6a | - | Room connections |
| U1 | CSS1 | CSS326-24G-2S+ | 192.168.31.9 | 24x1G + 2x10G SFP+ |
| U1 | CSS1 | CSS326-24G-2S+ | 192.168.10.3 | 24x1G + 2x10G SFP+ |
### HAP ax³ Port Assignments
| Port | Connected To | VLAN | Notes |
|------|--------------|------|-------|
| ether1 | ISP Gateway | WAN | Vivacom ONT |
| ether2 | CAP XL ac | 10 (trunk) | Access Point |
| ether3 | CSS326-24G-2S+ | 10 (trunk) | Distribution Switch |
| ether4 | XTRM-U (Unraid) | 10 | Main Server |
| ether5 | Dell Monitor LAN | 10 | Kaloyan workstation |
### Backbone Links
| Link | From | To | Speed | Type |
|------|------|----|-------|------|
| **Primary** | ZX1-SFP1 | CSS1-SFP1 | 10G | SFP+ DAC |
| Router→Core | HAP1 H-4 | ZX1-1 | 2.5G | Cat6a |
| Router→Dist | HAP1 H-3 | CSS1-1 | 1G | Cat6a |
| Server Bond | ZX1-2/3 | XTRM-U via PP2 | 2x 2.5G | Cat6a |
| Router→CAP | HAP1 ether2 | CAP XL ac | 1G | Cat6a |
| Router→Dist | HAP1 ether3 | CSS1-1 | 1G | Cat6a |
| Router→Server | HAP1 ether4 | XTRM-U | 1G | Cat6a |
| Router→Dell | HAP1 ether5 | Dell Monitor | 1G | Cat6a |
---
## IP Address Allocation
### Network: 192.168.31.0/24
### VLAN Summary
#### Infrastructure Devices
| VLAN | Subnet | Gateway | Purpose |
|------|--------|---------|---------|
| 10 | 192.168.10.0/24 | 192.168.10.1 | Management |
| 20 | 192.168.20.0/24 | 192.168.20.1 | Trusted |
| 25 | 192.168.25.0/24 | 192.168.25.1 | Kids |
| 30 | 192.168.30.0/24 | 192.168.30.1 | IoT |
| 40 | 192.168.1.0/24 | 192.168.1.1 | CatchAll |
| IP | Device | Type | MAC |
|----|--------|------|-----|
| 192.168.31.1 | HAP1 \| hAP ax³ | Router | 78:9A:18:2C:A5:48 |
| 192.168.31.2 | XTRM-U | Server | A8:B8:E0:02:B6:15 |
| 192.168.31.6 | CAP \| cAP XL ac | Access Point | 18:FD:74:54:3D:BC |
| 192.168.31.22 | ZX1 \| ZX-SWTGW218AS | Switch | 1C:2A:A3:1E:78:67 |
| 192.168.31.9 | CSS1 \| CSS326-24G-2S+ | Switch | F4:1E:57:C9:BD:09 |
### VLAN 10 - Infrastructure Devices
#### Containers (br0 Macvlan)
| IP | Device | Type |
|----|--------|------|
| 192.168.10.1 | HAP1 \| hAP ax³ | Router |
| 192.168.10.3 | CSS1 \| CSS326-24G-2S+ | Switch |
| 192.168.10.4 | ZX1 \| ZX-SWTGW218AS | Switch |
| 192.168.10.2 | CAP \| cAP XL ac | Access Point |
| 192.168.10.10 | AdGuard Home (Unraid macvlan) | DNS Secondary |
| 192.168.10.20 | XTRM-U | Server |
| 192.168.10.103 | XTRM-Nobara | Failover Node |
| 192.168.10.200 | NanoKVM | Remote KVM |
| IP | Container | Purpose |
|----|-----------|---------|
| 192.168.31.4 | AdGuard Home | DNS Secondary |
| 192.168.31.5 | Unbound | Recursive DNS (stopped) |
| 192.168.31.12 | TimeMachine | macOS backups |
#### DHCP Ranges
| Range | Purpose |
|-------|---------|
| 192.168.31.10-99 | Reserved (static) |
| 192.168.31.100-200 | DHCP Pool |
| 192.168.31.201-254 | Reserved |
For complete device-to-VLAN mapping, see `06-VLAN-DEVICE-ASSIGNMENT.md`.
---
@@ -122,12 +130,12 @@ flowchart TB
### HAP1 (MikroTik Router)
**Network:** 172.17.0.0/16 (bridge)
**Network:** 172.17.0.0/24 (veth)
| Container | IP | Purpose |
|-----------|-----|---------|
| AdGuard Home | 172.17.0.5 | DNS Primary (DoH/DoT/DoQ) |
| Tailscale | 172.17.0.4 | VPN mesh |
| AdGuard Home | 172.17.0.2 | DNS Primary (DoH/DoT/DoQ) |
| Tailscale | 172.17.0.3 | VPN mesh |
### XTRM-U (Unraid Server)
@@ -236,13 +244,25 @@ flowchart TB
| External Port | Destination | Service |
|---------------|-------------|---------|
| 80 | 192.168.31.2:8001 | Traefik HTTP |
| 443 | 192.168.31.2:44301 | Traefik HTTPS |
| 853 | 172.17.0.5:853 | AdGuard DoT |
| 8853 | 172.17.0.5:8853 | AdGuard DoQ |
| 32400 | 192.168.31.2:32400 | Plex |
| 51413 | 192.168.31.2:51413 | Transmission |
| 21115-21119 | 192.168.31.2 | RustDesk |
| 80 | 192.168.10.20:8001 | Traefik HTTP |
| 443 | 192.168.10.20:44301 | Traefik HTTPS |
| 32400 | 192.168.10.20:32400 | Plex |
| 51413 | 192.168.10.20:51413 | Transmission |
| 21115-21119 | 192.168.10.20 | RustDesk |
### Hairpin NAT (internal access to WAN IP)
| Destination | To | Service |
|-------------|-----|---------|
| 62.73.120.142:80 | 192.168.10.20:8001 | Traefik HTTP |
| 62.73.120.142:443 | 192.168.10.20:44301 | Traefik HTTPS |
### AdGuard DNS (pending - not configured yet)
| External Port | Destination | Service |
|---------------|-------------|---------|
| 853 | 172.17.0.2:853 | AdGuard DoT |
| 8853 | 172.17.0.2:8853 | AdGuard DoQ |
---
@@ -256,11 +276,11 @@ flowchart TB
end
subgraph HAP1["HAP1 (Primary)"]
AGH1["AdGuard Home<br/>172.17.0.5"]
AGH1["AdGuard Home<br/>172.17.0.2"]
end
subgraph XTRMU["XTRM-U (Secondary)"]
AGH2["AdGuard Home<br/>192.168.31.4"]
AGH2["AdGuard Home<br/>192.168.10.10"]
end
subgraph Sync["Sync"]
@@ -282,10 +302,9 @@ flowchart TB
| SSID | Band | Security | Purpose |
|------|------|----------|---------|
| XTRM | 5GHz | WPA2/WPA3 | Primary devices |
| XTRM | 2.4GHz | WPA/WPA2 | Legacy support |
| XTRM2 | 2.4GHz | WPA/WPA2 | IoT devices |
**CAPsMAN:** HAP1 manages CAP access point
**CAPsMAN:** HAP1 manages CAP XL ac (192.168.10.2) - both 2.4GHz and 5GHz radios active
---
@@ -306,15 +325,42 @@ flowchart TB
---
## CSS326 Port Assignments (Configured 2026-02-02)
| Port | Label | Device/Room | VLAN | Notes |
|------|-------|-------------|------|-------|
| 1 | HAP-Trunk | HAP Uplink | Trunk | 10,20,25,30 tagged |
| 2 | KVM-V10 | NanoKVM | 10 | Management |
| 3-15 | - | - | 1 | Available |
| 16 | Kids-B1 | Boys Room | 25 | Family VLAN |
| 17 | Kids-B2 | Boys Room | 25 | Family VLAN |
| 18 | Kids-G1 | Girls Room | 25 | Family VLAN |
| 19 | Main-M1 | Main Bedroom | 20 | Trusted VLAN |
| 20 | Main-M2 | Main Bedroom | 20 | Trusted VLAN |
| 21 | Main-M3 | Main Bedroom | 20 | Trusted VLAN |
| 22 | LR-L1 | Living Room | 30 | IoT VLAN |
| 23 | LR-L2 | Living Room | 30 | IoT VLAN (Settop box) |
| 24 | LR-L3 | Living Room | 30 | IoT VLAN |
| SFP1 | ZX1-10G | ZX1 Switch | Trunk | 10G Backbone |
| SFP2 | - | - | 1 | Available |
## Room Outlets
| Room | Outlets | Switch Ports | Status |
|------|---------|--------------|--------|
| Living Room | L1, L2, L3 | CSS1-22/23/24 | Active |
| Main Bedroom | M1, M2, M3 | CSS1-19/20/21 | Active |
| Boys Room | B1, B2 | CSS1-17/18 | Active |
| Girls Room | G1 | CSS1-16 | Unused |
| Corridor | C1 (CAP) | HAP1 H-2 | Active |
| Room | Outlets | Switch Ports | VLAN | Status |
|------|---------|--------------|------|--------|
| Living Room | L1, L2, L3 | CSS1-22/23/24 | 30 | Active |
| Main Bedroom | M1, M2, M3 | CSS1-19/20/21 | 20 | Active |
| Boys Room | B1, B2 | CSS1-17/18 | 25 | Active |
| Girls Room | G1 | CSS1-16 | 25 | Active |
| Corridor | C1 (CAP) | HAP1 ether2 | 10 | Active |
---
## SMB Shares
| Share | Path | Size | Access | Consumers |
|-------|------|------|--------|-----------|
| roms | /mnt/user/roms | 2.3 TB | Guest (read-only) | Nobara (/mnt/roms), Recalbox (network mount) |
---

View File

@@ -1,6 +1,6 @@
# Critical Services
**Last Updated:** 2026-01-25
**Last Updated:** 2026-01-31
Services that must remain operational for network functionality and security.
@@ -21,21 +21,23 @@ Services that must remain operational for network functionality and security.
| Instance | Host | IP | Role |
|----------|------|-----|------|
| Primary | HAP1 | 172.17.0.5 | Main DNS, DoH/DoT/DoQ |
| Secondary | XTRM-U | 192.168.31.4 | Failover DNS |
| Primary | HAP1 (container) | 172.17.0.2 | Main DNS |
| Secondary | XTRM-U (macvlan) | 192.168.10.10 | Failover DNS |
**Endpoints:**
- DoH: `https://dns.xtrm-lab.org/dns-query`
- DoT: `tls://dns.xtrm-lab.org:853`
- DoQ: `quic://dns.xtrm-lab.org:8853`
**Failover:** Automatic via Netwatch (ping + DNS resolution checks)
**Config Sync:** adguardhome-sync (every 30 min)
**Config Sync:** adguardhome-sync (every 30 min, Unraid → MikroTik)
**Upstream:** Quad9 DoH (`https://dns10.quad9.net/dns-query`)
**Upstream:** Quad9 DoH (`https://dns.quad9.net/dns-query`)
**Web UI:**
- Primary: http://192.168.10.1:3000
- Secondary: http://192.168.10.10:3000
- Credentials: jazzymc / 7RqWElENNbZnPW
**Recovery:**
1. If primary fails → clients use secondary (192.168.31.4)
2. Restart container on HAP1: `/container/start adguardhome`
1. If primary fails → automatic failover to secondary (192.168.10.10)
2. Manual restart: `/container start [find name~"adguard"]`
---
@@ -44,25 +46,28 @@ Services that must remain operational for network functionality and security.
| Function | Details |
|----------|---------|
| WAN | 62.73.120.142 via Vivacom fiber |
| LAN | 192.168.31.0/24 |
| NAT | Port forwarding to XTRM-U |
| VLANs | 10 (Mgmt), 20 (Trusted), 25 (Kids), 30 (IoT), 40 (CatchAll) |
| NAT | Port forwarding to XTRM-U (192.168.10.20) |
| Firewall | RouterOS firewall rules |
**Recovery:**
1. Physical access to HAP1
2. Reset: hold reset button 5s
3. Reconfigure via WinBox or SSH
3. Reconfigure via WinBox or SSH (port 2222)
---
### DHCP (HAP1)
| Pool | Range |
|------|-------|
| Dynamic | 192.168.31.100-200 |
| Lease Time | 24 hours |
| VLAN | Pool | Range |
|------|------|-------|
| 10 (Mgmt) | pool-vlan10 | 192.168.10.100-200 |
| 20 (Trusted) | pool-vlan20 | 192.168.20.100-200 |
| 25 (Kids) | pool-vlan25 | 192.168.25.100-200 |
| 30 (IoT) | pool-vlan30 | 192.168.30.100-200 |
| 40 (CatchAll) | dhcp | 192.168.1.10-254 |
**Static Leases:** Managed in RouterOS DHCP server
**Lease Time:** 30 minutes
---
@@ -199,6 +204,25 @@ When recovering from full outage:
---
## Active Failover: XTRM-Nobara
Critical services are replicated on the Nobara workstation with automatic VRRP failover:
| Service | Primary (XTRM-U) | Failover (XTRM-Nobara) |
|---------|-------------------|------------------------|
| Traefik | 192.168.10.20 | 192.168.10.103 |
| Vaultwarden | 192.168.10.20 | 192.168.10.103 |
| Authentik | 192.168.10.20 | 192.168.10.103 |
| AdGuard Home | 192.168.10.20 | 192.168.10.103 |
**VIP:** 192.168.10.250 (floats between XTRM-U and XTRM-Nobara via Keepalived VRRP)
**Failover time:** ~4 seconds
See: `10-FAILOVER-NOBARA.md` for full documentation.
---
## Future: XTRM-N1 Survival Node
When hardware upgrade completes, these services will have replicas on XTRM-N1:

View File

@@ -1,6 +1,6 @@
# Other Services
**Last Updated:** 2026-01-25
**Last Updated:** 2026-02-24
Non-critical services that enhance functionality but don't affect core network operation.
@@ -64,7 +64,7 @@ Non-critical services that enhance functionality but don't affect core network o
| diode-auth | 172.18.0.74 | Token service |
| diode-agent | host | Network scanner |
**Discovery:** 192.168.31.0/24 every 30 minutes
**Discovery:** 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24 every 30 minutes
### Unimus
@@ -104,6 +104,26 @@ Non-critical services that enhance functionality but don't affect core network o
---
## Gaming
### Minecraft Server
| Component | IP | Port | Address |
|-----------|-----|------|---------|
| minecraft | 172.18.0.80 | 25565 | minecraft.xtrm-lab.org |
**Image:** itzg/minecraft-server (Java Edition)
**Version:** Latest (1.21.11)
**Mode:** Survival, Normal difficulty, PVP enabled
**Max Players:** 10
**RAM:** 2 GB
**Online Mode:** Yes (requires paid account)
**Data:** `/mnt/user/appdata/minecraft/data`
**NAT:** WAN:25565 → 192.168.10.20:25565 + hairpin NAT
**Dockge Stack:** `minecraft`
---
## Media
### Plex
@@ -130,6 +150,23 @@ Non-critical services that enhance functionality but don't affect core network o
**Purpose:** Torrent client
### Roms (SMB Share)
| Property | Value |
|----------|-------|
| Share Path | /mnt/user/roms |
| Protocol | SMB (guest access, read-only) |
| Size | 2.3 TB (49 systems) |
**Consumers:**
| Device | Mount Point | Method |
|--------|-------------|--------|
| Nobara | /mnt/roms | fstab (CIFS, guest, systemd.automount) |
| Recalbox | /recalbox/share/roms_network | custom.sh boot script (CIFS) |
**Recalbox:** Network roms are bind-mounted over local rom directories at boot via `/recalbox/share/system/custom.sh`. Local roms were deleted from SD card to save space.
---
## Productivity
@@ -182,7 +219,7 @@ Non-critical services that enhance functionality but don't affect core network o
| Network | IP |
|---------|-----|
| br0 macvlan | 192.168.31.12 |
| br0 macvlan | 192.168.10.12 |
**Purpose:** macOS Time Machine backup target
@@ -219,7 +256,7 @@ Non-critical services that enhance functionality but don't affect core network o
| Host | IP |
|------|-----|
| HAP1 | 172.17.0.4 |
| HAP1 | 172.17.0.3 |
**Purpose:** Mesh VPN for remote access
@@ -239,14 +276,16 @@ Non-critical services that enhance functionality but don't affect core network o
## Container Management
### Portainer
### Dockge
| Network | Port |
|---------|------|
| bridge | 9002 |
| bridge | 5001 |
**Purpose:** Docker container management UI
**Access:** http://192.168.31.2:9002 or via Tailscale
**Purpose:** Docker Compose stack management UI
**Access:** http://192.168.10.20:5001
**Data:** `/mnt/user/appdata/dockge/data`
**Stacks:** `/mnt/user/appdata/dockge/stacks`
---
@@ -254,9 +293,15 @@ Non-critical services that enhance functionality but don't affect core network o
| Service | Reason | Status |
|---------|--------|--------|
| Portainer | Replaced by Dockge | Removed |
| Unbound | Redundant (AdGuard upstream) | Stopped |
| DoH-Server | Redundant (AdGuard built-in) | Removed |
| stunnel-dot | Redundant (AdGuard built-in) | Removed |
| Pi-hole | Replaced by AdGuard Home | Removed |
| Pangolin | Not in use | Removed |
| Slurp'it | Replaced by Diode | Removed |
| binhex-plexpass | Duplicate of Plex | Removed |
| HomeAssistant_inabox | Duplicate of Home-Assistant-Container | Removed |
| Docker-WebUI | Unused, non-functional | Removed |
| hass-unraid | No config, unused | Removed |
| nextcloud-aio-mastercontainer | Replaced by Nextcloud container | Removed |

View File

@@ -1,219 +0,0 @@
# VLAN Device Assignment Map
**Last Updated:** 2026-01-25
**Status:** Phase 1 Complete - Ready for Switch Configuration
**Purpose:** Complete inventory of all network devices with VLAN assignments
---
## VLAN Summary
| VLAN | Name | Subnet | Gateway | Purpose | Devices |
|------|------|--------|---------|---------|---------|
| 1 | Legacy | 192.168.31.0/24 | 192.168.31.1 | Current flat network | To be deprecated |
| 10 | Mgmt | 192.168.10.0/24 | 192.168.10.1 | Infrastructure devices | 6 |
| 20 | Trusted | 192.168.20.0/24 | 192.168.20.1 | Family personal devices | 9 |
| 25 | Kids | 192.168.25.0/24 | 192.168.25.1 | Kids devices | 6 |
| 30 | IoT | 192.168.30.0/24 | 192.168.30.1 | Smart home devices | 14 |
| 35 | Cameras | 192.168.35.0/24 | 192.168.35.1 | Security cameras | 1 |
| 40 | Servers | 192.168.40.0/24 | 192.168.40.1 | Servers & printers | 1 |
| 50 | Guest | 192.168.50.0/24 | 192.168.50.1 | Guest WiFi | 7 |
| **Total** | | | | | **44** |
---
## VLAN 10 - Management (Infrastructure)
| Target IP | MAC Address | Device | Notes |
|-----------|-------------|--------|-------|
| 192.168.10.1 | 78:9A:18:2C:A5:48 | HAP1 (hAP ax³) | Router - Gateway for all VLANs |
| 192.168.10.2 | 18:FD:74:54:3D:BC | CAP XL ac | Access point - CAPsMAN managed |
| 192.168.10.3 | F4:1E:57:C9:BD:09 | CSS326-24G-2S+ | 24-port switch - Room distribution |
| 192.168.10.4 | 1C:2A:A3:1E:78:67 | ZX1 (ZX-SWTGW218AS) | 8-port 2.5G switch - Server rack |
| 192.168.10.10 | 02:42:C0:A8:1F:04 | AdGuard Home | DNS server (Unraid Docker) |
| 192.168.10.11 | 48:DA:35:6F:BE:50 | NanoKVM | Remote KVM - IPMI alternative |
| 192.168.10.20 | A8:B8:E0:02:B6:15 | XTRM-U (Unraid) | Main server - Docker host, NAS |
**Note:** Router containers (AdGuard MikroTik 172.17.0.2, Tailscale 172.17.0.3) are on containers-br bridge, not VLANs.
---
## VLAN 20 - Trusted (Family Devices)
| Target IP | MAC Address | Device | Owner |
|-----------|-------------|--------|-------|
| 192.168.20.10 | 82:6D:FB:D9:E0:47 | MacBook Air | Nora |
| 192.168.20.11 | AA:ED:8B:2A:40:F1 | Samsung S25 Ultra | Kaloyan |
| 192.168.20.12 | F2:B8:14:61:C8:27 | iPhone | Dancho |
| 192.168.20.13 | 82:EC:EF:B5:F2:AF | MacBook Pro (WiFi) | Kaloyan |
| 192.168.20.14 | 90:91:64:70:0D:86 | Notebook | Kimi |
| 192.168.20.15 | 2A:2B:BA:86:D4:AF | iPhone | Kimi |
| 192.168.20.16 | 08:92:04:C6:07:C5 | MacBook Pro (LAN) | Kaloyan |
| 192.168.20.17 | 1C:83:41:32:F3:AF | Gaming PC | Kaloyan |
| 192.168.20.18 | A4:D1:D2:7B:52:BE | iPad | Compusbg |
---
## VLAN 25 - Kids (Parental Controls)
| Target IP | MAC Address | Device | Owner |
|-----------|-------------|--------|-------|
| 192.168.25.12 | F2:B8:14:61:C8:27 | iPhone | Dancho |
| 192.168.25.13 | 70:85:C2:75:64:E5 | Windows Device | Dancho |
| 192.168.25.14 | 90:91:64:70:0D:86 | Notebook | Kimi |
| 192.168.25.15 | 2A:2B:BA:86:D4:AF | iPhone | Kimi |
| 192.168.25.18 | A4:D1:D2:7B:52:BE | iPad | Compusbg |
| 192.168.25.19 | CC:5E:F8:D3:37:D3 | XTRM-Ally | Kids Gaming |
**Note:** Some devices appear in both VLAN 20 and 25 - assignment depends on which SSID/port they connect to.
---
## VLAN 30 - IoT (Smart Home)
| Target IP | MAC Address | Device | Location |
|-----------|-------------|--------|----------|
| 192.168.30.10 | 50:2C:C6:7A:55:39 | GREE Air Conditioner | Living Room |
| 192.168.30.11 | B0:37:95:79:AF:9B | LG TV (LAN) | Living Room |
| 192.168.30.12 | DC:03:98:6B:5A:3A | LG TV (WiFi) | Living Room |
| 192.168.30.13 | D0:E7:82:F7:65:DD | Chromecast | Living Room |
| 192.168.30.14 | B0:4A:39:3F:9A:14 | Roborock S7 Vacuum | Living Room |
| 192.168.30.20 | 94:27:70:1E:0C:EE | Bosch Smart Oven | Kitchen |
| 192.168.30.21 | C8:D7:78:40:65:40 | Bosch Dishwasher | Kitchen |
| 192.168.30.22 | C8:D7:78:D6:DC:FC | Bosch Washer | Kids Bathroom |
| 192.168.30.31 | 18:DE:50:5B:C8:A6 | Tuya Smart Device 1 | - |
| 192.168.30.32 | 38:1F:8D:04:6F:E4 | Tuya Smart Device 2 | - |
| 192.168.30.33 | 38:A5:C9:44:7B:80 | IoT lwip0 Device 1 | - |
| 192.168.30.34 | 38:A5:C9:44:7B:F1 | IoT lwip0 Device 2 | - |
| 192.168.30.38 | D4:AD:FC:BE:13:B0 | Shenzhen Intellirocks | - |
| 192.168.30.39 | C8:5C:CC:52:EA:53 | Xiaomi Air Purifier | - |
---
## VLAN 35 - Cameras (Security)
| Target IP | MAC Address | Device | Location |
|-----------|-------------|--------|----------|
| 192.168.35.10 | 48:9E:9D:0E:16:F7 | Reolink Doorbell | Front door |
---
## VLAN 40 - Servers (Services)
| Target IP | MAC Address | Device | Purpose |
|-----------|-------------|--------|---------|
| 192.168.40.19 | 64:4E:D7:D8:43:3E | HP LaserJet | Network printer |
---
## VLAN 50 - Guest (Isolated)
| Target IP | MAC Address | Device | Notes |
|-----------|-------------|--------|-------|
| 192.168.50.10 | AC:87:A3:77:8F:BD | Apple Device | Unknown owner |
| 192.168.50.11 | 22:4C:7F:1D:85:8E | Unknown Device | Privacy MAC |
| 192.168.50.12 | D0:C9:07:92:1A:8E | Unknown Device | Private vendor |
| 192.168.50.13 | D0:C9:07:8C:C9:46 | Unknown Device | Private vendor |
| 192.168.50.14 | C6:2A:59:AD:17:90 | Unknown Device | Random MAC |
| 192.168.50.15 | E6:17:3D:D3:96:D3 | Unknown Device | Random MAC |
| 192.168.50.16 | 72:F5:14:2D:F0:18 | Unknown Device | Stale |
---
## MAC Address Quick Reference
### VLAN 10 - Management
```
78:9A:18:2C:A5:48 HAP1 Router
18:FD:74:54:3D:BC CAP XL ac
F4:1E:57:C9:BD:09 CSS326 Switch
1C:2A:A3:1E:78:67 ZX1 Switch
02:42:C0:A8:1F:04 AdGuard Home
48:DA:35:6F:BE:50 NanoKVM
A8:B8:E0:02:B6:15 XTRM-U Unraid
```
### VLAN 20 - Trusted
```
82:6D:FB:D9:E0:47 Nora MacBook
AA:ED:8B:2A:40:F1 Kaloyan S25
F2:B8:14:61:C8:27 Dancho iPhone
82:EC:EF:B5:F2:AF Kaloyan MacBook WiFi
90:91:64:70:0D:86 Kimi Notebook
2A:2B:BA:86:D4:AF Kimi iPhone
08:92:04:C6:07:C5 Kaloyan MacBook LAN
1C:83:41:32:F3:AF Kaloyan Gaming PC
A4:D1:D2:7B:52:BE Compusbg iPad
```
### VLAN 25 - Kids
```
F2:B8:14:61:C8:27 Dancho iPhone
70:85:C2:75:64:E5 Dancho Windows
90:91:64:70:0D:86 Kimi Notebook
2A:2B:BA:86:D4:AF Kimi iPhone
A4:D1:D2:7B:52:BE Compusbg iPad
CC:5E:F8:D3:37:D3 XTRM-Ally
```
### VLAN 30 - IoT
```
50:2C:C6:7A:55:39 GREE AC
B0:37:95:79:AF:9B LG TV (LAN)
DC:03:98:6B:5A:3A LG TV (WiFi)
D0:E7:82:F7:65:DD Chromecast
B0:4A:39:3F:9A:14 Roborock Vacuum
94:27:70:1E:0C:EE Bosch Oven
C8:D7:78:40:65:40 Bosch Dishwasher
C8:D7:78:D6:DC:FC Bosch Washer
18:DE:50:5B:C8:A6 Tuya Device 1
38:1F:8D:04:6F:E4 Tuya Device 2
38:A5:C9:44:7B:80 lwip0 Device 1
38:A5:C9:44:7B:F1 lwip0 Device 2
D4:AD:FC:BE:13:B0 Intellirocks
C8:5C:CC:52:EA:53 Xiaomi Air Purifier
```
### VLAN 35 - Cameras
```
48:9E:9D:0E:16:F7 Reolink Doorbell
```
### VLAN 40 - Servers
```
64:4E:D7:D8:43:3E HP LaserJet
```
### VLAN 50 - Guest
```
AC:87:A3:77:8F:BD Unknown Apple
22:4C:7F:1D:85:8E Unknown Random MAC
D0:C9:07:92:1A:8E Unknown Private 1
D0:C9:07:8C:C9:46 Unknown Private 2
C6:2A:59:AD:17:90 Unknown .138
E6:17:3D:D3:96:D3 Unknown .250
72:F5:14:2D:F0:18 Unknown Stale
```
---
## Configuration Status
### MikroTik hAP ax³ ✅
- [x] VLAN interfaces created (10, 20, 25, 30, 35, 40, 50)
- [x] IP addresses assigned to all VLANs
- [x] DHCP servers configured for all VLANs
- [x] DHCP pools configured
- [x] Static DHCP leases (44 devices)
- [x] Bridge VLAN table entries
- [x] Firewall rules for inter-VLAN isolation
- [ ] VLAN filtering enabled (pending switch config)
### CSS326 Switch ⏳
- [ ] VLAN configuration via SwOS
- [ ] Port assignments
### Next Steps
1. Configure CSS326 switch VLANs via SwOS (http://192.168.31.9)
2. Enable VLAN filtering on MikroTik bridge
3. Test connectivity

View File

@@ -1,6 +1,6 @@
# Hardware Inventory
**Last Updated:** 2026-01-25
**Last Updated:** 2026-02-24
---
@@ -12,7 +12,7 @@
|----------|-------|
| **Role** | Router, WiFi Controller, DNS |
| **Location** | 19" Rack U3 (on shelf) |
| **IP** | 192.168.31.1 |
| **IP** | 192.168.10.1 |
| **MAC** | 78:9A:18:2C:A5:48 |
| **OS** | RouterOS 7.20.6 |
| **Serial** | - |
@@ -36,10 +36,12 @@
|----------|-------|
| **Role** | Distribution Switch |
| **Location** | 19" Rack U1 |
| **IP** | 192.168.31.9 |
| **IP** | 192.168.10.3 |
| **MAC** | F4:1E:57:C9:BD:09 |
| **OS** | SwOS |
| **OS** | SwOS 2.16 |
| **Serial** | - |
| **Docs** | https://help.mikrotik.com/docs/spaces/UM/pages/17498168/CSS326-24G-2S+RM |
| **Web UI** | http://192.168.10.3 |
**Ports:** 24x 1G RJ45, 2x 10G SFP+
- SFP1: 10G DAC to ZX1
@@ -53,7 +55,7 @@
|----------|-------|
| **Role** | Core Switch (2.5GbE) |
| **Location** | 10" Rack U7 (on shelf) |
| **IP** | 192.168.31.7 |
| **IP** | 192.168.10.4 |
| **MAC** | 1C:2A:A3:1E:78:67 |
| **Serial** | - |
@@ -73,12 +75,15 @@
|----------|-------|
| **Role** | Wireless Access Point |
| **Location** | Corridor (ceiling) |
| **IP** | 192.168.31.6 |
| **IP** | 192.168.10.2 |
| **MAC** | 18:FD:74:54:3D:BC |
| **OS** | RouterOS 7.x |
| **OS** | RouterOS 7.21.1 |
| **Serial** | HCT085KBH8B |
| **SSH** | `ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.2` |
**Managed by:** HAP1 CAPsMAN
**Radios:** wifi1 (2.4GHz XTRM2), wifi2 (5GHz XTRM) - both active
**Factory reset:** 2026-02-13 (CAPsMAN certificate regenerated)
---
@@ -101,27 +106,35 @@
|----------|-------|
| **Role** | Production Server |
| **Location** | 10" Rack U1-U4 |
| **IP** | 192.168.31.2 |
| **IP** | 192.168.10.20 |
| **OS** | Unraid 6.x |
**Motherboard:** Replaced 2026-02-24 (new board, details TBD)
**Network:**
| Interface | MAC | Speed |
|-----------|-----|-------|
| eth1 | A8:B8:E0:02:B6:15 | 2.5G |
| eth2 | A8:B8:E0:02:B6:16 | 2.5G |
| eth3 | A8:B8:E0:02:B6:17 | 2.5G |
| eth4 | A8:B8:E0:02:B6:18 | 2.5G |
| **bond0** | (virtual) | 5G aggregate |
| br0 | 38:05:25:35:8E:7A | 2.5G |
**Storage:**
- Cache: (current NVMe)
- Array: 3.5" HDDs
**Storage:**
| Device | Model | Size | Role | Status |
|--------|-------|------|------|--------|
| sdb | HUH721010ALE601 (serial 7PHBNYZC) | 10TB | Parity | OK |
| disk1 | HUH721010ALE601 (serial 2TKK3K1D) | 10TB | Data (ZFS) | **FAILED** — clicking/head crash, emulated from parity |
| nvme0n1 | Samsung 990 EVO Plus 1TB | 1TB | Cache pool (RAIDZ1) | OK |
| nvme1n1 | Samsung 990 EVO Plus 1TB | 1TB | Cache pool (RAIDZ1) | OK |
| nvme2n1 | Samsung 990 EVO Plus 1TB | 1TB | Cache pool (RAIDZ1) | OK |
**ZFS Pools:**
| Pool | Devices | Profile | Usable | Purpose |
|------|---------|---------|--------|---------|
| disk1 | md1p1 (parity-emulated) | single | 9.1TB | Main data (roms, media, appdata, backups) |
| cache | 3x Samsung 990 EVO Plus 1TB NVMe | RAIDZ1 | ~1.8TB | Docker, containers |
**Virtual IPs:**
| IP | Purpose |
|----|---------|
| 192.168.31.4 | AdGuard Home (macvlan) |
| 192.168.31.15 | (reserved) |
| 192.168.10.10 | AdGuard Home (macvlan) - DNS Failover |
---
@@ -159,16 +172,56 @@
---
## Workstations
### XTRM-Nobara | Nobara Linux Workstation
| Property | Value |
|----------|-------|
| **Role** | Workstation + Failover Node |
| **Location** | Main Bedroom |
| **IP** | 192.168.10.103 |
| **MAC** | 08:92:04:C6:07:C5 |
| **OS** | Nobara Linux (Fedora 43 based) |
| **CPU** | AMD Ryzen 9 6900HX (8C/16T) |
| **RAM** | 16 GB |
| **Storage** | 477GB NVMe (OS) + 1.8TB NVMe (btrfs pool with OS drive) |
| **Network** | enp5s0 (2.5G Ethernet) |
| **Switch Port** | CSS1-20 via PP1 M2 |
| **SSH** | `ssh nobara` (key: ~/.ssh/id_ed25519_nobara) |
**Failover Services:** Traefik, Vaultwarden, Authentik, AdGuard Home
**Keepalived:** systemd service, BACKUP priority 100, VIP 192.168.10.250
---
## End Devices (Wired)
| Device | Room | Outlet | Switch Port | MAC |
|--------|------|--------|-------------|-----|
| LGTV | Living Room | L3 | CSS1-24 | - |
| XTRM-Nobara | Main Bedroom | M2 | CSS1-20 | 08:92:04:C6:07:C5 |
| Dell Display | Main Bedroom | M3 | CSS1-21 | - |
| Dancho | Boys Room | B1 | CSS1-18 | - |
| KVM Switch | - | Direct | CSS1-2 | - |
## End Devices (WiFi)
### Recalbox | Raspberry Pi 3
| Property | Value |
|----------|-------|
| **Role** | Retro Gaming Console |
| **Location** | Living Room |
| **IP** | 192.168.25.30 |
| **MAC** | B8:27:EB:32:B2:13 |
| **OS** | Recalbox |
| **VLAN** | 25 (Kids) |
| **SSID** | XTRM2 (2.4GHz) |
| **SSH** | `ssh root@192.168.25.30` (password: `recalboxroot`) |
**Roms:** Network-mounted from Unraid SMB share (//192.168.10.20/roms)
**Boot script:** `/recalbox/share/system/custom.sh` (mounts roms at boot)
---
## Future Hardware (Planned)
@@ -179,6 +232,7 @@ See: `wip/UPGRADE-2026-HARDWARE.md`
|--------|------|--------|
| XTRM-N5 (Minisforum N5 Air) | Production server | Planned |
| XTRM-N1 (N100 ITX) | Survival node | Planned |
| 3x Samsung 990 EVO Plus 1TB | XTRM-N5 NVMe pool | Planned |
| 3x Samsung 990 EVO Plus 1TB | XTRM-U cache pool (RAIDZ1) | **Installed** 2026-02-24 |
| 2x Fikwot FX501Pro 512GB | XTRM-N1 mirror | Planned |
| 1x 10TB+ HDD | Replace failed disk1 | **Needed** |
| MikroTik CRS310-8G+2S+IN | Replace ZX1 | Future |

View File

@@ -1,11 +1,11 @@
# Device Port Utilization
**Last Updated:** 2026-01-25
**Last Updated:** 2026-02-06
**Legend:** 🟢 Connected | ⚪ Enabled/No Link | 🔘 Disabled | 🩷 High Speed (≥2.5G)
---
## HAP1 | MikroTik hAP ax³ (192.168.31.1)
## HAP1 | MikroTik hAP ax³ (192.168.10.1)
```
┌─────────────────────────────────────────────────────────┐
@@ -29,7 +29,7 @@ Connections:
---
## CSS1 | MikroTik CSS326-24G-2S+ (192.168.31.9)
## CSS1 | MikroTik CSS326-24G-2S+ (192.168.10.3)
```
┌───────────────────────────────────────────────────────────────────────────┐
@@ -68,7 +68,7 @@ Port Details:
---
## ZX1 | ZX-SWTGW218AS (192.168.31.22)
## ZX1 | ZX-SWTGW218AS (192.168.10.4)
```
┌─────────────────────────────────────────────────────────┐

View File

@@ -1,141 +0,0 @@
# Infrastructure Changelog
## 2026-01-27
### VLAN Filtering Rolled Back
- [VLAN] Enabled VLAN filtering - caused connectivity issues
- [VLAN] ZX1 switch unreachable after activation (no management IP responding)
- [VLAN] CSS326 traffic routing through ZX1 (not direct eth3 link)
- [VLAN] **Rolled back** - VLAN filtering disabled
- [CONFIG] Added eth4 (ZX1) to all VLAN tagged lists for future use
- [STATUS] Network back to Legacy mode (192.168.31.0/24)
- [TODO] Need physical access to ZX1 to configure VLAN trunking
### Issues Identified
- ZX1 switch not responding on documented IP 192.168.31.22
- ZX1 may need VLAN trunk configuration before re-enabling filtering
- All CSS326 traffic goes via ZX1→HAP1, not direct CSS326→HAP1 link (STP?)
# Infrastructure Changelog
## 2026-01-26
### VLAN Filtering Activated ✅
- [VLAN] **VLAN filtering enabled on MikroTik bridge - SUCCESSFUL**
- [VLAN] Internet connectivity verified (ping 1.1.1.1, google.com)
- [VLAN] DNS resolution working through AdGuard
- [VLAN] All previous fixes (DHCP DNS, firewall, NAT masquerade) working correctly
- [STATUS] Network segmentation now ACTIVE
### Local AI Stack Deployed
- [AI] Deployed Ollama container with Intel GPU passthrough
- [AI] Deployed Open WebUI at http://192.168.31.2:3080
- [AI] Installed qwen2.5-coder:7b base model
- [AI] Created custom `unraid-assistant` model with infrastructure knowledge:
- Network topology (all VLANs, IPs, gateways)
- 45+ Docker containers (names, ports, purposes)
- RouterOS 7 commands and patterns
- Traefik labels and Authentik middleware
- All external URLs (xtrm-lab.org)
- [AI] Created `/usr/local/bin/ai` terminal helper command
- [AI] Stopped non-critical containers for RAM: karakeep, unimus, homarr, netdisco-*
### VLAN Activation Attempt & Fixes
- [VLAN] Configured CSS326 switch VLANs via SwOS web interface
- [VLAN] Enabled VLAN filtering on MikroTik - caused internet outage
- [VLAN] Rolled back VLAN filtering to restore connectivity
- [VLAN] **ROOT CAUSE IDENTIFIED:** Multiple configuration issues
### Issues Fixed
- [FIX] DHCP DNS now points to each VLAN gateway instead of legacy 192.168.31.1
- VLAN 20: 192.168.20.1, VLAN 25: 192.168.25.1, etc.
- [FIX] Added DNS redirect rules for all VLANs (src-address-list=all-vlans)
- [FIX] Added all VLAN interfaces to LAN firewall interface list
- [FIX] Added NAT masquerade rules for VLAN traffic to AdGuard container
- [BACKUP] MikroTik config saved before activation attempt
### Current Status
- MikroTik: Fully configured, fixes applied, ready for activation
- CSS326: VLANs configured, port assignments done
- VLAN Filtering: OFF (ready to enable when convenient)
- Next: Enable VLAN filtering + force DHCP renewal on devices
## 2026-01-25 (Update 3)
### VLAN Phase 1 Complete
- [VLAN] Added VLAN 25 (Kids) - interface, IP, DHCP server, pool, bridge entry
- [VLAN] Fixed VLAN 10 (Management) leases - correct IPs per device assignment doc
- [VLAN] Fixed VLAN 30 (IoT) leases - all 14 devices with correct IPs
- [VLAN] Added VLAN 25 (Kids) leases - 6 devices including XTRM-Ally
- [VLAN] Added VLAN 50 (Guest) leases - 7 unknown devices
- [VLAN] Added firewall rules for VLAN 25 (Kids → IoT, Legacy, DNS)
- [VLAN] Total devices configured: 44
### Device Discovery
- [NETWORK] Discovered XTRM-Ally gaming device → assigned to Kids VLAN
- [NETWORK] Discovered Dancho Windows device → assigned to Kids VLAN
- [NETWORK] Discovered 2x lwip0 IoT devices → assigned to IoT VLAN
- [NETWORK] Discovered 3x unknown devices → assigned to Guest VLAN
### Documentation Updates
- [DOCS] Updated 03-VLAN-DEVICE-ASSIGNMENT.md - complete device inventory (44 devices)
- [DOCS] Updated 11-VLAN-IMPLEMENTATION.md - Phase 1 complete status
- [DOCS] All VLANs now documented: 10, 20, 25, 30, 35, 40, 50
### Next Steps
- CSS326 switch VLAN configuration via SwOS
- Enable VLAN filtering on MikroTik bridge
- Test connectivity
## 2026-01-25
### VLAN Implementation (Prepared)
- [VLAN] Created 6 VLANs on MikroTik bridge (10, 20, 30, 35, 40, 50)
- [VLAN] Configured IP addresses for all VLAN interfaces
- [VLAN] Created DHCP servers and pools for each VLAN
- [VLAN] Added static DHCP leases mapping MACs to VLAN IPs
- [VLAN] Configured bridge VLAN table with tagged/untagged ports
- [VLAN] Set WiFi ports PVID=20 (Trusted VLAN default)
- [VLAN] Added inter-VLAN firewall rules (active)
- [VLAN] VLAN filtering NOT YET ENABLED (pending CSS326 switch config)
- [DOCS] Added docs/11-VLAN-IMPLEMENTATION.md
- [SCRIPTS] Added scripts/mikrotik-vlan-setup.rsc
- [SCRIPTS] Added scripts/mikrotik-vlan-enable.rsc
### MikroTik Containers
- [CONTAINER] AdGuard Home container running on MikroTik
- [CONTAINER] Tailscale container configured (inactive)
- [CONTAINER] Container bridge (containers-br) with NAT
### DNS Configuration
- [DNS] AdGuard Home as primary DNS (172.17.0.2)
- [DNS] DNS redirect rules for all clients
- [DNS] DoT/DoH upstream configured in AdGuard
## Previous Changes
See git history for earlier changes.
## 2026-01-25 (Update 2)
### DNS Configuration
- [DNS] Updated both AdGuard instances to use Quad9 DoH
- [DNS] MikroTik AdGuard: upstream=https://dns.quad9.net/dns-query
- [DNS] Unraid AdGuard: upstream=https://dns.quad9.net/dns-query
- [DNS] Bootstrap DNS: 9.9.9.9, 149.112.112.112
### Containers
- [CONTAINER] Fixed Tailscale container authentication
- [CONTAINER] Tailscale DNS changed from 8.8.8.8 to 172.17.0.1,1.1.1.1 (fallback)
- [CONTAINER] Tailscale route fixed: 100.64.0.0/10 → 172.17.0.3
### Documentation
- [DOCS] Created 02-PORT-UTILIZATION.md with ASCII port diagrams
- [DOCS] Updated 09-MIKROTIK-ADGUARD-DOT-DOH.md with Quad9 DoH config
### Network
- [NETWORK] Enabled CSS326 SFP1 port - 10G backbone link to ZX1 now active
### Documentation Fix
- [DOCS] Fixed ZX1 switch IP: 192.168.31.22 (was incorrectly documented as .7)

View File

@@ -0,0 +1,211 @@
# VLAN Device Assignment Map
**Last Updated:** 2026-02-14
**Purpose:** Complete inventory of all network devices with VLAN assignments
---
## VLAN Summary
| VLAN | Name | Subnet | Gateway | Purpose |
|------|------|--------|---------|---------|
| 10 | Mgmt | 192.168.10.0/24 | 192.168.10.1 | Infrastructure devices |
| 20 | Trusted | 192.168.20.0/24 | 192.168.20.1 | Family personal devices |
| 25 | Kids | 192.168.25.0/24 | 192.168.25.1 | Kids devices |
| 30 | IoT | 192.168.30.0/24 | 192.168.30.1 | Smart home devices |
| 35 | Cameras | 192.168.35.0/24 | 192.168.35.1 | Security cameras |
| 40 | Servers | 192.168.40.0/24 | 192.168.40.1 | Servers & printers |
| 50 | Guest | 192.168.50.0/24 | 192.168.50.1 | Guest WiFi |
---
## VLAN 10 - Management (Infrastructure)
| IP | MAC Address | Device | Notes | Comment |
|----|-------------|--------|-------|---------|
| 192.168.10.1 | 78:9A:18:2C:A5:48 | HAP1 (hAP ax³) | Router | Gateway for all VLANs |
| 192.168.10.10 | 02:42:C0:A8:1F:04 | AdGuard Home | DNS (Unraid) | Secondary DNS |
| 192.168.10.2 | 18:FD:74:54:3D:BC | CAP XL ac | Access point | CAPsMAN managed |
| 192.168.10.3 | F4:1E:57:C9:BD:09 | CSS326-24G-2S+ | 24-port switch | Room distribution |
| 192.168.10.4 | 1C:2A:A3:1E:78:67 | ZX1 (ZX-SWTGW218AS) | 8-port 2.5G switch | Server rack |
| 192.168.10.20 | A8:B8:E0:02:B6:15 | XTRM-U (Unraid) | Main server | Docker host, NAS |
| 192.168.10.103 | 08:92:04:C6:07:C5 | XTRM-Nobara | Failover node | Keepalived BACKUP |
| 192.168.10.200 | 48:DA:35:6F:BE:50 | NanoKVM | Remote KVM | IPMI alternative |
| 172.17.0.2 | 46:D0:27:F7:1F:CA | AdGuard (MikroTik) | DNS (Router) | Primary DNS, DoH/DoT |
| 172.17.0.3 | 0C:AB:39:8D:8C:FC | Tailscale (MikroTik) | VPN container | Remote access |
---
## VLAN 20 - Trusted (Family Devices)
| IP | MAC Address | Device | Owner | Comment |
|----|-------------|--------|-------|---------|
| 192.168.20.10 | 82:6D:FB:D9:E0:47 | MacBook Air | Nora | Primary laptop |
| 192.168.20.11 | AA:ED:8B:2A:40:F1 | Samsung S25 Ultra | Kaloyan | Primary phone |
| 192.168.20.12 | F2:B8:14:61:C8:27 | iPhone | Dancho | |
| 192.168.20.13 | 82:EC:EF:B5:F2:AF | MacBook Pro (WiFi) | Kaloyan | Work laptop wireless |
| 192.168.20.14 | 90:91:64:70:0D:86 | Notebook | Kimi | |
| 192.168.20.15 | 2A:2B:BA:86:D4:AF | iPhone | Kimi | |
| 192.168.20.16 | 08:92:04:C6:07:C5 | MacBook Pro (LAN) | Kaloyan | Via Dell KVM dock |
| 192.168.20.17 | 1C:83:41:32:F3:AF | Gaming PC | Kaloyan | Main bedroom |
| 192.168.20.18 | A4:D1:D2:7B:52:BE | iPad | Compusbg | Work tablet |
---
## VLAN 25 - Kids (Kids Devices)
| IP | MAC Address | Device | Owner | Comment |
|----|-------------|--------|-------|---------|
| 192.168.25.12 | F2:B8:14:61:C8:27 | iPhone | Dancho | |
| 192.168.25.14 | 90:91:64:70:0D:86 | Notebook | Kimi | |
| 192.168.25.15 | 2A:2B:BA:86:D4:AF | iPhone | Kimi | |
| 192.168.25.18 | A4:D1:D2:7B:52:BE | iPad | Compusbg | Work tablet |
| 192.168.25.30 | B8:27:EB:32:B2:13 | Recalbox (RPi3) | Gaming | Retro gaming, WiFi XTRM2 |
---
## VLAN 30 - IoT (Smart Home)
| IP | MAC Address | Device | Location | Comment |
|----|-------------|--------|----------|---------|
| 192.168.30.10 | 50:2C:C6:7A:55:39 | Air Conditioner | Living Room | GREE Electric |
| 192.168.30.30 | 64:4E:D7:D8:43:3E | HP LaserJet M110w | Office | WiFi printer |
| 192.168.30.40 | B0:37:95:79:AF:9B | LG TV (Ethernet) | Living Room | Use ONE interface only for AirPlay |
| 192.168.30.41 | DC:03:98:6B:5A:3A | LG TV (WiFi) | Living Room | Use ONE interface only for AirPlay |
| 192.168.30.42 | D0:E7:82:F7:65:DD | Chromecast | Living Room | Requires WPA2+AES (no TKIP) |
| 192.168.30.14 | B0:4A:39:3F:9A:14 | Roborock S7 Vacuum | Living Room | Needs cloud access |
| 192.168.30.20 | 94:27:70:1E:0C:EE | Bosch Smart Oven | Kitchen | Home Connect app |
| 192.168.30.21 | C8:D7:78:40:65:40 | Bosch Dishwasher | Kitchen | Home Connect app |
| 192.168.30.22 | C8:D7:78:D6:DC:FC | Bosch Washer | Kids Bathroom | Home Connect app |
| 192.168.30.31 | 18:DE:50:5B:C8:A6 | Tuya Smart Device | - | OUI: Tuya Smart Inc. |
| 192.168.30.5 | 38:1F:8D:04:6F:E4 | Tuya Smart Gateway (JMWZG1) | - | Requires WPA+TKIP |
| 192.168.30.33 | D4:AD:FC:BE:13:B0 | Tuya Smart Device | - | OUI: Tuya Smart Inc. |
| 192.168.30.39 | C8:5C:CC:52:EA:53 | Xiaomi Air Purifier | - | Mi Home app |
| 192.168.30.50 | FC:D5:D9:EB:6A:82 | Settop Box (LAN) | Living Room | CSS326 Port 23 |
| 192.168.30.51 | 08:FB:EA:61:9D:3A | Settop Box (WiFi) | Living Room | XTRM2 2.4GHz |
---
## VLAN 35 - Cameras (Security)
| IP | MAC Address | Device | Location | Comment |
|----|-------------|--------|----------|---------|
| 192.168.35.10 | 48:9E:9D:0E:16:F7 | Reolink Doorbell | Front door | PoE powered |
---
## VLAN 40 - Servers (Services)
| IP | MAC Address | Device | Purpose | Comment |
|----|-------------|--------|---------|---------|
| — | — | — | — | Printer moved to VLAN 30 |
---
## VLAN 50 - Guest (Isolated)
| IP | MAC Address | Device | Notes | Comment |
|----|-------------|--------|-------|---------|
| 192.168.50.10 | AC:87:A3:77:8F:BD | Apple Device | Unknown owner | OUI: Apple Inc. |
| 192.168.50.11 | 22:4C:7F:1D:85:8E | Unknown Device | Random MAC | Privacy MAC |
| 192.168.50.12 | D0:C9:07:92:1A:8E | Unknown Device | Private vendor | Hidden OUI |
| 192.168.50.13 | D0:C9:07:8C:C9:46 | Unknown Device | Private vendor | Same as .12 |
| 192.168.50.100-200 | - | Guest devices | Dynamic | Internet only |
---
## MAC Address Quick Reference
### By VLAN (for switch port assignment)
**VLAN 10 - Mgmt:**
```
78:9A:18:2C:A5:48 HAP1
A8:B8:E0:02:B6:15 XTRM-U
18:FD:74:54:3D:BC CAP XL ac
F4:1E:57:C9:BD:09 CSS326
1C:2A:A3:1E:78:67 ZX1
48:DA:35:6F:BE:50 NanoKVM
08:92:04:C6:07:C5 XTRM-Nobara (Failover)
```
**VLAN 20 - Trusted:**
```
82:6D:FB:D9:E0:47 Nora MacBook
AA:ED:8B:2A:40:F1 Kaloyan S25
F2:B8:14:61:C8:27 Dancho iPhone
82:EC:EF:B5:F2:AF Kaloyan MacBook WiFi
90:91:64:70:0D:86 Kimi Notebook
2A:2B:BA:86:D4:AF Kimi iPhone
08:92:04:C6:07:C5 Kaloyan MacBook LAN
1C:83:41:32:F3:AF Kaloyan Game PC
A4:D1:D2:7B:52:BE Compusbg iPad
```
**VLAN 30 - IoT:**
```
64:4E:D7:D8:43:3E HP LaserJet M110w
B0:37:95:79:AF:9B LG TV (Ethernet)
DC:03:98:6B:5A:3A LG TV (WiFi)
D0:E7:82:F7:65:DD Chromecast
B0:4A:39:3F:9A:14 Roborock Vacuum
94:27:70:1E:0C:EE Bosch Oven
C8:5C:CC:52:EA:53 Xiaomi Air Purifier
C8:D7:78:D6:DC:FC Bosch Washer
C8:D7:78:40:65:40 Bosch Dishwasher
50:2C:C6:7A:55:39 GREE Appliance
18:DE:50:5B:C8:A6 Tuya Device 1
38:1F:8D:04:6F:E4 Tuya Smart Gateway (JMWZG1)
D4:AD:FC:BE:13:B0 Intellirocks Device
FC:D5:D9:EB:6A:82 Settop Box (LAN)
08:FB:EA:61:9D:3A Settop Box (WiFi)
```
**VLAN 35 - Cameras:**
```
48:9E:9D:0E:16:F7 Reolink Doorbell
```
**VLAN 40 - Servers:**
```
(empty - printer moved to VLAN 30)
```
**VLAN 50 - Guest:**
```
AC:87:A3:77:8F:BD Apple Device (unknown)
22:4C:7F:1D:85:8E Random MAC device
D0:C9:07:92:1A:8E Private Vendor 1
D0:C9:07:8C:C9:46 Private Vendor 2
```
---
## Device Count Summary
| VLAN | Device Count | Comment |
|------|--------------|---------|
| 10 - Mgmt | 10 | Infrastructure + failover |
| 20 - Trusted | 9 | Family devices |
| 25 - Kids | 5 | Kids devices + Recalbox |
| 30 - IoT | 14 | Smart home devices |
| 35 - Cameras | 1 | Security |
| 40 - Servers | 1 | Services |
| 50 - Guest | 4 | Unknown/unidentified devices |
| **Total** | **40** | All devices categorized |
---
## OUI Lookup Reference
| OUI Prefix | Vendor | Type |
|------------|--------|------|
| B0:37:95 | LG Electronics | TV/Displays (LAN) |
| DC:03:98 | LG Innotek | TV/Displays (WiFi) |
| 50:2C:C6 | GREE Electric Appliances (Zhuhai) | AC/Appliances |
| 18:DE:50 | Tuya Smart Inc. | IoT Platform |
| 38:1F:8D | Xiaomi | Smart Home Devices |
| D4:AD:FC | Shenzhen Intellirocks Tech | Smart Devices |
| AC:87:A3 | Apple Inc. | Consumer Electronics |
| D0:C9:07 | Private (IEEE hidden) | Unknown |
| 22:xx:xx | Locally Administered | Random/Private MAC |

View File

@@ -0,0 +1,229 @@
# WiFi and CAPsMAN Configuration
**Last Updated:** 2026-02-26
**Purpose:** Document WiFi network settings, CAPsMAN configuration, and device compatibility requirements
---
## Network Overview
| SSID | Band | Purpose | Password |
|------|------|---------|----------|
| XTRM | 5GHz | Primary network (fast devices) | `M0stW4nt3d@home` |
| XTRM2 | 2.4GHz | IoT/Legacy devices | `M0stW4nt3d@IoT` |
---
## XTRM (5GHz) - wifi1
**Target:** Modern devices (phones, laptops, tablets)
| Setting | Value |
|---------|-------|
| SSID | XTRM |
| Band | 5GHz |
| Mode | 802.11ax (WiFi 6) |
| Channel | 5180 MHz (ch 36) |
| Width | 40MHz |
| Security | WPA2-PSK + WPA3-PSK |
| Cipher | CCMP (AES) |
| 802.11r (FT) | Enabled |
| Password | `M0stW4nt3d@home` |
---
## XTRM2 (2.4GHz) - wifi2
**Target:** IoT devices, legacy devices, smartwatches
### CRITICAL COMPATIBILITY REQUIREMENTS
Some devices (Tuya JMWZG1 gateway, Amazfit TREX3, iPad 2) require legacy settings:
| Setting | Value | Reason |
|---------|-------|--------|
| SSID | XTRM2 | |
| Band | 2.4GHz | IoT compatibility |
| Mode | **802.11g** | Legacy device support |
| Channel | **1 (2412 MHz)** | Most compatible |
| Width | **20MHz** | Required for old devices |
| Security | **WPA-PSK + WPA2-PSK** | WPA needed for legacy |
| Cipher | **TKIP + CCMP** | TKIP required for old devices |
| 802.11r (FT) | **Disabled** | Causes issues with IoT |
| Password | `M0stW4nt3d@IoT` | |
### Devices Requiring WPA + TKIP
| Device | MAC Address | Model | Notes |
|--------|-------------|-------|-------|
| Roborock S7 Vacuum | B0:4A:39:3F:9A:14 | S7 | Requires WPA+TKIP |
| Amazfit TREX3 | TBD | Smartwatch | Requires WPA+TKIP |
| Tuya Smart Gateway | 38:1F:8D:04:6F:E4 | JMWZG1 | Requires WPA+TKIP |
| iPad 2 | TBD | A1395/A1396 | Legacy device |
### RouterOS Commands for XTRM2
```routeros
# Working configuration for legacy devices
/interface wifi set wifi2 \
channel.frequency=2412 \
channel.band=2ghz-g \
channel.width=20mhz \
security.authentication-types=wpa-psk,wpa2-psk \
security.encryption=tkip,ccmp \
security.ft=no \
security.ft-over-ds=no \
security.passphrase="M0stW4nt3d@IoT"
```
### Fallback (Maximum Compatibility)
If devices still can't connect, use WPA-only with TKIP-only:
```routeros
/interface wifi set wifi2 \
security.authentication-types=wpa-psk \
security.encryption=tkip
```
---
## CAPsMAN Configuration
### Manager (HAP ax³ - 192.168.10.1)
| Setting | Value |
|---------|-------|
| Enabled | Yes |
| Interfaces | bridge, vlan10-mgmt |
| Certificate | Auto-generated |
### CAP Device (cAP XL ac - 192.168.10.2)
| Setting | Value |
|---------|-------|
| caps-man-addresses | 192.168.10.1 |
| discovery-interfaces | bridgeLocal |
| slaves-datapath | capdp (bridge=bridgeLocal, vlan-id=40) |
| certificate | request |
| RouterOS | 7.21.1 |
| SSH Port | 2222 |
| SSH (via proxy) | See ProxyJump command below |
**SSH Access:** Direct SSH to CAP is unreliable. Use ProxyJump through Unraid:
```bash
ssh -o ProxyCommand="ssh -i ~/.ssh/id_ed25519_unraid -p 422 -W %h:%p root@192.168.10.20" -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.2
```
### CAP Bridge VLAN Filtering
The CAP runs bridge VLAN filtering to properly tag/untag WiFi client traffic before sending it to the HAP over the trunk link (ether1):
| Setting | Value |
|---------|-------|
| bridgeLocal | vlan-filtering=yes, pvid=10 |
| ether1 (trunk) | bridge port, PVID=10 |
| wifi1, wifi2 | dynamic bridge ports, PVID=40 (set by datapath vlan-id) |
**Bridge VLAN Table:**
| VLAN | ether1 | wifi1 | wifi2 | bridgeLocal | Purpose |
|------|--------|-------|-------|-------------|---------|
| 10 | untagged | - | - | untagged | Management |
| 20 | tagged | tagged | tagged | - | Trusted |
| 25 | tagged | tagged | tagged | - | Kids |
| 30 | tagged | tagged | tagged | - | IoT |
| 35 | tagged | tagged | tagged | - | Cameras |
| 40 | tagged | untagged | untagged | - | CatchAll (default) |
### CAP Interfaces
| Interface | Radio | Band | SSID | Security | Status |
|-----------|-------|------|------|----------|--------|
| cap-wifi1 | wifi2 | 5GHz | XTRM | WPA2/WPA3-PSK, CCMP | Working (Ch 52/5260, 40MHz, DFS) |
| cap-wifi2 | wifi1 | 2.4GHz | XTRM2 | WPA2-PSK, CCMP | Working (Ch 6/2437, 20MHz) |
**Note:** cap-wifi2 uses WPA2+CCMP only (not WPA+TKIP like HAP's local wifi2). Legacy IoT devices requiring TKIP will only work on HAP1's local wifi2.
---
## WiFi Access List
**Status:** VLAN assignment via access list is **active**. Each entry has a `vlan-id` that assigns the device to the correct VLAN upon WiFi association. This works on both HAP (local) and CAP (remote, via bridge VLAN filtering).
**30+ entries** configured (MAC-based accept rules with VLAN IDs + 1 default catch-all):
| # | MAC | Device | VLAN |
|---|-----|--------|------|
| 0 | AA:ED:8B:2A:40:F1 | Samsung S25 Ultra - Kaloyan | 20 |
| 1 | 82:6D:FB:D9:E0:47 | MacBook Air - Nora | 20 |
| 12 | CE:B8:11:EA:8D:55 | MacBook - Kaloyan | 20 |
| 13 | BE:A7:95:87:19:4A | MacBook 5GHz - Kaloyan | 20 |
| 27 | B8:27:EB:32:B2:13 | RecalBox RPi3 | 25 |
| 28 | CC:5E:F8:D3:37:D3 | ASUS ROG Ally - Kaloyan | 20 |
| 31 | C8:5C:CC:40:B4:AA | Xiaomi Air Purifier 2 | 30 |
| 32 | (any) | Default - VLAN40 | 40 (catch-all) |
**Default behavior:** Devices not in the access list get VLAN 40 (CatchAll) via the default rule and the datapath `vlan-id=40`.
### Show Full Access List
```routeros
/interface wifi access-list print
```
---
## Troubleshooting
### Device can see XTRM2 but can't connect
1. Check security settings - device may need WPA (not WPA2)
2. Check cipher - device may need TKIP (not CCMP/AES)
3. Try 802.11g mode instead of 802.11n
4. Use channel 1, 6, or 11
### Device connects but disconnects immediately
1. Check if 802.11r (Fast Transition) is disabled
2. Check VLAN assignment - CAP clients need special rule
3. Check channel width - use 20MHz for stability
### CAP not connecting to CAPsMAN
1. Check certificate - remove old cert and re-request
2. Check firewall - ports 5246-5247 UDP must be open
3. Check interface binding - CAPsMAN must listen on correct interface
---
## Backup Files
| File | Location | Purpose |
|------|----------|---------|
| wifi-backup-working.rsc | Router files | WiFi config export |
| config-backup-working.backup | Router files | Full system backup |
---
## Quick Reference
### Show WiFi status
```routeros
/interface wifi print
/interface wifi monitor wifi2 once
/interface wifi registration-table print
```
### Show security settings
```routeros
/interface wifi security print detail
:put [/interface wifi get wifi2 security.authentication-types]
:put [/interface wifi get wifi2 security.encryption]
```
### Check CAPsMAN
```routeros
/interface wifi capsman print
/interface wifi capsman remote-cap print
```

380
docs/08-DNS-ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,380 @@
# DNS Architecture with AdGuard Failover
**Last Updated:** 2026-02-26
---
## Overview
Dual AdGuard DNS setup with automatic failover. All DNS queries are filtered through AdGuard for ad-blocking, and if the primary (MikroTik) fails, traffic automatically switches to secondary (Unraid).
---
## Architecture
```
┌─────────────────────────────────────┐
│ INTERNET │
│ │
│ External clients (DoT/DoH) │
│ dns.xtrm-lab.org:853 (DoT) │
│ dns.xtrm-lab.org:8443 (DoH) │
└──────────────┬──────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ MikroTik hAP ax³ (192.168.10.1) │
│ │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ AdGuard Home (PRIMARY) │ │
│ │ Container: 172.17.0.2 │ │
│ │ Web UI: http://192.168.10.1:3000 │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Filters │ │ Blocklists │ │ Clients │ │ │
│ │ │ (synced) │ │ 143K rules │ │ (synced) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ Netwatch monitors every 10s │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ Container UP Container DOWN │
│ │ │ │
│ ▼ ▼ │
│ NAT → 172.17.0.2 NAT → 192.168.10.10 │
│ (MikroTik) (Unraid Failover) │
└──────────────────────────────────────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
NAT Redirect NAT Redirect NAT Redirect
│ │ │
┌───────┴───────┐ ┌────────┴────────┐ ┌────────┴────────┐
│ VLAN 10 │ │ VLAN 20/25 │ │ VLAN 30/40 │
│ Management │ │ Trusted/Kids │ │ IoT/CatchAll │
│ 192.168.10.x │ │ 192.168.20.x │ │ 192.168.30.x │
│ │ │ 192.168.25.x │ │ 192.168.1.x │
└───────────────┘ └─────────────────┘ └─────────────────┘
```
---
## AdGuard Instances
| Instance | Role | IP | Port | Web UI |
|----------|------|-----|------|--------|
| MikroTik | Primary | 172.17.0.2 | 53 | http://192.168.10.1:3000 |
| Unraid | Secondary/Failover | 192.168.10.10 | 3000 | http://192.168.10.10:3000 |
### Credentials (Same for Both)
| Username | Password |
|----------|----------|
| jazzymc | 7RqWElENNbZnPW |
---
## DNS Redirect Rules
All DNS queries (port 53) from any VLAN are intercepted and redirected:
| VLAN | Subnet | Redirected To |
|------|--------|---------------|
| 10 | 192.168.10.0/24 | 172.17.0.2:53 |
| 20 | 192.168.20.0/24 | 172.17.0.2:53 |
| 25 | 192.168.25.0/24 | 172.17.0.2:53 |
| 30 | 192.168.30.0/24 | 172.17.0.2:53 |
| 40 | 192.168.1.0/24 | 172.17.0.2:53 |
**Note:** Clients don't need any DNS configuration - even if they use 8.8.8.8, traffic is intercepted by NAT.
### NAT Rules on MikroTik
```routeros
# Exception rules (prevent loops) - MUST BE FIRST
/ip firewall nat
add chain=dstnat action=accept protocol=udp src-address=172.17.0.0/24 dst-port=53 comment="[DNS] Allow MikroTik AdGuard outbound"
add chain=dstnat action=accept protocol=udp src-address=192.168.10.10 dst-port=53 comment="[DNS] Allow Unraid AdGuard outbound"
# VLAN redirect rules
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.10.0/24 dst-port=53 comment="[DNS] VLAN10 Mgmt redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.20.0/24 dst-port=53 comment="[DNS] VLAN20 Trusted redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.25.0/24 dst-port=53 comment="[DNS] VLAN25 Kids redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.30.0/24 dst-port=53 comment="[DNS] VLAN30 IoT redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.1.0/24 dst-port=53 comment="[DNS] VLAN40 CatchAll redirect"
# Masquerade for return traffic
add chain=srcnat action=masquerade protocol=udp src-address=192.168.10.0/24 dst-address=172.17.0.2 dst-port=53 comment="[DNS] VLAN10 masquerade"
# ... (similar for other VLANs)
```
---
## Automatic Failover
### How It Works (Dual Health Check)
Two independent Netwatch monitors trigger failover:
| Monitor | Type | What It Checks | Interval | Timeout |
|---------|------|----------------|----------|---------|
| Ping | simple | Container reachable | 10s | 3s |
| DNS | dns | DNS queries work | 30s | 10s |
**Either monitor failing triggers failover to Unraid.**
### Failure Scenarios Covered
| Scenario | Ping Check | DNS Check | Failover? |
|----------|------------|-----------|-----------|
| Container crashed | Fail | Fail | Yes |
| Container stopped | Fail | Fail | Yes |
| Network/routing issue | Fail | Fail | Yes |
| Upstream DNS unreachable | Pass | Fail | Yes |
| AdGuard overloaded | Pass | Fail | Yes |
| Everything working | Pass | Pass | No |
### Failover Timeline
| Event | Detection Time | Total Switchover |
|-------|----------------|------------------|
| Container crash (ping) | ~10-13 seconds | ~13-16 seconds |
| DNS failure (resolution) | ~30-40 seconds | ~33-43 seconds |
| Recovery | ~10-30 seconds | Automatic |
### Failover Scripts
```routeros
# dns-failover-down (runs when either check fails)
/system script add name=dns-failover-down dont-require-permissions=yes source={
:log warning "DNS Failover: Switching to Unraid"
/ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=192.168.10.10 to-ports=3000
}
# dns-failover-up (runs when check recovers)
/system script add name=dns-failover-up dont-require-permissions=yes source={
:log info "DNS Failover: Switching back to MikroTik"
/ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=172.17.0.2 to-ports=53
}
```
### Netwatch Configuration
```routeros
# Monitor 1: Ping check (fast crash detection)
/tool netwatch add type=simple host=172.17.0.2 interval=10s timeout=3s \
up-script=dns-failover-up down-script=dns-failover-down \
comment="AdGuard failover monitor"
# Monitor 2: DNS resolution check (functional verification)
/tool netwatch add type=dns host=google.com interval=30s timeout=10s \
up-script=dns-failover-up down-script=dns-failover-down \
comment="AdGuard DNS resolution check"
```
---
## Sync Configuration
Settings are synced from Unraid (source of truth) to MikroTik every 30 minutes.
### What Syncs
| Feature | Synced |
|---------|--------|
| Filter lists (blocklists) | Yes |
| User rules (custom blocks/allows) | Yes |
| Client settings (per-device rules) | Yes |
| Services (blocked services) | Yes |
| Rewrites (custom DNS entries) | Yes |
| DNS server config | No |
| DHCP settings | No |
| Query logs/stats | No |
### Sync Container
Container: `adguardhome-sync` at 192.168.10.11 (br0 macvlan, static IP)
```yaml
# /mnt/user/appdata/dockge/stacks/adguard-sync/adguardhome-sync.yaml
cron: "*/30 * * * *"
runOnStart: true
origin:
url: http://192.168.10.10:3000
username: jazzymc
password: 7RqWElENNbZnPW
replica:
url: http://192.168.10.1:3000
username: jazzymc
password: 7RqWElENNbZnPW
```
**Note:** The sync container is on the `br0` macvlan network with a static IP to avoid conflicts with infrastructure devices.
---
## Container Configuration (MikroTik)
### Container Details
| Setting | Value |
|---------|-------|
| Image | adguard/adguardhome:latest |
| Interface | veth-adguard |
| IP | 172.17.0.2/24 |
| Gateway | 172.17.0.1 |
| Root dir | usb1/adguard/root |
| Config mount | usb1/adguard/conf → /opt/adguardhome/conf |
| Work mount | usb1/adguard/work → /opt/adguardhome/work |
| Start on boot | Yes |
### Container Commands
```routeros
# Check status
/container print
# Start container
/container start 0
# Stop container
/container stop 0
# View logs
/log print where topics~"container"
```
---
## Upstream DNS
Both AdGuard instances use the same upstream:
| Upstream | Type |
|----------|------|
| https://dns.quad9.net/dns-query | Primary (DoH) |
| 9.9.9.9 | Bootstrap |
| 149.112.112.112 | Bootstrap secondary |
---
## Management
| Task | Where to Do It |
|------|----------------|
| Change blocklists | Unraid AdGuard (syncs to MikroTik) |
| Add custom rules | Unraid AdGuard |
| Add client settings | Unraid AdGuard |
| View query logs | MikroTik AdGuard (real-time) |
| Check failover status | MikroTik `/tool netwatch print` |
---
## Troubleshooting
### Check Failover Status
```routeros
/tool netwatch print
# Both monitors should show STATUS=up normally
# Monitor 0: Ping check
# Monitor 1: DNS resolution check
```
### Check Current DNS Target
```routeros
/ip firewall nat print where comment~"VLAN10 Mgmt redirect"
# to-addresses should be 172.17.0.2 (normal) or 192.168.10.10 (failover)
```
### View Failover Logs
```routeros
/log print where message~"Failover"
```
### Manual Failover Test
```routeros
# Stop container (triggers failover)
/container stop 0
# Wait 15 seconds, check NAT rules switched to 192.168.10.10
# Start container (triggers recovery)
/container start 0
# Wait 15 seconds, check NAT rules switched back to 172.17.0.2
```
### DNS Not Working
1. Check container is running: `/container print`
2. Check netwatch status: `/tool netwatch print`
3. Test DNS directly: `:resolve google.com server=172.17.0.2`
4. Check NAT rules: `/ip firewall nat print where comment~"DNS"`
5. **Check /32 routes exist:** `/ip route print where dst-address~"172.17.0.[23]"`
6. **Ping container:** `/ping 172.17.0.2 count=3`
### Container Reachable but DNS Fails
If ping works but DNS queries timeout:
1. Check container can reach upstream: Look for timeout errors in logs
2. Verify /32 routes: Missing routes cause ECMP issues
3. Check NAT masquerade: `/ip firewall nat print where comment~"Container"`
4. Verify routes:
```routeros
/ip route print where dst-address~"172.17"
# Should show /32 routes for each container IP
```
### Sync Not Working
```bash
# On Unraid
docker logs adguardhome-sync --tail 20
# Check connectivity
docker exec adguardhome-sync ping -c 2 192.168.10.10
docker exec adguardhome-sync ping -c 2 192.168.10.1
```
---
## Container Network Routing
### Important: /32 Host Routes Required
When running multiple containers on the same subnet (172.17.0.0/24), specific host routes are required to prevent ECMP routing issues:
```routeros
# Without these routes, return traffic may go to wrong container
/ip route add dst-address=172.17.0.2/32 gateway=veth-adguard comment="AdGuard container - specific route"
/ip route add dst-address=172.17.0.3/32 gateway=veth-tailscale comment="Tailscale container - specific route"
```
**Why this matters:** Each veth interface creates a /24 route. With multiple veth interfaces on the same subnet, RouterOS enables ECMP load balancing, sending return traffic to random interfaces.
---
## Quick Reference
### Normal Operation
- DNS queries → MikroTik AdGuard (172.17.0.2)
- Ad blocking active
- ~143,000 filter rules
### During Failover
- DNS queries → Unraid AdGuard (192.168.10.10)
- Ad blocking still active (same rules synced)
- Automatic, no manual intervention needed
### Recovery
- Automatic when container comes back up
- NAT rules switch back to MikroTik
- No DNS interruption for clients

208
docs/09-TAILSCALE-VPN.md Normal file
View File

@@ -0,0 +1,208 @@
# MikroTik Tailscale Container Setup
**Last Updated:** 2026-02-06
---
## Overview
Tailscale VPN running as a container on MikroTik hAP ax³, providing remote access to the home network via the Tailscale mesh network.
---
## Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ MikroTik hAP ax³ (192.168.10.1) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Container Network (172.17.0.0/24) │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────────┐ │ │
│ │ │ AdGuard Home │ │ Tailscale │ │ │
│ │ │ 172.17.0.2 │ │ 172.17.0.3 │ │ │
│ │ │ veth-adguard │ │ veth-tailscale │ │ │
│ │ └─────────────────────┘ └─────────────────────────┘ │ │
│ │ │ │ │ │
│ │ └───────────┬───────────────┘ │ │
│ │ │ │ │
│ │ Gateway: 172.17.0.1 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ NAT Masquerade │
│ │ │
│ WAN (ether1) │
└──────────────────────────────┬──────────────────────────────────────┘
┌─────────────────────┐
│ Tailscale Network │
│ 100.x.x.x mesh │
│ │
│ Home Router IP: │
│ 100.74.219.35 │
└─────────────────────┘
```
---
## Container Details
| Setting | Value |
|---------|-------|
| Image | tailscale/tailscale:latest |
| Interface | veth-tailscale |
| Container IP | 172.17.0.3/24 |
| Gateway | 172.17.0.1 |
| Tailscale IP | 100.74.219.35 |
| Root dir | usb1/tailscale/root |
| State mount | usb1/tailscale → /var/lib/tailscale |
| DNS | 8.8.8.8 |
| Start on boot | Yes |
| Networking mode | Userspace (TS_USERSPACE=true) |
---
## Environment Variables
| Variable | Value | Purpose |
|----------|-------|---------|
| TS_AUTHKEY | tskey-auth-... | One-time auth key (used during setup) |
| TS_STATE_DIR | /var/lib/tailscale | Persistent state directory |
| TS_USERSPACE | true | Required for MikroTik containers (no /dev/net/tun) |
---
## Network Configuration
### veth Interface
```routeros
/interface veth add address=172.17.0.3/24 gateway=172.17.0.1 name=veth-tailscale
```
### Gateway IP on Interface
```routeros
/ip address add address=172.17.0.1/24 interface=veth-tailscale comment="Tailscale container gateway"
```
### NAT Masquerade for Internet Access
```routeros
/ip firewall nat add chain=srcnat action=masquerade src-address=172.17.0.0/24 out-interface-list=WAN comment="Container network NAT"
```
### Firewall Forward Rules
```routeros
/ip firewall filter add chain=forward action=accept dst-address=172.17.0.0/24 comment="[Container] Forward to container network"
/ip firewall filter add chain=forward action=accept src-address=172.17.0.0/24 comment="[Container] Forward from container network"
```
---
## Container Setup Commands
### Create Mounts
```routeros
/container mounts add list=ts-state src=usb1/tailscale dst=/var/lib/tailscale
```
### Create Environment Variables
```routeros
/container envs add list=ts-env key=TS_STATE_DIR value=/var/lib/tailscale
/container envs add list=ts-env key=TS_USERSPACE value=true
/container envs add list=ts-env key=TS_AUTHKEY value=<your-auth-key>
```
### Create Container
```routeros
/container add remote-image=tailscale/tailscale:latest interface=veth-tailscale \
root-dir=usb1/tailscale/root mountlists=ts-state envlists=ts-env \
dns=8.8.8.8 start-on-boot=yes logging=yes
```
---
## Management
### Check Container Status
```routeros
/container print
```
### View Logs
```routeros
/log print where topics~"container" and message~"tailscale"
```
### Start/Stop Container
```routeros
/container start [find name~"tailscale"]
/container stop [find name~"tailscale"]
```
---
## Troubleshooting
### Container Won't Start (Exit Status 1)
**Cause:** Missing /dev/net/tun device (default for Tailscale)
**Solution:** Enable userspace networking mode:
```routeros
/container envs add list=ts-env key=TS_USERSPACE value=true
```
### Can't Reach Internet from Container
**Cause:** Missing NAT masquerade or gateway IP
**Solution:**
1. Verify gateway IP on veth interface:
```routeros
/ip address print where interface=veth-tailscale
```
2. Verify NAT masquerade rule:
```routeros
/ip firewall nat print where src-address=172.17.0.0/24
```
### Container Not Connecting to Tailscale
1. Check DNS resolution works (logs should show no timeout)
2. Verify auth key is valid and not expired
3. Check firewall isn't blocking outbound HTTPS
---
## Tailscale Network Devices
| Tailscale IP | Device | Status |
|--------------|--------|--------|
| 100.74.219.35 | MikroTik hAP ax³ (container) | Online |
| 100.100.208.70 | xtrm-unraid | Online |
| 100.112.103.7 | hapax3 (old native install) | Offline |
| 100.75.93.123 | mikrotik-tailscale (previous container) | Offline |
---
## Important Notes
1. **Userspace Networking Required:** MikroTik containers don't have /dev/net/tun access, so TS_USERSPACE=true is mandatory
2. **Auth Key:** After initial authentication, the key is no longer needed - state is persisted in the mount
3. **Container Network:** Both AdGuard and Tailscale share the 172.17.0.0/24 network but have separate veth interfaces
4. **Accept Routes:** If subnet routing is needed, add TS_EXTRA_ARGS="--accept-routes" to environment

276
docs/10-FAILOVER-NOBARA.md Normal file
View File

@@ -0,0 +1,276 @@
# Failover Infrastructure - Nobara (XTRM-Nobara)
**Last Updated:** 2026-02-13
**Purpose:** Temporary failover for critical services during Unraid maintenance windows.
---
## Overview
A Docker-based replica of critical services runs on the Nobara Linux workstation (XTRM-Nobara) with automatic failover via Keepalived VRRP. When Unraid goes offline, the virtual IP floats to Nobara and services continue operating.
```
Clients → 192.168.10.250 (VIP) → XTRM-U (MASTER, priority 150)
↓ failover (~4 seconds)
XTRM-Nobara (BACKUP, priority 100)
```
---
## Machines
| Role | Host | IP | Interface | Priority |
|------|------|-----|-----------|----------|
| **MASTER** | XTRM-U (Unraid) | 192.168.10.20 | br0 | 150 |
| **BACKUP** | XTRM-Nobara | 192.168.10.103 | enp5s0 | 100 |
| **VIP** | Shared | 192.168.10.250 | — | — |
---
## Replicated Services
| Service | Image | Ports (Nobara) | Domain |
|---------|-------|----------------|--------|
| **Traefik** | traefik:latest | 80, 443, 8080 | *.xtrm-lab.org |
| **Vaultwarden** | vaultwarden/server:latest | internal:80 | vault.xtrm-lab.org |
| **Authentik** | ghcr.io/goauthentik/server:2025.8.1 | internal:9000 | auth.xtrm-lab.org |
| **Authentik Worker** | ghcr.io/goauthentik/server:2025.8.1 | — | — |
| **PostgreSQL** | postgres:17 | internal:5432 | — |
| **Redis** | redis:7-alpine | internal:6379 | — |
| **AdGuard Home** | adguard/adguardhome:latest | 192.168.10.103:53, 3000 | — |
---
## File Locations
### Nobara (XTRM-Nobara)
| Path | Contents |
|------|----------|
| `/home/failover/docker-compose.yml` | Main compose stack |
| `/home/failover/traefik/` | Traefik config, certs, acme.json |
| `/home/failover/vaultwarden/` | Vaultwarden data (copy from Unraid) |
| `/home/failover/authentik/` | Authentik media & templates |
| `/home/failover/postgres/` | PostgreSQL data + initial dump |
| `/home/failover/redis/` | Redis data |
| `/home/failover/adguard/` | AdGuard conf & work dirs |
| `/etc/keepalived/keepalived.conf` | Keepalived VRRP config |
| `/usr/local/bin/check_failover.sh` | Health check script |
| `/usr/local/bin/failover-notify.sh` | State change notification script |
| `/var/log/keepalived-failover.log` | Failover event log |
### Unraid (XTRM-U)
| Path | Contents |
|------|----------|
| `/mnt/user/appdata/keepalived/keepalived.conf` | Keepalived VRRP config |
| `/mnt/user/appdata/keepalived/check_services.sh` | Health check script |
---
## Keepalived Configuration
### VRRP Parameters
| Parameter | Value |
|-----------|-------|
| Virtual Router ID | 51 |
| Auth Type | PASS |
| Auth Password | xtrm2026 |
| Advertisement Interval | 1 second |
| Health Check Interval | 5 seconds |
| Fail Threshold | 3 missed checks |
| Recovery Threshold | 2 successful checks |
### Unraid (MASTER)
- Runs as Docker container: `local/keepalived` (built from alpine + keepalived + curl)
- Priority: 150 (+ health check weight 2 = 152 when healthy)
- Health check: curls `http://localhost:8183/api/overview` (Traefik dashboard)
- Preemption: enabled (will reclaim VIP from Nobara when healthy)
```bash
# Start/stop on Unraid
docker start keepalived
docker stop keepalived
docker logs keepalived
```
### Nobara (BACKUP)
- Runs as systemd service: `keepalived.service`
- Priority: 100 (+ health check weight 2 = 102 when healthy)
- Health check: verifies Traefik and Vaultwarden containers are running
- `nopreempt` set (won't fight for VIP if Unraid is healthy)
```bash
# Start/stop on Nobara
sudo systemctl start keepalived
sudo systemctl stop keepalived
sudo journalctl -u keepalived -f
```
---
## DNS Strategy
**Approach:** Local DNS override via AdGuard Home.
To route traffic through the VIP for internal clients, configure AdGuard DNS rewrite rules to resolve `*.xtrm-lab.org``192.168.10.250`. External (Cloudflare) DNS remains pointed at Unraid's public IP.
---
## Operations
### Before Maintenance (Data Sync)
Run these commands from the Mac to sync latest data to Nobara:
```bash
# 1. Sync Vaultwarden data
ssh unraid "tar czf - -C /mnt/user/appdata vaultwarden/" | \
ssh nobara "tar xzf - -C /home/failover/"
# 2. Dump and sync Authentik database
ssh unraid "docker exec postgresql17 pg_dump -U authentik_user authentik_db" | \
ssh nobara "cat > /home/failover/postgres/authentik_dump.sql"
# 3. Sync AdGuard config
ssh unraid "tar czf - -C /mnt/user/appdata/adguardhome conf/ work/" | \
ssh nobara "tar xzf - -C /home/failover/adguard/"
# 4. Sync Traefik config and certs
ssh unraid "tar czf - -C /mnt/user/appdata/traefik traefik.yml dynamic.yml acme.json certs/" | \
ssh nobara "tar xzf - -C /home/failover/traefik/"
```
**Note:** `ssh unraid` = `ssh -i ~/.ssh/id_ed25519_unraid -p 422 root@192.168.10.20`
### Start Failover Services
```bash
# On Nobara
cd /home/failover
sudo docker compose up -d
sudo systemctl start keepalived
```
### Stop Failover Services
```bash
# On Nobara
cd /home/failover
sudo docker compose down
sudo systemctl stop keepalived
```
### Test Failover
```bash
# 1. Check VIP location
ssh unraid "ip addr show br0 | grep inet"
ssh nobara "ip addr show enp5s0 | grep inet"
# 2. Simulate Unraid failure
ssh unraid "docker stop keepalived"
# 3. Verify VIP moved to Nobara (wait ~4 seconds)
ssh nobara "ip addr show enp5s0 | grep inet"
# 4. Restore Unraid
ssh unraid "docker start keepalived"
# 5. Verify VIP returned to Unraid
ssh unraid "ip addr show br0 | grep inet"
```
### Check Status
```bash
# Nobara service status
ssh nobara "sudo docker ps --format 'table {{.Names}}\t{{.Status}}'"
# Nobara keepalived state
ssh nobara "sudo journalctl -u keepalived -n 10 --no-pager"
# Unraid keepalived state
ssh unraid "docker logs keepalived --tail 10"
# Which machine holds the VIP?
ping -c 1 192.168.10.250
```
---
## Traefik Configuration (Failover)
The Nobara Traefik instance has a **reduced** dynamic.yml that only serves the four critical services:
| Router | Domain | Backend |
|--------|--------|---------|
| vaultwarden-secure | vault.xtrm-lab.org | http://vaultwarden:80 |
| authentik-secure | auth.xtrm-lab.org | http://authentik:9000 |
| traefik-secure | traefik.xtrm-lab.org | api@internal |
TLS certificates are shared (copied from Unraid's acme.json + static certs).
---
## Limitations
- **Data is a point-in-time snapshot.** Changes made on Unraid after the last sync are not reflected on Nobara. Re-sync before maintenance.
- **No real-time replication.** Vaultwarden passwords saved during failover will not sync back to Unraid automatically.
- **Only critical services replicated.** Other services (Plex, Gitea, NetBox, etc.) will be offline during maintenance.
- **External DNS not updated.** Failover only works for clients using the local DNS (AdGuard) that resolves to the VIP. External access via Cloudflare will not failover.
---
## SSH Access
```bash
# From Mac to Nobara (passwordless, key-based)
ssh nobara
# or: ssh -i ~/.ssh/id_ed25519_nobara jazzymc@192.168.10.103
# Sudo on Nobara requires password: (check password manager)
```
---
## Recovery After Maintenance
1. Bring Unraid back online
2. Verify all Unraid services are running: `docker ps`
3. Keepalived on Unraid will auto-reclaim VIP (preemption)
4. Stop failover on Nobara: `cd /home/failover && sudo docker compose down`
5. If Vaultwarden was used during failover, manually export/import any new entries
---
## Architecture Diagram
```
┌─────────────────────┐
│ 192.168.10.250 │
│ (VRRP VIP) │
└─────────┬───────────┘
┌───────────────┼───────────────┐
│ │
┌─────────▼─────────┐ ┌─────────▼─────────┐
│ XTRM-U (Unraid) │ │ XTRM-Nobara │
│ 192.168.10.20 │ │ 192.168.10.103 │
│ MASTER (150) │ │ BACKUP (100) │
│ │ │ │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Traefik │ │ │ │ Traefik │ │
│ │ Vaultwarden │ │ │ │ Vaultwarden │ │
│ │ Authentik │ │ │ │ Authentik │ │
│ │ AdGuard │ │ │ │ AdGuard │ │
│ │ + 25 more │ │ │ │ PostgreSQL │ │
│ └──────────────┘ │ │ │ Redis │ │
│ │ │ └──────────────┘ │
│ Keepalived (Docker)│ │ Keepalived (systemd)│
└────────────────────┘ └────────────────────┘
```

View File

@@ -0,0 +1,167 @@
# Cross-VLAN Casting & Streaming
Configuration for casting/streaming from VLANs 10 (Mgmt), 20 (Trusted), and 25 (Kids) to devices on VLAN 30 (IoT).
## Casting Devices
| Device | MAC (Ethernet) | MAC (WiFi) | Static IP | VLAN |
|--------|---------------|------------|-----------|------|
| LG TV (webOS) | B0:37:95:79:AF:9B | DC:03:98:6B:5A:3A | .40 (eth) / .41 (wifi) | 30 |
| Chromecast | — | D0:E7:82:F7:65:DD | .42 | 30 |
All IPs in subnet `192.168.30.0/24`.
## What Works
| Feature | From VLAN 20/25/10 | Notes |
|---------|-------------------|-------|
| AirPlay (Mac → LG TV) | Yes | TV must use ONE interface only (see below) |
| Smart View (Samsung → LG TV) | Yes | Works without issues |
| YouTube Cast (phone → TV/Chromecast) | Yes | Via TV Link Code, not device discovery |
| Chromecast casting | Yes | Requires mDNS repeater |
## What Doesn't Work
| Feature | Reason |
|---------|--------|
| LG ThinQ remote app | Client-side subnet check — app refuses if phone and TV are on different subnets. No workaround. |
## MikroTik Configuration
### 1. Address List
```routeros
/ip/firewall/address-list
add list=casting-devices address=192.168.30.40 comment="LG TV Ethernet"
add list=casting-devices address=192.168.30.41 comment="LG TV WiFi"
add list=casting-devices address=192.168.30.42 comment="Chromecast"
```
### 2. Firewall Rules (Forward Chain)
Bidirectional rules — casting devices need to initiate connections back (AirPlay uses separate UDP channels for timing/control).
```routeros
/ip/firewall/filter
# Forward: source VLANs → IoT
add chain=forward action=accept src-address=192.168.20.0/24 dst-address=192.168.30.0/24 comment="Allow Trusted to IoT (casting)"
add chain=forward action=accept src-address=192.168.25.0/24 dst-address=192.168.30.0/24 comment="Allow Kids to IoT (casting)"
add chain=forward action=accept src-address=192.168.10.0/24 dst-address=192.168.30.0/24 comment="Allow Mgmt to IoT"
# Return: casting devices → source VLANs
add chain=forward action=accept src-address-list=casting-devices dst-address=192.168.20.0/24 comment="Allow casting devices to Trusted (casting return)"
add chain=forward action=accept src-address-list=casting-devices dst-address=192.168.25.0/24 comment="Allow casting devices to Kids (casting return)"
add chain=forward action=accept src-address-list=casting-devices dst-address=192.168.10.0/24 comment="Allow casting devices to Mgmt (casting return)"
```
These rules must be **before** the IoT block rules:
```routeros
# Block IoT → other VLANs (AFTER the return rules above)
add chain=forward action=drop src-address=192.168.30.0/24 dst-address=192.168.10.0/24 comment="Block IoT to Management"
add chain=forward action=drop src-address=192.168.30.0/24 dst-address=192.168.20.0/24 comment="Block IoT to Trusted"
```
### 3. FastTrack Exclusion (Mangle)
FastTrack bypasses conntrack/firewall — must exclude inter-VLAN casting traffic.
```routeros
/ip/firewall/mangle
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.20.0/24 dst-address=192.168.30.0/24 comment="No FastTrack: Trusted<->IoT (casting)"
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.30.0/24 dst-address=192.168.20.0/24 comment="No FastTrack: IoT<->Trusted (casting)"
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.25.0/24 dst-address=192.168.30.0/24 comment="No FastTrack: Kids<->IoT (casting)"
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.30.0/24 dst-address=192.168.25.0/24 comment="No FastTrack: IoT<->Kids (casting)"
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.10.0/24 dst-address=192.168.30.0/24 comment="No FastTrack: Mgmt<->IoT (casting)"
add chain=forward action=mark-connection new-connection-mark=no-fasttrack passthrough=yes src-address=192.168.30.0/24 dst-address=192.168.10.0/24 comment="No FastTrack: IoT<->Mgmt (casting)"
```
FastTrack rule must use `connection-mark=no-mark`:
```routeros
/ip/firewall/filter
add chain=forward action=fasttrack-connection connection-state=established,related connection-mark=no-mark comment="defconf: fasttrack"
```
### 4. mDNS Repeater
Enables cross-VLAN device discovery (AirPlay, Chromecast).
```routeros
/ip/dns/set mdns-repeat-ifaces=1-vlan10-mgmt,2-vlan20-trusted,3-vlan25-family,4-vlan30-iot
```
### 5. IGMP Proxy
Enables multicast forwarding (SSDP/UPnP discovery).
```routeros
/routing/igmp-proxy/interface
add interface=4-vlan30-iot upstream=yes threshold=1
add interface=2-vlan20-trusted upstream=no threshold=1
add interface=3-vlan25-family upstream=no threshold=1
add interface=1-vlan10-mgmt upstream=no threshold=1
```
### 6. DHCP Static Leases
```routeros
/ip/dhcp-server/lease
add address=192.168.30.40 mac-address=B0:37:95:79:AF:9B server=dhcp-vlan30 comment="LG TV Ethernet"
add address=192.168.30.41 mac-address=DC:03:98:6B:5A:3A server=dhcp-vlan30 comment="LG TV WiFi"
add address=192.168.30.42 mac-address=D0:E7:82:F7:65:DD server=dhcp-vlan30 comment="Chromecast"
```
### 7. WiFi Access List
```routeros
/interface/wifi/access-list
add mac-address=DC:03:98:6B:5A:3A action=accept vlan-id=30 comment="LG TV WiFi"
add mac-address=D0:E7:82:F7:65:DD action=accept vlan-id=30 comment="Chromecast"
```
## Troubleshooting
### AirPlay Black Screen on LG TV
**Root cause**: LG TV connected via both Ethernet AND WiFi simultaneously.
The TV advertises AirPlay via mDNS on one interface but streams on the other, creating asymmetric routing. The Mac connects to one IP, but the TV sends return traffic from a different IP.
**Fix**: Use only ONE connection on the TV — either Ethernet or WiFi, not both. Disconnect the unused one in TV settings.
- Ethernet MAC: `B0:37:95:79:AF:9B` → 192.168.30.40
- WiFi MAC: `DC:03:98:6B:5A:3A` → 192.168.30.41
### Do NOT Use Masquerade NAT
Masquerade (srcnat) was tried to make cross-VLAN traffic appear local. This breaks AirPlay because:
- AirPlay negotiates separate UDP feedback channels (timing port 7010, control 6001, timing 6002)
- With masquerade, TV sends feedback to the router IP (192.168.30.1) instead of the Mac's real IP
- Result: control channel works but video/audio never arrives → black screen
### Chromecast Setup Issues
The Chromecast can only be set up via the Google Home app (no web interface).
**Common setup failure**: Google Home app finds the Chromecast via Bluetooth, connects to its setup WiFi hotspot, but then says "Could not communicate with your Chromecast."
**Fix** (on phone before setup):
1. Disable mobile data
2. Disable VPN
3. Turn off "Switch to mobile data when WiFi is unstable"
4. Enable Location services (required by Google Home)
5. Clear Google Home app cache
**WiFi requirements**: Chromecast requires **WPA2 with AES/CCMP** encryption. It will NOT connect to networks using TKIP. The XTRM2 (2.4GHz) security profile was changed from TKIP to CCMP to support this:
```routeros
/interface/wifi/security/set sec-xtrm2 encryption=ccmp
```
### VPN Interference
If your Mac is connected to WireGuard VPN, the VPN overrides the default route — local traffic bypasses WiFi and goes through the VPN tunnel. Disconnect VPN before casting.
### CAP VLAN Limit
The CAP XL ac may show "maximum VLAN count for interface was reached." If a device can't connect to WiFi, try disabling the CAP interfaces temporarily to force connection to the HAP's radio directly.

View File

@@ -0,0 +1,275 @@
# Development Environment
**Last Updated:** 2026-03-08
Web-based development environment running directly on Unraid, providing VS Code IDE with full host access to Claude Code, Cooperator CLI, Docker, and all project repositories.
---
## OpenVSCode Server
| Property | Value |
|----------|-------|
| **URL** | https://code.xtrm-lab.org |
| **Auth** | Authentik forward auth (SSO) |
| **Port** | 3100 (host-native, not a container) |
| **Binary** | `/mnt/user/appdata/openvscode/current/` (symlink) |
| **Config** | `/mnt/user/appdata/openvscode/config/` |
| **Boot Script** | `/mnt/user/appdata/openvscode/start.sh` |
| **Log** | `/mnt/user/appdata/openvscode/server.log` |
**Why host-native?** Running directly on Unraid (not in a container) means the VS Code terminal has full access to `claude`, `cooperator`, `node`, `npm`, `docker`, `git`, and all host tools. No volume mount hacks or container-breaking updates.
### Persistence
All data lives on the array (`/mnt/user/`) — survives Unraid OS updates:
| Component | Path | Purpose |
|-----------|------|---------|
| Server binary | `/mnt/user/appdata/openvscode/openvscode-server-v1.109.5-linux-x64/` | VS Code server |
| Symlink | `/mnt/user/appdata/openvscode/current` → version dir | Easy version switching |
| VS Code config | `/mnt/user/appdata/openvscode/config/` | Extensions, settings, themes |
| Start script | `/mnt/user/appdata/openvscode/start.sh` | Startup with PATH setup |
### Updating OpenVSCode Server
```bash
# Download new version
cd /mnt/user/appdata/openvscode
curl -fsSL "https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-vX.Y.Z/openvscode-server-vX.Y.Z-linux-x64.tar.gz" -o new.tar.gz
tar xzf new.tar.gz && rm new.tar.gz
# Switch symlink and restart
ln -sfn openvscode-server-vX.Y.Z-linux-x64 current
pkill -f "openvscode-server.*--port 3100"
/mnt/user/appdata/openvscode/start.sh
```
Extensions and settings are preserved (stored separately in `config/`).
### Traefik Routing
Defined in `/mnt/user/appdata/traefik/dynamic.yml`:
```yaml
openvscode-secure:
rule: "Host(`code.xtrm-lab.org`)"
entryPoints: [https]
middlewares: [default-headers, authentik-forward-auth]
tls:
certResolver: cloudflare
service: openvscode
# ...
openvscode:
loadBalancer:
servers:
- url: "http://192.168.10.20:3100"
```
---
## Claude Code
| Property | Value |
|----------|-------|
| **Version** | 2.1.71 |
| **Binary** | `/mnt/user/appdata/claude-code/.npm-global/bin/claude` |
| **Symlink** | `/root/.local/bin/claude` |
| **Config** | `/mnt/user/appdata/claude-code/.claude.json``/root/.claude.json` |
| **Settings** | `/mnt/user/appdata/claude-code/.claude/``/root/.claude/` |
| **Boot Script** | `/mnt/user/appdata/claude-code/install-claude.sh` |
### Persistence
npm global prefix set to `/mnt/user/appdata/claude-code/.npm-global/` (array-backed). Boot script creates symlinks from `/root/` to persistent paths.
### Updating Claude Code
```bash
source /root/.bashrc
npm install -g @anthropic-ai/claude-code
claude --version
```
---
## Cooperator CLI
| Property | Value |
|----------|-------|
| **Version** | 3.36.1 |
| **Binary** | `/mnt/user/appdata/claude-code/.npm-global/bin/cooperator` |
| **Config** | `~/.cooperator/.env` (Shortcut token, Confluence, git config) |
| **Registry** | `@ampeco:registry=https://gitlab.com/api/v4/projects/71775017/packages/npm/` |
| **npm auth** | `/root/.npmrc` (GitLab PAT) |
### What Cooperator Install Sets Up
- **Commands** — `~/.claude/commands/cooperator` → cooperator's claude-commands
- **Agents** — `~/.claude/agents/implementation-task-executor.md`
- **Skills** — 12 cooperator skills (shortcut-operations, create-feature-story, gitlab-operations, etc.)
- **Shortcut API** — validated via `~/.cooperator/.env` token
### Updating Cooperator
```bash
source /root/.bashrc
npm install -g @ampeco/cooperator
cooperator --version
```
**Note:** `/root/.npmrc` is in RAM — recreated on boot if needed. The GitLab PAT is stored in `/boot/config/go` would need a persistent `.npmrc` setup if token changes frequently.
---
## GitLab CLI (glab)
| Property | Value |
|----------|-------|
| **Version** | 1.89.0 |
| **Binary** | `/usr/local/bin/glab` (RAM — lost on reboot) |
| **Config** | `~/.config/glab-cli/config.yml` |
| **Auth** | GitLab PAT (same as npm registry token) |
**Note:** glab binary at `/usr/local/bin/` is lost on Unraid reboot. Add to boot script or persist to appdata.
---
## Python (via uv)
| Property | Value |
|----------|-------|
| **uv** | `/root/.local/bin/uv` |
| **Python** | 3.12.13 (managed by uv) |
| **mikrotik-mcp venv** | `/mnt/user/projects/mikrotik-mcp/venv/` |
| **unraid-mcp venv** | `/mnt/user/projects/unraid-mcp/.venv/` |
---
## Custom Skills
6 custom skills synced from Mac to `/mnt/user/appdata/claude-code/custom-skills/`:
| Skill | Description |
|-------|-------------|
| ev-compliance-story | EV regulatory compliance story creation |
| ev-protocol-expert | OCPP/OCPI/AFIR protocol expertise |
| frontend-designer | Nova/Vue component design |
| mikrotik-admin | MikroTik router management via MCP |
| prd-generator | Product requirements documents |
| unraid-admin | Unraid server management via MCP |
Symlinked to `~/.claude/skills/` alongside 12 cooperator skills (18 total).
---
## MCP Servers
### Registered (TODO)
The following MCP servers need to be registered via `claude mcp add` on Unraid:
| Server | Command | Status |
|--------|---------|--------|
| **shortcut** | `node /mnt/user/appdata/claude-code/mcp-server-shortcut/dist/index.js` | Built, needs `claude mcp add` |
| **mikrotik** | `/mnt/user/projects/mikrotik-mcp/venv/bin/python -m mikrotik_mcp.server` | Venv ready, needs `claude mcp add` |
| **unraid** | `/mnt/user/projects/unraid-mcp/.venv/bin/python -m unraid_mcp.main` | Venv ready, needs `claude mcp add` |
| **playwright** | `npx -y @playwright/mcp@latest --isolated` | npx available, needs `claude mcp add` |
| **smartbear** | `npx -y @smartbear/mcp@latest` | npx available, needs `claude mcp add` |
### Environment Variables for MCPs
- **mikrotik**: `DEVICES_PATH=/mnt/user/projects/mikrotik-mcp/devices.json`
- **unraid**: `UNRAID_API_URL`, `UNRAID_API_KEY`, `UNRAID_MCP_TRANSPORT=stdio`, `UNRAID_VERIFY_SSL=false`
- **shortcut**: `SHORTCUT_API_TOKEN` (from `~/.cooperator/.env`)
---
## Projects Workspace
All projects at `/mnt/user/projects/`, opened as default folder in VS Code.
### Personal Projects (Gitea)
| Project | Gitea Repo | Description |
|---------|-----------|-------------|
| infrastructure | jazzymc/infrastructure | This repo — home lab documentation |
| claude-skills | jazzymc/claude-skills | Claude Code custom skills |
| mikrotik-mcp | jazzymc/mikrotik-mcp | MikroTik MCP server |
| unraid-mcp | jazzymc/unraid-mcp | Unraid MCP server |
| unraid-glass | jazzymc/unraid-glass | Unraid dashboard plugin |
| openclaw | jazzymc/openclaw | OpenClaw game project |
| nanobot-mcp | jazzymc/nanobot-mcp | Nanobot MCP server |
| nanobot-hkuds | jazzymc/nanobot-hkuds | Nanobot HKU DS |
| xtrm-agent | jazzymc/xtrm-agent | AI agent framework |
| geekmagic-smalltv | jazzymc/geekmagic-smalltv | SmallTV firmware |
| homarr | jazzymc/homarr | Homarr dashboard fork |
| shortcut-daily-sync | jazzymc/shortcut-daily-sync | Shortcut sync tool |
**Remote URL format:** `https://jazzymc:<token>@git.xtrm-lab.org/jazzymc/<repo>.git`
### AMPECO Work Projects
| Project | Source | Type |
|---------|--------|------|
| backend | GitLab (ampeco/apps/charge/backend) | Git clone |
| crm | GitLab (ampeco/apps/charge/crm) | Git clone |
| marketplace | GitLab (ampeco/apps/charge/marketplace) | Git clone |
| mobile-2 | GitLab (ampeco/apps/charge/mobile-2) | Git clone |
| ad-hoc-payment-web-app | GitLab (ampeco/apps/charge/external-apps/) | Git clone |
| dev-proxy | GitLab (ampeco/apps/shared/dev-proxy) | Git clone |
| ampeco-custom-dashboard-widgets-boilerplate | GitHub (ampeco/) | Git clone |
| docs | Local rsync | Reference docs |
| stories | Local rsync | Product stories |
| booking-ewa | Local rsync | Booking app |
| ewa-ui | Local rsync | EWA frontend |
| design-tokens | Local rsync | Design system tokens |
| ampeco-backup | Local rsync | Configuration backups |
| central_registry | Local rsync | Service registry |
| CCode-UI-Distribution-1.0.0 | Local rsync | UI distribution |
| automations | Local rsync | Automation scripts |
**GitLab auth:** OAuth2 PAT in remote URLs.
---
## Boot Sequence
`/boot/config/go` triggers on Unraid boot:
1. **Wait for array** — polls for `/mnt/user/appdata/claude-code` (up to 5 min)
2. **Claude Code setup**`/mnt/user/appdata/claude-code/install-claude.sh`
- Creates symlinks (`/root/.local/bin/claude`, `/root/.claude`, `/root/.claude.json`)
- Writes `.bashrc` with persistent npm PATH
3. **OpenVSCode Server**`/mnt/user/appdata/openvscode/start.sh`
- Kills any existing instance
- Starts on port 3100 with persistent config dir
- Sources Claude/Cooperator PATH for terminal sessions
---
## Architecture Diagram
```
Browser → https://code.xtrm-lab.org
Traefik (443) → Authentik SSO check
OpenVSCode Server (:3100, host-native)
Unraid Host Shell
├── claude (2.1.71)
├── cooperator (3.36.1)
├── glab (1.89.0)
├── node (22.18.0) / npm (10.9.3) / bun (1.3.10)
├── uv + python 3.12
├── docker / docker compose
├── git
└── /mnt/user/projects/
├── ampeco/ (18 AMPECO work projects)
├── infrastructure/
├── claude-skills/
├── mikrotik-mcp/
└── ... (12 personal repos)
```

405
docs/CHANGELOG.md Normal file
View File

@@ -0,0 +1,405 @@
# Infrastructure Changelog
**Purpose:** Major infrastructure events only. Minor changes are in git commit messages.
---
## 2026-02-28
### Docker Container Audit & Migration to Dockge
- **[DOCKER]** Removed 4 orphan images: nextcloud/all-in-one, olprog/unraid-docker-webui, ghcr.io/ich777/doh-server, ghcr.io/idmedia/hass-unraid
- **[DOCKER]** Removed ancient pgAdmin4 v2.1 (status=Created) and fenglc/pgadmin4 image
- **[DOCKER]** Removed spaceinvaderone/ha_inabox image (replaced by Home-Assistant-Container)
- **[TRAEFIK]** Removed Docker provider constraint (`traefik.constraint=valid`) — Docker labels now auto-discovered
- **[TRAEFIK]** Cleaned up dynamic.yml: removed 14 stale/migrated router+service pairs (pangolin, pihole, doh, netbox, and services now using Docker labels)
- **[TRAEFIK]** Added dockge-secure router to dynamic.yml
- **[DOCKER]** Created 6 new Dockge stacks: docker-socket-proxy, tuyagateway, firefly, seekandwatch, ha-time-machine, homeassistant (replaced inabox with Container)
- **[DOCKER]** Migrated ALL 53 containers from dockerman to Dockge compose stacks (100% coverage)
- **[DOCKER]** Fixed Nextcloud Traefik rule: empty Host() → Host(`cloud.xtrm-lab.org`)
- **[DOCKER]** Fixed UptimeKuma Traefik rule: empty Host() → Host(`uptime.xtrm-lab.org`)
- **[DOCKER]** Fixed Homarr domain: `homarr.xtrm-lab.org``xtrm-lab.org` (root domain)
- **[DOCKER]** Fixed Netdisco entrypoint: `websecure``https`
- **[DOCKER]** Removed stale `traefik.constraint=valid` from Dockhand
- **[DOCKER]** Fixed Transmission middleware: removed non-existent `transmission-headers@file`
- **[DOCKER]** Added Authentik forward auth middleware to: n8n, homarr, transmission, speedtest-tracker, uptime-kuma, firefly, seekandwatch, open-webui, traefik dashboard, dockge, netalertx, urbackup, unimus
- **[DOCKER]** Added Traefik labels to: vaultwarden, open-webui (ai.xtrm-lab.org), firefly, seekandwatch
- **[DOCKER]** Added missing Unraid labels (icon, managed, webui) to: ntfy, timemachine, ollama, docker-socket-proxy, tuyagateway, all new stacks
- **[DOCKER]** Moved ollama + open-webui from bridge to dockerproxy network
- **[DOCKER]** Moved fireflyiii + firefly-data-importer from none to dockerproxy network
- **[DOCKER]** Moved SeekAndWatch from bridge to dockerproxy network
- **[DOCKER]** Removed traefik labels from host-network containers (plex, netalertx) — routed via dynamic.yml only
- **[DOCKER]** Fixed NetAlertX: added read_only, proper capabilities (NET_RAW/NET_ADMIN), and UID 20211
- **[DOCKER]** Removed empty netbox stack directory
## 2026-03-09
### Claude Code Tooling Completion
- **[SERVICE]** Installed Cooperator CLI v3.36.1 on Unraid (`npm install -g @ampeco/cooperator`)
- **[SERVICE]** Ran `cooperator install --non-interactive` — symlinked commands, agents, 12 skills to `~/.claude/`
- **[SERVICE]** Created `~/.cooperator/.env` with Shortcut API token, Confluence token, git config
- **[SERVICE]** Installed glab CLI v1.89.0 on Unraid (`/usr/local/bin/glab`) — authenticated as kaloyan.danchev
- **[SERVICE]** Installed uv package manager + Python 3.12.13 on Unraid
- **[SERVICE]** Created Python venvs for mikrotik-mcp and unraid-mcp projects
- **[SERVICE]** Copied MikroTik SSH key from Mac to Unraid — SSH to HAP ax3 verified working
- **[SERVICE]** Synced 6 custom Claude skills to `/mnt/user/appdata/claude-code/custom-skills/` (ev-compliance-story, ev-protocol-expert, frontend-designer, mikrotik-admin, prd-generator, unraid-admin)
- **[SERVICE]** Built shortcut MCP server at `/mnt/user/appdata/claude-code/mcp-server-shortcut/`
- **[SERVICE]** Enabled Claude plugins: ralph-loop, claude-md-management, playground
- **[DOCS]** Updated 12-DEVELOPMENT-ENVIRONMENT.md with Cooperator, glab, Python, skills, MCP sections
#### TODO — MCP Server Registration
The following MCP servers are built/ready but need `claude mcp add` registration (requires interactive Claude session on Unraid):
- shortcut, mikrotik, unraid, playwright, smartbear
## 2026-03-08
### Development Environment Setup
- **[SERVICE]** Installed OpenVSCode Server as host-native process (port 3100, not a container) — accessible at https://code.xtrm-lab.org
- **[SERVICE]** Traefik route added in dynamic.yml with Authentik forward auth
- **[SERVICE]** Boot auto-start via `/boot/config/go``/mnt/user/appdata/openvscode/start.sh`
- **[SERVICE]** Claude Code updated to v2.1.71, persistent at `/mnt/user/appdata/claude-code/.npm-global/`
- **[SERVICE]** Cooperator CLI v3.36.1 installed globally (`npm install -g @ampeco/cooperator`)
- **[SERVICE]** Created `/mnt/user/projects/` workspace with 12 personal repos (Gitea) + 18 AMPECO work projects (GitLab)
- **[DOCS]** Added `12-DEVELOPMENT-ENVIRONMENT.md` documenting full dev environment setup
### Docker Maintenance
- **[DOCKER]** Created Unraid Docker Manager XML templates for 11 containers missing them (adguardhome, gitea, minecraft, ntfy, ollama, open-webui, etc.)
- **[DOCKER]** Pulled new images for all 30 active Dockge stacks, 14 containers received updates
- **[DOCKER]** Cleaned up dangling images: 10.95 GB reclaimed
- **[DOCKER]** Organized all 42 containers into Docker Folders (12 folders: Infrastructure, Security, Monitoring, DevOps, Media, etc.)
- **[DOCKER]** Pushed 6 local-only projects to Gitea (claude-skills, mikrotik-mcp, unraid-mcp, nanobot-mcp, nanobot-hkuds, openclaw)
### Service Fixes
- **[FIX]** Gitea DB connection: fixed hardcoded PostgreSQL IP (172.18.0.13) → hostname `postgresql17` in compose and app.ini
- **[FIX]** Traefik: removed stale stopped container blocking restart
- **[FIX]** Redis: removed stale stopped container blocking recreate
## 2026-02-26
### WiFi & CAP VLAN Fixes
- **[WIFI]** Fixed 5GHz channel overlap: HAP wifi1 reduced from 80MHz to 40MHz at 5180MHz, CAP cap-wifi1 at 5220MHz (no overlap)
- **[WIFI]** Restored all 29 WiFi access-list MAC→VLAN entries (were missing/lost)
- **[WIFI]** Fixed cap-wifi2 band mismatch: was `band=2ghz-n` with frequency=5220 (5GHz), corrected to frequency=2412
- **[CAPSMAN]** Enabled bridge VLAN filtering on CAP (cAP XL ac) — all VLANs now properly tagged through CAP
- **[CAPSMAN]** CAP bridgeLocal config: vlan-filtering=yes, pvid=10, VLANs 10/20/25/30/35/40 with proper tagged/untagged members
- **[CAPSMAN]** Set `capdp` datapath vlan-id=40 for default PVID on dynamic wifi bridge ports
- **[CAPSMAN]** VLAN assignment through CAP now working — access-list vlan-id entries propagate correctly
- **[NETWORK]** Fixed AdGuard Home IP conflict: container was at 192.168.10.2 (CAP's IP), now static at 192.168.10.10
- **[NETWORK]** Fixed adguardhome-sync IP conflict: was at 192.168.10.3 (CSS326's IP), now static at 192.168.10.11
- **[WIFI]** Added Xiaomi Air Purifier 2 (C8:5C:CC:40:B4:AA) to access-list as VLAN 30 (IoT)
### WiFi Quality Optimization
- **[WIFI]** Fixed 2.4GHz co-channel interference: HAP on ch 1 (2412), CAP moved from ch 1 to ch 6 (2437)
- **[WIFI]** Fixed 5GHz overlap: HAP stays ch 36 (5180, 40MHz), CAP moved from ch 44 (5220) to ch 52 (5260, DFS)
- **[WIFI]** Fixed CAP 2.4GHz width from 40MHz to 20MHz for IoT compatibility
- **[WIFI]** TX power kept at defaults (17/16 dBm) — reduction caused kitchen coverage loss through concrete walls
## 2026-02-24
### Motherboard Replacement & NVMe Cache Pool
- **[HARDWARE]** Replaced XTRM-U motherboard — new MAC `38:05:25:35:8E:7A`, DHCP lease updated on MikroTik
- **[HARDWARE]** Confirmed disk1 (10TB HGST HUH721010ALE601, serial 2TKK3K1D) mechanically dead — clicking heads, fails on multiple SATA ports and new motherboard
- **[STORAGE]** Created new Unraid-managed cache pool: 3x Samsung 990 EVO Plus 1TB NVMe, ZFS RAIDZ1 (~1.8TB usable)
- **[STORAGE]** Pool settings: autotrim=on, compression=on
- **[DOCKER]** Migrated Docker from btrfs loopback image (disk1 HDD) to ZFS on NVMe cache pool
- **[DOCKER]** Docker now uses ZFS storage driver directly on `cache/system/docker` dataset
- **[DOCKER]** Recreated `dockerproxy` bridge network, rebuilt all 39 container templates
- **[DOCKER]** Restarted Dockge and critical stacks (adguardhome, ntfy, gitea, woodpecker, etc.)
- **[STORAGE]** Deleted old `docker.img` (200GB) from disk1
- **[INCIDENT]** disk1 still running in parity-emulated mode — replacement drive needed
### Post-Migration Container Cleanup
- **[NETWORK]** Fixed Traefik unreachable: removed stale Docker bridge (duplicate 172.18.0.0/16 subnet) + 7 orphaned bridges
- **[DOCKER]** Removed deprecated containers: DoH-Server, binhex-plexpass (duplicate of Plex)
- **[DOCKER]** Removed obsolete containers: HomeAssistant_inabox, Docker-WebUI, hass-unraid
- **[DOCKER]** Removed nextcloud-aio-mastercontainer (replaced by Nextcloud container)
- **[SERVICE]** Fixed adguardhome-sync: recreated config file (was directory from migration), switched to br0 network for macvlan reachability
- **[SERVICE]** Fixed diode stack: recreated .env, nginx.conf, OAuth2 client config; ran Hydra DB migration and client bootstrap
- **[SERVICE]** Fixed diode-agent: corrected YAML format, secrets, and Hydra authentication
- **[SERVICE]** Started unmarr (Homarr fork, 172.18.0.81) and rustfs (S3-compatible storage)
- **[DOCKER]** Final state: 53 containers running, pgAdmin4 stopped (utility)
- **[DOCS]** Updated 03-SERVICES-OTHER.md with removed containers
---
## 2026-02-14
### CAP XL ac Recovery
- **[WIRELESS]** Factory reset CAP XL ac (lost credentials)
- **[WIRELESS]** Reconfigured CAPsMAN: regenerated certificate, CAP re-enrolled with `certificate=request`
- **[WIRELESS]** Both CAP radios now active: wifi1 (2.4GHz XTRM2) + wifi2 (5GHz XTRM)
- **[WIRELESS]** CAP now running RouterOS 7.21.1
- **[WIRELESS]** Enabled SSH on CAP port 2222 for user xtrm with mikrotik key
- **[WIRELESS]** Confirmed WiFi access list has no VLAN assignment (rolled back Jan 27)
### Roms Network Share
- **[SERVICE]** Shared /mnt/user/roms (2.3TB, 49 systems) via SMB from Unraid
- **[SERVICE]** Mounted on Nobara at /mnt/roms (fstab, CIFS guest, systemd.automount)
- **[SERVICE]** Mounted on Recalbox via custom.sh boot script (CIFS bind mounts)
- **[SERVICE]** Deleted local roms from Recalbox SD card (~12.5GB freed)
### WiFi DHCP Fix
- **[NETWORK]** Fixed DHCP not working on HAP1 local WiFi (wifi1/wifi2)
- **[NETWORK]** Root cause: VLAN 40 had wifi1/wifi2 as **tagged** instead of **untagged** — DHCP responses had 802.1Q tags clients couldn't process
- **[NETWORK]** Fix: `/interface bridge vlan set` wifi1,wifi2 to untagged for VLAN 40
### Minecraft Server Deployed
- **[SERVICE]** Deployed Minecraft Java Edition (itzg/minecraft-server) on Unraid
- **[SERVICE]** Version 1.21.11, Survival mode, 2GB RAM, max 10 players
- **[SERVICE]** Docker IP 172.18.0.80, port 25565, Dockge stack `minecraft`
- **[NETWORK]** NAT port forward WAN:25565 → 192.168.10.20:25565
- **[NETWORK]** Hairpin NAT for internal access via minecraft.xtrm-lab.org
- **[SERVICE]** Added Unraid labels with Minecraft icon
### Documentation Updates
- **[DOCS]** Updated 07-WIFI-CAPSMAN-CONFIG.md: CAP both radios working, access list status
- **[DOCS]** Updated 01-NETWORK-MAP.md: Fixed CAP IP (.6→.2), added Nobara and SMB shares
- **[DOCS]** Updated 04-HARDWARE-INVENTORY.md: CAP details, added Recalbox device
- **[DOCS]** Updated 06-VLAN-DEVICE-ASSIGNMENT.md: Added Nobara (VLAN 10) and Recalbox (VLAN 25)
- **[DOCS]** Updated 03-SERVICES-OTHER.md: Added Roms SMB share, Minecraft server section
---
## 2026-02-13
### Failover Infrastructure Deployed
- **[SERVICE]** Deployed Docker failover stack on XTRM-Nobara (Traefik, Vaultwarden, Authentik, AdGuard Home)
- **[SERVICE]** Installed Docker CE 29.2.1 + Docker Compose 5.0.2 on Nobara
- **[SERVICE]** Deployed Keepalived VRRP for automatic failover (VIP: 192.168.10.250)
- **[SERVICE]** Unraid: Keepalived as Docker container (local/keepalived, MASTER priority 150)
- **[SERVICE]** Nobara: Keepalived as systemd service (BACKUP priority 100)
- **[SERVICE]** Replicated data: Vaultwarden DB, Authentik PostgreSQL dump (864MB), AdGuard config, Traefik certs
- **[NETWORK]** Added VRRP protocol to Nobara firewall (firewalld)
- **[NETWORK]** Configured SSH key auth to Nobara (id_ed25519_nobara, passwordless)
- **[NETWORK]** Added SSH config alias: `ssh nobara`
- **[DOCS]** Created 10-FAILOVER-NOBARA.md with full failover documentation
- **[DOCS]** Updated 02-SERVICES-CRITICAL.md with failover section
- **[DOCS]** Updated 04-HARDWARE-INVENTORY.md with XTRM-Nobara specs
- **[DOCS]** Updated README.md and CLAUDE.md with Nobara references
---
## 2026-02-06
### Unraid Flash Drive Failure
- **[INCIDENT]** Unraid flash drive crashing - migration procedure created
- **[DOCS]** Created incident report with full flash drive replacement procedure
### Documentation Restructure
- **[DOCS]** Restructured docs/ from 23 files to clean 9-doc structure
- **[DOCS]** Archived 12 completed VLAN migration project docs to archive/vlan-migration/
- **[DOCS]** Archived 5 done/superseded WIP docs (VLAN proposals, AI stack, Fossorial, DNS backup)
- **[DOCS]** Created standing reference docs: 08-DNS-ARCHITECTURE.md, 09-TAILSCALE-VPN.md
- **[DOCS]** Renamed docs to clean numbering (05-PORT-UTILIZATION, 06-VLAN-DEVICE-ASSIGNMENT, 07-WIFI-CAPSMAN-CONFIG)
- **[DOCS]** Merged 00-CHANGELOG.md + 06-CHANGELOG.md → CHANGELOG.md
- **[DOCS]** Updated all core docs with current VLAN IPs (192.168.31.x → 192.168.10.x)
- **[DOCS]** Fixed CSS1 IP: 192.168.10.9 → 192.168.10.3, ZX1 IP: 192.168.10.7 → 192.168.10.4
- **[DOCS]** Cleaned 06-VLAN-DEVICE-ASSIGNMENT.md: removed migration-era columns and sections, fixed VLAN 25 subnet
- **[DOCS]** Updated README.md, CLAUDE.md, archive/README.md, wip/README.md
---
## 2026-02-01
### WIP Documentation
- **[DOCS]** Added KVM-SWITCH-MAC-NOBARA.md - Software KVM for Mac/Nobara switching
- DDC/CI monitor control (Dell U3821DW) + HID++ Logitech peripheral switching
- Scripts created on Mac at ~/scripts/
---
## 2026-01-31
### Docker Cleanup
- **[DOCKER]** Removed 18 unused images (~4.9 GB reclaimed)
- **[DOCKER]** Removed 12 dangling images (old builds, untagged)
- **[DOCKER]** Removed Slurpit stack images (warehouse, portal, scanner, scraper)
- **[DOCKER]** Removed unused MongoDB 8 and MariaDB 11 images
- **[DOCKER]** Removed 35 orphaned volumes (~1.15 GB reclaimed)
- **[DOCKER]** Removed 28 anonymous dangling volumes
- **[DOCKER]** Removed 6 nextcloud_aio_* volumes (from old AIO install)
- **[DOCKER]** Removed orphaned redis-data volume
- **[DOCKER]** **Total reclaimed: ~6 GB**
### Kept (Stopped Containers)
- open-webui, ollama (AI stack - for future use)
- pgAdmin4 (database management)
- diode-hydra-migrate, diode-auth-bootstrap (one-time migration jobs)
---
## 2026-01-27
### VLAN Filtering Rolled Back
- **[VLAN]** Enabled VLAN filtering - caused connectivity issues
- **[VLAN]** ZX1 switch unreachable after activation (no management IP responding)
- **[VLAN]** CSS326 traffic routing through ZX1 (not direct eth3 link)
- **[VLAN]** **Rolled back** - VLAN filtering disabled
- **[CONFIG]** Added eth4 (ZX1) to all VLAN tagged lists for future use
- **[STATUS]** Network back to Legacy mode (192.168.31.0/24)
- **[TODO]** Need physical access to ZX1 to configure VLAN trunking
### Issues Identified
- ZX1 switch not responding on documented IP 192.168.31.22
- ZX1 may need VLAN trunk configuration before re-enabling filtering
- All CSS326 traffic goes via ZX1→HAP1, not direct CSS326→HAP1 link (STP?)
---
## 2026-01-26
### VLAN Filtering Activated
- **[VLAN]** VLAN filtering enabled on MikroTik bridge - SUCCESSFUL
- **[VLAN]** Internet connectivity verified (ping 1.1.1.1, google.com)
- **[VLAN]** DNS resolution working through AdGuard
- **[VLAN]** All previous fixes (DHCP DNS, firewall, NAT masquerade) working correctly
- **[STATUS]** Network segmentation now ACTIVE
### Local AI Stack Deployed
- **[AI]** Deployed Ollama container with Intel GPU passthrough
- **[AI]** Deployed Open WebUI at http://192.168.31.2:3080
- **[AI]** Installed qwen2.5-coder:7b base model
- **[AI]** Created custom `unraid-assistant` model with infrastructure knowledge
- **[AI]** Created `/usr/local/bin/ai` terminal helper command
- **[AI]** Stopped non-critical containers for RAM: karakeep, unimus, homarr, netdisco-*
### VLAN Activation Attempt & Fixes
- **[VLAN]** Configured CSS326 switch VLANs via SwOS web interface
- **[VLAN]** Enabled VLAN filtering on MikroTik - caused internet outage
- **[VLAN]** Rolled back VLAN filtering to restore connectivity
- **[VLAN]** **ROOT CAUSE IDENTIFIED:** Multiple configuration issues
### Issues Fixed
- **[FIX]** DHCP DNS now points to each VLAN gateway instead of legacy 192.168.31.1
- **[FIX]** Added DNS redirect rules for all VLANs (src-address-list=all-vlans)
- **[FIX]** Added all VLAN interfaces to LAN firewall interface list
- **[FIX]** Added NAT masquerade rules for VLAN traffic to AdGuard container
- **[BACKUP]** MikroTik config saved before activation attempt
---
## 2026-01-25
### VLAN Phase 1 Complete
- **[VLAN]** Added VLAN 25 (Kids) - interface, IP, DHCP server, pool, bridge entry
- **[VLAN]** Fixed VLAN 10 (Management) leases - correct IPs per device assignment doc
- **[VLAN]** Fixed VLAN 30 (IoT) leases - all 14 devices with correct IPs
- **[VLAN]** Added VLAN 25 (Kids) leases - 6 devices including XTRM-Ally
- **[VLAN]** Added VLAN 50 (Guest) leases - 7 unknown devices
- **[VLAN]** Added firewall rules for VLAN 25 (Kids → IoT, Legacy, DNS)
- **[VLAN]** Total devices configured: 44
### VLAN Implementation (Prepared)
- **[VLAN]** Created 6 VLANs on MikroTik bridge (10, 20, 30, 35, 40, 50)
- **[VLAN]** Configured IP addresses for all VLAN interfaces
- **[VLAN]** Created DHCP servers and pools for each VLAN
- **[VLAN]** Added static DHCP leases mapping MACs to VLAN IPs
- **[VLAN]** Configured bridge VLAN table with tagged/untagged ports
- **[VLAN]** Set WiFi ports PVID=20 (Trusted VLAN default)
- **[VLAN]** Added inter-VLAN firewall rules (active)
- **[VLAN]** VLAN filtering NOT YET ENABLED (pending CSS326 switch config)
- **[DOCS]** Added docs/11-VLAN-IMPLEMENTATION.md
- **[SCRIPTS]** Added scripts/mikrotik-vlan-setup.rsc and mikrotik-vlan-enable.rsc
### DNS Configuration
- **[DNS]** Updated both AdGuard instances to use Quad9 DoH
- **[DNS]** Bootstrap DNS: 9.9.9.9, 149.112.112.112
### MikroTik Containers
- **[CONTAINER]** AdGuard Home container running on MikroTik (172.17.0.2)
- **[CONTAINER]** Tailscale container configured (172.17.0.3)
- **[CONTAINER]** Fixed Tailscale container authentication
- **[CONTAINER]** Container bridge (containers-br) with NAT
### Network
- **[NETWORK]** Enabled CSS326 SFP1 port - 10G backbone link to ZX1 now active
### Documentation
- **[DOCS]** Created 02-PORT-UTILIZATION.md with ASCII port diagrams
- **[DOCS]** Fixed ZX1 switch IP: 192.168.31.22 (was incorrectly documented as .7)
### Incident
- **[INCIDENT]** DNS outage after MikroTik restart - multiple root causes fixed:
- NAT rules blocking AdGuard outbound DNS (added exception rules)
- DHCP pushing wrong DNS (8.8.8.8 → 192.168.31.1)
- NAT redirect pointing to wrong IP/port (172.17.0.5:5355 → 192.168.31.4:53)
- Asymmetric routing (added srcnat masquerade for DNS redirect)
- **[SERVICE]** Removed MikroTik AdGuard Home container (storage/overlay errors)
- **[SERVICE]** Removed MikroTik Tailscale container (root directory missing)
- **[SERVICE]** Removed Pi-hole/Unbound leftovers from MikroTik (veth, mounts, envs)
- **[NETWORK]** Consolidated DNS architecture: MikroTik → Unraid AdGuard (192.168.31.4) only
- **[DOCS]** Created incident reports in docs/incidents/
- **[DOCS]** Restructured documentation - consolidated into 5 core docs + archive
- **[NETBOX]** Added shelf devices for rack organization (U9, U7, U3)
---
## 2026-01-24
- **[NETBOX]** Standardized device names to NetBox convention (HAP1, CSS1, ZX1)
- **[DOCS]** Created NETWORK-PHYSICAL-MAP.md with complete port maps
---
## 2026-01-23
- **[SERVICE]** Deployed Diode network discovery stack
- **[SERVICE]** Removed Slurp'it (replaced by Diode + NetDisco)
- **[SERVICE]** Consolidated NetBox Redis to shared instance
- **[SERVICE]** Removed redundant DNS services (Unbound, DoH-Server, stunnel-dot)
---
## 2026-01-22
- **[SERVICE]** Migrated NetBox to shared PostgreSQL 17
- **[SERVICE]** Deployed AdGuard Home on MikroTik (primary DNS)
- **[SERVICE]** Deployed AdGuard Home on Unraid (secondary DNS)
- **[SERVICE]** Removed Pi-hole (replaced by AdGuard Home)
- **[DOCS]** Created INFRASTRUCTURE-DIAGRAM.md
---
## 2026-01-21
- **[BACKUP]** Configured Rclone sync to Google Drive
---
## 2026-01-19
- **[SERVICE]** Deployed NetBox IPAM/DCIM
- **[SERVICE]** Deployed NetDisco network discovery
- **[NETWORK]** Enabled SNMP on all MikroTik devices
---
## 2026-01-18
- **[SERVICE]** Deployed Gitea git server
- **[SERVICE]** Deployed Woodpecker CI
- **[NETWORK]** Configured CAPsMAN on HAP1
- **[WIRELESS]** CAP added to CAPsMAN management
---
## 2026-01-17
- **[SERVICE]** Deployed Portainer CE
---
## Previous History
For detailed history before 2026-01-17, see archived changelogs in `archive/`.
---
## Format Guide
```markdown
### YYYY-MM-DD
- **[CATEGORY]** Brief description
Categories:
- [DEVICE] - Hardware added/removed/changed
- [SERVICE] - Container/service deployed/removed
- [NETWORK] - Network topology/config changes
- [WIRELESS] - WiFi/CAPsMAN changes
- [BACKUP] - Backup configuration
- [DOCS] - Major documentation changes
- [INCIDENT] - Outages and fixes
- [VLAN] - VLAN configuration changes
- [DOCKER] - Docker maintenance
```

View File

@@ -1,8 +1,8 @@
# Archived Documentation
> ⚠️ **OBSOLETE - DO NOT UPDATE**
> **OBSOLETE - DO NOT UPDATE**
These documents are from the legacy documentation structure (pre-2026-01-25).
These documents are from completed projects and legacy documentation.
They are kept for historical reference only.
**For current documentation, see the parent `docs/` folder:**
@@ -10,7 +10,28 @@ They are kept for historical reference only.
- `02-SERVICES-CRITICAL.md` - Essential services
- `03-SERVICES-OTHER.md` - Non-critical services
- `04-HARDWARE-INVENTORY.md` - Hardware details
- `05-CHANGELOG.md` - Major events
- `05-PORT-UTILIZATION.md` - Device port assignments
- `06-VLAN-DEVICE-ASSIGNMENT.md` - VLAN device mapping
- `07-WIFI-CAPSMAN-CONFIG.md` - WiFi and CAPsMAN settings
- `08-DNS-ARCHITECTURE.md` - DNS failover architecture
- `09-TAILSCALE-VPN.md` - Tailscale VPN setup
- `CHANGELOG.md` - Change history
## Subfolders
### vlan-migration/
12 documents from the VLAN migration project (completed 2026-01-31):
- Migration plans (v1, v2, v3)
- Implementation status trackers
- Setup progress logs
- DNS/AdGuard/Tailscale project docs (superseded by standing docs 08- and 09-)
- Device migration worksheet
### Legacy Docs (root archive/)
- Pre-2026-01-25 documentation structure
- Completed WIP items (VLAN proposals, AI stack, Fossorial tunnels)
- Historical changelogs
**Do not reference these archived documents for current state.**
All relevant information has been migrated to the new structure.

View File

@@ -97,7 +97,7 @@ add address=192.168.10.10 mac-address=02:42:C0:A8:1F:04 comment="AdGuard Unraid"
add address=192.168.10.2 mac-address=18:FD:74:54:3D:BC comment="CAP XL ac" server=dhcp-mgmt
add address=192.168.10.3 mac-address=F4:1E:57:C9:BD:09 comment="CSS326" server=dhcp-mgmt
add address=192.168.10.4 mac-address=1C:2A:A3:1E:78:67 comment="ZX1" server=dhcp-mgmt
add address=192.168.10.11 mac-address=48:DA:35:6F:BE:50 comment="NanoKVM" server=dhcp-mgmt
add address=192.168.10.200 mac-address=48:DA:35:6F:BE:50 comment="NanoKVM" server=dhcp-mgmt
```
### VLAN 20 - Trusted

View File

@@ -0,0 +1,409 @@
# VLAN Setup Progress
**Created:** 2026-01-28
**Status:** IN PROGRESS
**Last Updated:** 2026-01-28
---
## CRITICAL WARNING
**ALWAYS ASK FOR EXPLICIT CONFIRMATION BEFORE:**
1. Enabling VLAN filtering (`/interface bridge set bridge vlan-filtering=yes`)
2. Changing bridge port PVID values
3. Modifying bridge VLAN table
**Reason:** When VLAN filtering was enabled on 2026-01-28, the entire network lost connectivity:
- WiFi devices: No DHCP, no internet
- Wired devices on CSS326 (not VLAN 10): No DHCP, no internet
- Even with manual IP/DNS/gateway assignment: No internet
- Only VLAN 10 devices (Unraid on ether4/5) continued working
**Root Cause (suspected):** Bridge VLAN table or NAT/masquerade configuration issue for VLAN 1 traffic.
**Recovery:** User had to manually troubleshoot and fix the configuration.
---
## Current Network State
### Hardware Topology
```
Internet (62.73.120.142)
┌──────────────────────────────────────────────────────────────┐
│ HAP1 | MikroTik hAP ax³ │
│ IP: 192.168.88.1 │
│ RouterOS: 7.21.1 │
│ │
│ Ports: │
│ ├── ether1: WAN (DHCP from ISP) │
│ ├── ether2: CAP XL ac (via PP1) │
│ ├── ether3: CSS326 switch │
│ ├── ether4: Unraid eth1 ──┐ VLAN 10 (PVID=10) │
│ ├── ether5: Unraid eth2 ──┘ │
│ ├── wifi1: XTRM (5GHz) │
│ └── wifi2: XTRM2 (2.4GHz) │
│ │
│ Installed Packages: routeros, wifi-qcom, container, │
│ user-manager │
└──────────────────────────────────────────────────────────────┘
│ ether2
┌──────────────────────────────────────────────────────────────┐
│ CAP | MikroTik cAP XL ac │
│ IP: 192.168.88.250 │
│ RouterOS: 7.21.1 │
│ CAPsMAN managed by HAP1 │
│ │
│ WiFi (provisioned via CAPsMAN): │
│ ├── cap-wifi1: XTRM2 (2.4GHz) │
│ └── cap-wifi2: XTRM (5GHz) │
└──────────────────────────────────────────────────────────────┘
│ ether3
┌──────────────────────────────────────────────────────────────┐
│ CSS326-24G-2S+ │
│ IP: 192.168.88.254 │
│ SwOS │
│ (VLAN config pending) │
└──────────────────────────────────────────────────────────────┘
```
### SSH Access
| Device | IP | Port | User | Auth |
|--------|-----|------|------|------|
| HAP1 | 192.168.88.1 | 22 | xtrm | SSH key (~/.ssh/mikrotik_key) |
| CAP | 192.168.88.250 | 2222 | xtrm | SSH key (~/.ssh/mikrotik_key) |
| Unraid | 192.168.10.20 (pending) | 422 | root | SSH key (~/.ssh/id_ed25519_unraid) |
### WiFi Configuration
| SSID | Band | Password | Security |
|------|------|----------|----------|
| XTRM | 5GHz | M0stW4nt3d@home | WPA2/WPA3 |
| XTRM2 | 2.4GHz | M0stW4nt3d@IoT | WPA2 |
---
## VLAN Architecture (Planned)
| VLAN ID | Name | Subnet | Gateway | Purpose | Assignment Method |
|---------|------|--------|---------|---------|-------------------|
| 1 | Default | 192.168.88.0/24 | 192.168.88.1 | Current LAN (transition) | Default |
| 10 | Management | 192.168.10.0/24 | 192.168.10.1 | Infrastructure devices | Port-based |
| 20 | Trusted | 192.168.20.0/24 | 192.168.20.1 | Family devices | RADIUS MAC auth |
| 25 | Kids | 192.168.25.0/24 | 192.168.25.1 | Kids devices | RADIUS MAC auth |
| 30 | IoT | 192.168.30.0/24 | 192.168.30.1 | Smart home devices | RADIUS MAC auth |
| 35 | Cameras | 192.168.35.0/24 | 192.168.35.1 | Security cameras | Port-based |
| 40 | Servers | 192.168.40.0/24 | 192.168.40.1 | Services | Port-based |
| 50 | Guest | 192.168.50.0/24 | 192.168.50.1 | Unknown/Guest devices | RADIUS default |
### Assignment Strategy
- **Port-based:** Wired devices with dedicated ports (Unraid, cameras)
- **RADIUS MAC auth:** WiFi devices - MikroTik User Manager assigns VLAN based on MAC
- **Default VLAN 50:** Unknown devices get internet-only access
---
## Current Configuration Status
### VLAN 10 - Management (IN PROGRESS)
**Status:** Configured, waiting for Unraid to renew DHCP
**What's Done:**
- [x] VLAN interface created: `vlan10-mgmt`
- [x] IP assigned: `192.168.10.1/24`
- [x] DHCP pool: `192.168.10.100-192.168.10.200`
- [x] DHCP server: `dhcp-mgmt` (DNS: 8.8.8.8)
- [x] Static leases created for VLAN 10 devices
- [x] Bridge VLAN table configured
- [x] ether4/ether5 PVID set to 10
- [x] VLAN filtering enabled on bridge
**What's Pending:**
- [ ] Unraid needs to renew DHCP to get 192.168.10.20
- [ ] Verify Unraid connectivity on new IP
- [ ] Update Unraid SSH connection string in CLAUDE.md
**Bridge VLAN Table:**
```
VLAN 1: tagged=bridge, untagged=ether2,ether3,wifi1,wifi2
VLAN 10: tagged=bridge, untagged=ether4,ether5
```
**Bridge Ports:**
```
ether2: PVID=1 (CAP)
ether3: PVID=1 (CSS326)
ether4: PVID=10 (Unraid)
ether5: PVID=10 (Unraid)
wifi1: PVID=1 (XTRM 5GHz)
wifi2: PVID=1 (XTRM2 2.4GHz)
```
### VLAN 10 Static Leases
| IP | MAC | Device | Status |
|----|-----|--------|--------|
| 192.168.10.2 | 18:FD:74:54:3D:BC | CAP XL ac | Waiting |
| 192.168.10.3 | F4:1E:57:C9:BD:09 | CSS326 | Waiting |
| 192.168.10.10 | 02:42:C0:A8:1F:04 | AdGuard (Unraid) | Waiting |
| 192.168.10.200 | 48:DA:35:6F:BE:50 | NanoKVM | Waiting |
| 192.168.10.20 | A8:B8:E0:02:B6:15 | XTRM-U Unraid | Waiting |
### User Manager (Installed, Not Configured)
**Status:** Package installed, not enabled
**Purpose:** RADIUS server for MAC-based VLAN assignment on WiFi
**Next Steps:**
1. Enable User Manager
2. Add router as RADIUS client (NAS)
3. Create user entries with MAC addresses and VLAN attributes
4. Configure WiFi for RADIUS MAC authentication
5. Set default VLAN 50 for unknown MACs
---
## Device Inventory by VLAN
### VLAN 10 - Management (5 devices)
| Target IP | MAC | Device | Connection |
|-----------|-----|--------|------------|
| 192.168.10.2 | 18:FD:74:54:3D:BC | CAP XL ac | ether2 via PP1 |
| 192.168.10.3 | F4:1E:57:C9:BD:09 | CSS326 | ether3 |
| 192.168.10.10 | 02:42:C0:A8:1F:04 | AdGuard (Unraid) | Container |
| 192.168.10.200 | 48:DA:35:6F:BE:50 | NanoKVM | CSS326 port |
| 192.168.10.20 | A8:B8:E0:02:B6:15 | XTRM-U Unraid | ether4/5 |
### VLAN 20 - Trusted (5 devices)
| Target IP | MAC | Device | Owner |
|-----------|-----|--------|-------|
| 192.168.20.10 | 82:6D:FB:D9:E0:47 | MacBook Air | Nora |
| 192.168.20.11 | AA:ED:8B:2A:40:F1 | Samsung S25 Ultra | Kaloyan |
| 192.168.20.13 | 82:EC:EF:B5:F2:AF | MacBook Pro (WiFi) | Kaloyan |
| 192.168.20.16 | 08:92:04:C6:07:C5 | MacBook Pro (LAN) | Kaloyan |
| 192.168.20.17 | 1C:83:41:32:F3:AF | Gaming PC | Kaloyan |
### VLAN 25 - Kids (4 devices)
| Target IP | MAC | Device | Owner |
|-----------|-----|--------|-------|
| 192.168.25.12 | F2:B8:14:61:C8:27 | iPhone | Dancho |
| 192.168.25.14 | 90:91:64:70:0D:86 | Notebook | Kimi |
| 192.168.25.15 | 2A:2B:BA:86:D4:AF | iPhone | Kimi |
| 192.168.25.18 | A4:D1:D2:7B:52:BE | iPad | Compusbg |
### VLAN 30 - IoT (12 devices)
| Target IP | MAC | Device |
|-----------|-----|--------|
| 192.168.30.10 | 50:2C:C6:7A:55:39 | GREE AC |
| 192.168.30.11 | B0:37:95:79:AF:9B | LG TV (LAN) |
| 192.168.30.12 | DC:03:98:6B:5A:3A | LG TV (WiFi) |
| 192.168.30.13 | D0:E7:82:F7:65:DD | Chromecast |
| 192.168.30.14 | B0:4A:39:3F:9A:14 | Roborock Vacuum |
| 192.168.30.20 | 94:27:70:1E:0C:EE | Bosch Oven |
| 192.168.30.21 | C8:D7:78:40:65:40 | Bosch Dishwasher |
| 192.168.30.22 | C8:D7:78:D6:DC:FC | Bosch Washer |
| 192.168.30.31 | 18:DE:50:5B:C8:A6 | Tuya Device 1 |
| 192.168.30.32 | 38:1F:8D:04:6F:E4 | Tuya Device 2 |
| 192.168.30.38 | D4:AD:FC:BE:13:B0 | Intellirocks |
| 192.168.30.39 | C8:5C:CC:52:EA:53 | Xiaomi Air Purifier |
### VLAN 35 - Cameras (1 device)
| Target IP | MAC | Device |
|-----------|-----|--------|
| 192.168.35.10 | 48:9E:9D:0E:16:F7 | Reolink Doorbell |
### VLAN 40 - Servers (1 device)
| Target IP | MAC | Device |
|-----------|-----|--------|
| 192.168.40.19 | 64:4E:D7:D8:43:3E | HP LaserJet |
### VLAN 50 - Guest/Unknown (4 devices)
| Target IP | MAC | Notes |
|-----------|-----|-------|
| 192.168.50.10 | AC:87:A3:77:8F:BD | Unknown Apple device |
| 192.168.50.11 | 22:4C:7F:1D:85:8E | Random MAC (privacy) |
| 192.168.50.12 | D0:C9:07:92:1A:8E | Unknown |
| 192.168.50.13 | D0:C9:07:8C:C9:46 | Unknown |
---
## Useful Commands
### Check VLAN Status
```routeros
/interface vlan print
/interface bridge vlan print detail
/interface bridge port print
/interface bridge print where name=bridge
```
### Check DHCP Leases
```routeros
/ip dhcp-server lease print
/ip dhcp-server lease print where server=dhcp-mgmt
```
### Check User Manager
```routeros
/user-manager print
/user-manager user print
/user-manager router print
```
### Rollback VLAN Filtering
```routeros
/interface bridge set bridge vlan-filtering=no
```
### Force DHCP Renewal on Unraid
```bash
# On Unraid terminal
/etc/rc.d/rc.inet1 restart
# Or
dhclient -r eth0 && dhclient eth0
```
---
## Next Steps (In Order)
1. **Complete VLAN 10 Setup**
- Restart network on Unraid to get new IP (192.168.10.20)
- Verify connectivity
- Update CLAUDE.md with new Unraid IP
2. **Configure User Manager for RADIUS**
- Enable User Manager
- Add router as NAS (RADIUS client)
- Configure WiFi for MAC authentication
3. **Create Other VLANs**
- VLAN 20 (Trusted) - interface, DHCP, firewall
- VLAN 25 (Kids) - interface, DHCP, firewall
- VLAN 30 (IoT) - interface, DHCP, firewall
- VLAN 35 (Cameras) - interface, DHCP, firewall
- VLAN 40 (Servers) - interface, DHCP, firewall
- VLAN 50 (Guest) - interface, DHCP, firewall (default for unknown)
4. **Add MAC-VLAN Mappings to User Manager**
- Add all trusted device MACs → VLAN 20
- Add all kids device MACs → VLAN 25
- Add all IoT device MACs → VLAN 30
- Default (no match) → VLAN 50
5. **Configure Inter-VLAN Firewall Rules**
- Management → All (full access)
- Trusted → IoT, Cameras, Servers (control)
- Kids → Limited (parental controls)
- IoT → Internet only
- Cameras → Isolated
- Guest → Internet only
6. **Test and Verify**
- Test each VLAN connectivity
- Test inter-VLAN access rules
- Test unknown device goes to VLAN 50
---
## Firewall Rules (Planned)
```routeros
# Allow established/related
/ip firewall filter add chain=forward connection-state=established,related action=accept
# Management can access everything
/ip firewall filter add chain=forward src-address=192.168.10.0/24 action=accept
# Trusted can access IoT, Cameras, Servers
/ip firewall filter add chain=forward src-address=192.168.20.0/24 dst-address=192.168.30.0/24 action=accept
/ip firewall filter add chain=forward src-address=192.168.20.0/24 dst-address=192.168.35.0/24 action=accept
/ip firewall filter add chain=forward src-address=192.168.20.0/24 dst-address=192.168.40.0/24 action=accept
# IoT - Internet only (block inter-VLAN)
/ip firewall filter add chain=forward src-address=192.168.30.0/24 dst-address=192.168.0.0/16 action=drop
# Cameras - Isolated
/ip firewall filter add chain=forward src-address=192.168.35.0/24 dst-address=192.168.0.0/16 action=drop
# Guest - Internet only
/ip firewall filter add chain=forward src-address=192.168.50.0/24 dst-address=192.168.0.0/16 action=drop
# Drop all other inter-VLAN
/ip firewall filter add chain=forward src-address=192.168.0.0/16 dst-address=192.168.0.0/16 action=drop
```
---
## Incident Log
### 2026-01-28: Network Outage After VLAN Filtering Enabled
**Timeline:**
1. VLAN 10 interface, DHCP, static leases configured
2. Bridge VLAN table configured (VLAN 1 and VLAN 10)
3. ether4/ether5 PVID set to 10
4. VLAN filtering enabled
5. **Result:** All non-VLAN 10 devices lost connectivity
**Symptoms:**
- WiFi devices: No DHCP assignment
- CSS326 connected devices: No DHCP assignment
- Manual IP configuration: Still no internet
- VLAN 10 devices (Unraid): Working correctly
**Suspected Cause:**
- Bridge VLAN table may not have been properly configured for VLAN 1
- NAT masquerade may not have been applied to VLAN 1 traffic
- Possible missing egress tagging configuration
**Resolution:** Manual fix by user (details TBD)
**Lessons Learned:**
1. **ALWAYS** test VLAN config on a single device first before enabling filtering
2. **ALWAYS** ask for explicit user confirmation before enabling VLAN filtering
3. Have rollback command ready: `/interface bridge set bridge vlan-filtering=no`
4. Keep WinBox/MAC-based access available for recovery
5. Document exact state before making changes
---
## Pre-Change Checklist (MANDATORY)
Before enabling VLAN filtering, verify:
- [ ] Bridge VLAN table has VLAN 1 with all non-VLAN ports as untagged
- [ ] Bridge itself is tagged in all VLANs
- [ ] NAT masquerade rule covers all internal networks
- [ ] DHCP servers exist for all active VLANs
- [ ] Static routes/addresses configured if needed
- [ ] WinBox or MAC-based access available for recovery
- [ ] User has confirmed they are ready for potential outage
- [ ] Rollback command documented: `/interface bridge set bridge vlan-filtering=no`
---
## Reference Documents
- `docs/03-VLAN-DEVICE-ASSIGNMENT.md` - Full device inventory
- `docs/04-VLAN-MIGRATION-PLAN.md` - Original migration plan
- `docs/11-VLAN-IMPLEMENTATION.md` - VLAN architecture overview
- `docs/wip/VLAN-PROPOSAL.md` - Initial proposal

View File

@@ -0,0 +1,594 @@
# VLAN Setup Plan v2 - Critical Approach
**Created:** 2026-01-28
**Status:** PLANNING
**Approach:** Step-by-step with verification before each change
---
## CRITICAL RULES
1. **NO CHANGES WITHOUT EXPLICIT USER APPROVAL**
2. **VERIFY current state before each step**
3. **TEST after each step before proceeding**
4. **HAVE ROLLBACK ready for each step**
5. **STOP and assess if anything unexpected happens**
---
## Prerequisites
- Router: MikroTik hAP ax³ (freshly reset to factory defaults)
- Current IP: 192.168.88.1 (factory default)
- Access: WinBox or physical console available for recovery
---
## Phase 1: Basic Router Setup
### Step 1.1: Create User `xtrm`
**Action:**
```routeros
/user add name=xtrm password=M0stW4nt3d@xtrm group=full
```
**Verification:**
```routeros
/user print
```
**Expected Result:**
- User `xtrm` exists with group `full`
**Rollback:**
```routeros
/user remove xtrm
```
---
### Step 1.2: Change SSH Port to 2222
**Action:**
```routeros
/ip service set ssh port=2222
```
**Verification:**
```routeros
/ip service print where name=ssh
```
**Expected Result:**
- SSH service on port 2222
**Rollback:**
```routeros
/ip service set ssh port=22
```
**Test:** SSH to router on port 2222
---
### Step 1.3: Import SSH Key for User `xtrm`
**Prerequisite:** Upload `mikrotik_key.pub` to router via WinBox Files
**Action:**
```routeros
/user ssh-keys import public-key-file=mikrotik_key.pub user=xtrm
```
**Verification:**
```routeros
/user ssh-keys print
```
**Expected Result:**
- SSH key associated with user `xtrm`
**Test:** SSH with key authentication (no password)
---
## Phase 2: WiFi & CAPsMAN Setup
### Step 2.1: Create Security Profiles
**Action:**
```routeros
# For XTRM (5GHz) - High security
/interface wifi security add name=sec-xtrm authentication-types=wpa2-psk,wpa3-psk passphrase=M0stW4nt3d@home
# For XTRM2 (2.4GHz) - IoT compatibility
/interface wifi security add name=sec-xtrm2 authentication-types=wpa-psk,wpa2-psk passphrase=M0stW4nt3d@IoT
```
**Verification:**
```routeros
/interface wifi security print
```
**Expected Result:**
- `sec-xtrm`: WPA2-PSK + WPA3-PSK
- `sec-xtrm2`: WPA-PSK + WPA2-PSK (for old devices)
---
### Step 2.2: Create Configuration Profiles
**Action:**
```routeros
/interface wifi configuration add name=cfg-xtrm ssid=XTRM security=sec-xtrm country=Bulgaria
/interface wifi configuration add name=cfg-xtrm2 ssid=XTRM2 security=sec-xtrm2 country=Bulgaria
```
**Verification:**
```routeros
/interface wifi configuration print
```
---
### Step 2.3: Apply WiFi to Local Radios
**Action:**
```routeros
# wifi1 = 5GHz radio → XTRM
/interface wifi set wifi1 configuration=cfg-xtrm configuration.ssid=XTRM disabled=no
# wifi2 = 2.4GHz radio → XTRM2
/interface wifi set wifi2 configuration=cfg-xtrm2 configuration.ssid=XTRM2 disabled=no
```
**Verification:**
```routeros
/interface wifi print
```
**Test:** Connect a device to each SSID, verify internet works
---
### Step 2.4: Enable CAPsMAN
**Action:**
```routeros
/interface wifi capsman set enabled=yes interfaces=bridge
```
**Verification:**
```routeros
/interface wifi capsman print
```
---
### Step 2.5: Create CAPsMAN Provisioning Rules
**Action:**
```routeros
# For 5GHz radios → XTRM
/interface wifi provisioning add action=create-dynamic-enabled master-configuration=cfg-xtrm supported-bands=5ghz-a,5ghz-n,5ghz-ac
# For 2.4GHz radios → XTRM2
/interface wifi provisioning add action=create-dynamic-enabled master-configuration=cfg-xtrm2 supported-bands=2ghz-g,2ghz-n
```
**Verification:**
```routeros
/interface wifi provisioning print
```
---
### Step 2.6: Configure CAP to Join CAPsMAN
**On CAP device (192.168.88.250 or via WinBox):**
```routeros
/interface wifi cap set enabled=yes discovery-interfaces=bridge caps-man-addresses=""
```
**Verification on HAP:**
```routeros
/interface wifi capsman remote-cap print
/interface wifi radio print
```
**Expected Result:**
- CAP appears as connected
- CAP radios show up (cap-wifi1, cap-wifi2)
**Test:** Connect device to XTRM/XTRM2 via CAP, verify internet
---
## Phase 3: Install Additional Packages
### Step 3.1: Install User Manager and Container Packages
**Action:**
1. Download packages from MikroTik website (arm64, version 7.21.1)
2. Upload to router via WinBox:
- `user-manager-7.21.1-arm64.npk`
- `container-7.21.1-arm64.npk` (if not already installed)
3. Reboot router
**Verification after reboot:**
```routeros
/system package print
```
**Expected Result:**
- `user-manager` package listed
- `container` package listed
---
## Phase 4: Network Reconfiguration (CRITICAL)
### Step 4.0: Pre-Change Verification
**Before ANY changes, verify current state:**
```routeros
echo "=== CURRENT STATE ==="
/ip address print
/ip pool print
/ip dhcp-server print
/ip dhcp-server network print
/interface bridge print
/interface bridge port print
/interface bridge vlan print
/ip firewall nat print
```
**Document the output before proceeding!**
---
### Step 4.1: Change Network to 192.168.31.0/24
**Current:** 192.168.88.0/24 (factory default)
**Target:** 192.168.31.0/24
**Action (all in one command block to minimize disruption):**
```routeros
/ip address set [find where address~"192.168.88"] address=192.168.31.1/24
/ip pool set [find where name="default-dhcp"] ranges=192.168.31.100-192.168.31.254
/ip dhcp-server network set [find where address="192.168.88.0/24"] address=192.168.31.0/24 gateway=192.168.31.1 dns-server=8.8.8.8
```
**After change:** Reconnect to WiFi to get new IP
**Verification:**
```routeros
/ip address print
/ip pool print
/ip dhcp-server network print
/ping 8.8.8.8 count=2
```
**Test:** Browse internet from connected device
---
### Step 4.2: Create VLAN40 Interface (Catch-All)
**IMPORTANT:** Do NOT move IP to VLAN interface yet!
**Action:**
```routeros
/interface vlan add interface=bridge name=vlan40-catchall vlan-id=40
```
**Verification:**
```routeros
/interface vlan print
```
**Expected Result:**
- `vlan40-catchall` interface exists
- Network still works (IP still on bridge)
---
### Step 4.3: Add VLAN40 to Bridge VLAN Table
**Action:**
```routeros
/interface bridge vlan add bridge=bridge vlan-ids=40 tagged=bridge untagged=ether2,ether3,wifi1,wifi2
```
**Verification:**
```routeros
/interface bridge vlan print detail
```
---
### Step 4.4: Create VLAN40 DHCP Infrastructure
**Action:**
```routeros
# Create pool for VLAN40
/ip pool add name=pool-vlan40 ranges=192.168.31.100-192.168.31.254
# Add IP to VLAN40 interface (SECOND IP - keep bridge IP!)
/ip address add address=192.168.31.1/24 interface=vlan40-catchall
# This will show warning about duplicate - that's expected for now
```
**Verification:**
```routeros
/ip address print
```
**Expected:** TWO entries for 192.168.31.1 (bridge AND vlan40)
---
### Step 4.5: STOP AND VERIFY
**Before enabling VLAN filtering:**
1. Can you ping 192.168.31.1?
2. Can you access router via SSH?
3. Can you access router via WinBox?
4. Is internet working?
**If ANY answer is NO - STOP and troubleshoot!**
---
### Step 4.6: Enable VLAN Filtering (REQUIRES EXPLICIT USER APPROVAL)
⚠️ **THIS STEP REQUIRES USER TO TYPE "APPROVED" BEFORE EXECUTION** ⚠️
**Pre-flight checks:**
```routeros
/interface bridge vlan print detail
/interface bridge port print
```
**Ensure:**
- VLAN 40 has all current ports as untagged
- Bridge is tagged in VLAN 40
**Action:**
```routeros
/interface bridge set bridge vlan-filtering=yes
```
**Immediate verification:**
```routeros
/ping 8.8.8.8 count=2
```
**If ping fails - IMMEDIATELY rollback:**
```routeros
/interface bridge set bridge vlan-filtering=no
```
---
### Step 4.7: Post-Activation Cleanup
**Only after confirming VLAN filtering works:**
1. Move DHCP server to VLAN40 interface:
```routeros
/ip dhcp-server set defconf interface=vlan40-catchall
```
2. Remove duplicate IP from bridge:
```routeros
/ip address remove [find where interface=bridge and address~"192.168.31"]
```
**Verification:**
```routeros
/ip address print
/ip dhcp-server print
```
---
## Phase 5: Create VLAN10 (Management - Port Based)
### Step 5.1: Create VLAN10 Interface
**Action:**
```routeros
/interface vlan add interface=bridge name=vlan10-mgmt vlan-id=10
/ip address add address=192.168.10.1/24 interface=vlan10-mgmt
```
---
### Step 5.2: Create VLAN10 DHCP
**Action:**
```routeros
/ip pool add name=pool-mgmt ranges=192.168.10.100-192.168.10.200
/ip dhcp-server add address-pool=pool-mgmt interface=vlan10-mgmt name=dhcp-mgmt
/ip dhcp-server network add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=8.8.8.8
```
---
### Step 5.3: Create VLAN10 Static Leases
**Action:**
```routeros
/ip dhcp-server lease
add address=192.168.10.2 mac-address=18:FD:74:54:3D:BC comment="CAP XL ac" server=dhcp-mgmt
add address=192.168.10.3 mac-address=F4:1E:57:C9:BD:09 comment="CSS326" server=dhcp-mgmt
add address=192.168.10.10 mac-address=02:42:C0:A8:1F:04 comment="AdGuard Unraid" server=dhcp-mgmt
add address=192.168.10.11 mac-address=48:DA:35:6F:BE:50 comment="NanoKVM" server=dhcp-mgmt
add address=192.168.10.20 mac-address=A8:B8:E0:02:B6:15 comment="XTRM-U Unraid" server=dhcp-mgmt
```
---
### Step 5.4: Configure Bridge for VLAN10
**Action:**
```routeros
# Add VLAN10 to bridge table - ether4/ether5 as untagged (Unraid ports)
/interface bridge vlan add bridge=bridge vlan-ids=10 tagged=bridge untagged=ether4,ether5
# Set PVID on Unraid ports
/interface bridge port set [find interface=ether4] pvid=10
/interface bridge port set [find interface=ether5] pvid=10
```
---
### Step 5.5: STOP AND TEST VLAN10
⚠️ **REQUIRES USER APPROVAL TO PROCEED** ⚠️
**Test:**
1. Unraid should get IP 192.168.10.20
2. Unraid should have internet access
3. Other devices still work on VLAN40
---
## Phase 6: Create Remaining VLANs
### VLAN Overview
| VLAN | Name | Subnet | Purpose | Assignment |
|------|------|--------|---------|------------|
| 10 | Management | 192.168.10.0/24 | Infrastructure | Port-based |
| 20 | Trusted | 192.168.20.0/24 | Family devices | RADIUS |
| 25 | Kids | 192.168.25.0/24 | Kids devices | RADIUS |
| 30 | IoT | 192.168.30.0/24 | Smart home | RADIUS |
| 35 | Cameras | 192.168.35.0/24 | Security | Port-based |
| 40 | Catch-All | 192.168.31.0/24 | Default/Unknown | Default |
### Step 6.1-6.4: Create Each VLAN
**Repeat for each VLAN (20, 25, 30, 35):**
```routeros
# Create interface
/interface vlan add interface=bridge name=vlanXX-name vlan-id=XX
# Add IP
/ip address add address=192.168.XX.1/24 interface=vlanXX-name
# Create pool
/ip pool add name=pool-vlanXX ranges=192.168.XX.100-192.168.XX.200
# Create DHCP server
/ip dhcp-server add address-pool=pool-vlanXX interface=vlanXX-name name=dhcp-vlanXX
# Create DHCP network
/ip dhcp-server network add address=192.168.XX.0/24 gateway=192.168.XX.1 dns-server=8.8.8.8
# Add to bridge VLAN table (tagged only - RADIUS will assign)
/interface bridge vlan add bridge=bridge vlan-ids=XX tagged=bridge
```
---
## Phase 7: Configure User Manager (RADIUS)
### Step 7.1: Enable User Manager
```routeros
/user-manager set enabled=yes
```
### Step 7.2: Add Router as RADIUS Client
```routeros
/user-manager router add name=local address=127.0.0.1 shared-secret=radius-secret
```
### Step 7.3: Add MAC-VLAN Mappings
**For each device, add user with MAC and VLAN attribute:**
```routeros
# Example for trusted device
/user-manager user add name=AA:ED:8B:2A:40:F1 password="" shared-users=1
/user-manager user set [find name=AA:ED:8B:2A:40:F1] attributes="Tunnel-Type:VLAN,Tunnel-Medium-Type:IEEE-802,Tunnel-Private-Group-Id:20"
```
### Step 7.4: Configure WiFi for RADIUS
```routeros
/interface wifi security set sec-xtrm radius=yes
/interface wifi security set sec-xtrm2 radius=yes
```
---
## Phase 8: Activation Plan
### Step 8.1: Final Pre-Activation Checklist
- [ ] All VLAN interfaces created
- [ ] All DHCP servers configured
- [ ] All static leases added
- [ ] User Manager configured with all MACs
- [ ] WiFi configured for RADIUS
- [ ] WinBox access verified
- [ ] Rollback command ready
### Step 8.2: Staged Activation
1. **Test VLAN10 only** (port-based, Unraid)
2. **Verify 24 hours**
3. **Test VLAN20** (one trusted device via RADIUS)
4. **Verify 24 hours**
5. **Enable remaining VLANs**
---
## Rollback Commands
**Disable VLAN filtering (emergency):**
```routeros
/interface bridge set bridge vlan-filtering=no
```
**Reset to factory:**
```routeros
/system reset-configuration no-defaults=no
```
---
## Device Inventory Reference
See: `docs/03-VLAN-DEVICE-ASSIGNMENT.md`
---
## Verification Commands
```routeros
# Check VLAN status
/interface vlan print
/interface bridge vlan print detail
/interface bridge port print
# Check DHCP
/ip dhcp-server print
/ip dhcp-server lease print
# Check connectivity
/ping 8.8.8.8 count=3
/ping 192.168.31.1 count=3
# Check User Manager
/user-manager user print
/user-manager router print
```

View File

@@ -0,0 +1,352 @@
# VLAN Setup Plan v3 - Safe Mode Approach
**Created:** 2026-01-31
**Status:** PLANNING
**Approach:** Safe Mode with atomic commands for auto-rollback protection
---
## Lessons Learned from Previous Failures
1. **IP on bridge stops working** when VLAN filtering is enabled
2. **Duplicate same IP** on bridge + VLAN interface causes routing confusion
3. **VLAN interface doesn't receive traffic** until VLAN filtering is enabled
4. **Solution**: Use Safe Mode + atomic script execution
---
## Prerequisites
- Router: MikroTik hAP ax³
- Current IP: 192.168.1.1/24 on bridge
- Access: WinBox connected via **MAC address** (not IP!)
- CAPsMAN: Already configured and working
---
## Phase 1: Preparation (No Risk)
### Step 1.1: Backup Current Configuration
```routeros
/system backup save name=before-vlan-v3
/export file=before-vlan-v3
```
Download both files from WinBox → Files.
### Step 1.2: Verify Current State
```routeros
/ip address print
/interface bridge print
/interface bridge port print
/interface bridge vlan print
/ip dhcp-server print
```
**Expected:**
- IP 192.168.1.1/24 on bridge
- VLAN filtering = no
- No bridge VLANs configured
---
## Phase 2: Create VLAN Infrastructure (Safe - No Filtering Yet)
### Step 2.1: Create VLAN 40 Interface
```routeros
/interface vlan add interface=bridge name=vlan40-catchall vlan-id=40
```
**Verify:**
```routeros
/interface vlan print
```
### Step 2.2: Add VLAN 40 to Bridge Table
All LAN ports untagged, bridge tagged (for CPU access):
```routeros
/interface bridge vlan add bridge=bridge vlan-ids=40 tagged=bridge untagged=ether2,ether3,ether4,ether5,wifi1,wifi2
```
**Verify:**
```routeros
/interface bridge vlan print detail
```
### Step 2.3: Set PVID on All LAN Ports
```routeros
/interface bridge port set [find interface=ether2] pvid=40
/interface bridge port set [find interface=ether3] pvid=40
/interface bridge port set [find interface=ether4] pvid=40
/interface bridge port set [find interface=ether5] pvid=40
/interface bridge port set [find interface=wifi1] pvid=40
/interface bridge port set [find interface=wifi2] pvid=40
```
**Verify:**
```routeros
/interface bridge port print
```
**Expected:** All ports show PVID=40
### Step 2.4: Add IP to VLAN Interface
This creates a "duplicate" IP temporarily:
```routeros
/ip address add address=192.168.1.1/24 interface=vlan40-catchall comment="VLAN40-Management"
```
**Verify:**
```routeros
/ip address print
```
**Expected:** Two entries for 192.168.1.1 (bridge and vlan40-catchall)
### Step 2.5: Create VLAN40 DHCP Pool (if not exists)
```routeros
/ip pool add name=pool-vlan40 ranges=192.168.1.10-192.168.1.250
```
### Step 2.6: Verify Everything Before Critical Step
```routeros
:put "=== VLAN Interface ==="
/interface vlan print
:put "=== Bridge VLANs ==="
/interface bridge vlan print detail
:put "=== Bridge Ports (check PVID) ==="
/interface bridge port print
:put "=== IP Addresses ==="
/ip address print
:put "=== Ping Test ==="
/ping 8.8.8.8 count=2
```
**STOP HERE if anything is wrong!**
---
## Phase 3: Enable VLAN Filtering (Critical - Use Safe Mode)
### Step 3.1: Enter Safe Mode in WinBox
1. In WinBox, press **Ctrl+X**
2. You'll see "Safe Mode" indicator in title bar
3. All changes will auto-rollback if connection is lost
### Step 3.2: Create the Activation Script
Create a script that does everything atomically:
```routeros
/system script add name=activate-vlan source={
# Enable VLAN filtering
/interface bridge set bridge vlan-filtering=yes
# Move DHCP server to VLAN interface
/ip dhcp-server set [find name~"defconf"] interface=vlan40-catchall
# Wait 2 seconds for changes to apply
:delay 2s
# Remove duplicate IP from bridge (keep only VLAN interface IP)
/ip address remove [find interface=bridge and address~"192.168.1.1"]
:put "VLAN activation complete"
}
```
### Step 3.3: Run the Script (While in Safe Mode!)
```routeros
/system script run activate-vlan
```
### Step 3.4: Verify Immediately
```routeros
/ping 8.8.8.8 count=3
/ip address print
/interface bridge print
```
### Step 3.5: If Everything Works - Exit Safe Mode
Press **Ctrl+X** again to confirm and save changes.
### Step 3.6: If Connection Lost
- Wait up to 10 minutes
- Router will auto-rollback to previous state
- Reconnect via WinBox (MAC address)
---
## Phase 4: Verification
### Step 4.1: Check All Settings
```routeros
:put "=== Bridge VLAN Filtering ==="
/interface bridge print where name=bridge
:put "=== IP Addresses ==="
/ip address print
:put "=== DHCP Server ==="
/ip dhcp-server print
:put "=== Internet Test ==="
/ping 8.8.8.8 count=3
```
**Expected:**
- vlan-filtering=yes on bridge
- IP 192.168.1.1/24 ONLY on vlan40-catchall
- DHCP server on vlan40-catchall
- Internet working
### Step 4.2: Test Client Connectivity
From a device on the network:
1. Disconnect and reconnect WiFi
2. Check if you get IP from 192.168.1.x range
3. Test internet access
---
## Phase 5: Add Additional VLANs (After VLAN40 is Stable)
Wait 24-48 hours to ensure VLAN40 is stable before adding more VLANs.
### VLAN Overview
| VLAN | Name | Subnet | Purpose | Assignment |
|------|------|--------|---------|------------|
| 10 | Management | 192.168.10.0/24 | Infrastructure | Port-based (ether4,5) |
| 20 | Trusted | 192.168.20.0/24 | Family devices | RADIUS |
| 25 | Kids | 192.168.25.0/24 | Kids devices | RADIUS |
| 30 | IoT | 192.168.30.0/24 | Smart home | RADIUS |
| 40 | Catch-All | 192.168.1.0/24 | Default/Unknown | Default |
### Step 5.1: Create VLAN 10 (Management)
```routeros
# Create VLAN interface
/interface vlan add interface=bridge name=vlan10-mgmt vlan-id=10
# Add IP
/ip address add address=192.168.10.1/24 interface=vlan10-mgmt
# Add to bridge VLAN table - ether4/5 untagged for Unraid
/interface bridge vlan add bridge=bridge vlan-ids=10 tagged=bridge untagged=ether4,ether5
# Update PVID on Unraid ports
/interface bridge port set [find interface=ether4] pvid=10
/interface bridge port set [find interface=ether5] pvid=10
# Remove ether4/5 from VLAN40
/interface bridge vlan set [find vlan-ids=40] untagged=ether2,ether3,wifi1,wifi2
# Create DHCP for VLAN10
/ip pool add name=pool-vlan10 ranges=192.168.10.100-192.168.10.200
/ip dhcp-server add address-pool=pool-vlan10 interface=vlan10-mgmt name=dhcp-vlan10 disabled=no
/ip dhcp-server network add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=8.8.8.8
```
### Step 5.2: Add Static Leases for VLAN10
```routeros
/ip dhcp-server lease
add address=192.168.10.2 mac-address=18:FD:74:54:3D:BC comment="CAP XL ac" server=dhcp-vlan10
add address=192.168.10.3 mac-address=F4:1E:57:C9:BD:09 comment="CSS326" server=dhcp-vlan10
add address=192.168.10.20 mac-address=A8:B8:E0:02:B6:15 comment="Unraid" server=dhcp-vlan10
```
---
## Rollback Commands
### Emergency: Disable VLAN Filtering
```routeros
/interface bridge set bridge vlan-filtering=no
```
### Full Rollback: Restore Backup
```routeros
/system backup load name=before-vlan-v3
```
### Factory Reset (Last Resort)
Hold reset button while powering on until LEDs flash.
---
## Safe Mode Quick Reference
| Action | WinBox | CLI |
|--------|--------|-----|
| Enter Safe Mode | Ctrl+X | Ctrl+X |
| Exit & Save | Ctrl+X | Ctrl+X |
| Exit & Discard | Close WinBox | Ctrl+D |
| Auto-rollback | ~10 minutes | ~10 minutes |
**Important:** Safe Mode only protects while you're connected. If disconnected, changes rollback automatically.
---
## Checklist Before Enabling VLAN Filtering
- [ ] Backup saved and downloaded
- [ ] WinBox connected via MAC (not IP)
- [ ] VLAN interface created
- [ ] Bridge tagged in VLAN table
- [ ] All ports have correct PVID
- [ ] IP added to VLAN interface
- [ ] Safe Mode entered (Ctrl+X)
- [ ] Ready to run activation script
---
## Troubleshooting
### Lost Connection After Enabling Filtering
1. Wait 10 minutes for Safe Mode rollback
2. If no rollback: Connect via WinBox MAC discovery
3. Run: `/interface bridge set bridge vlan-filtering=no`
### DHCP Not Working
Check DHCP server interface:
```routeros
/ip dhcp-server print
```
Should show `interface=vlan40-catchall`
### Internet Not Working
Check NAT:
```routeros
/ip firewall nat print
```
Should have masquerade rule for WAN.
### Devices Not Getting IP
1. Check bridge VLAN table has ports as untagged
2. Check ports have correct PVID
3. Check DHCP pool has available addresses

View File

@@ -0,0 +1,340 @@
# VLAN Setup Complete - Session Summary
**Date:** 2026-01-31
**Status:** COMPLETED
**Backup:** `vlan-setup-complete-2026-01-31.backup` and `.rsc` on router
---
## Executive Summary
Successfully implemented VLAN network segmentation on MikroTik hAP ax³ with:
- Port-based VLAN assignment for wired infrastructure
- MAC-based dynamic VLAN assignment for WiFi devices via access-list
- CAPsMAN configured for CAP XL ac management
---
## Current Network Configuration
### Router Access
| Method | IP | Port | User | Notes |
|--------|-----|------|------|-------|
| WinBox | 192.168.10.1 | 8291 | xtrm | Primary management |
| WebFig | 192.168.10.1 | 80 | xtrm | Web interface |
| SSH (Mac) | 192.168.10.1 | **2222** | xtrm | Key: ~/.ssh/mikrotik_key |
| SSH (Unraid) | 192.168.10.1 | **2222** | unraid | Key: ~/.ssh/id_ed25519 |
| WinBox | 192.168.1.1 | 8291 | xtrm | Via VLAN 40 |
| WinBox | 192.168.20.1 | 8291 | xtrm | Via VLAN 20 |
**Important:** SSH is on port **2222**, not 22!
### VLAN Structure (Implemented)
| VLAN | Name | Subnet | Gateway | DHCP Pool | Status |
|------|------|--------|---------|-----------|--------|
| 10 | Management | 192.168.10.0/24 | 192.168.10.1 | .100-.200 | ✅ Working |
| 20 | Trusted | 192.168.20.0/24 | 192.168.20.1 | .100-.200 | ✅ Working |
| 25 | Kids | 192.168.25.0/24 | 192.168.25.1 | .100-.200 | ✅ Configured |
| 30 | IoT | 192.168.30.0/24 | 192.168.30.1 | .100-.200 | ✅ Configured |
| 40 | Catch-All | 192.168.1.0/24 | 192.168.1.1 | .10-.250 | ✅ Default |
### Port Assignments
```
HAP ax³ Ports:
├── ether1: WAN (ISP DHCP)
├── ether2: CAP XL ac → VLAN 10 (PVID=10)
├── ether3: CSS326 switch → VLAN 10 (PVID=10)
├── ether4: Unraid eth1 → VLAN 10 (PVID=10)
├── ether5: Unraid eth2 → VLAN 10 (PVID=10)
├── wifi1: XTRM (5GHz) → Tagged VLANs 20,25,30,40
└── wifi2: XTRM2 (2.4GHz) → Tagged VLANs 20,25,30,40
```
### Bridge VLAN Table
```routeros
# VLAN 10 - Management (port-based)
vlan-ids=10 tagged=bridge untagged=ether2,ether3,ether4,ether5
# VLAN 20 - Trusted (WiFi MAC-based)
vlan-ids=20 tagged=bridge,wifi1,wifi2
# VLAN 25 - Kids (WiFi MAC-based)
vlan-ids=25 tagged=bridge,wifi1,wifi2
# VLAN 30 - IoT (WiFi MAC-based)
vlan-ids=30 tagged=bridge,wifi1,wifi2
# VLAN 40 - Catch-All (WiFi default)
vlan-ids=40 tagged=bridge untagged=wifi1,wifi2
```
---
## WiFi Configuration
### SSIDs
| SSID | Band | Interface | Password | Security |
|------|------|-----------|----------|----------|
| XTRM | 5GHz | wifi1 | M0stW4nt3d@home | WPA2/WPA3 |
| XTRM2 | 2.4GHz | wifi2 | M0stW4nt3d@IoT | WPA2 |
### WiFi Datapath (Critical for VLAN)
```routeros
/interface wifi datapath
add name=dp-vlan bridge=bridge
/interface wifi configuration
set cfg-xtrm datapath=dp-vlan
set cfg-xtrm2 datapath=dp-vlan
```
### WiFi Access-List (MAC-based VLAN Assignment)
The access-list assigns VLANs based on client MAC address:
```routeros
/interface wifi access-list
# VLAN 20 - Trusted devices
add action=accept mac-address=AA:ED:8B:2A:40:F1 vlan-id=20 comment="Samsung S25 Ultra - Kaloyan"
add action=accept mac-address=CE:B8:11:EA:8D:55 vlan-id=20 comment="MacBook - Kaloyan"
add action=accept mac-address=BE:A7:95:87:19:4A vlan-id=20 comment="MacBook 5GHz - Kaloyan"
# VLAN 25 - Kids devices
add action=accept mac-address=F2:B8:14:61:C8:27 vlan-id=25 comment="iPhone - Dancho"
add action=accept mac-address=90:91:64:70:0D:86 vlan-id=25 comment="Notebook - Kimi"
add action=accept mac-address=2A:2B:BA:86:D4:AF vlan-id=25 comment="iPhone - Kimi"
# VLAN 30 - IoT devices
add action=accept mac-address=D0:E7:82:F7:65:DD vlan-id=30 comment="Chromecast"
add action=accept mac-address=94:27:70:1E:0C:EE vlan-id=30 comment="Bosch Oven"
add action=accept mac-address=C8:5C:CC:52:EA:53 vlan-id=30 comment="Xiaomi Air Purifier"
add action=accept mac-address=18:DE:50:5B:C8:A6 vlan-id=30 comment="Tuya Device 1"
add action=accept mac-address=38:1F:8D:04:6F:E4 vlan-id=30 comment="Tuya Device 2"
add action=accept mac-address=D4:AD:FC:BE:13:B0 vlan-id=30 comment="Intellirocks"
# Default - VLAN 40 for unknown devices (MUST be last!)
add action=accept vlan-id=40 comment="Default - VLAN40"
```
**Important:** The default rule (no MAC specified) must be LAST in the list!
---
## VLAN 10 Verified Devices
| IP | MAC | Device | Status |
|----|-----|--------|--------|
| 192.168.10.1 | 78:9A:18:2C:A5:48 | HAP ax³ (Gateway) | ✅ |
| 192.168.10.2 | 18:FD:74:54:3D:BC | CAP XL ac | ✅ |
| 192.168.10.3 | F4:1E:57:C9:BD:09 | CSS326 Switch | ✅ |
| 192.168.10.10 | 02:42:C0:A8:1F:04 | AdGuard (Unraid) | ✅ |
| 192.168.10.20 | A8:B8:E0:02:B6:15 | Unraid Server | ✅ Verified |
| 192.168.10.200 | 48:DA:35:6F:BE:50 | NanoKVM | ✅ |
---
## CAPsMAN Configuration
```routeros
/interface wifi capsman
set enabled=yes interfaces=wifi1,wifi2 package-path="" upgrade-policy=suggest-same-version
/interface wifi provisioning
add action=create-enabled master-configuration=cfg-xtrm name-format=identity slave-configurations=cfg-xtrm2 supported-bands=5ghz-ax
add action=create-enabled master-configuration=cfg-xtrm2 name-format=identity slave-configurations=cfg-xtrm supported-bands=2ghz-ax
```
---
## Critical Lessons Learned
### 1. VLAN Filtering Breaks IP on Bridge
When you enable `vlan-filtering=yes` on the bridge:
- IP address on the bridge interface **stops working**
- You **must** have IP on the VLAN interface instead
- Never have same IP on both bridge and VLAN interface simultaneously
### 2. Correct Order of Operations
```
1. Create VLAN interfaces
2. Add IPs to VLAN interfaces (can have temporary duplicate)
3. Configure bridge VLAN table
4. Set port PVIDs
5. Add VLAN interfaces to firewall interface lists (LAN)
6. Enable VLAN filtering
7. Remove IP from bridge (if any duplicate)
8. Move DHCP server to VLAN interface
```
### 3. WiFi VLAN Assignment
- **Do NOT use** `action=query-radius` without configured RADIUS users
- **Use** WiFi datapath with `bridge=bridge`
- **Use** access-list with `vlan-id=XX` for MAC-based assignment
- WiFi interfaces must be **tagged** in bridge VLAN table for dynamic VLANs
### 4. Firewall Interface Lists
After creating VLAN interfaces, add them to the LAN list:
```routeros
/interface list member add list=LAN interface=vlan10-mgmt
/interface list member add list=LAN interface=vlan20-trusted
/interface list member add list=LAN interface=vlan25-kids
/interface list member add list=LAN interface=vlan30-iot
/interface list member add list=LAN interface=vlan40-catchall
```
### 5. Safe Mode
- Enter with **Ctrl+X** in WinBox
- Changes auto-rollback if connection lost (~10 minutes)
- Exit and save with **Ctrl+X** again
---
## Useful Commands
### Verify VLAN Status
```routeros
/interface bridge print where name=bridge
/interface bridge vlan print detail
/interface bridge port print
/ip address print
```
### Check WiFi Clients and VLAN Assignment
```routeros
/interface wifi registration-table print
/interface wifi access-list print
```
### Check DHCP Leases per VLAN
```routeros
/ip dhcp-server lease print where server=dhcp-vlan10
/ip dhcp-server lease print where server=dhcp-vlan20
```
### Add New Device to Access-List
```routeros
/interface wifi access-list add action=accept mac-address=XX:XX:XX:XX:XX:XX vlan-id=20 comment="Device Name" place-before=[find comment="Default - VLAN40"]
```
### Emergency Rollback
```routeros
/interface bridge set bridge vlan-filtering=no
```
### Restore from Backup
```routeros
/system backup load name=vlan-setup-complete-2026-01-31
```
---
## Pending Tasks
1. **Configure CAP XL ac to join CAPsMAN**
- CAP is on VLAN 10 at 192.168.10.2
- Needs provisioning to extend WiFi coverage
2. **Configure CSS326 for VLAN Trunking**
- Switch is on VLAN 10 at 192.168.10.3
- Needs VLAN configuration for room distribution
3. **Add Remaining Devices to Access-List**
- As devices connect, add their MACs to appropriate VLANs
4. **Configure Inter-VLAN Firewall Rules**
- Management → All (full access)
- Trusted → IoT (control smart home)
- IoT → Internet only (isolated)
- Guest → Internet only (isolated)
5. **Test VLAN 25 (Kids) and VLAN 30 (IoT)**
- Connect devices and verify DHCP/internet
---
## Connection Commands Reference
### SSH to Unraid (VLAN 10)
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422
```
### SSH to MikroTik (port 2222!)
From Mac:
```bash
ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.1
```
From Unraid:
```bash
ssh -p 2222 unraid@192.168.10.1
```
### Quick Status from Unraid
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422 "docker ps -a --format 'table {{.Names}}\t{{.Status}}'"
```
---
## Backup Files on Router
| File | Size | Description |
|------|------|-------------|
| vlan-setup-complete-2026-01-31.backup | 177.6 KiB | Binary backup (full restore) |
| vlan-setup-complete-2026-01-31.rsc | 12.5 KiB | Script export (readable) |
**Download via:** WinBox → Files → Select file → Download
---
## Network Diagram (Current)
```
Internet
┌───────────────────────────────────────────────────────────────┐
│ HAP ax³ (192.168.10.1) │
│ RouterOS 7.21.1 │
│ │
│ VLAN 10: 192.168.10.0/24 (Management) │
│ VLAN 20: 192.168.20.0/24 (Trusted) │
│ VLAN 25: 192.168.25.0/24 (Kids) │
│ VLAN 30: 192.168.30.0/24 (IoT) │
│ VLAN 40: 192.168.1.0/24 (Catch-All/Default) │
│ │
│ ether2 ─┬─ CAP XL ac (192.168.10.2) │
│ ether3 ─┼─ CSS326 (192.168.10.3) ─── NanoKVM (.199) │
│ ether4 ─┼─ Unraid (192.168.10.20) │
│ ether5 ─┘ │
│ │
│ wifi1 (XTRM 5GHz) ──┬── VLAN 20/25/30/40 via access-list │
│ wifi2 (XTRM2 2.4GHz)─┘ │
└───────────────────────────────────────────────────────────────┘
```
---
## Session Timeline
1. **CAPsMAN Setup** - Configured WiFi profiles (cfg-xtrm, cfg-xtrm2) and security
2. **Research** - Studied MikroTik forums for correct VLAN approach
3. **VLAN Infrastructure** - Created VLANs 10, 20, 25, 30, 40 with DHCP
4. **Safe Mode Implementation** - Used atomic script for VLAN filtering
5. **WiFi VLAN** - Configured datapath and access-list for MAC-based assignment
6. **Verification** - Tested connectivity on all VLANs
7. **Backup** - Created `vlan-setup-complete-2026-01-31`
---
**Document Version:** 1.0
**Last Updated:** 2026-01-31

View File

@@ -0,0 +1,521 @@
# AdGuard Configuration Plan for VLAN Structure
**Created:** 2026-01-31
**Status:** IMPLEMENTED
**Prerequisites:** VLAN setup complete (doc 15)
**See Also:** [17-DNS-ADGUARD-FAILOVER.md](17-DNS-ADGUARD-FAILOVER.md) - Complete implementation with failover
---
## Overview
Configure AdGuard DNS filtering for the new VLAN-segmented network with:
- MikroTik container as primary DNS (172.17.0.2)
- Unraid AdGuard as secondary DNS (192.168.10.10)
- DNS redirect for all VLANs
- Different filtering policies per VLAN (Kids stricter)
---
## Current State
| Component | IP | Status |
|-----------|-----|--------|
| AdGuard (Unraid) | 192.168.10.10 | Running |
| AdGuard (MikroTik) | 172.17.0.2 | Not installed |
| adguardhome-sync | 172.18.0.27 | Running |
---
## Network Architecture (VLAN-Aware)
```
┌─────────────────────────────────────────────────────────────────────────┐
│ INTERNET │
│ │
│ Mobile/Remote ──► dns.xtrm-lab.org ──► WAN:853 (DoT) │
│ ──► WAN:8443 (DoH) │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ MikroTik hAP ax³ │
│ 192.168.10.1 │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ AdGuard Container │ │
│ │ 172.17.0.2 (primary) │ │
│ │ │ │
│ │ Ports: 53 (DNS), 80 (HTTP), 443 (HTTPS), 853 (DoT) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────┴────────────────────────────────┐ │
│ │ DNS Redirect Rules │ │
│ │ │ │
│ │ VLAN 10 (192.168.10.0/24) ─► 172.17.0.2:53 Management │ │
│ │ VLAN 20 (192.168.20.0/24) ─► 172.17.0.2:53 Trusted │ │
│ │ VLAN 25 (192.168.25.0/24) ─► 172.17.0.2:53 Kids │ │
│ │ VLAN 30 (192.168.30.0/24) ─► 172.17.0.2:53 IoT │ │
│ │ VLAN 40 (192.168.1.0/24) ─► 172.17.0.2:53 Catch-All │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Unraid (VLAN 10) │
│ 192.168.10.20 │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ AdGuard Container (secondary) │ │
│ │ 192.168.10.10 │ │
│ │ │ │
│ │ Upstream: MikroTik AdGuard (172.17.0.2) │ │
│ │ Failover: Quad9 DoH │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ adguardhome-sync │ │
│ │ 172.18.0.27 │ │
│ │ │ │
│ │ Syncs: MikroTik ◄─► Unraid (filters, rewrites, clients) │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## Phase 1: MikroTik Container Setup
### 1.1 Create Container Infrastructure
```routeros
# Container mode (if not already enabled)
/system/device-mode/update container=yes
# Create veth interface
/interface veth add address=172.17.0.2/24 gateway=172.17.0.1 name=veth-adguard
# Add to bridge
/interface bridge port add bridge=bridge interface=veth-adguard
# Gateway IP for container network
/ip address add address=172.17.0.1/24 interface=veth-adguard
```
### 1.2 Create Container Mounts
```routeros
# Create USB directory structure first
/file print # verify usb1 exists
# Create mounts
/container mounts add name=agh-config src=usb1/adguard/conf dst=/opt/adguardhome/conf
/container mounts add name=agh-work src=usb1/adguard/work dst=/opt/adguardhome/work
```
### 1.3 Pull and Create Container
```routeros
# Environment variables
/container envs add name=agh-env key=TZ value="Europe/Sofia"
# Pull image and create container
/container add remote-image=adguard/adguardhome:latest \
interface=veth-adguard \
root-dir=usb1/adguard/root \
mounts=agh-config,agh-work \
envlist=agh-env \
dns=8.8.8.8 \
logging=yes \
start-on-boot=yes \
name=adguardhome
# Wait for extraction (check status)
/container print
# Start when status shows "stopped" (not "extracting")
/container start [find name=adguardhome]
```
---
## Phase 2: NAT Rules for All VLANs
### 2.1 Exception Rules (MUST BE FIRST)
```routeros
# Allow AdGuard containers' own DNS queries (prevent loops)
/ip firewall nat add chain=dstnat action=accept protocol=udp \
src-address=172.17.0.0/24 dst-port=53 \
comment="[DNS] Allow MikroTik AdGuard outbound" place-before=0
/ip firewall nat add chain=dstnat action=accept protocol=udp \
src-address=192.168.10.10 dst-port=53 \
comment="[DNS] Allow Unraid AdGuard outbound" place-before=1
/ip firewall nat add chain=dstnat action=accept protocol=tcp \
src-address=192.168.10.10 dst-port=53 \
comment="[DNS] Allow Unraid AdGuard outbound TCP" place-before=2
```
### 2.2 VLAN DNS Redirect Rules
```routeros
# VLAN 10 - Management (192.168.10.0/24)
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=udp src-address=192.168.10.0/24 dst-port=53 \
comment="[DNS] VLAN10 Mgmt redirect"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=tcp src-address=192.168.10.0/24 dst-port=53 \
comment="[DNS] VLAN10 Mgmt redirect TCP"
# VLAN 20 - Trusted (192.168.20.0/24)
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=udp src-address=192.168.20.0/24 dst-port=53 \
comment="[DNS] VLAN20 Trusted redirect"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=tcp src-address=192.168.20.0/24 dst-port=53 \
comment="[DNS] VLAN20 Trusted redirect TCP"
# VLAN 25 - Kids (192.168.25.0/24)
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=udp src-address=192.168.25.0/24 dst-port=53 \
comment="[DNS] VLAN25 Kids redirect"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=tcp src-address=192.168.25.0/24 dst-port=53 \
comment="[DNS] VLAN25 Kids redirect TCP"
# VLAN 30 - IoT (192.168.30.0/24)
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=udp src-address=192.168.30.0/24 dst-port=53 \
comment="[DNS] VLAN30 IoT redirect"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=tcp src-address=192.168.30.0/24 dst-port=53 \
comment="[DNS] VLAN30 IoT redirect TCP"
# VLAN 40 - Catch-All (192.168.1.0/24)
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=udp src-address=192.168.1.0/24 dst-port=53 \
comment="[DNS] VLAN40 CatchAll redirect"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 \
protocol=tcp src-address=192.168.1.0/24 dst-port=53 \
comment="[DNS] VLAN40 CatchAll redirect TCP"
```
### 2.3 Masquerade Rules for Return Traffic
```routeros
# Masquerade for all VLAN subnets to AdGuard
/ip firewall nat add chain=srcnat action=masquerade protocol=udp \
src-address=192.168.10.0/24 dst-address=172.17.0.2 dst-port=53 \
comment="[DNS] VLAN10 masquerade"
/ip firewall nat add chain=srcnat action=masquerade protocol=udp \
src-address=192.168.20.0/24 dst-address=172.17.0.2 dst-port=53 \
comment="[DNS] VLAN20 masquerade"
/ip firewall nat add chain=srcnat action=masquerade protocol=udp \
src-address=192.168.25.0/24 dst-address=172.17.0.2 dst-port=53 \
comment="[DNS] VLAN25 masquerade"
/ip firewall nat add chain=srcnat action=masquerade protocol=udp \
src-address=192.168.30.0/24 dst-address=172.17.0.2 dst-port=53 \
comment="[DNS] VLAN30 masquerade"
/ip firewall nat add chain=srcnat action=masquerade protocol=udp \
src-address=192.168.1.0/24 dst-address=172.17.0.2 dst-port=53 \
comment="[DNS] VLAN40 masquerade"
```
### 2.4 External Access (DoT/DoH)
```routeros
# DoT (DNS over TLS) - port 853
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=853 \
protocol=tcp in-interface=ether1 dst-port=853 \
comment="[DNS] DoT external"
# DoH (DNS over HTTPS) - port 8443 → 443
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=443 \
protocol=tcp in-interface=ether1 dst-port=8443 \
comment="[DNS] DoH external"
```
### 2.5 Web UI Access
```routeros
# AdGuard Web UI on port 3000 from Management VLAN
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=80 \
protocol=tcp dst-address=192.168.10.1 dst-port=3000 \
comment="[DNS] AdGuard Web UI"
```
---
## Phase 3: Firewall Filter Rules
```routeros
# Allow traffic to container network
/ip firewall filter add chain=input action=accept dst-address=172.17.0.0/24 \
comment="[Container] Allow to container network" place-before=0
/ip firewall filter add chain=input action=accept src-address=172.17.0.0/24 \
comment="[Container] Allow from container network" place-before=1
/ip firewall filter add chain=forward action=accept dst-address=172.17.0.0/24 \
comment="[Container] Forward to container network"
/ip firewall filter add chain=forward action=accept src-address=172.17.0.0/24 \
comment="[Container] Forward from container network"
```
---
## Phase 4: MikroTik DNS Settings
```routeros
# Point MikroTik's own DNS resolver to AdGuard container
/ip dns set servers=172.17.0.2 allow-remote-requests=yes
```
---
## Phase 5: AdGuard Initial Configuration
### 5.1 Access Web UI
After container starts, access: `http://192.168.10.1:3000`
### 5.2 Initial Setup Wizard
| Setting | Value |
|---------|-------|
| Admin Interface | All interfaces, port 80 |
| DNS Server | All interfaces, port 53 |
| Username | admin |
| Password | (set secure password) |
### 5.3 Upstream DNS
```
# Primary (encrypted)
https://dns.quad9.net/dns-query
# Fallback to Unraid AdGuard
192.168.10.10
```
### 5.4 Bootstrap DNS
```
9.9.9.9
149.112.112.112
```
### 5.5 TLS Configuration (for DoT/DoH)
| Setting | Value |
|---------|-------|
| Server Name | dns.xtrm-lab.org |
| Certificate Path | /opt/adguardhome/conf/fullchain.pem |
| Key Path | /opt/adguardhome/conf/privkey.pem |
**Certificate upload:**
```bash
# From Mac - copy certificates to MikroTik USB
scp -P 2222 /path/to/fullchain.pem xtrm@192.168.10.1:usb1/adguard/conf/
scp -P 2222 /path/to/privkey.pem xtrm@192.168.10.1:usb1/adguard/conf/
```
---
## Phase 6: Client Configuration per VLAN
### 6.1 DHCP Network Settings
Update each VLAN's DHCP to advertise AdGuard as DNS:
```routeros
/ip dhcp-server network
set [find address=192.168.10.0/24] dns-server=192.168.10.10
set [find address=192.168.20.0/24] dns-server=192.168.10.10
set [find address=192.168.25.0/24] dns-server=192.168.10.10
set [find address=192.168.30.0/24] dns-server=192.168.10.10
set [find address=192.168.1.0/24] dns-server=192.168.10.10
```
**Note:** We use 192.168.10.10 (Unraid AdGuard) as the advertised DNS because:
1. Clients can reach it directly on VLAN 10
2. The NAT redirect still captures all DNS traffic to 172.17.0.2
3. If redirect fails, clients fall back to Unraid AdGuard
---
## Phase 7: AdGuard Sync Configuration
### 7.1 Update adguardhome-sync on Unraid
Edit `/mnt/user/appdata/adguardhome-sync/adguardhome-sync.yaml`:
```yaml
origin:
url: http://172.17.0.2 # MikroTik AdGuard (via router internal)
username: admin
password: YOUR_PASSWORD
replicas:
- url: http://192.168.10.10 # Unraid AdGuard
username: admin
password: YOUR_PASSWORD
cron: "0 */30 * * * *" # Every 30 minutes
api:
port: 8080
features:
dns:
rewrites: true
filters: true
clients: true
services: true
```
### 7.2 Restart Sync Container
```bash
docker restart adguardhome-sync
```
---
## Phase 8: Kids VLAN Special Configuration (Optional)
For stricter filtering on VLAN 25 (Kids), you can:
### Option A: Separate AdGuard Client Profile
In AdGuard → Settings → Client Settings, add clients for Kids VLAN:
- Identifier: 192.168.25.0/24
- Name: Kids Devices
- Enable: SafeSearch, Block Adult Sites
- Custom filters: stricter blocklists
### Option B: Redirect to Different DNS (More Complex)
Create separate DNS redirect for VLAN 25 to a different filtering service.
---
## Verification Checklist
After implementation, verify:
- [ ] Container running: `/container print` shows "running"
- [ ] DNS resolution: `:resolve google.com server=172.17.0.2`
- [ ] VLAN 10 DNS: `nslookup google.com` from Unraid
- [ ] VLAN 20 DNS: Test from trusted device
- [ ] VLAN 25 DNS: Test from kids device
- [ ] VLAN 30 DNS: Test from IoT device
- [ ] VLAN 40 DNS: Test from catch-all device
- [ ] DoT external: `kdig @dns.xtrm-lab.org +tls google.com`
- [ ] DoH external: `curl https://dns.xtrm-lab.org:8443/dns-query?name=google.com`
- [ ] Web UI accessible: `http://192.168.10.1:3000`
- [ ] Sync working: Check adguardhome-sync logs
---
## Troubleshooting
### Container won't start
```routeros
# Check container status
/container print detail
# Check logs
:log print where topics~"container"
# Common fix: recreate container
/container remove [find name=adguardhome]
# Then repeat Phase 1.3
```
### DNS not redirecting
```routeros
# Check NAT rules are active
/ip firewall nat print where comment~"DNS"
# Test packet flow
/tool sniffer quick port=53
```
### Sync not working
```bash
# On Unraid, check sync logs
docker logs adguardhome-sync
# Verify connectivity
curl -u admin:password http://172.17.0.2/control/status
```
---
## Quick Reference Commands
```routeros
# Check AdGuard container
/container print where name=adguardhome
# Restart AdGuard
/container stop [find name=adguardhome]
/container start [find name=adguardhome]
# Test DNS
:resolve google.com server=172.17.0.2
# Check DNS NAT rules
/ip firewall nat print where comment~"DNS"
# Backup before changes
/system backup save name=pre-adguard-$(date)
```
---
## Files Location
| Item | Location |
|------|----------|
| MikroTik AdGuard Config | usb1/adguard/conf/AdGuardHome.yaml |
| MikroTik AdGuard Work | usb1/adguard/work/ |
| MikroTik TLS Certs | usb1/adguard/conf/*.pem |
| Unraid AdGuard Config | /mnt/user/appdata/adguardhome/ |
| Sync Config | /mnt/user/appdata/adguardhome-sync/ |
---
## Implementation Order
1. **Backup MikroTik** - `/system backup save name=pre-adguard`
2. **Phase 1** - Container setup (requires device mode update + reboot)
3. **Phase 2** - NAT rules (careful with order!)
4. **Phase 3** - Firewall filters
5. **Phase 4** - MikroTik DNS settings
6. **Test** - Verify DNS works
7. **Phase 5** - AdGuard web configuration
8. **Phase 6** - DHCP updates
9. **Phase 7** - Sync setup
10. **Phase 8** - Kids filtering (optional)
---
**Document Version:** 1.0
**Last Updated:** 2026-01-31

View File

@@ -0,0 +1,415 @@
# DNS Architecture with AdGuard Failover
**Created:** 2026-01-31
**Updated:** 2026-01-31
**Status:** Implemented
**Backup:** `dns-dual-failover-2026-01-31.backup`
---
## Overview
Dual AdGuard DNS setup with automatic failover. All DNS queries are filtered through AdGuard for ad-blocking, and if the primary (MikroTik) fails, traffic automatically switches to secondary (Unraid).
---
## Architecture
```
┌─────────────────────────────────────┐
│ INTERNET │
│ │
│ External clients (DoT/DoH) │
│ dns.xtrm-lab.org:853 (DoT) │
│ dns.xtrm-lab.org:8443 (DoH) │
└──────────────┬──────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ MikroTik hAP ax³ (192.168.10.1) │
│ │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ AdGuard Home (PRIMARY) │ │
│ │ Container: 172.17.0.2 │ │
│ │ Web UI: http://192.168.10.1:3000 │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Filters │ │ Blocklists │ │ Clients │ │ │
│ │ │ (synced) │ │ 143K rules │ │ (synced) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ Netwatch monitors every 10s │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ Container UP Container DOWN │
│ │ │ │
│ ▼ ▼ │
│ NAT → 172.17.0.2 NAT → 192.168.10.10 │
│ (MikroTik) (Unraid Failover) │
└──────────────────────────────────────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
NAT Redirect NAT Redirect NAT Redirect
│ │ │
┌───────┴───────┐ ┌────────┴────────┐ ┌────────┴────────┐
│ VLAN 10 │ │ VLAN 20/25 │ │ VLAN 30/40 │
│ Management │ │ Trusted/Kids │ │ IoT/CatchAll │
│ 192.168.10.x │ │ 192.168.20.x │ │ 192.168.30.x │
│ │ │ 192.168.25.x │ │ 192.168.1.x │
└───────────────┘ └─────────────────┘ └─────────────────┘
```
---
## AdGuard Instances
| Instance | Role | IP | Port | Web UI |
|----------|------|-----|------|--------|
| MikroTik | Primary | 172.17.0.2 | 53 | http://192.168.10.1:3000 |
| Unraid | Secondary/Failover | 192.168.10.10 | 3000 | http://192.168.10.10:3000 |
### Credentials (Same for Both)
| Username | Password |
|----------|----------|
| jazzymc | 7RqWElENNbZnPW |
---
## DNS Redirect Rules
All DNS queries (port 53) from any VLAN are intercepted and redirected:
| VLAN | Subnet | Redirected To |
|------|--------|---------------|
| 10 | 192.168.10.0/24 | 172.17.0.2:53 |
| 20 | 192.168.20.0/24 | 172.17.0.2:53 |
| 25 | 192.168.25.0/24 | 172.17.0.2:53 |
| 30 | 192.168.30.0/24 | 172.17.0.2:53 |
| 40 | 192.168.1.0/24 | 172.17.0.2:53 |
**Note:** Clients don't need any DNS configuration - even if they use 8.8.8.8, traffic is intercepted by NAT.
### NAT Rules on MikroTik
```routeros
# Exception rules (prevent loops) - MUST BE FIRST
/ip firewall nat
add chain=dstnat action=accept protocol=udp src-address=172.17.0.0/24 dst-port=53 comment="[DNS] Allow MikroTik AdGuard outbound"
add chain=dstnat action=accept protocol=udp src-address=192.168.10.10 dst-port=53 comment="[DNS] Allow Unraid AdGuard outbound"
# VLAN redirect rules
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.10.0/24 dst-port=53 comment="[DNS] VLAN10 Mgmt redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.20.0/24 dst-port=53 comment="[DNS] VLAN20 Trusted redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.25.0/24 dst-port=53 comment="[DNS] VLAN25 Kids redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.30.0/24 dst-port=53 comment="[DNS] VLAN30 IoT redirect"
add chain=dstnat action=dst-nat to-addresses=172.17.0.2 to-ports=53 protocol=udp src-address=192.168.1.0/24 dst-port=53 comment="[DNS] VLAN40 CatchAll redirect"
# Masquerade for return traffic
add chain=srcnat action=masquerade protocol=udp src-address=192.168.10.0/24 dst-address=172.17.0.2 dst-port=53 comment="[DNS] VLAN10 masquerade"
# ... (similar for other VLANs)
```
---
## Automatic Failover
### How It Works (Dual Health Check)
Two independent Netwatch monitors trigger failover:
| Monitor | Type | What It Checks | Interval | Timeout |
|---------|------|----------------|----------|---------|
| Ping | simple | Container reachable | 10s | 3s |
| DNS | dns | DNS queries work | 30s | 10s |
**Either monitor failing triggers failover to Unraid.**
### Failure Scenarios Covered
| Scenario | Ping Check | DNS Check | Failover? |
|----------|------------|-----------|-----------|
| Container crashed | ✗ Fail | ✗ Fail | ✅ Yes |
| Container stopped | ✗ Fail | ✗ Fail | ✅ Yes |
| Network/routing issue | ✗ Fail | ✗ Fail | ✅ Yes |
| Upstream DNS unreachable | ✓ Pass | ✗ Fail | ✅ Yes |
| AdGuard overloaded | ✓ Pass | ✗ Fail | ✅ Yes |
| Everything working | ✓ Pass | ✓ Pass | ❌ No |
### Failover Timeline
| Event | Detection Time | Total Switchover |
|-------|----------------|------------------|
| Container crash (ping) | ~10-13 seconds | ~13-16 seconds |
| DNS failure (resolution) | ~30-40 seconds | ~33-43 seconds |
| Recovery | ~10-30 seconds | Automatic |
### Failover Scripts
```routeros
# dns-failover-down (runs when either check fails)
/system script add name=dns-failover-down dont-require-permissions=yes source={
:log warning "DNS Failover: Switching to Unraid"
/ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=192.168.10.10 to-ports=3000
}
# dns-failover-up (runs when check recovers)
/system script add name=dns-failover-up dont-require-permissions=yes source={
:log info "DNS Failover: Switching back to MikroTik"
/ip firewall nat set [find where comment~"VLAN" and comment~"redirect"] to-addresses=172.17.0.2 to-ports=53
}
```
### Netwatch Configuration
```routeros
# Monitor 1: Ping check (fast crash detection)
/tool netwatch add type=simple host=172.17.0.2 interval=10s timeout=3s \
up-script=dns-failover-up down-script=dns-failover-down \
comment="AdGuard failover monitor"
# Monitor 2: DNS resolution check (functional verification)
/tool netwatch add type=dns host=google.com interval=30s timeout=10s \
up-script=dns-failover-up down-script=dns-failover-down \
comment="AdGuard DNS resolution check"
```
---
## Sync Configuration
Settings are synced from Unraid (source of truth) to MikroTik every 30 minutes.
### What Syncs
| Feature | Synced |
|---------|--------|
| Filter lists (blocklists) | ✅ |
| User rules (custom blocks/allows) | ✅ |
| Client settings (per-device rules) | ✅ |
| Services (blocked services) | ✅ |
| Rewrites (custom DNS entries) | ✅ |
| DNS server config | ❌ |
| DHCP settings | ❌ |
| Query logs/stats | ❌ |
### Sync Container
```yaml
# /mnt/user/appdata/adguard-sync/adguardhome-sync.yaml
cron: "*/30 * * * *"
runOnStart: true
origin:
url: http://192.168.10.10:3000
username: jazzymc
password: 7RqWElENNbZnPW
replicas:
- url: http://192.168.10.1:3000
username: jazzymc
password: 7RqWElENNbZnPW
features:
dns:
serverConfig: false
accessLists: true
rewrites: true
filters: true
clientSettings: true
services: true
```
**Note:** The sync container must be connected to both `dockerproxy` and `br0` networks to reach both AdGuard instances.
---
## Container Configuration (MikroTik)
### Container Details
| Setting | Value |
|---------|-------|
| Image | adguard/adguardhome:latest |
| Interface | veth-adguard |
| IP | 172.17.0.2/24 |
| Gateway | 172.17.0.1 |
| Root dir | usb1/adguard/root |
| Config mount | usb1/adguard/conf → /opt/adguardhome/conf |
| Work mount | usb1/adguard/work → /opt/adguardhome/work |
| Start on boot | Yes |
### Container Commands
```routeros
# Check status
/container print
# Start container
/container start 0
# Stop container
/container stop 0
# View logs
/log print where topics~"container"
```
---
## Upstream DNS
Both AdGuard instances use the same upstream:
| Upstream | Type |
|----------|------|
| https://dns.quad9.net/dns-query | Primary (DoH) |
| 9.9.9.9 | Bootstrap |
| 149.112.112.112 | Bootstrap secondary |
---
## Management
| Task | Where to Do It |
|------|----------------|
| Change blocklists | Unraid AdGuard (syncs to MikroTik) |
| Add custom rules | Unraid AdGuard |
| Add client settings | Unraid AdGuard |
| View query logs | MikroTik AdGuard (real-time) |
| Check failover status | MikroTik `/tool netwatch print` |
---
## Troubleshooting
### Check Failover Status
```routeros
/tool netwatch print
# Both monitors should show STATUS=up normally
# Monitor 0: Ping check
# Monitor 1: DNS resolution check
```
### Check Current DNS Target
```routeros
/ip firewall nat print where comment~"VLAN10 Mgmt redirect"
# to-addresses should be 172.17.0.2 (normal) or 192.168.10.10 (failover)
```
### View Failover Logs
```routeros
/log print where message~"Failover"
```
### Manual Failover Test
```routeros
# Stop container (triggers failover)
/container stop 0
# Wait 15 seconds, check NAT rules switched to 192.168.10.10
# Start container (triggers recovery)
/container start 0
# Wait 15 seconds, check NAT rules switched back to 172.17.0.2
```
### DNS Not Working
1. Check container is running: `/container print`
2. Check netwatch status: `/tool netwatch print`
3. Test DNS directly: `:resolve google.com server=172.17.0.2`
4. Check NAT rules: `/ip firewall nat print where comment~"DNS"`
5. **Check /32 routes exist:** `/ip route print where dst-address~"172.17.0.[23]"`
6. **Ping container:** `/ping 172.17.0.2 count=3`
### Container Reachable but DNS Fails
If ping works but DNS queries timeout:
1. Check container can reach upstream: Look for timeout errors in logs
2. Verify /32 routes: Missing routes cause ECMP issues
3. Check NAT masquerade: `/ip firewall nat print where comment~"Container"`
4. Verify routes:
```routeros
/ip route print where dst-address~"172.17"
# Should show /32 routes for each container IP
```
### Sync Not Working
```bash
# On Unraid
docker logs adguardhome-sync --tail 20
# Check connectivity
docker exec adguardhome-sync ping -c 2 192.168.10.10
docker exec adguardhome-sync ping -c 2 192.168.10.1
```
---
## Container Network Routing
### Important: /32 Host Routes Required
When running multiple containers on the same subnet (172.17.0.0/24), specific host routes are required to prevent ECMP routing issues:
```routeros
# Without these routes, return traffic may go to wrong container
/ip route add dst-address=172.17.0.2/32 gateway=veth-adguard comment="AdGuard container - specific route"
/ip route add dst-address=172.17.0.3/32 gateway=veth-tailscale comment="Tailscale container - specific route"
```
**Why this matters:** Each veth interface creates a /24 route. With multiple veth interfaces on the same subnet, RouterOS enables ECMP load balancing, sending return traffic to random interfaces.
---
## Backups
| Backup | Description |
|--------|-------------|
| `pre-adguard-2026-01-31` | Before AdGuard setup |
| `adguard-container-running-2026-01-31` | Container working, before NAT |
| `adguard-synced-2026-01-31` | After sync configured |
| `adguard-failover-complete-2026-01-31` | Single ping failover |
| `routing-fix-complete-2026-01-31` | After /32 routing fix |
| `dns-dual-failover-2026-01-31` | Dual health check (current) |
### Restore Command
```routeros
/system backup load name=dns-dual-failover-2026-01-31
```
---
## Quick Reference
### Normal Operation
- DNS queries → MikroTik AdGuard (172.17.0.2)
- Ad blocking active
- ~143,000 filter rules
### During Failover
- DNS queries → Unraid AdGuard (192.168.10.10)
- Ad blocking still active (same rules synced)
- Automatic, no manual intervention needed
### Recovery
- Automatic when container comes back up
- NAT rules switch back to MikroTik
- No DNS interruption for clients
---
**Document Version:** 1.1
**Last Updated:** 2026-01-31
**Changes:** Added dual health check (ping + DNS), documented /32 routing fix

View File

@@ -0,0 +1,224 @@
# MikroTik Tailscale Container Setup
**Created:** 2026-01-31
**Status:** Implemented
**Backup:** `tailscale-working-2026-01-31.backup`
---
## Overview
Tailscale VPN running as a container on MikroTik hAP ax³, providing remote access to the home network via the Tailscale mesh network.
---
## Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ MikroTik hAP ax³ (192.168.10.1) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Container Network (172.17.0.0/24) │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────────┐ │ │
│ │ │ AdGuard Home │ │ Tailscale │ │ │
│ │ │ 172.17.0.2 │ │ 172.17.0.3 │ │ │
│ │ │ veth-adguard │ │ veth-tailscale │ │ │
│ │ └─────────────────────┘ └─────────────────────────┘ │ │
│ │ │ │ │ │
│ │ └───────────┬───────────────┘ │ │
│ │ │ │ │
│ │ Gateway: 172.17.0.1 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ NAT Masquerade │
│ │ │
│ WAN (ether1) │
└──────────────────────────────┬──────────────────────────────────────┘
┌─────────────────────┐
│ Tailscale Network │
│ 100.x.x.x mesh │
│ │
│ Home Router IP: │
│ 100.74.219.35 │
└─────────────────────┘
```
---
## Container Details
| Setting | Value |
|---------|-------|
| Image | tailscale/tailscale:latest |
| Interface | veth-tailscale |
| Container IP | 172.17.0.3/24 |
| Gateway | 172.17.0.1 |
| Tailscale IP | 100.74.219.35 |
| Root dir | usb1/tailscale/root |
| State mount | usb1/tailscale → /var/lib/tailscale |
| DNS | 8.8.8.8 |
| Start on boot | Yes |
| Networking mode | Userspace (TS_USERSPACE=true) |
---
## Environment Variables
| Variable | Value | Purpose |
|----------|-------|---------|
| TS_AUTHKEY | tskey-auth-... | One-time auth key (used during setup) |
| TS_STATE_DIR | /var/lib/tailscale | Persistent state directory |
| TS_USERSPACE | true | Required for MikroTik containers (no /dev/net/tun) |
---
## Network Configuration
### veth Interface
```routeros
/interface veth add address=172.17.0.3/24 gateway=172.17.0.1 name=veth-tailscale
```
### Gateway IP on Interface
```routeros
/ip address add address=172.17.0.1/24 interface=veth-tailscale comment="Tailscale container gateway"
```
### NAT Masquerade for Internet Access
```routeros
/ip firewall nat add chain=srcnat action=masquerade src-address=172.17.0.0/24 out-interface-list=WAN comment="Container network NAT"
```
### Firewall Forward Rules
```routeros
/ip firewall filter add chain=forward action=accept dst-address=172.17.0.0/24 comment="[Container] Forward to container network"
/ip firewall filter add chain=forward action=accept src-address=172.17.0.0/24 comment="[Container] Forward from container network"
```
---
## Container Setup Commands
### Create Mounts
```routeros
/container mounts add list=ts-state src=usb1/tailscale dst=/var/lib/tailscale
```
### Create Environment Variables
```routeros
/container envs add list=ts-env key=TS_STATE_DIR value=/var/lib/tailscale
/container envs add list=ts-env key=TS_USERSPACE value=true
/container envs add list=ts-env key=TS_AUTHKEY value=<your-auth-key>
```
### Create Container
```routeros
/container add remote-image=tailscale/tailscale:latest interface=veth-tailscale \
root-dir=usb1/tailscale/root mountlists=ts-state envlists=ts-env \
dns=8.8.8.8 start-on-boot=yes logging=yes
```
---
## Management
### Check Container Status
```routeros
/container print
```
### View Logs
```routeros
/log print where topics~"container" and message~"tailscale"
```
### Start/Stop Container
```routeros
/container start [find name~"tailscale"]
/container stop [find name~"tailscale"]
```
---
## Troubleshooting
### Container Won't Start (Exit Status 1)
**Cause:** Missing /dev/net/tun device (default for Tailscale)
**Solution:** Enable userspace networking mode:
```routeros
/container envs add list=ts-env key=TS_USERSPACE value=true
```
### Can't Reach Internet from Container
**Cause:** Missing NAT masquerade or gateway IP
**Solution:**
1. Verify gateway IP on veth interface:
```routeros
/ip address print where interface=veth-tailscale
```
2. Verify NAT masquerade rule:
```routeros
/ip firewall nat print where src-address=172.17.0.0/24
```
### Container Not Connecting to Tailscale
1. Check DNS resolution works (logs should show no timeout)
2. Verify auth key is valid and not expired
3. Check firewall isn't blocking outbound HTTPS
---
## Tailscale Network Devices
| Tailscale IP | Device | Status |
|--------------|--------|--------|
| 100.74.219.35 | MikroTik hAP ax³ (container) | Online |
| 100.100.208.70 | xtrm-unraid | Online |
| 100.112.103.7 | hapax3 (old native install) | Offline |
| 100.75.93.123 | mikrotik-tailscale (previous container) | Offline |
---
## Important Notes
1. **Userspace Networking Required:** MikroTik containers don't have /dev/net/tun access, so TS_USERSPACE=true is mandatory
2. **Auth Key:** After initial authentication, the key is no longer needed - state is persisted in the mount
3. **Container Network:** Both AdGuard and Tailscale share the 172.17.0.0/24 network but have separate veth interfaces
4. **Accept Routes:** If subnet routing is needed, add TS_EXTRA_ARGS="--accept-routes" to environment
---
## Backups
| Backup | Description |
|--------|-------------|
| pre-tailscale-2026-01-31 | Before Tailscale setup |
| tailscale-working-2026-01-31 | Tailscale container running |
---
**Document Version:** 1.0
**Last Updated:** 2026-01-31

View File

@@ -0,0 +1,173 @@
# Device Migration Worksheet
**Last Updated:** 2026-02-01
**Purpose:** Planning worksheet for VLAN/IP reassignment
---
## All Devices by VLAN
### VLAN 10 - Management (Infrastructure)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| HAP1 (hAP ax³) | 78:9A:18:2C:A5:48 | 192.168.10.1 | 10 | | |
| CAP XL ac | 18:FD:74:54:3D:BC | 192.168.10.2 | 10 | | |
| CSS326-24G-2S+ | F4:1E:57:C9:BD:09 | 192.168.10.3 | 10 | | |
| ZX1 (ZX-SWTGW218AS) | 1C:2A:A3:1E:78:67 | 192.168.10.4 | 10 | | |
| AdGuard Home (Unraid) | 02:42:C0:A8:1F:04 | 192.168.10.10 | 10 | | |
| XTRM-U (Unraid) | A8:B8:E0:02:B6:15 | 192.168.10.20 | 10 | | |
| NanoKVM | 48:DA:35:6F:BE:50 | 192.168.10.200 | 10 | | |
| AdGuard (MikroTik) | 46:D0:27:F7:1F:CA | 172.17.0.2 | 10 | | |
| Tailscale (MikroTik) | 0C:AB:39:8D:8C:FC | 172.17.0.3 | 10 | | |
---
### VLAN 20 - Trusted (Family Devices)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| MacBook Air (Nora) | 82:6D:FB:D9:E0:47 | 192.168.20.10 | 20 | | |
| Samsung S25 Ultra (Kaloyan) | AA:ED:8B:2A:40:F1 | 192.168.20.11 | 20 | | |
| iPhone (Dancho) | F2:B8:14:61:C8:27 | 192.168.20.12 | 20 | | |
| MacBook Pro WiFi (Kaloyan) | 82:EC:EF:B5:F2:AF | 192.168.20.13 | 20 | | |
| Notebook (Kimi) | 90:91:64:70:0D:86 | 192.168.20.14 | 20 | | |
| iPhone (Kimi) | 2A:2B:BA:86:D4:AF | 192.168.20.15 | 20 | | |
| MacBook Pro LAN (Kaloyan) | 08:92:04:C6:07:C5 | 192.168.20.16 | 20 | | |
| Gaming PC (Kaloyan) | 1C:83:41:32:F3:AF | 192.168.20.17 | 20 | | |
| iPad (Compusbg) | A4:D1:D2:7B:52:BE | 192.168.20.18 | 20 | | |
---
### VLAN 25 - Kids Devices
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| iPhone (Dancho) | F2:B8:14:61:C8:27 | 192.168.20.12 | 25 | | |
| Notebook (Kimi) | 90:91:64:70:0D:86 | 192.168.20.14 | 25 | | |
| iPhone (Kimi) | 2A:2B:BA:86:D4:AF | 192.168.20.15 | 25 | | |
| iPad (Compusbg) | A4:D1:D2:7B:52:BE | 192.168.20.18 | 25 | | |
---
### VLAN 30 - IoT (Smart Home)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| GREE Air Conditioner | 50:2C:C6:7A:55:39 | 192.168.30.10 | 30 | | |
| LG TV (LAN) | B0:37:95:79:AF:9B | 192.168.30.11 | 30 | | |
| LG TV (WiFi) | DC:03:98:6B:5A:3A | 192.168.30.12 | 30 | | |
| Chromecast | D0:E7:82:F7:65:DD | 192.168.30.13 | 30 | | |
| Roborock S7 Vacuum | B0:4A:39:3F:9A:14 | 192.168.30.14 | 30 | | |
| Bosch Smart Oven | 94:27:70:1E:0C:EE | 192.168.30.20 | 30 | | |
| Bosch Dishwasher | C8:D7:78:40:65:40 | 192.168.30.21 | 30 | | |
| Bosch Washer | C8:D7:78:D6:DC:FC | 192.168.30.22 | 30 | | |
| Tuya Smart Device | 18:DE:50:5B:C8:A6 | 192.168.30.31 | 30 | | |
| Xiaomi Smart Device | 38:1F:8D:04:6F:E4 | 192.168.30.32 | 30 | | |
| Tuya/Intellirocks Device | D4:AD:FC:BE:13:B0 | 192.168.30.33 | 30 | | |
| Xiaomi Air Purifier | C8:5C:CC:52:EA:53 | 192.168.30.39 | 30 | | |
---
### VLAN 35 - Cameras (Security)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| Reolink Doorbell | 48:9E:9D:0E:16:F7 | 192.168.35.10 | 35 | | |
---
### VLAN 40 - Servers (Services)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| HP LaserJet | 64:4E:D7:D8:43:3E | 192.168.40.19 | 40 | | |
---
### VLAN 50 - Guest (Isolated)
| Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|--------|-------------|------------|--------------|----------|--------|
| Apple Device (unknown) | AC:87:A3:77:8F:BD | 192.168.50.10 | 50 | | |
| Unknown Device (Privacy MAC) | 22:4C:7F:1D:85:8E | 192.168.50.11 | 50 | | |
| Unknown Device | D0:C9:07:92:1A:8E | 192.168.50.12 | 50 | | |
| Unknown Device | D0:C9:07:8C:C9:46 | 192.168.50.13 | 50 | | |
---
## Summary
| VLAN | Name | Subnet | Device Count |
|------|------|--------|--------------|
| 10 | Mgmt | 192.168.10.0/24 | 9 |
| 20 | Trusted | 192.168.20.0/24 | 9 |
| 25 | Kids | 192.168.25.0/24 | 4 |
| 30 | IoT | 192.168.30.0/24 | 12 |
| 35 | Cameras | 192.168.35.0/24 | 1 |
| 40 | Servers | 192.168.40.0/24 | 1 |
| 50 | Guest | 192.168.50.0/24 | 4 |
| **Total** | | | **40** |
---
## Flat List (All Devices)
| # | Device | MAC Address | Current IP | Current VLAN | New VLAN | New IP |
|---|--------|-------------|------------|--------------|----------|--------|
| 1 | HAP1 (hAP ax³) | 78:9A:18:2C:A5:48 | 192.168.10.1 | 10 | | |
| 2 | CAP XL ac | 18:FD:74:54:3D:BC | 192.168.10.2 | 10 | | |
| 3 | CSS326-24G-2S+ | F4:1E:57:C9:BD:09 | 192.168.10.3 | 10 | | |
| 4 | ZX1 (ZX-SWTGW218AS) | 1C:2A:A3:1E:78:67 | 192.168.10.4 | 10 | | |
| 5 | AdGuard Home (Unraid) | 02:42:C0:A8:1F:04 | 192.168.10.10 | 10 | | |
| 6 | XTRM-U (Unraid) | A8:B8:E0:02:B6:15 | 192.168.10.20 | 10 | | |
| 7 | NanoKVM | 48:DA:35:6F:BE:50 | 192.168.10.200 | 10 | | |
| 8 | AdGuard (MikroTik) | 46:D0:27:F7:1F:CA | 172.17.0.2 | 10 | | |
| 9 | Tailscale (MikroTik) | 0C:AB:39:8D:8C:FC | 172.17.0.3 | 10 | | |
| 10 | MacBook Air (Nora) | 82:6D:FB:D9:E0:47 | 192.168.20.10 | 20 | | |
| 11 | Samsung S25 Ultra (Kaloyan) | AA:ED:8B:2A:40:F1 | 192.168.20.11 | 20 | | |
| 12 | iPhone (Dancho) | F2:B8:14:61:C8:27 | 192.168.20.12 | 20/25 | | |
| 13 | MacBook Pro WiFi (Kaloyan) | 82:EC:EF:B5:F2:AF | 192.168.20.13 | 20 | | |
| 14 | Notebook (Kimi) | 90:91:64:70:0D:86 | 192.168.20.14 | 20/25 | | |
| 15 | iPhone (Kimi) | 2A:2B:BA:86:D4:AF | 192.168.20.15 | 20/25 | | |
| 16 | MacBook Pro LAN (Kaloyan) | 08:92:04:C6:07:C5 | 192.168.20.16 | 20 | | |
| 17 | Gaming PC (Kaloyan) | 1C:83:41:32:F3:AF | 192.168.20.17 | 20 | | |
| 18 | iPad (Compusbg) | A4:D1:D2:7B:52:BE | 192.168.20.18 | 20/25 | | |
| 19 | GREE Air Conditioner | 50:2C:C6:7A:55:39 | 192.168.30.10 | 30 | | |
| 20 | LG TV (LAN) | B0:37:95:79:AF:9B | 192.168.30.11 | 30 | | |
| 21 | LG TV (WiFi) | DC:03:98:6B:5A:3A | 192.168.30.12 | 30 | | |
| 22 | Chromecast | D0:E7:82:F7:65:DD | 192.168.30.13 | 30 | | |
| 23 | Roborock S7 Vacuum | B0:4A:39:3F:9A:14 | 192.168.30.14 | 30 | | |
| 24 | Bosch Smart Oven | 94:27:70:1E:0C:EE | 192.168.30.20 | 30 | | |
| 25 | Bosch Dishwasher | C8:D7:78:40:65:40 | 192.168.30.21 | 30 | | |
| 26 | Bosch Washer | C8:D7:78:D6:DC:FC | 192.168.30.22 | 30 | | |
| 27 | Tuya Smart Device | 18:DE:50:5B:C8:A6 | 192.168.30.31 | 30 | | |
| 28 | Xiaomi Smart Device | 38:1F:8D:04:6F:E4 | 192.168.30.32 | 30 | | |
| 29 | Tuya/Intellirocks Device | D4:AD:FC:BE:13:B0 | 192.168.30.33 | 30 | | |
| 30 | Xiaomi Air Purifier | C8:5C:CC:52:EA:53 | 192.168.30.39 | 30 | | |
| 31 | Reolink Doorbell | 48:9E:9D:0E:16:F7 | 192.168.35.10 | 35 | | |
| 32 | HP LaserJet | 64:4E:D7:D8:43:3E | 192.168.40.19 | 40 | | |
| 33 | Apple Device (unknown) | AC:87:A3:77:8F:BD | 192.168.50.10 | 50 | | |
| 34 | Unknown Device (Privacy MAC) | 22:4C:7F:1D:85:8E | 192.168.50.11 | 50 | | |
| 35 | Unknown Device | D0:C9:07:92:1A:8E | 192.168.50.12 | 50 | | |
| 36 | Unknown Device | D0:C9:07:8C:C9:46 | 192.168.50.13 | 50 | | |
---
## Notes
- Devices marked with `20/25` in Current VLAN are in both Trusted and Kids VLANs (kids devices with family access)
- MikroTik containers (AdGuard, Tailscale) use internal Docker IPs (172.17.0.x)
- Fill in "New VLAN" and "New IP" columns to plan migration
---
## HAP ax³ Port Assignments
| Port | Device | VLAN |
|------|--------|------|
| ether1 | ISP Gateway (WAN) | - |
| ether2 | CAP XL ac | 10 (trunk) |
| ether3 | CSS326-24G-2S+ | 10 (trunk) |
| ether4 | XTRM-U (Unraid) | 10 |
| ether5 | Dell Monitor LAN | 10 |

View File

@@ -0,0 +1,56 @@
# DNS Redirect Rules Backup
**Date:** 2026-01-27
**Reason:** Temporarily disabled during VLAN migration
**Status:** DISABLED - to be re-enabled after VLAN setup complete
## NAT Rules (dstnat)
| # | Comment | Chain | Action | Src Address | Dst Port | To Address | To Port |
|---|---------|-------|--------|-------------|----------|------------|---------|
| 3 | Allow MikroTik AdGuard outbound DNS | dstnat | accept | 172.17.0.0/24 | 53/udp | - | - |
| 25 | Allow Unraid AdGuard outbound DNS | dstnat | accept | 192.168.31.4 | 53/udp | - | - |
| 26 | Allow Unraid AdGuard outbound DNS TCP | dstnat | accept | 192.168.31.4 | 53/tcp | - | - |
| 27 | Redirect DNS to MikroTik AdGuard | dstnat | dst-nat | 192.168.31.0/24 | 53/udp | 172.17.0.2 | 53 |
| 28 | Redirect DNS to MikroTik AdGuard TCP | dstnat | dst-nat | 192.168.31.0/24 | 53/tcp | 172.17.0.2 | 53 |
| 30 | DNS over TLS (DoT) | dstnat | dst-nat | in-interface=eth1_WAN | 853/tcp | 172.17.0.2 | 853 |
| 31 | DNS over HTTPS (DoH) | dstnat | dst-nat | in-interface=eth1_WAN | 8443/tcp | 172.17.0.2 | 443 |
| 32 | Redirect VLAN DNS to AdGuard | dstnat | dst-nat | src-address-list=all-vlans | 53/udp | 172.17.0.2 | 53 |
| 33 | Redirect VLAN DNS to AdGuard TCP | dstnat | dst-nat | src-address-list=all-vlans | 53/tcp | 172.17.0.2 | 53 |
## NAT Rules (srcnat - masquerade)
| # | Comment | Chain | Action | Src Address | Dst Address | Dst Port |
|---|---------|-------|--------|-------------|-------------|----------|
| 8 | Masquerade DNS to MikroTik AdGuard | srcnat | masquerade | 192.168.31.0/24 | 172.17.0.2 | 53/udp |
| 9 | Masquerade DNS to MikroTik AdGuard TCP | srcnat | masquerade | 192.168.31.0/24 | 172.17.0.2 | 53/tcp |
| 34 | Masquerade VLAN DNS to AdGuard | srcnat | masquerade | src-address-list=all-vlans | 172.17.0.2 | 53/udp |
| 35 | Masquerade VLAN DNS to AdGuard TCP | srcnat | masquerade | src-address-list=all-vlans | 172.17.0.2 | 53/tcp |
## Filter Rules (forward - allow DNS)
| # | Comment | Chain | Action | Src Address List | Dst Address | Dst Port |
|---|---------|-------|--------|------------------|-------------|----------|
| 12 | VLAN: IoT to DNS | forward | accept | vlan-iot | 192.168.31.1 | 53/udp |
| 14 | VLAN: IoT to DNS TCP | forward | accept | vlan-iot | 192.168.31.1 | 53/tcp |
| 16 | VLAN: Cameras to DNS | forward | accept | vlan-cameras | 192.168.31.1 | 53/udp |
| 18 | VLAN: Guest to DNS | forward | accept | vlan-guest | 192.168.31.1 | 53/udp |
| 51 | VLAN: Kids to DNS | forward | accept | vlan-kids | 192.168.31.1 | 53/udp |
## Re-enable Commands
When ready to restore DNS redirect to AdGuard:
```routeros
# Enable NAT redirect rules
/ip firewall nat enable [find comment~"Redirect DNS" or comment~"Masquerade DNS"]
# Note: Filter rules (VLAN to DNS) should remain enabled - they just allow traffic
```
## Notes
- Rules 27, 28, 32, 33 are the main redirect rules that force DNS through AdGuard
- Rules 8, 9, 34, 35 are masquerade rules needed for AdGuard container to work
- Rules 3, 25, 26 allow AdGuard containers to make outbound DNS queries
- Filter rules 12, 14, 16, 18, 51 allow VLAN devices to reach DNS - these are OK to keep

View File

@@ -0,0 +1,41 @@
# Network Connectivity Issue
**Date:** 2026-01-31
**Status:** RESOLVED
**Severity:** Medium
## Symptoms (Initial)
- DNS resolution failing (8.8.8.8 timeout)
- Cannot connect to local services via 192.168.31.2
- Git push to Gitea failing
## Root Causes Identified
1. **DHCP DNS misconfiguration** - All VLANs were pushing 8.8.8.8 instead of gateway IP
2. **Legacy IP references** - Old 192.168.31.x IPs no longer valid after VLAN migration
3. **Macvlan limitation** - AdGuard on macvlan (br0) unreachable from host
## Resolution
1. Updated MikroTik DHCP network settings:
- VLAN 10: dns-server=192.168.10.1
- VLAN 20: dns-server=192.168.20.1
- VLAN 25: dns-server=192.168.25.1
- VLAN 30: dns-server=192.168.30.1
2. Renewed DHCP lease on Unraid: `dhcpcd -n br0`
3. Updated NetAlertX config with correct IP (192.168.10.20)
## Verification
- DNS now resolves via 192.168.10.1 (MikroTik gateway → AdGuard)
- Git push to Gitea working
- All services accessible
## Lessons Learned
- After VLAN migration, update all hardcoded IPs
- DHCP DNS should point to gateway, not external servers
- Macvlan containers need shim interface for host communication

View File

@@ -0,0 +1,200 @@
# Incident: Unraid Flash Drive Failure
**Date:** 2026-02-06
**Severity:** P1 - Server at risk
**Status:** In Progress
**Affected:** XTRM-U (Unraid NAS)
---
## Symptoms
Unraid flash drive experiencing crashes/instability. Risk of complete failure and data loss of boot configuration.
---
## Migration Procedure: Replace Flash Drive
### Step 1: Retrieve Flash Backup
Try these options in order of preference:
**Option A - Fresh backup from WebGUI (if server still boots):**
1. Open http://192.168.10.20 in browser
2. Go to **Main** tab → click on **Flash** device
3. Under Flash Device Settings, click **FLASH BACKUP**
4. Download the ZIP file to your Mac
**Option B - Google Drive (daily Rclone backup):**
```bash
# From Mac (if rclone is installed)
rclone copy drive:Backups/unraid-flash ~/Desktop/unraid-flash-backup/
# Or download manually from Google Drive web UI
# Folder: Backups/unraid-flash
```
**Option C - Local backup on Unraid (if server boots but WebGUI broken):**
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422
# Backup is at:
ls /mnt/user/Backup/unraid-flash/
# Copy it off the server:
scp -P 422 -i ~/.ssh/id_ed25519_unraid root@192.168.10.20:/mnt/user/Backup/unraid-flash/* ~/Desktop/unraid-flash-backup/
```
**Option D - Direct copy from failing drive:**
1. Shut down server
2. Remove flash drive, insert into Mac
3. Copy entire contents to `~/Desktop/unraid-flash-backup/`
---
### Step 2: Prepare New USB Drive
**Requirements:**
- USB 2.0 recommended (more reliable than USB 3.0 for this purpose)
- Capacity: 4 GB minimum, 32 GB maximum
- Reputable brand (SanDisk, Samsung, Kingston)
- Must have a unique hardware GUID
**Write the backup to new drive:**
1. Download [Unraid USB Flash Creator](https://unraid.net/download) for macOS
2. Insert new USB drive into Mac
3. Open Flash Creator
4. For **Operating System**, scroll down and select **"Use custom"**
5. Browse to your backup ZIP file from Step 1
6. Select the new USB drive as destination
7. Click **Write** and wait for completion
**If you don't have a backup ZIP** (only raw files from Option D):
1. In Flash Creator, select the Unraid OS version matching your current install
2. Write a fresh Unraid install to the new drive
3. After writing, mount the drive and copy your backed-up `config/` folder onto it, replacing the default one
---
### Step 3: Swap Drives and Boot
1. Shut down XTRM-U if still running
2. Remove the old (failing) flash drive
3. Insert the new USB drive
4. Power on the server
5. Wait for boot (1-2 minutes)
6. Try accessing WebGUI at http://192.168.10.20
**If WebGUI doesn't load:**
- Connect a monitor to the server to check boot messages
- Verify the USB drive is detected in BIOS
- Ensure boot order has USB first
---
### Step 4: Transfer License
You will see an "Invalid, missing or expired registration key" message. This is expected.
1. In WebGUI, go to **Tools → Registration**
2. Click **Replace Key**
3. Enter the email address associated with your Unraid account
4. Check your email for the confirmation/license key
5. Follow the link or paste the key file URL into the Registration page
6. Click **Done**
**Important warnings:**
- Replacing the key **permanently blacklists** the old USB drive - it can never be used with Unraid again
- First license transfer can be done at any time
- Subsequent transfers: once per 12 months via the automated system
- If you need another transfer within 12 months, contact [Unraid support](https://unraid.net/contact) with old GUID, new GUID, license key, and purchase email
**If you can't find your license:**
- Log into https://account.unraid.net to view your keys
- Check email for original purchase confirmation
---
### Step 5: Post-Migration Verification
Run through this checklist after the server is back up:
**Array & Storage:**
- [ ] WebGUI loads at http://192.168.10.20
- [ ] Array starts normally (Main tab → Start)
- [ ] All disks show healthy status
- [ ] Shares are accessible
**Docker & Services:**
```bash
ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422
# Check all containers
docker ps -a --format 'table {{.Names}}\t{{.Status}}'
# Start any stopped critical containers (in order):
docker start postgresql17 # Wait 30s
docker start Redis # Wait 10s
docker start traefik
docker start authentik authentik-worker
docker start vaultwarden
```
**Network:**
- [ ] SSH works: `ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422`
- [ ] DNS failover AdGuard reachable: http://192.168.10.10:3000
- [ ] AdGuard sync working (check `docker logs adguardhome-sync --tail 5`)
- [ ] External URLs working (https://xtrm-lab.org)
**Services checklist:**
- [ ] Traefik reverse proxy (https://xtrm-lab.org)
- [ ] Authentik SSO (https://auth.xtrm-lab.org)
- [ ] Gitea (https://git.xtrm-lab.org)
- [ ] Uptime Kuma (https://uptime.xtrm-lab.org)
- [ ] Vaultwarden (https://vault.xtrm-lab.org)
- [ ] Plex (https://plex.xtrm-lab.org)
**Backup:**
- [ ] Verify Rclone config still present: `rclone listremotes` (should show `drive:`)
- [ ] Test flash backup: trigger manual backup from WebGUI or User Scripts
- [ ] Verify cron schedule for flash backup is active
---
### Step 6: Prevention
After successful migration:
1. **Enable Unraid Connect** (if not already) for automated cloud flash backup:
- Settings → Management Access → Unraid Connect
- Sign in with your unraid.net account
- Enable Flash Backup
2. **Verify Rclone cron** is scheduled:
```bash
# Check user scripts plugin for flash backup schedule
ls /boot/config/plugins/user.scripts/scripts/
```
3. **Keep a spare USB drive** prepared with a fresh Unraid install - makes future recovery faster
4. **Test backup restoration** periodically - don't wait for a failure to discover your backup is incomplete
---
## References
- [Unraid Docs: Changing the Flash Device](https://docs.unraid.net/unraid-os/system-administration/maintain-and-update/changing-the-flash-device/)
- [Unraid Docs: Licensing FAQ](https://docs.unraid.net/unraid-os/troubleshooting/licensing-faq/)
- Internal: `docs/02-SERVICES-CRITICAL.md` (startup order)
---
## Resolution
*Update this section when migration is complete:*
- **Date resolved:**
- **New USB drive:**
- **License transferred:** Yes/No
- **Services verified:** Yes/No
- **Backup reconfigured:** Yes/No

View File

@@ -0,0 +1,91 @@
# Incident: Disk1 Hardware Failure (Clicking / SATA Link Failure)
**Date:** 2026-02-20
**Severity:** P2 - Degraded (no redundancy)
**Status:** Open — awaiting replacement drive (motherboard replaced, NVMe cache pool added Feb 24)
**Affected:** XTRM-U (Unraid NAS) — disk1 (data drive)
---
## Summary
disk1 (10TB HGST Ultrastar HUH721010ALE601, serial `2TKK3K1D`) has physically failed. The drive dropped off the SATA bus on Feb 18 at 19:15 and is now exhibiting clicking (head failure). The Unraid md array is running in **degraded/emulated mode**, reconstructing disk1 data from parity on the fly. All data is intact but there is **zero redundancy**.
---
## Timeline
| When | What |
|------|------|
| Feb 18 ~19:15 | `ata5: qc timeout` → multiple hard/soft resets → `reset failed, giving up``ata5.00: disable device` |
| Feb 18 19:17 | `super.dat` updated — md array marked disk1 as `DISK_DSBL` (213 errors) |
| Feb 20 13:14 | Investigation started. `sdc` completely absent from `/dev/`. ZFS pool `disk1` running on emulated `md1p1` with 0 errors |
| Feb 20 ~13:30 | Server rebooted, disk moved to new SATA port (ata5 → ata6). Same failure: `ata6: reset failed, giving up`. Clicking noise confirmed |
| Feb 24 | Motherboard replaced. Dead drive confirmed still dead on new hardware. New SATA port assignment. Drive is mechanically failed (clicking heads) |
| Feb 24 | New cache pool created: 3x Samsung 990 EVO Plus 1TB NVMe, ZFS RAIDZ1. Docker migrated from HDD loopback to NVMe ZFS |
## Drive Details
| Field | Value |
|-------|-------|
| Model | HUH721010ALE601 (HGST/WD Ultrastar He10) |
| Serial | 2TKK3K1D |
| Capacity | 10TB (9766436812 sectors) |
| Array slot | disk1 (slot 1) |
| Filesystem | ZFS (on md1p1) |
| Last known device | sdc |
| Accumulated md errors | 213 |
## Current State
- **Array**: STARTED, degraded — disk1 emulated from parity (`sdb`)
- **ZFS pool `disk1`**: ONLINE, 0 errors, mounted on `md1p1` (parity reconstruction)
- **Parity drive** (`sdb`, serial `7PHBNYZC`): DISK_OK, 0 errors
- **All services**: Running normally (Docker containers, VMs)
- **Risk**: If parity drive fails, data is **unrecoverable**
## Diagnosis
- Drive fails on multiple SATA ports → not a port/cable issue
- Clicking noise on boot → mechanical head failure
- dmesg shows link responds but device never becomes ready → drive electronics partially functional, platters/heads dead
- Drive is beyond DIY repair
## Root Cause
Mechanical failure of the hard drive (clicking = head crash or seized actuator). Not related to cache drive migration that happened around the same time — confirmed by syslog showing clean SATA link failure.
---
## Recovery Plan
### Step 1: Get Replacement Drive
- Must be 10TB or larger
- Check WD warranty: serial `HUH721010ALE601_2TKK3K1D` at https://support-en.wd.com/app/warrantycheck
- Any 3.5" SATA drive works (doesn't need to match model)
### Step 2: Install & Rebuild
1. Power off the server
2. Remove dead drive, install replacement in any SATA port
3. Boot Unraid
4. Go to **Main** → click on **Disk 1** (will show as "Not installed" or unmapped)
5. Stop the array
6. Assign the new drive to the **Disk 1** slot
7. Start the array — Unraid will prompt to **rebuild** from parity
8. Rebuild will take many hours for 10TB — do NOT interrupt
### Step 3: Post-Rebuild
1. Verify ZFS pool `disk1` is healthy: `zpool status disk1`
2. Run parity check from Unraid UI
3. Run SMART extended test on new drive: `smartctl -t long /dev/sdX`
4. Verify all ZFS datasets are intact
---
## Notes
- Server is safe to run in degraded mode indefinitely, just without parity protection
- Avoid heavy writes if possible to reduce risk to parity drive
- New cache pool (3x Samsung 990 EVO Plus 1TB, ZFS RAIDZ1) now hosts all Docker containers
- Old docker.img loopback deleted from disk1 (200GB freed)
- Since disk1 uses ZFS on md, the rebuild reconstructs the raw block device — ZFS doesn't need any separate repair

View File

@@ -0,0 +1,110 @@
# WIP: Dedicated Console Port on ether5
**Status:** Pending consideration
**Created:** 2026-01-31
**Purpose:** Emergency management access independent of VLAN configuration
---
## Rationale
If VLAN or bridge configuration breaks, having a dedicated port with static IP provides guaranteed router access without relying on the main network setup.
---
## Current State
| Port | Current Use | PVID |
|------|-------------|------|
| ether5 | Unraid eth2 (bond member) | 10 |
---
## Proposed Configuration
### Remove ether5 from Bridge
```routeros
# Backup first
/system backup save name=pre-console-port
# Remove from bridge
/interface bridge port remove [find interface=ether5]
```
### Assign Static IP
```routeros
# Isolated subnet - not used by any VLAN
/ip address add address=192.168.99.1/24 interface=ether5 comment="Console Port - Emergency Access"
```
### Firewall Rule
```routeros
# Allow all management traffic from console port
/ip firewall filter add chain=input action=accept in-interface=ether5 \
comment="Console Port - Allow All" place-before=0
```
---
## Access Instructions
1. Connect laptop directly to **ether5** (rightmost port on hAP ax³)
2. Configure laptop with static IP:
- IP: `192.168.99.2`
- Netmask: `255.255.255.0`
- Gateway: `192.168.99.1`
3. Access router:
- **WinBox:** 192.168.99.1:8291
- **SSH:** `ssh -p 2222 xtrm@192.168.99.1`
- **WebFig:** http://192.168.99.1
---
## Impact Assessment
### Pros
- Always-available management access
- Independent of bridge/VLAN state
- Works even if filtering misconfigured
### Cons
- Loses one port from bridge (ether5)
- Unraid bonding reduced to single link (ether4 only)
- Physical security concern (anyone plugging in gets router access)
---
## Alternatives
### Option A: Use ether5 (Current Proposal)
- Simple, dedicated port
- Sacrifices Unraid bond member
### Option B: Use ether2 (CAP XL ac port)
- CAP currently on ether2
- Would need to move CAP to switch port
- More complex but preserves Unraid bond
### Option C: Separate VLAN for Management
- Keep ether5 in bridge
- Create untagged management VLAN on ether5
- More complex but keeps port in bridge
---
## Decision
- [ ] Implement Option A (ether5 dedicated)
- [ ] Implement Option B (move CAP)
- [ ] Implement Option C (management VLAN)
- [ ] Defer - not needed
---
**Notes:**
- Consider physical labeling of port if implemented
- Document in network map
- Keep emergency access instructions printed/offline

View File

@@ -104,7 +104,7 @@ pipeline:
when:
path: configs/xtrm-n5/**
commands:
- ssh root@192.168.31.2 "cd /path && docker compose up -d"
- ssh root@192.168.10.20 "cd /path && docker compose up -d"
secrets: [ssh_key]
deploy-n1:

View File

@@ -0,0 +1,120 @@
# Home Assistant Setup
**Status:** IN PROGRESS
**Priority:** High
**Started:** 2026-02-07
## Overview
Home Assistant OS (HAOS) running as a libvirt VM on Unraid, with custom dashboards, themes, and smart home integrations.
## Infrastructure
| Component | Detail |
|-----------|--------|
| VM | HAOS on libvirt (Unraid host) |
| IP | 192.168.10.50 (VLAN 10 — Management) |
| Access | Web UI at `http://192.168.10.50:8123` |
| VM Management | `virsh qemu-agent-command "Home Assistant"` from Unraid |
| Container | `homeassistant` Docker container inside HAOS |
## Completed
### Integrations
| Integration | Type | Devices | Notes |
|-------------|------|---------|-------|
| Gree AC (manual) | Custom component (`gree_manual`) | 1 AC unit | Cross-VLAN via L3 unicast; generic key `a3K8Bx%2r8Y7#xDh` |
| Xiaomi Miot | HACS integration (`xiaomi_miot`) | 11 devices | 2FA verification required; BLE sensors work via cloud |
| Tuya / Smart Life | Built-in | Smart Curtain, switches, lights | Paired via Smart Life QR code |
| Roborock | Via Xiaomi Miot | S7 Pro Ultra | On 192.168.31.x (Xiaomi router subnet) |
| Bosch Home Connect | Built-in (`home_connect`) | Oven, Washing Machine | OAuth2 via developer.home-connect.com |
**Xiaomi devices discovered:**
- 4x Miaomiaoce BLE temp/humidity sensors (Living Room, Kitchen, Boys Room, Bedroom)
- 2x Air Purifiers (Living Room — zhimi.mc1, Boys Room — cpa4)
- 1x Air Purifier 4 Compact (on VLAN 30)
- 1x Humidifier (Living Room — deerma.jsq2w)
- 1x Roborock S7 Pro Ultra
- 1x Xiaomi Router
- 1x Mi Smart Home Hub
**Bosch Home Connect devices:**
- Bosch Oven HRG7784B1 — temperature, door state, programs, child lock, remote control
- Bosch Washing Machine WGB24400BY — programs, progress, spin speed, temperature, remaining time, door state, child lock
### Theme — visionOS
| File | Path (inside HA) | Source |
|------|-------------------|--------|
| visionOS theme | `/config/themes/visionos.yaml` | [homeassistant-visionos-theme](https://github.com/Nezz/homeassistant-visionos-theme) |
| Liquid Glass theme | `/config/themes/liquid_glass.yaml` | Same repo |
| card-mod.js (v4.2.0) | `/config/www/card-mod.js` | Enables backdrop-filter CSS effects |
| Mushroom Cards (v5.0.10) | `/config/www/mushroom.js` | Clean card collection for dashboards |
- Both JS files registered as Lovelace resources via websocket API (`lovelace/resources/create`)
- visionOS set as default theme via startup automation in `automations.yaml`
### Dashboards
Two custom Lovelace dashboards (not the default Overview):
| Dashboard | URL Path | Columns | Optimized For |
|-----------|----------|---------|---------------|
| Mobile | `/dash-mobile` | 2 | Phone screens |
| Desktop | `/dash-desktop` | 4 | Desktop/tablet |
Both use **Sections** view type with **Mushroom Cards**. Created via HA websocket API (`lovelace/dashboards/create` + `lovelace/config/save`).
**Sections on both dashboards:**
1. **Header** — Title card + chips (weather, outside temp, vacuum status, phone battery)
2. **Climate Control** — Living Room thermostat, Kitchen thermostat, Gree AC
3. **Temperatures** — 4 indoor Miaomiaoce BLE sensors + outside temp/humidity
4. **Radiators** — Living Room, Main Bedroom, Girls Room
5. **Bosch Appliances** — Oven (status, temp, door) + Washer (status, time left, progress)
6. **Lights** — Living Room, Dining Room, Bedroom LED strip, Picture Frame lamp
7. **Switches** — Entrance (x2), Bathroom (x2), Kids Bathroom (x2), Boys Lamp
8. **Curtain & Vacuum** — Smart Curtain, Roborock S7, Vacuum battery
Desktop dashboard has expanded Bosch sections with program selectors, child lock, spin speed, wash temperature, and remote control status.
### Startup Automation
```yaml
# /config/automations.yaml
- id: set_visionos_theme
alias: "Set visionOS Theme on Startup"
trigger:
- platform: homeassistant
event: start
action:
- service: frontend.set_theme
data:
name: visionos
```
## Known Issues
| Issue | Detail | Workaround |
|-------|--------|------------|
| Xiaomi devices on 192.168.31.x unreachable | Air purifiers, humidifier, Roborock on Xiaomi router subnet | Switch to cloud-only polling in xiaomi_miot config |
| Cross-VLAN broadcast discovery | UDP broadcasts don't cross VLANs | Use manual IP config (e.g., `gree_manual` component) |
| `/config/www/` not served after creation | HA needs full core restart to detect new `www` directory | `ha core restart` from HAOS VM |
| `automations.yaml` syntax | Appending to `[]` creates invalid YAML | Always overwrite file, never append after `[]` |
## Pending Work
- [ ] Switch Xiaomi air purifiers/humidifier to cloud-only mode for reliable polling
- [ ] Add more dashboard sections as new devices are added
- [ ] Evaluate HACS frontend cards (mini-graph-card, apexcharts-card) for richer data display
- [ ] Set up HA mobile app companion for phone notifications and presence detection
## Technical Notes
- **File transfer to HA:** base64 encode → virsh guest-exec → docker exec -i tee (chunk at 50KB for large files)
- **HAOS minimal toolset:** Only `/usr/bin/curl`, `/sbin/ip` available — no wget/nc/python3/which
- **Dashboard URL paths:** Must contain a hyphen (e.g., `dash-mobile`, not `mobile`)
- **Lovelace resources:** Must be registered via websocket API, not by writing storage files directly
- **HA API token:** Generated JWT with HMAC-SHA256 from refresh token's `jwt_key` in `/config/.storage/auth`
- **Home Connect OAuth2:** Register app at developer.home-connect.com, use redirect URI `https://my.home-assistant.io/redirect/oauth`, disable "One Time Token Mode" (breaks HA token refresh)

View File

@@ -0,0 +1,255 @@
# One-Key KVM: Mac ↔ Nobara
**Status:** WIP - Nobara → Mac working, Mac → Nobara needs work
**Hardware:** Dell U3821DW, MX Keys S, MX Master 4 for Mac
**Updated:** 2026-02-01
## Overview
Software KVM solution to switch the Dell U3821DW ultrawide monitor and Logitech MX peripherals between Mac (MacBook Air M3) and Nobara Linux using DDC/CI and HID++ commands.
## Hardware Mapping
### Monitor Inputs
| Input | Code | Port | Computer |
|-------|------|------|----------|
| USB-C | 27 | USB-C | Mac |
| HDMI 2 | 18 | HDMI 2 | Nobara |
### Peripheral Hosts (Logi Bolt)
| Host | Index (HID++) | Connection | Computer |
|------|---------------|------------|----------|
| 1 | 0x00 | Bolt #1 | MacBook Air (Bluetooth?) |
| 2 | 0x01 | Bolt #1 | Nobara (xtrm-pc) |
| 3 | 0x02 | Bolt #2 | MacBook Air (via monitor hub) |
### Devices
- **Monitor:** Dell U3821DW (38" Ultrawide, DDC/CI enabled)
- **Keyboard:** Logitech MX Keys S (Easy-Switch capable)
- **Mouse:** Logitech MX Master 4 for Mac (Easy-Switch capable)
- **Receiver:** Logi Bolt USB (PID: 046d:c548)
## Nobara Setup
### 1. Install dependencies
```bash
sudo dnf install ddcutil
```
### 2. Add user to i2c group (requires reboot)
```bash
sudo usermod -aG i2c $USER
```
### 3. Install hidapitester
```bash
curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-linux-amd64.zip -o /tmp/hidapitester.zip
unzip -o /tmp/hidapitester.zip -d ~/bin/
chmod +x ~/bin/hidapitester
```
### 4. Udev rule for non-root HID access
```bash
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c548", MODE="0666"' | \
sudo tee /etc/udev/rules.d/99-logitech-bolt.rules
sudo udevadm control --reload-rules && sudo udevadm trigger
```
### 5. Reboot
```bash
sudo reboot
```
### 6. Verify setup
```bash
# Check i2c group membership
groups | grep i2c
# Check monitor detection
ddcutil detect
# Check Bolt receiver
~/bin/hidapitester --vidpid 046d/c548 --list-detail
```
### 7. Copy script and set up shortcut
```bash
# Copy script
mkdir -p ~/scripts
cp /path/to/xtrm/infrastructure/scripts/kvm/to_mac.sh ~/scripts/
chmod +x ~/scripts/to_mac.sh
# Set up keyboard shortcut (Ctrl+Shift+Up)
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \
"$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings | sed "s/]$/, '\/org\/gnome\/settings-daemon\/plugins\/media-keys\/custom-keybindings\/custom-kvm\/']/")"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ name 'KVM Switch to Mac'
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ command '/home/jazzymc/scripts/to_mac.sh'
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom-kvm/ binding '<Shift><Control>Up'
```
## Mac Setup
### 1. Install dependencies
```bash
# Install m1ddc (DDC control for Apple Silicon)
brew install m1ddc
# Install hidapitester
curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-macos-arm64.zip -o /tmp/hidapitester.zip
unzip -o /tmp/hidapitester.zip -d ~/bin/
chmod +x ~/bin/hidapitester
```
### 2. Copy script
```bash
mkdir -p ~/scripts
cp /path/to/xtrm/infrastructure/scripts/kvm/to_nobara.sh ~/scripts/
chmod +x ~/scripts/to_nobara.sh
```
### 3. Set up keyboard shortcut
TODO: Configure via Logi Options+ or macOS Shortcuts app
## Scripts
### Switch to Mac (Run on Nobara) - WORKING
**Location:** `~/scripts/to_mac.sh`
```bash
#!/bin/bash
# KVM Switch: Nobara → Mac
# Switches monitor to USB-C and peripherals to Host 3 (Mac)
#
# Host mapping (0-indexed in HID++):
# Host 1 (0x01): Nobara (xtrm-pc)
# Host 3 (0x02): Mac (Kaloyan's MacBook Air)
#
# HID++ command format: ReportID, DeviceIdx, FeatureIdx, Function, HostIdx, 0, 0
# Mouse: device 0x03, feature 0x0E (CHANGE_HOST)
# Keyboard: device 0x02, feature 0x0A (CHANGE_HOST)
# Function 0x10 = setCurrentHost (function 0 << 4)
HIDAPITESTER="$HOME/bin/hidapitester"
echo "Switching to Mac..."
# 1. Switch Mouse (MX Master 4) to Host 3 (Mac)
echo " Mouse -> Mac..."
"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \
--open --length 7 --send-output 0x10,0x03,0x0E,0x10,0x02,0x00,0x00 2>/dev/null || \
echo " [WARN] Mouse switch failed"
# 2. Switch Keyboard (MX Keys S) to Host 3 (Mac)
echo " Keyboard -> Mac..."
"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \
--open --length 7 --send-output 0x10,0x02,0x0A,0x10,0x02,0x00,0x00 2>/dev/null || \
echo " [WARN] Keyboard switch failed"
# 3. Switch Monitor to USB-C (Dell U3821DW input code: 27)
echo " Monitor -> USB-C..."
if command -v ddcutil &>/dev/null; then
ddcutil setvcp 60 27 2>/dev/null || \
echo " [WARN] Monitor switch failed (DDC/CI disabled or permissions issue)"
else
echo " [WARN] ddcutil not installed"
fi
echo "Done!"
```
### Switch to Nobara (Run on Mac) - NEEDS WORK
**Location:** `~/scripts/to_nobara.sh`
```bash
#!/bin/bash
# KVM Switch: Mac → Nobara
# TODO: Needs correct HID++ feature indices for Mac's Bolt receiver
echo "Switching to Nobara..."
# Switch Monitor to HDMI 2
m1ddc set input 18
# TODO: Find correct HID++ commands for Mac
# The feature indices may differ on Mac's Bolt receiver
# Use: hidapitester --vidpid 046d/c548 --list-detail
# Then use solaar (if available) or HID++ protocol to find feature indices
echo "Done!"
```
## HID++ Command Reference
### Command Format
| Byte | Purpose | Description |
|------|---------|-------------|
| 0 | Report ID | 0x10 (short report) |
| 1 | Device Index | Device slot on Bolt receiver (0x01-0x06) |
| 2 | Feature Index | **Device-specific** - must be discovered per device |
| 3 | Function | 0x10 = setCurrentHost (function 0 << 4) |
| 4 | Host Index | 0x00=Host1, 0x01=Host2, 0x02=Host3 |
| 5-6 | Padding | 0x00, 0x00 |
### Current Device Configuration (Nobara Bolt Receiver)
| Device | Solaar Index | HID++ Device Index | CHANGE_HOST Feature Index |
|--------|--------------|-------------------|---------------------------|
| MX Keys S | 2 | 0x02 | 0x0A (10) |
| MX Master 4 for Mac | 3 | 0x03 | 0x0E (14) |
### Finding Feature Indices
The CHANGE_HOST feature index varies per device. To find it:
```bash
# On Linux with solaar
solaar show <device_number> 2>&1 | strings | grep "CHANGE HOST"
# Look for: "14: CHANGE HOST {1814}" - the number before the colon is the feature index
```
## DDC Input Codes (Dell U3821DW)
| Input | Code | Hex |
|-------|------|-----|
| DisplayPort 1 | 15 | 0x0F |
| DisplayPort 2 | 16 | 0x10 |
| HDMI 1 | 17 | 0x11 |
| HDMI 2 | 18 | 0x12 |
| USB-C | 27 | 0x1B |
## Troubleshooting
### Monitor doesn't switch
- **DDC/CI disabled:** Monitor Menu → Others → DDC/CI → On
- **Linux permissions:** Ensure user in `i2c` group, reboot after adding
- **Verify:** `ddcutil detect` should show monitor
### Peripherals don't switch
- **Wrong feature index:** Feature indices are device-specific and must be discovered
- **Device offline:** Move mouse/press key to wake device before switching
- **Wrong device index:** Check `solaar show` for correct device numbers
### Solaar vs hidapitester
- `solaar config` doesn't reliably switch hosts on some devices
- Use `hidapitester` with correct HID++ commands instead
- Solaar is useful for discovering device info and feature indices
## Files Location
**Nobara:**
- `~/scripts/to_mac.sh` - Switch to Mac (working)
- `~/bin/hidapitester` - HID control tool
**Mac:**
- `~/scripts/to_nobara.sh` - Switch to Nobara (needs work)
- `~/bin/hidapitester` - HID control tool
**Repository:**
- `infrastructure/scripts/kvm/to_mac.sh`
- `infrastructure/scripts/kvm/to_nobara.sh`
## TODO
- [x] Nobara → Mac switching (working)
- [x] Set up keyboard shortcut on Nobara (Ctrl+Shift+Up)
- [ ] **Mac → Nobara switching** - needs correct HID++ feature indices for Mac's Bolt receiver
- [ ] Set up keyboard shortcut on Mac
- [ ] Test monitor switching from Mac side

View File

@@ -8,9 +8,9 @@ Planned changes, evaluations, and ideas not yet implemented.
| Status | Meaning |
|--------|---------|
| 📋 PLANNED | Approved, waiting for resources/time |
| 🔬 EVALUATING | Under investigation/research |
| 💡 IDEA | Concept, needs further definition |
| PLANNED | Approved, waiting for resources/time |
| EVALUATING | Under investigation/research |
| IDEA | Concept, needs further definition |
---
@@ -20,24 +20,30 @@ Planned changes, evaluations, and ideas not yet implemented.
| Document | Status | Priority | Description |
|----------|--------|----------|-------------|
| [UPGRADE-2026-HARDWARE.md](UPGRADE-2026-HARDWARE.md) | 📋 PLANNED | High | N5 Air + N100 server migration |
| [GITOPS-CONTAINERS.md](GITOPS-CONTAINERS.md) | 💡 IDEA | Medium | Container config in Git with CI/CD |
| [UPGRADE-2026-HARDWARE.md](UPGRADE-2026-HARDWARE.md) | PLANNED | High | N5 Air + N100 server migration |
| [GITOPS-CONTAINERS.md](GITOPS-CONTAINERS.md) | IDEA | Medium | Container config in Git with CI/CD |
### Network
| Document | Status | Priority | Description |
|----------|--------|----------|-------------|
| [VLAN-SEGMENTATION.md](VLAN-SEGMENTATION.md) | 📋 PLANNED | Medium | Network segmentation (Secure/IoT/Kids/Guest) |
| [FOSSORIAL-TUNNELS.md](FOSSORIAL-TUNNELS.md) | 💡 IDEA | Low | Self-hosted Pangolin/Gerbil tunnels |
| [CONSOLE-PORT-ETHER5.md](CONSOLE-PORT-ETHER5.md) | EVALUATING | Low | Console/serial port on HAP1 ether5 |
| [KVM-SWITCH-MAC-NOBARA.md](KVM-SWITCH-MAC-NOBARA.md) | EVALUATING | Medium | Software KVM for Mac/Nobara switching |
### Smart Home
| Document | Status | Priority | Description |
|----------|--------|----------|-------------|
| [HOME-ASSISTANT-SETUP.md](HOME-ASSISTANT-SETUP.md) | IN PROGRESS | High | HAOS VM, dashboards, themes, integrations |
### Applications
| Document | Status | Priority | Description |
|----------|--------|----------|-------------|
| [REMOTE-GAMING.md](REMOTE-GAMING.md) | 🔬 EVALUATING | Low | Sunshine + Moonlight game streaming |
| [REMOTE-GAMING.md](REMOTE-GAMING.md) | EVALUATING | Low | Sunshine + Moonlight game streaming |
---
## Completed Items
Move to main docs or archive when done. Update `05-CHANGELOG.md` with major completions.
Move to main docs or archive when done. Update `CHANGELOG.md` with major completions.

92
scripts/kvm/README.md Normal file
View File

@@ -0,0 +1,92 @@
# KVM Switch: Mac ↔ Nobara
## Hardware
- **Monitor:** Dell U3821DW (USB-C to Mac, HDMI 2 to Nobara)
- **Keyboard:** Logitech MX Keys S
- **Mouse:** Logitech MX Master 4
- **Bolt #1:** Connected to Nobara (Channel 2)
- **Bolt #2:** Connected to Mac via monitor USB hub (Channel 3)
## Switching Behavior
| Direction | Monitor | Peripherals |
|-----------|---------|-------------|
| Nobara → Mac | Auto (DDC) | Auto (HID++) |
| Mac → Nobara | Auto (DDC) | Manual Easy-Switch |
## Channel Setup
| Channel | Connection | Computer |
|---------|------------|----------|
| 2 | Bolt #1 | Nobara |
| 3 | Bolt #2 | Mac |
---
## Nobara Setup
### 1. Install dependencies
```bash
sudo dnf install ddcutil
sudo usermod -aG i2c $USER
# Reboot required for i2c group
```
### 2. Install hidapitester
```bash
mkdir -p ~/bin
curl -sL https://github.com/todbot/hidapitester/releases/latest/download/hidapitester-linux-amd64.zip -o /tmp/hidapitester.zip
unzip -o /tmp/hidapitester.zip -d ~/bin/
chmod +x ~/bin/hidapitester
```
### 3. Udev rule for Bolt
```bash
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c548", MODE="0666"' | sudo tee /etc/udev/rules.d/99-logitech-bolt.rules
sudo udevadm control --reload-rules && sudo udevadm trigger
```
### 4. Copy script
```bash
mkdir -p ~/scripts
cp to_mac.sh ~/scripts/
chmod +x ~/scripts/to_mac.sh
```
### 5. Keyboard shortcut (Ctrl+Shift+Up)
Settings → Keyboard → Custom Shortcuts:
- Name: KVM to Mac
- Command: /home/USER/scripts/to_mac.sh
- Shortcut: Ctrl+Shift+Up
---
## Mac Setup
### 1. Install m1ddc
```bash
brew install m1ddc
```
### 2. Copy script
```bash
mkdir -p ~/scripts
cp to_nobara.sh ~/scripts/
chmod +x ~/scripts/to_nobara.sh
```
### 3. Usage
```bash
~/scripts/to_nobara.sh
# Then press Easy-Switch on keyboard/mouse to Channel 2
```
---
## DDC Input Codes (Dell U3821DW)
| Input | Code |
|-------|------|
| HDMI 2 | 18 |
| USB-C | 27 |

38
scripts/kvm/to_mac.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
# KVM Switch: Nobara → Mac
# Switches monitor to USB-C and peripherals to Host 3 (Mac)
#
# Device mapping:
# Keyboard: device 0x02, feature 0x0A
# Mouse: device 0x03, feature 0x0E
#
# Host mapping:
# Host 2 (0x01): Nobara
# Host 3 (0x02): Mac
HIDAPITESTER="$HOME/bin/hidapitester"
echo "Switching to Mac..."
# 1. Switch Mouse to Host 3 (Mac)
echo " Mouse -> Mac..."
"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \
--open --length 7 --send-output 0x10,0x03,0x0E,0x10,0x02,0x00,0x00 2>/dev/null || \
echo " [WARN] Mouse switch failed"
# 2. Switch Keyboard to Host 3 (Mac)
echo " Keyboard -> Mac..."
"$HIDAPITESTER" --vidpid 046d/c548 --usage 0x0001 --usagePage 0xff00 \
--open --length 7 --send-output 0x10,0x02,0x0A,0x10,0x02,0x00,0x00 2>/dev/null || \
echo " [WARN] Keyboard switch failed"
# 3. Switch Monitor to USB-C
echo " Monitor -> USB-C..."
if command -v ddcutil &>/dev/null; then
ddcutil setvcp 60 27 2>/dev/null || \
echo " [WARN] Monitor switch failed"
else
echo " [WARN] ddcutil not installed"
fi
echo "Done!"

8
scripts/kvm/to_nobara.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
# KVM Switch: Mac → Nobara
# Switches monitor to HDMI 2
# Peripherals: manually press Easy-Switch to Channel 2
echo "Switching to Nobara..."
echo " Monitor -> HDMI 2..."
m1ddc set input 18 2>/dev/null && echo "Done! Press Easy-Switch for Channel 2" || echo "Monitor switch failed"

66
scripts/vw-sync.sh Executable file
View File

@@ -0,0 +1,66 @@
#!/bin/bash
# Vaultwarden Sync: Unraid → MikroTik (cold standby)
# Run this from your Mac (must have VPN/network access to both devices)
#
# Usage: ./vw-sync.sh
# Syncs the Vaultwarden database from Unraid to MikroTik standby instance.
# The MikroTik container must be STOPPED during sync.
set -euo pipefail
UNRAID_SSH="ssh -i ~/.ssh/id_ed25519_unraid root@192.168.10.20 -p 422"
MIKROTIK_SSH="ssh -i ~/.ssh/mikrotik_key -p 2222 xtrm@192.168.10.1"
UNRAID_VW_PATH="/mnt/user/appdata/vaultwarden"
MIKROTIK_USB_PATH="usb1/vaultwarden/data"
HTTP_PORT=8888
echo "=== Vaultwarden Sync: Unraid → MikroTik ==="
echo ""
# 1. Check MikroTik container is stopped
echo "[1/5] Checking MikroTik Vaultwarden container status..."
STATUS=$($MIKROTIK_SSH ':foreach c in=[/container/find where name~"server"] do={:put [/container/get $c status]}' 2>/dev/null || echo "unknown")
if [ "$STATUS" = "running" ]; then
echo " Container is running. Stopping it..."
$MIKROTIK_SSH '/container/stop [find where name~"server"]'
sleep 5
fi
echo " Container is stopped."
# 2. Start temporary HTTP server on Unraid
echo "[2/5] Starting temp HTTP server on Unraid (port $HTTP_PORT)..."
$UNRAID_SSH "cd $UNRAID_VW_PATH && php -S 0.0.0.0:$HTTP_PORT &>/dev/null &"
sleep 2
# Verify it's responding
if ! $UNRAID_SSH "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:$HTTP_PORT/db.sqlite3" 2>/dev/null | grep -q "200"; then
echo " ERROR: HTTP server not responding. Aborting."
$UNRAID_SSH "pkill -f 'php -S' 2>/dev/null" || true
exit 1
fi
echo " HTTP server ready."
# 3. Fetch files to MikroTik
echo "[3/5] Syncing database to MikroTik..."
$MIKROTIK_SSH "/tool/fetch url=\"http://192.168.10.20:$HTTP_PORT/db.sqlite3\" dst-path=\"$MIKROTIK_USB_PATH/db.sqlite3\""
echo ""
echo "[4/5] Syncing RSA key and config..."
$MIKROTIK_SSH "/tool/fetch url=\"http://192.168.10.20:$HTTP_PORT/rsa_key.pem\" dst-path=\"$MIKROTIK_USB_PATH/rsa_key.pem\""
$MIKROTIK_SSH "/tool/fetch url=\"http://192.168.10.20:$HTTP_PORT/config.json\" dst-path=\"$MIKROTIK_USB_PATH/config.json\""
echo ""
# 5. Cleanup
echo "[5/5] Stopping HTTP server on Unraid..."
$UNRAID_SSH "pkill -f 'php -S' 2>/dev/null" || true
echo ""
echo "=== Sync complete! ==="
echo ""
echo "To START the standby Vaultwarden:"
echo " $MIKROTIK_SSH '/container/start [find where name~\"server\"]'"
echo ""
echo "To STOP it after maintenance:"
echo " $MIKROTIK_SSH '/container/stop [find where name~\"server\"]'"
echo ""
echo "Access URL: http://192.168.10.1:4743"