Installation
Self-host OpenTraderWorld on your own machine or server. Takes about 5 minutes.
Containerized only (for now)
OpenTraderWorld runs as a Docker Compose stack, the only supported deployment. A native install is possible but not recommended: Docker keeps the install non-intrusive (everything lives in containers and volumes) and quick to rebuild. See Get Docker for why, and for per-OS install steps.
Requirements
- Docker with Docker Compose. Don't have it? Get Docker covers macOS, Windows and Linux in a few commands.
- Linux, macOS, or Windows.
- A free port (5454 by default; ports 80 + 443 for the HTTPS modes). You can change it during setup.
Check Docker is ready:
docker --version
docker compose versionOne-command install (recommended)
curl -fsSL https://raw.githubusercontent.com/G-OTW/OpenTraderWorld/master/install.sh | bashThe installer checks Docker is ready, downloads the deploy files (only the deploy/ directory, no source code, no toolchain) into ./opentraderworld, then hands off to the guided setup below, which pulls the prebuilt images from Docker Hub.
Options go after bash -s --:
curl -fsSL https://raw.githubusercontent.com/G-OTW/OpenTraderWorld/master/install.sh | bash -s -- --dir ~/otw| Option | Default | Notes |
|---|---|---|
--dir <path> | ./opentraderworld | Install directory. Refuses a non-empty directory or an existing install. |
--ref <ref> | master | Branch or tag to install. |
--build | off | Clone the full source and build the images locally instead of pulling (needs git and the toolchain). |
From a git clone (alternative)
git clone https://github.com/G-OTW/OpenTraderWorld.git
cd OpenTraderWorld/deploy
./setup.shThe guided setup
Both paths above run deploy/setup.sh. It asks a few questions, generates strong secrets, writes the config, and starts everything.
It prompts for:
| Question | Default | Notes |
|---|---|---|
| Network mode | 1 (localhost) | 1 this machine only · 2 LAN over plain HTTP · 3 LAN over HTTPS with a real certificate · 4 public internet at your own domain. Changeable later, see Network & remote access. |
| Admin username | admin | The admin account is created for you; a strong password is generated and shown once. |
| HTTP port | 5454 | Modes 1–2 only; modes 3 and 4 use 80 + 443. |
| DuckDNS domain / token / LAN IP | none | Mode 3 only. |
| Public domain | none | Mode 4 only, and it must already resolve to this server. |
| Log level | info | trace / debug / info / warn / error. |
Database and session secrets are generated automatically, so you never type them. They are written to deploy/.env (file permissions 600, never committed to git).
At the end, let the script start the stack: it waits for the API, creates your admin account, and prints the generated password once, so copy it before closing the terminal.
By default the setup pulls the prebuilt images from Docker Hub: no Rust or Node toolchain, first start in a couple of minutes. Run ./setup.sh --build to build the three services from source instead (development, local changes).
Headless servers
The admin is created by core itself on first boot (from deploy/.env), so you don't need a browser on the server. Note the printed password and sign in from any machine that can reach the app.
Reinstalling over previous data
If Docker volumes from a previous install exist, the setup offers to wipe them. The default is No everywhere: wiping (and losing the previous database) only happens on an explicit y. Fresh secrets over an old database volume can't work, so declining aborts the setup rather than starting a broken stack.
Manual install (alternative)
If you prefer to configure by hand:
cd deploy
cp .env.example .envEdit .env and set at least:
POSTGRES_PASSWORD: a strong passwordDATABASE_URL: must contain the same password, e.g.postgres://otw:YOUR_PASSWORD@postgres:5432/opentraderworldSESSION_SECRET: a long random string
Then start the stack. By default this pulls the prebuilt images from Docker Hub (no Rust or Node toolchain required):
docker compose -f docker-compose.yml -f docker-compose.images.yml \
--env-file .env --env-file network.env up -dBuild from source instead
For development, or to run local changes, omit the images override and build the three services yourself (needs the toolchain; the Rust build is slow):
docker compose --env-file .env --env-file network.env up --build -dCreate the admin (manual installs only)
If you used ./setup.sh and let it start the stack, your admin already exists, so skip ahead.
Otherwise, open the app in your browser (http://localhost:5454 by default). On the first visit, OpenTraderWorld detects there is no admin yet and shows the setup wizard: choose a username and password (min 8 characters), submit, and you land on the dashboard. Passwords are stored hashed with argon2.
Create the admin from the CLI (headless, no browser)
Hit the first-run endpoint from inside the stack: it works regardless of your bind interface or TLS mode, and refuses (HTTP 409) if an admin already exists:
cd deploy
docker compose --env-file .env --env-file network.env exec -T caddy \
wget -qO- --header=Content-Type:application/json \
--post-data='{"username":"admin","password":"CHOOSE-A-STRONG-ONE"}' \
http://core:8080/api/setupVerify it's running
- App:
http://localhost:5454(or your chosen port/domain) - Health check:
http://localhost:5454/api/health→{"status":"ok","service":"otw-core",...}
cd deploy
docker compose ps # container status
docker compose logs -f core # follow core logsEveryday operations
Run these from deploy/:
| Action | Command |
|---|---|
| Start | docker compose up -d |
| Stop | docker compose down |
| View logs | docker compose logs -f |
| Pull newer images | docker compose -f docker-compose.yml -f docker-compose.images.yml pull && docker compose up -d |
| Rebuild after changing code (source build) | docker compose up --build -d |
| Stop and wipe all data | docker compose down -v |
Your data lives in Docker named volumes and persists across up/down. It is only deleted with down -v.
Next steps
- First steps: sign in, set defaults, install modules.
- Network & remote access: reach the app from other devices, LAN HTTPS, public exposure.
- Something wrong? See Troubleshooting.