Documentation

Run SimpleForge.

SimpleForge runs as a Docker image or native binary. You provide PostgreSQL. SimpleForge manages schemas, tenants, migrations, API keys, and the HTTP server.

Docker + PostgreSQL

Install model

SimpleForge does not own your database server. You do.

The app reads one config file, connects to PostgreSQL, runs migrations through the CLI, then serves the API. That same image can run admin commands and the long-running server.

1. Provide PostgreSQL

Use managed PostgreSQL, a VM, or your own container. SimpleForge only needs a reachable host, database, user, and password.

2. Create config.yaml

The config file is the source of truth for the SimpleForge server and CLI.

3. Run migrations

Initialize the public schema, create a tenant, run tenant migrations, and create an API key.

Optional

Customer-owned PostgreSQL in Docker

This is an example PostgreSQL container. It is not part of the SimpleForge image. It represents infrastructure owned by the operator.

services:
  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: simpleforge
      POSTGRES_USER: forger
      POSTGRES_PASSWORD: forger
    volumes:
      - customer_pgdata:/var/lib/postgresql/data
    ports:
      - "5433:5432"

volumes:
  customer_pgdata:

Start it from its own directory:

docker compose up -d
Configuration

Create config.yaml

For Docker installs, place config.yaml next to the SimpleForge compose file. The compose file mounts it into the container at SimpleForge's normal config path.

name: simpleforge
port: 8080
database:
  host: host.docker.internal
  port: 5433
  user: forger
  password: forger
  name: simpleforge
  sslmode: disable
log_pretty: true
log_levels:
  - info
  - warn
  - error

The database host must be reachable from inside the SimpleForge container. If PostgreSQL is on another server, use that server's hostname or IP address instead of host.docker.internal.

Docker

Create docker-compose.yml

This runs the SimpleForge image and mounts your config file into the container.

services:
  simpleforge:
    image: nomadisee/simpleforge:v0.0.1
    restart: unless-stopped
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./config.yaml:/home/simpleforge/.config/simpleforge/config.yaml:ro
    ports:
      - "8080:8080"

Start the server:

docker compose up -d
Setup

Initialize SimpleForge

Run these commands from the directory containing the SimpleForge compose file.

docker compose run --rm simpleforge public up --all
docker compose run --rm simpleforge tenant create mygame
docker compose run --rm simpleforge tenant up mygame --all
docker compose run --rm simpleforge api-key create mygame

Store the API key. It is shown once.

Verify

Check the server

curl http://localhost:8080/health

Create an attribute:

curl -X POST http://localhost:8080/tenant/mygame/attribute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "class",
    "options": [
      { "name": "warrior", "ordering": 1 }
    ]
  }'

Read attributes:

curl http://localhost:8080/tenant/mygame/attribute \
  -H "Authorization: Bearer YOUR_API_KEY"
CLI

Run admin commands

The same Docker image runs the server and the CLI. These commands start a temporary container, use the mounted config file, connect to PostgreSQL, then exit.

docker compose run --rm simpleforge public up --all
docker compose run --rm simpleforge tenant create mygame
docker compose run --rm simpleforge tenant up mygame --all
docker compose run --rm simpleforge api-key create mygame
docker compose run --rm simpleforge api-key rotate mygame
docker compose run --rm simpleforge api-key disable mygame
Update

Update SimpleForge

PostgreSQL data lives outside the SimpleForge image. Updating the image does not delete tenants, API keys, players, stats, events, or leaderboards.

docker compose pull simpleforge
docker compose run --rm simpleforge public up --all
docker compose run --rm simpleforge tenant up mygame --all
docker compose up -d

Version tags are immutable release points. Use nomadisee/simpleforge:v0.0.1 for a pinned release, or nomadisee/simpleforge:latest if you intentionally want the moving latest image.