Open source game server with authentication, users, lobbies, server scripting and an admin portal.
Game + Backend = Gamend
Discord | Guides | API Docs | Elixir Docs | Deployment Tutorial | Scaling Article
- Elixir 1.20 & Erlang/OTP 29 — see
.tool-versions, the same pins as gamend; with asdf just runasdf install - Rust (rustup) — required to build the WebRTC native dependency (
ex_sctp) - PostgreSQL — optional. Dev uses SQLite by default; set
GAMEND_DB_POSTGRES_*orGAMEND_DB_URLin.envto use Postgres instead, thenmix deps.clean gamend_core gamend_web --build && mix compile(the adapter is chosen at compile time).
- Copy
.env.exampleto.env. - Install dependencies and start the app from the repo root:
mix deps.get
mix dev.startThe app runs on localhost:4000 (SQLite database, device auth enabled).
With a gamend checkout beside this one at ../gamend, the engine is built from
it and edits there show up here. Without one, it comes from Hex.
mix test
mix lint # format check, credo --strict
mix precommit # compile, format, test, credo, API lintCI also runs dialyzer, mix deps.audit and a Docker build.
Working on this repository, human or agent: AGENTS.md.
Alternatively, run it in a container. It reads .env, so copy .env.example first:
docker compose upFor server plugins that run Godot headless, Dockerfile.godot adds Godot 4.7
on top of this image: build docker build -t gamend-starter . first, then
docker build -f Dockerfile.godot ..
You should now see on localhost:4000:
For multi-node deployment, you need Postgres, Redis, a scalable app service (Elixir nodes), and an nginx proxy that load-balances requests to the app replicas.
-
Configure
.envfile (copy.env.exampleto.env). -
Start services with 2 app replicas:
docker compose -f docker-compose.multi.yml up --scale app=2You can configure the:
modules/starter_config.json: Website settings (title, tagline, links) and branding paths (logo, favicon, banner, css).modules/plugins/starter_hook: An example Elixir plugin with custom hook logic. Build it so its hooks load locally:cd modules/plugins/starter_hook && mix deps.get && mix compile && mix plugin.bundle(or reload it from the admin console). The Docker build compiles plugins automatically..env: Secrets (oauth/email/etc.)..env.examplelists everyGAMEND_*setting and is generated: runmix gamend.settings.env_exampleafter a gamend update. It leaves outSENTRY_DSN, which the bundled Sentry client reads itself; nothing sends errors to Sentry until you add its logger handler (Sentry.LoggerHandler).priv/static/theme.css: The theme.priv/static/images: The images used in the website.
A minimal Godot demo project lives in godot/ — it logs in and
calls the example starter_hook.hello function over HTTP, WebSocket, and WebRTC.
See godot/README.md for setup (install the Gamend SDK from the
Asset Library, point
it at your server, run).
- Fork this repo.
- Go to fly.io (or another docker provider).
- Connect the app with the repo you forked.
- Launch the app and set your secrets. The
GAMEND_AUTH_SECRET_KEY_BASEinfly.tomlanddocker-compose.ymlis a public placeholder: generate your own withmix phx.gen.secret.

