🐦 BirdWatchAI Manual Part 8 · Advanced Community Feed
Part 8

Advanced Topics

For people who want to go past the defaults: managing the Docker stack from the command line, moving the data folder, running headless, tuning ONVIF motion, backups, and migrating an install between machines.

Docker commands cheat-sheet

The server edition is one container (plus the Watchtower sidecar for one-click updates). These are the operations you'll do most.

Day-to-day

docker logs -f birdwatch           # live log tail; Ctrl+C to stop tailing
docker restart birdwatch           # bounce the container without recreating
docker stop birdwatch              # stop
docker start birdwatch             # start
docker compose down                # stop both containers
docker compose up -d               # start both
docker stats                       # live CPU / RAM / network per container
docker ps                          # what's running

Updating

The dashboard's ⬆ Update available button is the easy path β€” it pulls the new image via the Watchtower sidecar and recreates the container in ~90 seconds. The shell equivalent:

cd ~/birdwatch
docker compose pull
docker compose up -d

(On Windows the path is %USERPROFILE%\BirdWatch and a birdwatch-update.cmd wrapper is included.)

Cleaning up

docker system prune -af           # remove all unused images, containers, networks
docker image prune -af            # just dangling images
Don't docker rm the birdwatch container blindly docker compose down followed by docker compose up -d is the right pattern β€” it recreates the container with the mounts and environment from your docker-compose.yml. A raw docker rm would lose those.

Custom data directory (server)

By default the data folder is ./data next to the docker-compose.yml file. To put it somewhere else (e.g. on an external SSD), edit the volumes: line under the birdwatch service:

volumes:
  - /mnt/ssd/birdwatch-data:/data
  - /etc/localtime:/etc/localtime:ro
  - /etc/timezone:/etc/timezone:ro

Then copy your existing data over first:

docker compose stop birdwatch
sudo mkdir -p /mnt/ssd/birdwatch-data
sudo rsync -aHv ~/birdwatch/data/ /mnt/ssd/birdwatch-data/
sudo chown -R 1000:1000 /mnt/ssd/birdwatch-data   # match the container's user
docker compose up -d

The container won't recreate the database β€” it'll keep using whatever's in the mounted directory.

Headless / autostart

Server (Linux)

The container has restart: unless-stopped and Docker itself auto-starts on boot via the systemd service it installs. There's nothing more to configure β€” power-cycle the box, log in, run docker ps, and the container should be back. If it isn't:

sudo systemctl status docker
sudo systemctl enable docker

Server (Windows + Docker Desktop)

Two layers need to come up: Docker Desktop, then the containers. Both are wired in Part 2 β†’ Windows + Docker. If you want belt-and-suspenders, the included setup-scheduled-task.ps1 registers a Scheduled Task that re-runs birdwatch-start.cmd at user login.

Docker Desktop on Windows requires a logged-in session β€” for truly hands-off operation you'll need auto-login on a dedicated account (netplwiz β†’ uncheck "Users must enter…"). Trade-off: anyone with physical access has that account's permissions. Acceptable for a homelab box, not a shared PC.

Desktop app

In Settings β†’ Advanced:

ONVIF & motion tuning

Cameras that support ONVIF (most Tapo models, plus many Reolink / Amcrest) can push motion events to the app over the network rather than the app polling for them. Two big wins: less CPU on the host, and zero false triggers from things the camera knows are noise.

To enable: Settings β†’ Camera β†’ Use ONVIF motion detection on. The camera also needs ONVIF turned on in its own app (Tapo: Advanced Settings β†’ Camera Account covers ONVIF too).

ONVIF subscription leases

BirdWatchAI subscribes to PullPoint motion events with a 1-hour lease that's renewed every ~45 minutes. After camera reboots, network churn, or container recreates, stale subscriptions on the camera side can refuse new ones with BadRequest until they expire. Two ways out:

Software motion (when ONVIF isn't available)

The app compares recent low-resolution frames and counts changed pixels. The knob is the Motion Threshold (% of pixels that must change). 5% is the default. The desktop's πŸ“ˆ Telemetry viewer graphs motion % over time so you can see how high real bird visits spike vs. background sway and pick a threshold just below the visits.

Backups & migration

What to back up

ItemWhere (desktop)Where (server)
Settings Data\config.json data/config.json
Detection database Data\detections.db + JSON sidecar data/birdwatch.db
Snapshots Data\Snapshots\ data/snapshots/
Video clips Data\Videos\ data/clips/
License license.key in program folder data/license.key
ID corrections log Data\corrections.jsonl data/corrections.jsonl

The bare minimum for "I want my settings + history back" is the database file plus config.json. The snapshots and videos are larger and optional.

Snapshot-style backup (server)

From the host, with the container stopped (briefly) so the SQLite file is in a consistent state:

cd ~/birdwatch
docker compose stop birdwatch
tar -czf ~/birdwatch-backup-$(date +%F).tar.gz data/
docker compose start birdwatch

Restore is the inverse: stop the container, untar over the existing data/, start it.

In-app backup (both editions)

The server's Settings β†’ Backups page can take a snapshot of config.json on demand and show a diff against any previous backup. The desktop app has an equivalent "Save settings to file" / "Load settings from file" pair under the Advanced tab. Neither bundles the database β€” use the file-system approach above for full backups.

Migrating to a new machine

  1. Set up BirdWatchAI on the new machine following the right install path in Part 2.
  2. Stop monitoring on both machines.
  3. Copy the data folder over (rsync / WinSCP / USB stick).
  4. Start the new machine; verify the dashboard shows the right history, settings, license.
  5. Deactivate the license on the old machine if you're moving rather than cloning β€” most licenses cap at one active install per key.
Don't run both at once Most cameras allow only a handful of simultaneous RTSP streams, and the community backend keys feeders by Device Key β€” running two installs with the same Device Key creates confusing duplicate data on the community side. Pick one machine and stop the other.

File & folder reference

Desktop (Windows)

All data lives in a Data folder beside the program (e.g. C:\Users\<you>\AppData\Local\BirdWatch AI\Data\):

ItemLocation
SettingsData\config.json (passwords encrypted)
Detection databaseData\detections.db (with a JSON backup)
SnapshotsData\Snapshots\ (configurable)
VideosData\Videos\
Uncertain detections…\ForReview\ subfolder
Video summariesData\VideoSummaries\
Music for summariesData\Music\
ID corrections logData\corrections.jsonl
LogsData\Logs\
Licenselicense.key (program folder)

Server (Docker)

All data lives in the data/ folder you mounted into the container (default ~/birdwatch/data/ on Linux, %USERPROFILE%\BirdWatch\data\ on Windows):

ItemLocation (inside data/)
Settingsconfig.json (passwords encrypted)
Detection databasebirdwatch.db (SQLite, WAL)
Snapshotssnapshots/
Video clipsclips/
Logslogs/ (also viewable on the Logs page)
Config backupsconfig.bak/
Data-protection keysdataprotection-keys/

Remote access

The server dashboard is just HTTP on port 8080. To reach it from outside your home network, the recommended path is a private mesh VPN β€” Tailscale is the easiest, free for personal use, and works over CGNAT.

  1. Install Tailscale on the Pi / Windows box / Linux host: curl -fsSL https://tailscale.com/install.sh | sh (Linux) or the Windows installer.
  2. Run sudo tailscale up (Linux) or sign in via the system tray (Windows).
  3. Install Tailscale on your phone / laptop and sign into the same account.
  4. Note the Tailscale IP or MagicDNS name of the host (e.g. birdwatch.tail-abcd.ts.net).
  5. Open http://<tailscale-ip>:8080 or http://birdwatch.tail-abcd.ts.net:8080 from anywhere.
Don't port-forward the dashboard to the public internet The dashboard has no authentication on the local network and the host is running Docker with broad permissions. Tailscale / WireGuard / a reverse-proxy with auth is the right pattern; raw port-forwarding is not.

Running multiple feeders

Desktop

Install (or copy the portable build) into separate folders β€” e.g. BirdWatchAI-Backyard\ and BirdWatchAI-FrontPorch\ β€” and run each. Each folder keeps its own settings, history, and snapshots. Each gets a different Device Key on the community side, so they show up as separate feeders.

Server

Either run the same compose stack on multiple hosts (one per camera), or β€” on a single host β€” duplicate the birdwatch service in docker-compose.yml with a different container name, host port, and data volume:

services:
  birdwatch-backyard:
    image: ghcr.io/joebarraco/birdwatchai-server:latest
    container_name: birdwatch-backyard
    restart: unless-stopped
    ports: ["8080:8080"]
    volumes: ["./data-backyard:/data", "/etc/localtime:/etc/localtime:ro"]

  birdwatch-frontporch:
    image: ghcr.io/joebarraco/birdwatchai-server:latest
    container_name: birdwatch-frontporch
    restart: unless-stopped
    ports: ["8081:8080"]
    volumes: ["./data-frontporch:/data", "/etc/localtime:/etc/localtime:ro"]

Each instance points at a different camera in its own settings, has its own history, and registers as its own feeder on the community side.

Coming soon

A few features have been designed but aren't shipping yet. They're listed here so you know they're on the way β€” none of them are in the current build.

Track progress on the release notes or the project roadmap.


Credits & support

BirdWatchAI is created by Joe Barraco / Bird Brain Solutions LLC. It builds on open technologies including ONNX Runtime (local AI), FFmpeg (video), LibVLC (streaming), OpenStreetMap & Leaflet (maps), Open-Meteo (weather), eBird-derived data (rarity), Wikipedia (species photos), and Supabase (community backend). Thank you for watching the birds with us.