Skip to content

Instantly share code, notes, and snippets.

  • Select an option

  • Save kenrmayfield/bec2900918e452ff2e6947a414b20f73 to your computer and use it in GitHub Desktop.

Select an option

Save kenrmayfield/bec2900918e452ff2e6947a414b20f73 to your computer and use it in GitHub Desktop.
Home Server Guide: Proxmox + HAOS + Frigate + Coral TPU (Verified Working Build)
# 🏡 Home Server Guide: Proxmox + HAOS + Frigate + Coral TPU
(Verified Working Build — Minimal First → Add Complexity Later)
This guide walks through building a reliable, low-maintenance **home-automation** and **NVR setup** using:
* **Proxmox VE** (host virtualization platform)
* **Home Assistant OS (HAOS)** in a VM
* **Frigate NVR** in a Debian 12 LXC (Docker-based)
* *Optional:* **Coral TPU** (object-detection acceleration)
* *Optional:* **GPU decoding** (Intel iGPU)
* *Optional:* **rclone** Google Drive continuous backup and storage cap
The first half builds a **minimal working setup** (guaranteed to work). The second half adds **advanced features** once the base is running cleanly.
---
## PART 1 – MINIMAL WORKING SETUP
### 1️⃣ Install Proxmox VE (PVE)
**Purpose:** Base virtualization platform that hosts HAOS (VM) and Frigate (LXC).
#### Steps
1. **Download & Install**
* Get the ISO from the official Proxmox website.
* Write to a USB drive (using Rufus or Balena Etcher), boot, and install with the default settings.
2. **Fix Enterprise Repository**
* *PVE is free, but we disable the paid enterprise repo to avoid update errors.*
```bash
# Disable the enterprise repository
sed -i 's|^deb .*pve-enterprise|# &|' /etc/apt/sources.list.d/pve-enterprise.list
# Add the no-subscription repository
echo "deb [http://download.proxmox.com/debian/pve](http://download.proxmox.com/debian/pve) bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-no-subscription.list
# Update and upgrade
apt update && apt full-upgrade -y
```
3. **Install Utilities**
```bash
apt install -y htop iotop curl jq usbutils unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
```
4. **Verify Hardware**
```bash
uname -a
lscpu
lsusb
lspci | grep -E "VGA|3D|Display"
```
---
### 2️⃣ Install Home Assistant OS (HAOS) VM
**Purpose:** Runs automations and smart-home integrations.
#### Steps
1. **Download & Decompress the QCOW2 Image**
* Run these commands from your Proxmox shell.
```bash
wget [https://github.com/home-assistant/operating-system/releases/latest/download/haos_ova.qcow2.xz](https://github.com/home-assistant/operating-system/releases/latest/download/haos_ova.qcow2.xz)
xz -d haos_ova.qcow2.xz
mv haos_ova.qcow2 haos.qcow2
```
2. **Create VM and Import Disk**
* `100` is the VM ID. Adjust resources as needed.
```bash
qm create 100 --name haos --memory 4096 --cores 2 --net0 virtio,bridge=vmbr0
qm importdisk 100 haos.qcow2 local-lvm
qm set 100 --scsihw virtio-scsi-single --scsi0 local-lvm:vm-100-disk-0
qm set 100 --boot order=scsi0
qm set 100 --bios ovmf
qm set 100 --efidisk0 local-lvm:vm-100-efi,size=4M,pre-enrolled-keys=1
qm start 100
```
3. **Access HAOS**
* Access via browser: `http://homeassistant.local:8123` or `http://<VM-IP>:8123`
---
### 3️⃣ Install Frigate NVR (Minimal Config)
**Purpose:** Provide NVR with both continuous and event-based recording. Frigate runs inside a Debian 12 **LXC** container using **Docker**.
#### Steps
1. **Create LXC Container**
* `101` is the LXC ID. Adjust resources as needed.
```bash
pct create 101 local:vztmpl/debian-12-standard_12.0-1_amd64.tar.zst \
--hostname frigate --memory 4096 --cores 4 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--rootfs local-lvm:16 \
--features nesting=1,fuse=1
pct start 101
pct exec 101 -- bash
```
2. **Install Docker (Inside the LXC)**
```bash
apt update
apt install -y ca-certificates curl gnupg lsb-release
install -m 0755 -d /etc/apt/keyrings
curl -fsSL [https://download.docker.com/linux/debian/gpg](https://download.docker.com/linux/debian/gpg) | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] [https://download.docker.com/linux/debian](https://download.docker.com/linux/debian) $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker
```
3. **Create Frigate Folders and Files**
```bash
mkdir -p /opt/frigate/{config,storage}
cd /opt/frigate
```
4. **Create `docker-compose.yml`**
```yaml
version: "3.9"
services:
frigate:
container_name: frigate
image: ghcr.io/blakeblackshear/frigate:stable
restart: unless-stopped
privileged: true
shm_size: "256m"
environment:
TZ: "America/Chicago" # <-- Set your Timezone
volumes:
- /opt/frigate/config:/config
- /opt/frigate/storage:/media/frigate
ports:
- "5000:5000"
- "1984:1984"
- "8554:8554"
- "8555:8555/tcp"
- "8555:8555/udp"
```
5. **Create Minimal `config.yml`**
* ***Important:*** *Replace `<USER>`, `<PASS>`, and `<CAM-IP>` with your camera's details.*
```yaml
mqtt:
enabled: false
detectors:
cpu1:
type: cpu
record:
enabled: true
retain:
days: 1
events:
retain:
default: 1
snapshots:
enabled: true
timestamp: true
bounding_box: true
go2rtc:
streams: {}
cameras:
example_camera: # <-- Name your camera
ffmpeg:
inputs:
- path: rtsp://<USER>:<PASS>@<CAM-IP>:554/stream1 # <-- High-res stream for record
roles: [record]
- path: rtsp://<USER>:<PASS>@<CAM-IP>:554/stream2 # <-- Low-res stream for detect
roles: [detect]
detect:
width: 640
height: 360
fps: 5
record:
enabled: true
retain:
days: 1
snapshots:
enabled: true
```
6. **Start Frigate**
```bash
cd /opt/frigate
docker compose up -d
docker ps
```
7. **Access Frigate UI**
* Access via browser: `http://<LXC-IP>:5000`
---
## PART 2 – ADD COMPLEXITY LATER
### 4️⃣ Add Coral TPU (Optional)
#### Proxmox Configuration
1. Verify the Coral is connected to the PVE host.
```bash
lsusb | grep -i "coral"
```
2. Edit the LXC configuration file on the **Proxmox host** (`/etc/pve/lxc/101.conf`).
```conf
# Add this line to the bottom
lxc.mount.entry: /dev/bus/usb /dev/bus/usb none bind,optional,create=dir
```
#### Frigate Configuration
1. Add the `devices` section to your `docker-compose.yml` (inside the LXC).
```yaml
# ... inside 'frigate' service block
# ... (shm_size, environment, volumes, etc.)
devices:
- /dev/bus/usb:/dev/bus/usb
ports:
# ...
```
2. Update the `detectors` block in your `config.yml` (inside the LXC).
```yaml
detectors:
coral:
type: edgetpu
device: usb
cpu1:
type: cpu
```
3. Restart Frigate.
```bash
cd /opt/frigate
docker compose restart frigate
```
---
### 5️⃣ Add iGPU Decoding (Optional)
This step reduces CPU usage by offloading video decoding to an Intel iGPU.
#### Proxmox Configuration
1. Edit the LXC configuration file on the **Proxmox host** (`/etc/pve/lxc/101.conf`).
```conf
# Add these two lines to the bottom
lxc.cgroup2.devices.allow: c 226:* rwm
lxc.mount.entry: /dev/dri /dev/dri none bind,optional,create=dir
```
#### Frigate Configuration
1. Add the `hwaccel_args` to the `ffmpeg` block for each camera in your `config.yml` (inside the LXC).
```yaml
cameras:
example_camera:
ffmpeg:
hwaccel_args: preset-vaapi # <-- Add this line
inputs:
# ...
```
2. Restart Frigate.
```bash
cd /opt/frigate
docker compose restart frigate
```
---
### 6️⃣ Add Google Drive Backup (rclone)
This is set up inside the Frigate LXC (`101`).
1. **Install rclone and inotify-tools**
```bash
apt install -y rclone inotify-tools
rclone config # <-- Follow prompts to set up your Google Drive remote (e.g., named 'gdrive')
```
2. **Real-time Uploader Script**
* Create the script `/usr/local/bin/frigate_upload_watch.sh`.
```bash
#!/usr/bin/env bash
SRC="/opt/frigate/storage"
DEST="gdrive:Frigate_Backups" # <-- Update 'gdrive' if your remote name is different
LOG="/var/log/frigate_rclone.log"
inotifywait -m -r -e close_write,moved_to,create "$SRC" | \
while read -r dir action file; do
rclone copyto "$dir/$file" "$DEST/${dir#${SRC}/}/$file" \
--log-file="$LOG" --log-level INFO --update
done
```
3. **Create Systemd Service**
* Create the file `/etc/systemd/system/frigate-upload-watch.service`.
```systemd
[Unit]
Description=Frigate -> Google Drive uploader
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/frigate_upload_watch.sh
Restart=always
RestartSec=3
User=root
[Install]
WantedBy=multi-user.target
```
4. **Start and Enable Service**
```bash
systemctl daemon-reload
systemctl enable --now frigate-upload-watch.service
```
---
### 7️⃣ Add Drive Storage Cap (Optional)
This is a script to automatically delete the oldest files from the Google Drive remote when the storage limit is reached.
1. **Config File**
* Create `/etc/gdrive_cap.conf`.
```conf
REMOTE="gdrive:Frigate_Backups" # <-- Match your rclone remote
CAP_BYTES="500G" # <-- Set your storage cap
```
2. **Enforcer Script**
* Create `/usr/local/bin/gdrive_cap_enforcer.sh`.
```bash
#!/usr/bin/env bash
set -euo pipefail
source /etc/gdrive_cap.conf
CAP=$(numfmt --from=iec $CAP_BYTES)
current=$(rclone lsf "$REMOTE" --files-only --format s --recursive | awk '{s+=$1} END{print s+0}')
if [ "$current" -le "$CAP" ]; then exit 0; fi
rclone lsf "$REMOTE" --files-only --format pst --separator '|' --recursive | sort -t'|' -k3,3 | \
while IFS='|' read -r path size mtime; do
[ "$current" -le "$CAP" ] && break
rclone deletefile "$REMOTE/$path"
current=$(( current - size ))
done
```
3. **Create Systemd Timer**
* Create `/etc/systemd/system/gdrive-cap-enforcer.timer`.
```systemd
[Timer]
OnBootSec=2min
OnUnitActiveSec=10min # <-- How often to run the check
AccuracySec=1min
Unit=gdrive-cap-enforcer.service
[Install]
WantedBy=timers.target
```
4. **Create Systemd Service for the Enforcer (for the timer to call)**
* Create `/etc/systemd/system/gdrive-cap-enforcer.service`.
```systemd
[Unit]
Description=Frigate Google Drive Capacity Enforcer
Requires=gdrive-cap-enforcer.timer
[Service]
Type=oneshot
ExecStart=/usr/local/bin/gdrive_cap_enforcer.sh
```
5. **Start and Enable Timer**
```bash
systemctl daemon-reload
systemctl enable --now gdrive-cap-enforcer.timer
```
---
## 🚀 Workflow Summary
| Step | Component | Purpose |
| :--- | :--- | :--- |
| **1** | Proxmox | Base OS / Virtualization Host |
| **2** | HAOS (VM) | Runs Home Automation / Integrations |
| **3** | Frigate (LXC + Docker) | NVR for Recording and Detection (CPU-only) |
| **4** | **Optional** Coral TPU | Accelerate Object Detection |
| **5** | **Optional** iGPU Decoding | Lower CPU usage for video decoding |
| **6** | **Optional** rclone | Real-time backup to Google Drive |
| **7** | **Optional** Drive Cap | Auto-delete oldest cloud files to enforce a limit |
**✅ End Result:** Frigate continuously records and shows events; HAOS runs separately; the system is **modular, stable, expandable, and easy to maintain**.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment