Install the gateway
The Beacon gateway is an open-source Go service you run next to your existing Frigate stack. This guide takes you from a running Frigate to signing in on your phone.
New to how the pieces fit together? Read the architecture overview first - this page assumes you know what the gateway, Frigate, and go2rtc each do.
Before you start
- A running Frigate instance with go2rtc and MQTT - i.e. the standard Frigate stack. A Coral (or other detector) is Frigate's concern, not the gateway's.
- Docker and Docker Compose on the same host as Frigate (simplest), or any host that can reach Frigate's MQTT broker and API.
- A way to reach the gateway from your phone: any TLS reverse proxy, a Cloudflare Tunnel, or Tailscale. See Exposing the gateway. The gateway does its own auth, so it does not need to sit behind Cloudflare Access or a VPN login.
- For push notifications: a Beacon Pro subscription, which delivers push through the hosted relay - no Apple Developer account or push keys of your own required. (Sign-in itself is free and needs no developer account.)
Quick start
-
Get the code
git clone https://github.com/tarazel/beacon-gateway.git cd beacon-gateway -
Create your config
Copy the example and edit it. Every setting is documented inline in the file, and summarized in the reference below.
cp .env.example .env # then edit .env - see the reference below -
Build & run
make build # gateway + beacon-admin CLI docker compose up -d --build # or: make docker -
Point the app at it
Open the Beacon app, enter your gateway's public URL on the Sign In screen, and sign in. The first person to sign in becomes the admin (the instance owner).
The compose file
The gateway ships with a docker-compose.yml that joins Frigate's existing
Docker network so it can reach the broker and API by container name. It publishes
no host port by default - a reverse proxy or tunnel on the same
network reaches it directly.
services:
gateway:
build: .
container_name: beacon-gateway
restart: unless-stopped
env_file: [ .env ]
expose: [ "8080" ] # no host port; reached over the Docker network
volumes:
- ./data:/app/data # SQLite database (persist this)
- ./secrets:/app/secrets:ro # optional - advanced self-signed push only
networks: [ frigate_default ]
networks:
frigate_default: # Frigate's existing network - check `docker network ls`
external: true
The network name frigate_default is the default for the standard
Frigate compose stack. If yours differs, run docker network ls and
update the networks block to match. On this network the gateway
reaches mosquitto:1883, frigate:5000, and
frigate:1984 by name.
Configuration reference
You set only a handful of values in .env - where Frigate is, your
cameras, your public URL, and one generated secret. Sign-in and push work
out of the box (the app's client IDs ship pre-set and the hosted relay is
the default), so there's nothing to configure for either. Every option - including
the advanced ones (broker auth, Cloudflare Access, Google sign-in, per-user access
control, running your own relay) - is documented inline in .env.example.
| Setting | What to set it to |
|---|---|
FRIGATE_BASE_URL | Your Frigate API base, e.g. http://frigate:5000. |
MQTT_BROKER | Frigate's MQTT broker, e.g. tcp://mosquitto:1883. |
GO2RTC_BASE_URL | go2rtc's API, e.g. http://frigate:1984 (for live view). |
CAMERAS_JSON | Your cameras - [{"id","display_name","stream"}]; stream must be the H.264 substream. |
PUBLIC_BASE_URL | The gateway's public HTTPS URL, e.g. https://beacon.example.com. |
JWT_SIGNING_KEY | A secret you generate: openssl rand -base64 48. |
Exposing the gateway
Your phone needs to reach the gateway over HTTPS. Pick whichever fits your setup - the gateway does its own authentication, so it should not be placed behind a second browser-based login (Cloudflare Access, an SSO portal, etc.), which native app requests can't complete.
Reverse proxy
Point Caddy, Nginx, or Traefik at beacon-gateway:8080 and terminate
TLS with your own certificate. The simplest option if you already run one.
Cloudflare Tunnel
Route a public hostname (e.g. beacon.example.com) to
http://beacon-gateway:8080 - no open ports at home. Keep it
off Cloudflare Access.
Tailscale
Put the gateway on your tailnet and reach it from your devices with no public exposure at all. Great for a private, family-only setup.
If you use Cloudflare, keep Bot Fight Mode off for the gateway's hostname (or exempt it). It serves a JavaScript challenge that native app clients can't solve, which will break sign-in and push enrichment.
Roles & invites
Beacon is multi-user by design. The first person to sign in becomes the admin; everyone else is a member. Admins manage users, cameras, and retention and see every camera; members are regular family users who can be scoped to specific cameras. The easiest way to add someone - without guessing their Apple email - is a single-use invite code they enter on the Sign In screen (from the app's Invites screen, or the CLI below).
beacon-admin list-users
beacon-admin set-role <id-or-email> <admin|member>
beacon-admin set-cameras <id-or-email> [camera ...] # no cameras = sees all
beacon-admin invite create --role member --expires 168h
beacon-admin invite list
beacon-admin invite delete <code>
The hosted relay & Beacon Pro
Push notifications are delivered by a hosted relay that Tarazel runs - the one piece of infrastructure you can't easily provision yourself, and what a Beacon Pro subscription unlocks. There's nothing to configure: no relay URL, no registration secret, no Apple Developer account or push keys of your own, and no instance IDs to copy by hand.
Beacon Pro is rolling out. The hosted relay and self-serve subscription are being finalized. Get in touch for early access.
How activation works
- Register - automatic, zero config. The gateway already points at Tarazel's relay. On your first sign-in as the owner it registers itself using your verified Apple/Google identity - no URL or secret to paste - and stores a private instance token. The relay verifies that identity directly and receives no user or camera data. Your instance begins a 15-day free trial, so push works right away.
- Subscribe - in the app. Open Settings → Upgrade and the app opens Stripe checkout in your browser. Your instance is linked to the subscription automatically - nothing to copy or paste.
- Activate. Stripe confirms the payment and the relay marks your instance active, so push keeps flowing. Cancel any time and it lapses at the end of the billing period; after the trial, an instance with no active subscription simply stops sending push until you subscribe.
The relay never sees your home. Your gateway keeps all user, scope, and mute logic and forwards only a list of device tokens plus an opaque payload; the relay signs and delivers it, and never sees a camera name, label, or image - the device fetches the readable notification content from your gateway.
Updating & health
Check the gateway is up:
curl https://beacon.example.com/healthz # -> ok
To update to a newer version, pull and rebuild - your data and config are preserved
in the mounted ./data and .env:
git pull
docker compose up -d --build