beaconDocs
Install & Deploy

Deployment Model

How a beacon is deployed — the CLI, the release images, and the stack it runs.

The Beacon CLI is the supported way to deploy and operate a beacon. It owns the Docker Compose files, secrets, and ingress configuration so you don't have to. This page explains what actually runs, so the rest of the deploy docs make sense.

The CLI drives everything

You never write Compose files or run docker directly. beacon create (or the guided beacon wizard) scaffolds a deployment directory and beacon up brings it online. Day-2 operations — upgrade, restart, status, logs — all go through the CLI too.

The whole lifecycle
curl -fsSL https://beacon-mc.io/install.sh | sh   # install the CLI
beacon                                            # create + deploy ~/.beacon
beacon status                                      # health probe
beacon upgrade 0.31.1 --yes                        # update later

Game operations live in the dashboard

The CLI is scoped to host operations (deploy, update, start, stop, inspect). People, invites, the allowlist, backups, server settings, and mods are managed in the web dashboard — open it with beacon admin. See Managing your beacon.

What runs in the stack

A beacon is a small set of containers on a private Compose network:

ServiceWhat it isExposed?
minecraftThe game server (itzg image; Paper by default)Public on 25565
webThe Next.js operator dashboardInternal only
admin-rpcPrivileged backend (Docker socket + RCON-write)Internal only
tailscale or caddyThe ingress proxy that fronts the dashboardSee Networking

The privilege boundary is deliberate: the public-facing web app never gets the Docker socket or RCON-write — every privileged action passes through admin-rpc. That's why you reach the dashboard through an ingress proxy rather than by exposing internal ports. See Ports & Access.

Release images

Beacon's images are public on GHCR — no GitHub token required:

  • ghcr.io/thoughts-on-things/beacon/web
  • ghcr.io/thoughts-on-things/beacon/admin-rpc

beacon up pulls these at the version pinned by BEACON_VERSION and recreates the stack. The minecraft, tailscale, and caddy services come from upstream images. Images ship for linux/amd64 and linux/arm64.

Requirements

  • A 64-bit Linux host (amd64 or arm64) with Docker Engine and Docker Compose v2.24+.
  • Node.js 20+ to run the beacon CLI.
  • One inbound TCP port per beacon for Minecraft (25565 for the first).
  • For custom-domain ingress, inbound TCP 80 + 443. For Tailscale, nothing extra.

New to hosting? Follow the end-to-end Hosting on a VPS walkthrough, which covers provisioning the host as well.

What beacon create writes

In the deployment directory (~/.beacon by default), the CLI generates:

  • .env — generated MC_RCON_PASSWORD, ADMIN_RPC_TOKEN, BEACON_SESSION_SECRET, the pinned BEACON_VERSION, the unique BEACON_INSTANCE / COMPOSE_PROJECT_NAME, and COMPOSE_PROFILES for the chosen ingress
  • docker-compose.yml and docker-compose.release.yml
  • tailscale-serve.json and Caddyfile (the inactive one is harmless)
  • .gitignore and a short project README

These are CLI-managed. Edit .env for settings the CLI exposes, but let beacon upgrade / beacon restart re-render the compose files — they're regenerated from the CLI's bundled templates so an older install picks up new service wiring. See Configuration.

Multiple beacons on one host

Run one beacon create per directory. Each gets a unique Docker project, container names, and Minecraft port (auto-assigned from 25565 up). Bare beacon opens a TUI to switch between registered beacons; scripts use --dir <path>.

Two beacons on one VPS
beacon create ~/beacons/survival --yes \
  --app-url https://survival.<tailnet>.ts.net \
  --tailscale-auth-key tskey-... \
  --mc-image itzg/minecraft-server:java25 --mc-version 26.1.2

beacon create ~/beacons/creative --yes \
  --app-url https://creative.<tailnet>.ts.net \
  --tailscale-auth-key tskey-... \
  --mc-image itzg/minecraft-server:java25 --mc-version 26.1.2

On this page