MCPcopy Index your code
hub / github.com/dmksnnk/star

github.com/dmksnnk/star @v0.3.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.1 ↗ · + Follow
448 symbols 1,643 edges 67 files 154 documented · 34% updated 3mo agov0.3.1 · 2026-03-22★ 752 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Star ⭐

Ever wanted to play a local game with a friend who is far away? Star makes local multiplayer games playable remotely!

How to Start

The application comes with two components: Registar, a server that manages connectivity between players, and Star, a client that forwards UDP traffic. It has a GUI or can be used via CLI.

You can use the publicly available server at https://registar.dmksnnk.xyz or deploy your own Registar server.

Deploy a Server

A pre-built Docker image is available at ghcr.io/dmksnnk/star/registar.

services:
  registar:
    image: ghcr.io/dmksnnk/star/registar:latest
    restart: unless-stopped
    environment:
      - SECRET=your-secret-here        # optional, omit for open access
      - CERT_DOMAINS=your-domain.com
      - CERT_DIR=/certs
    ports:
      - "80:80"          # HTTP unencrypted (redirects to HTTPS, used for ACME challenge)
      - "443:443/tcp"    # HTTP on top of TCP with TLS
      - "443:443/udp"    # HTTP/3 on top of UDP (QUIC)
    volumes:
      - certs:/certs

volumes:
  certs:

See Registar Server Configuration for all configuration options.

Deploying Behind a Reverse Proxy

Registar runs three services:

  • HTTP Server (TCP): Handles ACME challenges and redirects HTTP→HTTPS
  • HTTPS Server (TCP): Serves HTTP/1.1 & HTTP/2 and advertises HTTP/3 support via Alt-Svc.
  • HTTP/3 Server (UDP): Handles the actual QUIC game traffic.

Since Registar uses HTTP/3 (QUIC), it manages its own TLS certificates (via Let's Encrypt). The parts that can be proxied are the HTTP and HTTPS servers, but the HTTP/3 server must listen directly on the public UDP port (443/UDP), because we need the client's public IP addresses for NAT hole-punching.

  • Traffic to HTTP Server (TCP) can be routed normally via the proxy to HTTP_LISTEN (e.g., :8080). This handles redirects and ACME. Do not enable tlsChallenge in Traefik - it intercepts TLS-ALPN-01 and Registar won't be able to complete its ACME challenge. Use httpChallenge instead.
  • Traffic to HTTPS Server (TCP) must be routed using TCP Passthrough to HTTPS_LISTEN (e.g., :8443). The proxy should not terminate TLS for this service, as Registar manages its own certificates.
  • Map the HTTP/3 Server UDP port directly to the host's public UDP port (e.g., 443:8443/udp). This allows UDP traffic to coexist with Traefik's TCP traffic on port 443.

Here is an example of how to do it with Traefik:

docker-compose.yaml (registar service):

services:
  registar:
    image: ghcr.io/dmksnnk/star/registar:latest
    restart: unless-stopped
    environment:
      - HTTP_LISTEN=:8080
      - HTTPS_LISTEN=:8443
      - CERT_DIR=/certs
      - CERT_DOMAINS=registar.example.com
      - HTTPS_ADVERTISE_HTTP3_PORT=443   # advertise public UDP port for HTTP/3
      - HTTPS_REDIRECT_PORT=443          # redirect to public HTTPS port
      - SECRET_FILE=/run/secrets/registar_secret   # optional, omit for open access
    ports:
      - "443:8443/udp"   # HTTP/3 (QUIC) — bypasses Traefik (UDP not proxied)
    volumes:
      - certs:/certs
    secrets:
      - registar_secret

volumes:
  certs:

secrets:
  registar_secret:
    file: ./registar_secret

Traefik routes.yaml (registar entries):

http:
  routers:
    registar-http:
      entryPoints: [web]
      rule: "Host(`registar.example.com`)"
      service: registar-http
  services:
    registar-http:
      loadBalancer:
        servers:
          - url: "http://registar:8080"

tcp:
  routers:
    registar:
      entryPoints: [websecure]
      rule: "HostSNI(`registar.example.com`)"
      service: registar
      tls:
        passthrough: true   # registar handles TLS itself
  services:
    registar:
      loadBalancer:
        servers:
          - address: "registar:8443"

traefik.yaml (important — use httpChallenge, not tlsChallenge):

certificatesResolvers:
  letsencrypt:
    acme:
      httpChallenge:
        entryPoint: web

Game Host

Prebuilt client can be found at Releases page

If you are hosting the game, follow these steps:

  1. Run the Star client. This should open a default browser.

Client home screen 2. Fill in the server's URL. If the server requires a secret, expand Advanced and enter it. 3. Click "Host a Game". 4. Select a game from the list or enter a custom port to forward to.

Host screen 5. Click "Start Hosting". 6. Share the invite code with your friend.

Invite code screen

Game Peer

If you want only join a game, follow these steps:

  1. Run the Star client. This should open a default browser.

Client home screen 2. Fill in the server's URL. If the server requires a secret, expand Advanced and enter it. 3. Click "Join a Game". 4. Enter the invite code you received from the host and click "Connect".

Join screen 5. You will see the address where you can connect

Peer connected screen 6. Connect the game client to that address, here is an example from Stardew Valley:

stardew valley multiplayer connection screen

Registar Server Configuration

The server is configured using environment variables:

Variable Required Default Description
SECRET No Shared secret to restrict access. If unset, the server is open to anyone
SECRET_FILE No Path to a file containing the secret (takes precedence over SECRET)
LOG_LEVEL No INFO Logging level: INFO, DEBUG
HTTP_LISTEN No :80 HTTP listen address (redirects to HTTPS)
HTTPS_LISTEN No :443 HTTPS and HTTP/3 listen address
HTTPS_ADVERTISE_HTTP3_PORT No 443 Port advertised via Alt-Svc for HTTP/3 upgrade
HTTPS_REDIRECT_PORT No 443 Port used in HTTP→HTTPS redirects
CERT_SELF_SIGNED No false Use a self-signed certificate instead of Let's Encrypt (useful for testing)
CERT_DIR No certs Directory where certificates are stored
CERT_DOMAINS Yes (for Let's Encrypt) localhost Comma-separated list of domains for the certificate
RATE_LIMIT_EVERY No 100ms Minimum time between requests for the same IP (e.g., 100ms will allow 10 requests per second)
RATE_LIMIT_BURST No 10 Maximum number of requests allowed in a burst

Star CLI

When run without arguments, Star starts a local web UI server and opens it in the browser. Set LISTEN_ADDR to override the default listen address (default: 127.0.0.1 with a system-assigned port).

star [GLOBAL OPTIONS] COMMAND [COMMAND OPTIONS]

Global Options

Flag Required Default Description
--secret No Shared secret matching the registar server's SECRET, omit if the server has no secret
--registar Yes Registar server URL
--port No 0 Local UDP listen port; 0 means system-assigned
--ca-cert No Path to a CA certificate file for the registar server (used for testing or custom setups)
--log-level No INFO Logging level: DEBUG, INFO, WARN, ERROR

Commands

host — Host a Game

star [GLOBAL OPTIONS] host [OPTIONS]
Flag Required Default Description
--port No 24642 Local game port to forward traffic to (defaults to Stardew Valley)
--key No Game key to register; if not set, a new key is generated

After starting, the game key is printed to stdout. Share it with your friend.

peer — Join a Game

star [GLOBAL OPTIONS] peer [OPTIONS]
Flag Required Default Description
--key Yes Game key received from the host
--listen-port No 0 Local UDP port to listen on for game traffic; 0 means system-assigned

After connecting, the local address to point your game client at is printed to stdout.

Examples

Host a game on a custom port to forward traffic to:

star --registar https://registar.example.com host --port 12345

Join a game:

star --registar https://registar.example.com peer --key XXXX-XXXX

If the server requires a secret:

star --secret mysecret --registar https://registar.example.com host --port 12345

How It Works

The Registar server acts as a control server and a relay. When both sides join the server, it coordinates the NAT hole-punching to establish a direct P2P connection. If it fails, the server instructs both clients to initiate a relay connection, where the server forwards UDP traffic between them.

Everything above runs on top of QUIC/HTTP3, which makes every communication secured by TLS. For P2P connections, the server acts as a certificate authority (CA). It creates a new intermediate CA for each session and issues leaf certificates for both clients, so they can authenticate each other securely (mTLS).

The Star client is a UDP server that forwards UDP traffic over QUIC datagrams.

Development

TODO: add

See p2ptest/README.md about running integrations tests for NAT hole-punching.

HTTP/3

You can use a pre-built curl with HTTP/3 support from https://github.com/stunnel/static-curl.

Run in another terminal:

curl -Lv --cacert ca.crt --http3 http://localhost/-/health

Extension points exported contracts — how you extend this code

DatagramConn (Interface)
DatagramConn sends and receives datagrams.
internal/registar/client.go
Option (FuncType)
(no doc)
internal/relay/option.go
Option (FuncType)
Option is a functional option for configuring a Connector.
internal/registar/p2p/connector.go
Stream (Interface)
(no doc)
internal/registar/control/controller.go

Core symbols most depended-on inside this repo

Close
called by 79
internal/registar/client.go
String
called by 61
internal/registar/auth/key.go
Error
called by 58
internal/registar/auth/key.go
LocalAddr
called by 31
internal/platform/udp/conn.go
Context
called by 25
internal/registar/control/controller.go
NewKey
called by 21
internal/registar/auth/key.go
Read
called by 21
internal/platform/udp/conn.go
Header
called by 20
internal/registar/control/agent.go

Shape

Function 187
Method 172
Struct 76
TypeAlias 8
Interface 3
FuncType 2

Languages

Go100%

Modules by API surface

internal/registar/client.go32 symbols
internal/webserver/server.go21 symbols
internal/registar/server.go21 symbols
internal/platform/httpplatform/middleware.go20 symbols
internal/registar/p2p/connector.go19 symbols
internal/registar/admin/admin.go16 symbols
internal/registar/auth/key.go15 symbols
internal/webserver/sse.go14 symbols
internal/relay/relay.go14 symbols
cmd/registar/main.go14 symbols
internal/webserver/models.go13 symbols
internal/discovery/discovery.go13 symbols

For agents

$ claude mcp add star \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page