1. Provide PostgreSQL
Use managed PostgreSQL, a VM, or your own container. SimpleForge only needs a reachable host, database, user, and password.
SimpleForge runs as a Docker image or native binary. You provide PostgreSQL. SimpleForge manages schemas, tenants, migrations, API keys, and the HTTP server.
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.
Use managed PostgreSQL, a VM, or your own container. SimpleForge only needs a reachable host, database, user, and password.
The config file is the source of truth for the SimpleForge server and CLI.
Initialize the public schema, create a tenant, run tenant migrations, and create an API key.
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
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.
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
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.
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"
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
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.