beaconDocs
Networking & Access

Custom Domain & TLS

Serve the dashboard at your own domain with automatic HTTPS, and give players a friendly address.

There are two separate things you might want a domain for: a friendly address for players to connect to, and a public HTTPS dashboard for admins. They're independent — set up either or both.

A friendly address for players

The Minecraft server is public at the host's IP on MC_HOST_PORT (usually 25565). A custom address is just DNS pointing at that IP — no server change needed.

Add a DNS record

In your DNS provider, add an A record (and AAAA if the host has IPv6):

TypeNameValue
Amcthe host's public IPv4

Players then connect with mc.example.com (no port, since 25565 is the default).

Cloudflare users: proxy must be OFF

Set the record to DNS only (gray cloud). Cloudflare's proxy is HTTP-only; Minecraft is raw TCP and gets silently dropped through an orange cloud. This is the #1 "I added the record and it still won't connect" cause.

Tell the dashboard the address

So the How to join panel shows the friendly name, set it in .env:

MC_PUBLIC_HOST=mc.example.com

Then beacon restart. For a non-default port, add a _minecraft._tcp SRV record so players can still omit the port, and set MC_HOST_PORT / MC_PUBLIC_PORT to match. New CLI-created beacons configure SRV-friendly ports automatically.

Verify

dig +short mc.example.com
nc -vz mc.example.com 25565

A public HTTPS dashboard (Caddy)

By default the dashboard is private over Tailscale. Custom-domain mode instead runs a bundled Caddy reverse proxy that serves the dashboard at https://your.domain with an automatic certificate. One A record can cover both the dashboard (:443) and the game server (:25565).

Point the domain at the host

Add an A record (and AAAA if applicable) for the dashboard hostname at the host's public IP. Cloudflare users: DNS only (gray cloud) again — the orange-cloud proxy breaks Caddy's ACME challenge.

Open ports 80 and 443

Caddy needs inbound TCP 80 (ACME challenge + HTTP→HTTPS redirect) and 443 (the dashboard). Open both in the OS firewall and any cloud firewall:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Switch to custom-domain mode

Let the CLI write the config:

beacon create --yes --mode custom \
  --app-url https://friends.example.com \
  --acme-email ops@example.com \
  --mc-image itzg/minecraft-server:java25 --mc-version 26.1.2

Or set it in .env on an existing beacon, then beacon up:

COMPOSE_PROFILES=custom-domain
BEACON_DOMAIN=friends.example.com
PUBLIC_APP_URL=https://friends.example.com
BEACON_ACME_EMAIL=ops@example.com

First boot

Caddy obtains the certificate on first start — this takes 30–60 seconds, during which the dashboard returns 502. That's expected. Watch it with beacon logs caddy.

Switching ingress invalidates sessions

Changing ingress mode changes the dashboard's origin, so everyone signs in again on the new URL.

Certificates and rate limits

Caddy tries Let's Encrypt first and automatically falls through to ZeroSSL if LE is unavailable — most often because of LE's 5-certificates-per-week-per-domain limit after repeated redeploys. The ZeroSSL fallback needs an EAB account, which Caddy auto-provisions only if BEACON_ACME_EMAIL is set — that's why custom-domain mode requires it. Use a real inbox; both CAs email expiry notices there.

beacon nuke preserves Caddy's cert state by default, so iterating doesn't burn issuances. If you do hit the limit, switching to a fresh subdomain (a new identifier with its own counter) is the fastest unblock.

On this page