Cloud hosting
Managed Asobi is live at console.asobi.dev. This walkthrough takes you from nothing to a running game: install the asobi CLI, log in, pick your game, scaffold and edit your Lua, create an environment, deploy, and point your client at it. EU-hosted, and the core is open source, so you can self-host any time.
About 10 minutes to a running game. We run the servers and the database, so there is no Docker or Postgres to manage - just the asobi CLI and your Lua. Want to try free first? Self-host it locally in one command - no account needed.
Before you start. You need a browser signed in to console.asobi.dev. No server-side Lua yet? asobi init scaffolds a working starter match for you below, and the server Lua guide explains the callbacks when you want to go deeper.
1. Install the CLI
The asobi CLI is a single binary. Install the latest release with the one-line installer. On Linux and macOS:
curl -fsSL https://raw.githubusercontent.com/widgrensit/asobi-cli/main/install.sh | shOn Windows (PowerShell), or with winget install widgrensit.asobi / scoop install asobi:
irm https://raw.githubusercontent.com/widgrensit/asobi-cli/main/install.ps1 | iexPrefer to build from source? With Go 1.26+:
git clone https://github.com/widgrensit/asobi-cli
cd asobi-cli
go build -o bin/asobi ./cmd/asobi
ln -s $(pwd)/bin/asobi ~/bin/asobiCheck it is on your path:
asobi health2. Log in
Authenticate the CLI against the control plane. This uses a browser device-code flow, so no passwords or keys are typed into the terminal:
asobi loginIt opens the approval page at console.asobi.dev/dashboard/cli/login, where you are already signed in. Approve the session there and pick your tenant. The CLI stores its credentials in ~/.asobi/credentials.json (owner-only permissions) and you are ready to go.
Confirm the session any time with:
asobi whoami3. Select your game
Your CLI token is scoped to your tenant, which can hold several games, so you pick an active game the way gcloud picks a project. List the games in your tenant:
asobi gamesEach row shows a slug and a name. Set the active game by its slug (stored in ~/.asobi):
asobi use my-gameEvery later command then targets that game. Override it for a single command with --game <slug>, and check the active game any time with asobi whoami.
4. Scaffold your game
No Lua yet? asobi init writes a working starter game into a directory: a real minimal lua/match.lua plus a README to get you moving.
asobi init mygameOpen mygame/lua/match.lua and edit the match callbacks to build your game. See the server Lua guide and the game.* API reference for the full callback set.
Want to run it before deploying? asobi dev boots the asobi_lua image and Postgres locally in Docker - no account, no keys - and hot-reloads lua/ as you edit.
Multiple game modes
By itself match.lua loads as the default mode. To ship more than one mode, add a lua/config.lua manifest mapping mode names to files; clients then pick one with matchmaker.add {mode = ...}.
-- lua/config.lua
return {
default = "match.lua",
ranked = "ranked.lua"
}Want a whole backend, not just Lua? For a complete runnable example - docker-compose.yml, the mode manifest, and every ASOBI_* environment variable in one repo - scaffold from the backend template:
asobi init mybackend --template backendThat is the self-host on-ramp. The runtime config it exposes is documented on the Configuration page.
5. Create an environment
An environment is your own isolated engine with its own database. Create one named prod:
asobi create prodPick a size with --size (xs, s, m, or l) if you want more headroom than the default:
asobi create prod --size s6. Deploy your Lua
With the asobi init scaffold your Lua lives in lua/, so deploy that directory to the environment. The deploy is scoped to the active game you set with asobi use (or a --game override):
asobi deploy prod luaThe CLI zips your Lua, uploads it, and returns a generation number and a sha256. The running engine hot-reloads the new code into the live game: no restart, no dropped connections. Edit a file, run asobi deploy prod lua again, and the next match picks up the change while in-flight matches finish on the old code.
Closing the loop. For the callbacks that make up a match.lua (init, join, handle_input, tick), see the server Lua guide and the game.* API reference.
7. Manage your environments
List everything you have, with each environment's status and endpoint:
asobi envsStart, stop, and delete them as you go:
asobi start prod
asobi stop prod
asobi delete prodasobi config show prints the CLI's current context, and asobi health checks the engine is reachable.
8. Connect your client
Once an environment is started it has a public endpoint of the form <game-slug>-<env-name>.<tenant-slug>.asobi.dev, for example pong-prod.acme.asobi.dev. Copy the actual Endpoint shown in the dashboard or in asobi envs rather than assembling it by hand.
Your client SDK connects straight to that endpoint over a secure WebSocket on port 443. In Defold:
local asobi = require("asobi.client")
self.client = asobi.create("pong-prod.acme.asobi.dev", 443, true)Swap in your own endpoint. The Defold quickstart has the full client code: authenticate, join the matchmaker, and render the server's authoritative state.
How it works
The CLI talks to the Asobi control plane at console.asobi.dev. Each environment is your own single-tenant engine with its own database, isolated from every other tenant.
asobi deploy uploads a new generation of your Lua to the control plane, which pushes it to your engine. The engine hot-reloads it into the running game on the BEAM, so a deploy never restarts the server or drops a connected player.
Your client SDK connects directly to the environment's endpoint over WebSocket; game traffic does not go through the control plane. Asobi is single-node by design: one environment is one engine, kept simple and predictable.
That's the loop. Write Lua, asobi deploy, and your client connects to a live, hot-reloadable game with no infrastructure to run yourself.
Where next?
- Server Lua guide - write the match callbacks you deploy.
- Defold quickstart - the full client side of the loop.
- Self-host - run the same engine on your own infrastructure.