Skip to content

Fixed Homelab Deployment - 2026-01-24

Window: ~4 hours while family is away Goal: Internet working when family returns Backup plan: Beryl AX if things go wrong


Current State

Component Status

| Mini PC | Bare metal | | NAS | Bare metal | | Physical cabling | Not done | | ISP Modem | Bridge mode | | TP-Link AX3000 | Currently doing DHCP/Gateway/AP | | VPS/Headscale | Working | | Beryl AX | Available as backup |

Strategy

CURRENT:
[ISP Modem] → [AX3000 as Router+AP] → [Devices]
                    (keeps working while we set up)

TARGET:
[ISP Modem] → [Mini PC/OPNsense] → [Switch] → [AX3000 as AP only] → [Devices]

Critical moment: The cutover from AX3000-as-router to OPNsense. We do this LAST, when everything else is ready.


Pre-Deployment Checklist (Do BEFORE Jan 24)

Downloads (do on MacBook, save to USB)

Hardware prep - Mini PC

  • [ ] Find/label all Ethernet cables needed
  • [ ] Locate HDMI cable + USB keyboard for Mini PC install
  • [ ] Verify Mini PC boots (enter BIOS, check dual NIC visible)
  • [ ] Verify Beryl AX works (test as backup router)
  • [ ] Charge phone (for tethering if things go wrong)

Hardware prep - NAS (do BEFORE Jan 24)

  • [ ] Open NAS case
  • [ ] Install SSD (240GB Lexar) - boot drive
  • [ ] Install WD Purple 2TB - Frigate recordings
  • [ ] Install WD Red Plus 8TB - media/data
  • [ ] Verify all drives detected in BIOS
  • [ ] Close case, connect power + Ethernet cable ready

Hardware prep - Cameras (do BEFORE Jan 24)

  • [ ] Unbox cameras, verify contents (mounts, screws included)
  • [ ] Plan exact mounting locations (front door, back yard)
  • [ ] Measure cable runs (should be <15m each)
  • [ ] Prepare PoE cables (2x for Reolink cameras)
  • [ ] Prepare drill, bits, screwdriver, ladder
  • [ ] Set up Tapo C110 on phone app (get credentials ready)
  • [ ] Note camera default credentials (printed on camera or box)

Network planning

  • [ ] Decide IP scheme:
  • OPNsense LAN: 192.168.1.1
  • DHCP range: 192.168.1.100-199
  • Docker VM: 192.168.1.10
  • NAS: 192.168.1.12
  • Camera front: 192.168.1.101 (PoE)
  • Camera back: 192.168.1.102 (PoE)
  • Camera indoor: 192.168.1.103 (WiFi)
  • [ ] Note current AX3000 settings (for reference)
  • [ ] Note ISP modem settings (bridge mode config)

Note: Cameras on main LAN for Day 1. Move to VLAN 10 (192.168.10.x) later for isolation.

Credentials ready

  • [ ] Proxmox root password (write down)
  • [ ] OPNsense admin password (write down)
  • [ ] Tailscale auth key from Headscale (generate fresh)

Deployment Timeline

T-0:00 - Family Leaves, Start Clock

Verify everything ready

  • USB boot drive with Proxmox + OPNsense ISOs
  • Keyboard, HDMI cable
  • Ethernet cables
  • Phone charged (backup tether)
  • Beryl AX accessible

Phase 1: Physical Layer (30-45 min)

Internet stays on AX3000 during this phase

[ ] Unbox and power on switch
[ ] Connect to management interface (if needed)
[ ] No VLAN config needed for day 1 - just use as unmanaged

1.2 Cable the network

Current (keep working):
[ISP Modem] → [AX3000 WAN port]

New cables to add:
[AX3000 LAN port] → [Switch Port 7] (trunk for AP)
[Switch Port 2] → [Mini PC NIC2/LAN]
[Switch Port 4] → [NAS] (optional, skip if NAS not ready)

Leave disconnected for now:
[ISP Modem] → [Mini PC NIC1/WAN] (connect during cutover)

1.3 Verify switch works

[ ] Plug laptop into switch
[ ] Should get IP from AX3000 DHCP
[ ] Internet works through switch

Checkpoint: Switch working, cables ready. AX3000 still routing. ~45 min elapsed.


Phase 2: Proxmox Install (30-45 min)

Internet stays on AX3000 during this phase

2.1 Boot Mini PC from USB

[ ] Connect HDMI + keyboard to Mini PC
[ ] Insert Ventoy USB
[ ] Boot, select Proxmox ISO
[ ] Run installer

2.2 Proxmox Installation Options

Target disk: 512GB SSD (entire disk)
Country/Timezone: Paraguay / America/Asuncion
Password: [your chosen password]
Email: augusto@hermosilla.me
Hostname: pve.home.local

Management Network:
- Interface: Select NIC2 (LAN side, NOT the one for WAN passthrough)
- IP: 192.168.1.5/24 (temporary, AX3000 is still .1)
- Gateway: 192.168.1.1 (AX3000)
- DNS: 192.168.1.1 (AX3000)

2.3 Post-install access

[ ] Reboot Mini PC
[ ] Remove USB drive
[ ] Access Proxmox: https://192.168.1.5:8006
[ ] Login: root / [password]
# SSH to Proxmox
ssh root@192.168.1.5

# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Join mesh
tailscale up --login-server=https://hs.cronova.dev --authkey=YOUR_KEY

Checkpoint: Proxmox accessible via web UI and/or Tailscale. ~1.5 hours elapsed.


Phase 3: OPNsense VM (1-1.5 hours)

Internet stays on AX3000 during this phase

3.1 Upload OPNsense ISO to Proxmox

[ ] Proxmox UI  local storage  ISO Images
[ ] Upload OPNsense ISO

3.2 Identify NICs in Proxmox

# SSH to Proxmox
ip link show

# Note which NIC is which:
# - NIC1 (for WAN passthrough): usually the Intel one
# - NIC2 (for LAN bridge): the other one
# Check with: lspci | grep -i net

3.3 Create OPNsense VM

VM Settings:
- VM ID: 100
- Name: opnsense
- OS: Other (FreeBSD)
- ISO: OPNsense
- Disk: 20GB on local-lvm
- CPU: 2 cores
- RAM: 2048 MB
- Network 1: vmbr0 (LAN bridge)

For WAN, choose ONE option:

Option A - PCI Passthrough (better performance):
[ ] Proxmox → Datacenter → Host → System → IOMMU enabled
[ ] Add PCI device to VM (NIC1)
[ ] Requires reboot if IOMMU wasn't enabled

Option B - Bridge (simpler for day 1):
[ ] Create vmbr1 for WAN
[ ] Attach NIC1 to vmbr1
[ ] Add vmbr1 as second network to VM

3.4 Install OPNsense

[ ] Start VM, open console
[ ] Boot from ISO
[ ] Login: installer / opnsense
[ ] Install to disk
[ ] Reboot (remove ISO from VM)

3.5 Configure OPNsense (initial)

Console menu:
1) Assign interfaces
   - WAN: vtnet1 (or passthrough NIC)
   - LAN: vtnet0

2) Set interface IP
   - LAN: 192.168.1.2/24 (NOT .1 yet - AX3000 is still .1)
   - Enable DHCP: NO (AX3000 still doing DHCP)

[ ] Access OPNsense web UI: https://192.168.1.2
[ ] Login: root / opnsense
[ ] Run wizard but skip WAN config for now

3.6 Test OPNsense routing (without cutover)

[ ] From laptop, set manual IP: 192.168.1.50
[ ] Set gateway: 192.168.1.2 (OPNsense)
[ ] Set DNS: 8.8.8.8 (temporary)
[ ] Test: ping google.com

If works  OPNsense routing is functional
If fails  Debug before cutover

Checkpoint: OPNsense VM running, tested routing works. ~3 hours elapsed.


Phase 4: The Cutover (30 min)

This is when internet goes down briefly

4.1 Prepare

[ ] Tell any family member home that internet will be down briefly
[ ] Have Beryl AX ready (just in case)
[ ] Open OPNsense console (in case web UI unreachable)

4.2 Reconfigure OPNsense for production

OPNsense Console or Web UI:

[ ] Change LAN IP: 192.168.1.2 → 192.168.1.1
[ ] Enable DHCP Server:
    - Range: 192.168.1.100 - 192.168.1.199
    - DNS: 192.168.1.1 (OPNsense Unbound)
[ ] Configure WAN: DHCP (get IP from ISP modem)

4.3 Physical cutover

1. [ ] Unplug ISP modem cable from AX3000 WAN port
2. [ ] Plug that cable into Mini PC NIC1 (WAN)
3. [ ] Wait 30 seconds for OPNsense to get WAN IP
4. [ ] On AX3000: Disable DHCP server, set to AP mode
       - Or just let devices get new IPs from OPNsense

4.4 Verify internet works

[ ] On phone: Forget WiFi, reconnect
[ ] Should get IP from OPNsense (192.168.1.1xx)
[ ] Test: Open google.com
[ ] Test: Open youtube.com

4.5 If it doesn't work - BACKUP PLAN

Option A: Debug
- Check OPNsense console for errors
- Verify WAN has IP: Interfaces → WAN
- Check firewall rules allow outbound

Option B: Rollback (5 min)
- Unplug Mini PC from ISP modem
- Plug ISP modem back into AX3000 WAN
- Internet restored (old config)
- Debug OPNsense later

Option C: Beryl AX emergency
- Follow family-emergency-internet.md
- Beryl AX becomes temporary router

Checkpoint: Internet working through OPNsense! ~3.5 hours elapsed.


Phase 5: Post-Cutover (remaining time)

Internet is working, family can come home now

These are nice-to-have, not required for day 1:

5.1 Create Docker VM (optional)

[ ] Create Ubuntu/Debian VM
    - 2 vCPU, 8GB RAM, 100GB disk
    - Network: vmbr0, static IP 192.168.1.10
[ ] Install Docker
[ ] Join Tailscale

5.2 Deploy Pi-hole (optional)

[ ] On Docker VM
[ ] Configure OPNsense to use Pi-hole as DNS
[ ] Family gets ad-blocking

5.3 Configure DHCP reservations (optional)

OPNsense → Services → DHCPv4 → LAN → Static mappings
- Docker VM: 192.168.1.10
- NAS: 192.168.1.12

Phase 6: NAS Deployment (1.5-2 hours)

Optional - only if Mini PC + OPNsense done in under 2.5 hours

Decision point after Phase 4

  • Check time remaining
  • If 1.5+ hours left AND internet stable → proceed with NAS
  • If tight on time → defer NAS to another day

6.1 Connect NAS to network

[ ] Connect NAS to Switch Port 4
[ ] Power on NAS
[ ] Move keyboard/HDMI from Mini PC to NAS

6.2 Install Debian 12

[ ] Boot from Ventoy USB, select Debian ISO
[ ] Graphical install or text install

Partitioning (SSD 240GB only - will mount HDDs manually):
- /boot: 512MB (ext4)
- swap: 4GB
- /: remaining space (ext4)

DO NOT partition the Purple or Red Plus drives during install!

Network:
- Hostname: nas
- Domain: home.local
- IP: Will get DHCP initially, set static later

User:
- Root password: [your password]
- User: augusto
- User password: [your password]

Software:
- SSH server: YES
- Standard system utilities: YES
- Desktop: NO (server only)

6.3 Post-install: Static IP

# SSH to NAS (find IP from OPNsense DHCP leases)
ssh augusto@192.168.1.1xx

# Set static IP
sudo nano /etc/network/interfaces
auto enp0s31f6  # or your interface name
iface enp0s31f6 inet static
    address 192.168.1.12
    netmask 255.255.255.0
    gateway 192.168.1.1
    dns-nameservers 192.168.1.1
# Apply (will disconnect SSH - reconnect to .12)
sudo systemctl restart networking

# Verify
ip addr show
ping google.com

6.4 Mount data drives

# Identify drives
lsblk
sudo blkid

# Create mount points
sudo mkdir -p /mnt/{purple,data}

# Format drives (CAREFUL - destructive!)
# Purple 2TB for Frigate
sudo mkfs.ext4 -L purple /dev/sdX

# Red Plus 8TB for data
sudo mkfs.ext4 -L data /dev/sdY

# Get UUIDs
sudo blkid | grep -E "purple|data"

# Add to fstab
sudo nano /etc/fstab

Add these lines:

UUID=<purple-uuid>  /mnt/purple  ext4  defaults,noatime  0  2
UUID=<data-uuid>    /mnt/data    ext4  defaults,noatime  0  2
# Mount all
sudo mount -a

# Verify
df -h

6.5 Create Frigate directory

# Create directory for Frigate recordings
sudo mkdir -p /mnt/purple/frigate
sudo chown -R 1000:1000 /mnt/purple/frigate
sudo chmod 755 /mnt/purple/frigate

6.6 Install and configure NFS

# Install NFS server
sudo apt update
sudo apt install -y nfs-kernel-server

# Create export symlink
sudo mkdir -p /srv/frigate
sudo ln -s /mnt/purple/frigate /srv/frigate

# Configure export (for Docker VM)
echo '/srv/frigate 192.168.1.10(rw,sync,no_subtree_check,no_root_squash)' | sudo tee -a /etc/exports

# Apply exports
sudo exportfs -ra

# Verify
sudo exportfs -v

# Enable and start NFS
sudo systemctl enable nfs-kernel-server
sudo systemctl start nfs-kernel-server

6.7 Test NFS from Docker VM (if created)

# SSH to Docker VM
ssh user@192.168.1.10

# Install NFS client
sudo apt update
sudo apt install -y nfs-common

# Create mount point
sudo mkdir -p /mnt/nas/frigate

# Test mount
sudo mount -t nfs 192.168.1.12:/srv/frigate /mnt/nas/frigate

# Verify
df -h /mnt/nas/frigate

# Test write
touch /mnt/nas/frigate/test.txt
rm /mnt/nas/frigate/test.txt

# Add to fstab for persistence
echo '192.168.1.12:/srv/frigate  /mnt/nas/frigate  nfs  defaults,_netdev,nofail  0  0' | sudo tee -a /etc/fstab

6.8 Join NAS to Tailscale (optional)

# On NAS
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server=https://hs.cronova.dev --authkey=YOUR_KEY

Checkpoint: NAS running, NFS exporting, Docker VM can mount. ~5-5.5 hours total.


Phase 7: Cameras + Frigate (1.5-2 hours)

Can run in PARALLEL with Phases 5-6 if friend helps with physical

This phase has two parallel workstreams:

  • You: Deploy Frigate software (needs Docker VM + NFS ready)
  • Friend: Physical camera installation (can start earlier)

Parallel Workstream Diagram

TIME    YOU (Software)                    FRIEND (Physical)
─────────────────────────────────────────────────────────────
T+0     Phase 1-4: Mini PC + OPNsense     Help with cabling
        (critical path - needs focus)      Set up PoE switch

T+3.5h  Phase 5: Docker VM ─────────────► Start camera mounting
        Phase 6: NAS + NFS                 Run PoE cables
                                          Mount front camera
                                          Mount back camera

T+5h    Phase 7: Frigate deploy ─────────► Connect cameras to PoE
        Configure cameras                  Set up WiFi camera
        Test detection                     Aim and adjust cameras

T+6h    DONE - Family can come home!

7.1 Physical Camera Installation (Friend)

Can start after PoE switch is connected to main switch (Phase 1)

[ ] Choose mounting location (under eave, protected from rain)
[ ] Mark drill holes using mount template
[ ] Drill holes, insert anchors
[ ] Run PoE cable from PoE switch location to camera
[ ] Mount camera bracket
[ ] Connect PoE cable to camera
[ ] Attach camera to bracket, adjust angle
[ ] Verify LED lights up (PoE power working)
[ ] Same process as front door
[ ] Consider sun position (avoid direct sunlight in lens)
[ ] Ensure cable is protected from weather
[ ] Position in living area (shelf, mount, or table)
[ ] Plug into power outlet
[ ] Connect to WiFi via Tapo app
[ ] Note the RTSP credentials from Tapo app

7.2 Camera Network Configuration (You)

After OPNsense is working (Phase 4)

Configure DHCP Reservations
OPNsense → Services → DHCPv4 → LAN → Static Mappings

Add each camera by MAC address:
[ ] Front camera: 192.168.1.101 (get MAC from camera label or app)
[ ] Back camera: 192.168.1.102
[ ] Indoor camera: 192.168.1.103
Access Camera Web Interfaces
# After cameras get IPs, access web UI:
[ ] http://192.168.1.101 - Front (default: admin/blank or admin/admin)
[ ] http://192.168.1.102 - Back
# Tapo C110 uses app only, no web UI

# On each Reolink camera:
[ ] Change default password
[ ] Set static IP (or rely on DHCP reservation)
[ ] Enable RTSP: Device Settings  Network  Advanced  Port Settings
[ ] Note RTSP port (default 554)

7.3 Deploy Mosquitto MQTT (You)

Frigate needs MQTT for Home Assistant integration

# SSH to Docker VM
ssh user@192.168.1.10

# Deploy automation stack (Mosquitto)
cd /opt/homelab/repo/docker/fixed/docker-vm/automation

# Create .env if needed
cp .env.example .env
nano .env  # Set MQTT passwords

# Start Mosquitto
docker compose up -d mosquitto

# Verify
docker logs mosquitto

7.4 Deploy Frigate (You)

Requires: Docker VM, NFS mount, Mosquitto running

Verify NFS Mount
# Check NFS is mounted
df -h /mnt/nas/frigate

# If not mounted:
sudo mount -t nfs 192.168.1.12:/srv/frigate /mnt/nas/frigate
Update Frigate Config for Day 1 IPs
cd /opt/homelab/repo/docker/fixed/docker-vm/security

# Edit frigate.yml - change VLAN 10 IPs to main LAN IPs:
#   192.168.10.101 → 192.168.1.101
#   192.168.10.102 → 192.168.1.102
#   192.168.10.103 → 192.168.1.103
nano frigate.yml

# Replace credential placeholders:
#   {REOLINK_USER} → admin (or your username)
#   {REOLINK_PASS} → your-camera-password
#   {TAPO_USER} → your-tapo-username
#   {TAPO_PASS} → your-tapo-password
Create Secrets and Environment
# Create secrets directory
mkdir -p secrets
chmod 700 secrets

# Generate secrets
openssl rand -base64 32 > secrets/admin_token.txt
openssl rand -base64 32 > secrets/restic_password.txt
chmod 600 secrets/*.txt

# Create .env
cp .env.example .env
nano .env

# Set:
# FRIGATE_RECORDINGS=/mnt/nas/frigate
# FRIGATE_RTSP_PASSWORD=your-camera-password
Start Frigate
# Start Frigate (skip Vaultwarden for now if not needed)
docker compose up -d frigate

# Watch logs for errors
docker logs -f frigate

# Common issues:
# - "No such file or directory: /media/frigate" → NFS not mounted
# - "Connection refused" MQTT → Mosquitto not running
# - RTSP timeout → Wrong camera IP or credentials

7.5 Verify Frigate (You + Friend)

Access Frigate Web UI
[ ] Open http://192.168.1.10:5000 in browser
[ ] Should see 3 camera feeds (may take 30s to connect)
Check Each Camera
[ ] Front door: Live feed visible, detection working
[ ] Back yard: Live feed visible, detection working
[ ] Indoor: Live feed visible, detection working
Test Detection
[ ] Walk in front of each camera
[ ] Verify "person" detected (bounding box appears)
[ ] Check Events tab shows detections
Verify Hardware Acceleration
docker exec frigate vainfo
# Should show Intel QuickSync capabilities
Check Recordings
# On NAS, verify recordings are being written:
ls -la /mnt/purple/frigate/
# Should see camera directories with recordings

7.6 Camera Adjustments (Friend)

After verifying feeds in Frigate:

[ ] Adjust front camera angle for optimal coverage
[ ] Adjust back camera angle
[ ] Position indoor camera for best view
[ ] Tighten all mounts
[ ] Clean up cable runs (zip ties, clips)

Checkpoint: All cameras streaming to Frigate, detection working. ~6-6.5 hours total.


Day 1 Success Criteria

Minimum (must have)

  • [ ] Internet works through OPNsense
  • [ ] Family devices can browse/stream
  • [ ] OPNsense accessible for management

Nice to have (with friend's help)

  • [ ] Docker VM created
  • [ ] NAS running with Debian + NFS export
  • [ ] Cameras physically installed
  • [ ] Frigate running with all 3 cameras
  • [ ] Pi-hole running (ad-blocking)
  • [ ] Tailscale working on Proxmox/NAS

Defer to later

  • VLAN 10 for camera isolation
  • Home Assistant + automations
  • Media stack (*arr, Jellyfin)
  • Full backup automation
  • Start9 on RPi 4

Post-Deployment Tasks (after Jan 24)

Skip tasks if completed on Day 1

Task Priority Notes

| Install Debian on NAS | High | Skip if done Day 1 | | Set up NFS export for Frigate | High | Skip if done Day 1 | | Deploy Frigate + cameras | High | Skip if done Day 1 | | Configure VLANs for IoT | High | Move cameras to 192.168.10.x | | Deploy Pi-hole (if not done) | Medium | Ad-blocking | | Deploy Mosquitto + Home Assistant | Medium | Frigate → HA integration | | Deploy media stack (*arr, Jellyfin) | Medium | Entertainment | | Fine-tune Frigate zones/masks | Medium | Reduce false positives | | Configure UPS/NUT | Low | Graceful shutdown | | Set up backup automation | Low | Restic to NAS + cloud | | Start9 on RPi 4 | Low | Bitcoin node |


Emergency Contacts During Deployment

Issue Action

| Can't boot Proxmox | Check USB, try different USB port | | No network after Proxmox | Check NIC assignment, cables | | OPNsense no WAN IP | Check ISP modem bridge mode, try reboot modem | | Family needs internet NOW | Use Beryl AX (see family-emergency-internet.md) | | Something else broke | Rollback: ISP modem → AX3000 → devices |


Quick Reference: Key IPs

Device IP Role

| OPNsense LAN | 192.168.1.1 | Gateway, DHCP, DNS | | AX3000 (AP mode) | 192.168.1.2 | WiFi only | | Proxmox | 192.168.1.5 | Hypervisor management | | Docker VM | 192.168.1.10 | Container host, Frigate | | NAS | 192.168.1.12 | Storage, NFS server | | Camera Front | 192.168.1.101 | Reolink PoE | | Camera Back | 192.168.1.102 | Reolink PoE | | Camera Indoor | 192.168.1.103 | Tapo WiFi | | DHCP range | .100-.199 | Client devices |

Service URLs

Service URL

| Proxmox | https://192.168.1.5:8006 | | OPNsense | https://192.168.1.1 | | Frigate | http://192.168.1.10:5000 | | Camera Front | http://192.168.1.101 | | Camera Back | http://192.168.1.102 |


Plan created: 2026-01-21 Deployment date: 2026-01-24