Docs / Self-host

Self-host Asobi

Asobi is fully open-source and designed to be run on your own infrastructure. This guide walks through three deployment targets: Docker Compose (dev), a single server (production), and Kubernetes (scale).

Prefer managed? Asobi Cloud is coming — fully managed game servers, EU-sovereign hosting, per-environment scaling. Join the waitlist at asobi.dev/cloud.

Deployment targets

Docker Compose

The quickest way to run a real Asobi stack. Save this as docker-compose.yml:

services:
  postgres:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: asobi
    volumes: [pgdata:/var/lib/postgresql/data]
    ports: ["5432:5432"]

  asobi:
    image: ghcr.io/widgrensit/asobi_lua:latest
    depends_on: [postgres]
    environment:
      ASOBI_DB_HOST: postgres
      ASOBI_DB_NAME: asobi
      ASOBI_DB_USER: postgres
      ASOBI_DB_PASSWORD: postgres
      ERLANG_COOKIE: ${ERLANG_COOKIE}
    ports: ["8080:8080"]
    volumes:
      - ./game:/app/game:ro

volumes:
  pgdata:

Generate a cookie, then boot the stack:

export ERLANG_COOKIE=$(openssl rand -hex 32)
docker compose up -d

Asobi is now running on http://localhost:8080. Deploy your game with asobi deploy ./game and you're live.

Single VPS

For production on a single machine — a Hetzner AX41 (€40/mo) comfortably handles hundreds of concurrent players. Build a release from the Asobi source:

git clone https://github.com/widgrensit/asobi
cd asobi
rebar3 as prod release

# The release is at _build/prod/rel/asobi/
# Copy it to the server, run with:
bin/asobi daemon

Configure the release via config/prod_sys.config.src — environment variables, database credentials, and TLS settings are all there. See the config directory for full examples.

Systemd unit

# /etc/systemd/system/asobi.service
[Unit]
Description=Asobi game backend
After=network.target postgresql.service

[Service]
Type=notify
User=asobi
Environment=ERLANG_COOKIE=generate-a-real-one
Environment=HOME=/var/lib/asobi
ExecStart=/opt/asobi/bin/asobi foreground
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Reverse proxy (Caddy)

game.example.com {
    reverse_proxy localhost:8080
}

Caddy auto-issues TLS certs and handles WebSocket upgrades without config. Nginx works equally well — make sure proxy_set_header Upgrade $http_upgrade is set.

Kubernetes

For multi-tenant or multi-game deployments, run one pod per game-env. Our reference infra repo (widgrensit/asobi-infra) ships a Helm stack for Scaleway Kapsule: cert-manager, Prometheus, Loki, Velero, and CloudNativePG.

A minimal Deployment looks like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: asobi-my-game-live
  namespace: tenant-widgrensit
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: engine
          image: ghcr.io/widgrensit/asobi_lua:latest
          env:
            - name: ASOBI_DB_HOST
              valueFrom:
                secretKeyRef: { name: pg-credentials, key: host }
            - name: ERLANG_COOKIE
              valueFrom:
                secretKeyRef: { name: erlang-cookie, key: cookie }
          ports:
            - containerPort: 8080
          resources:
            requests: { cpu: 100m, memory: 256Mi }
            limits:   { cpu: 1000m, memory: 1Gi }

See the asobi-infra repo for the full cluster setup, NetworkPolicies, and tenant isolation patterns.

Backups

  • Postgres: everything Asobi persists lives in Postgres. Back up continuously (WAL shipping to S3-compatible storage) or at least nightly.
  • Lua bundles: your game source lives in git. That's the backup.
  • Zone snapshots: persistent worlds snapshot their state to Postgres every tick interval. They're restored automatically on startup.

Security checklist

  • Rotate the Erlang cookie. Never use a default value.
  • Set verify_peer for any outbound HTTPS (already the default in asobi).
  • Enable TLS in the reverse proxy; don't expose the raw 8080 port to the public internet.
  • Enable Postgres SSL for connections from other hosts.
  • Run the engine as a non-root user (the Docker image does this; bare metal should too).
  • Treat deploy keys like passwords. Rotate on employee offboarding.

Upgrades

Asobi releases are hot-code-loadable on the BEAM. For minor version bumps, deploy the new release and existing matches finish on the old code; new matches use the new code. No downtime. For major version bumps (breaking schema changes), run migrations via rebar3 kura migrate in a maintenance window.

Where next?