Docker
The server image is ghcr.io/moinchat/moin-server, for linux/amd64 and linux/arm64. It works with every setup; this page starts with coordinator only.
1. Write the configuration
Create moin-server.toml:
toml
data_dir = "/data"
name = "Game Night"
rooms = "managed"
[access]
bootstrap_secret = "correct-horse-battery-staple"Keep data_dir = "/data" in every configuration you use with the image. The bootstrap secret lets you claim the community from the app.
2. Start the server
sh
docker run -d --name moin-server --restart unless-stopped --stop-timeout 60 \
-v moin-data:/data \
-v "$(pwd)/moin-server.toml:/config/moin-server.toml:ro" \
ghcr.io/moinchat/moin-server:latestOr with Docker Compose, in a compose.yaml next to the configuration:
yaml
services:
moin-server:
image: ghcr.io/moinchat/moin-server:latest
restart: unless-stopped
stop_grace_period: 60s
volumes:
- moin-data:/data
- ./moin-server.toml:/config/moin-server.toml:ro
volumes:
moin-data:sh
docker compose up -d3. Claim the community
Print the server ID:
sh
docker exec moin-server moin-server admin --config /config/moin-server.toml statusWith Compose, use docker compose exec moin-server instead of docker exec moin-server. Every other admin command runs the same way.
Then carry on from the coordinator-only guide: claim the community in the app, create rooms and invite people.
Volumes
| Path | Contents |
|---|---|
/data | The server's data directory. Back it up; see the data directory. |
/config/moin-server.toml | The configuration. |
The server runs as UID and GID 10001. A named volume works as is; a bind-mounted /data must be writable by that user.
Without a mounted configuration, the image starts a coordinator-only community called "Moin Community" with no bootstrap secret. Make yourself administrator with roles set.
Other setups
Write the configuration from the setup's guide, add data_dir = "/data", and publish its ports.
Behind a reverse proxy: set http_bind to 0.0.0.0:8080 so the proxy can reach it, then publish the HTTP port to the host only and the UDP port to everyone:
sh
-p 127.0.0.1:8080:8080 -p 7443:7443/udpIf the proxy runs in a container on the same Docker network, skip the HTTP port and point the proxy at moin-server:8080.
Self-contained: the guide's configuration works as is:
sh
-p 443:443/tcp -p 443:443/udp -p 7842:7842/udpLogs
sh
docker logs -f moin-serverSee Logs.
Upgrading
latest is the newest release. A version tag such as 2026.1 never changes; use one to choose when you upgrade.
sh
docker pull ghcr.io/moinchat/moin-server:latest
docker rm -f moin-serverThen start it again with the same docker run command. With Compose: docker compose pull && docker compose up -d. The data volume carries over.
