Beacon documentation

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

Quick start

  1. Get the code

    git clone https://github.com/tarazel/beacon-gateway.git
    cd beacon-gateway
  2. 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
  3. Build & run

    make build                       # gateway + beacon-admin CLI
    docker compose up -d --build     # or: make docker
  4. 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.

SettingWhat to set it to
FRIGATE_BASE_URLYour Frigate API base, e.g. http://frigate:5000.
MQTT_BROKERFrigate's MQTT broker, e.g. tcp://mosquitto:1883.
GO2RTC_BASE_URLgo2rtc's API, e.g. http://frigate:1984 (for live view).
CAMERAS_JSONYour cameras - [{"id","display_name","stream"}]; stream must be the H.264 substream.
PUBLIC_BASE_URLThe gateway's public HTTPS URL, e.g. https://beacon.example.com.
JWT_SIGNING_KEYA 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

  1. 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.
  2. 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.
  3. 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