Multi-stage Dockerfile compiles wasm client + axum server in one Rust builder and copies into a debian:bookworm-slim runtime (non-root uid). docker-compose.yml binds localhost:8080 by default; docker-compose.prod.yml replaces ports with a Caddy reverse proxy on host 80/443 that talks to the voxel container over the internal network. Caddy auto-issues Let's Encrypt certs. DEPLOY.md covers the three deployment modes (local-only, VPS with Cloudflare or Caddy, Cloudflare Tunnel from a workstation).
113 lines
3.1 KiB
Markdown
113 lines
3.1 KiB
Markdown
# Deploying the voxel game
|
||
|
||
Three layers, pick the combination that fits.
|
||
|
||
## Local-only (development)
|
||
|
||
```sh
|
||
docker compose up --build
|
||
```
|
||
|
||
Serves on `http://localhost:8080`. `127.0.0.1`-bound — not reachable from
|
||
the network. Good for iterating on Docker without exposing anything.
|
||
|
||
## Anywhere with a public IP (the real deploy)
|
||
|
||
This assumes a cheap VPS with Docker + docker-compose-plugin installed.
|
||
Tested targets: Hetzner CPX11 (~$5/mo), DigitalOcean Basic Droplet ($4),
|
||
Vultr (~$2.50), Oracle Cloud Always Free tier (ARM Ampere instance — free
|
||
forever, just slow to provision).
|
||
|
||
### 1. SSH in and install Docker
|
||
|
||
Debian/Ubuntu host:
|
||
|
||
```sh
|
||
curl -fsSL https://get.docker.com | sh
|
||
sudo usermod -aG docker $USER # log out + back in
|
||
```
|
||
|
||
### 2. Get the code on the box
|
||
|
||
```sh
|
||
git clone https://maxgit.wg/max/terainia.git # or wherever you push it
|
||
cd terainia
|
||
```
|
||
|
||
### 3. Build + run
|
||
|
||
```sh
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
|
||
```
|
||
|
||
The container binds to `0.0.0.0:8080`. The first build takes ~5–8 min on
|
||
a small VPS because it compiles Rust + the wasm client; subsequent
|
||
builds are fast due to layer caching.
|
||
|
||
### 4. Put TLS in front
|
||
|
||
You have two clean options here.
|
||
|
||
**Option A — Cloudflare proxy (no cert on the VPS, simplest).**
|
||
|
||
- In your Cloudflare dashboard for `mxvs.art`, add an A record:
|
||
`voxel` → `<VPS public IP>`, proxy status **Proxied** (orange cloud).
|
||
- Cloudflare → SSL/TLS → set encryption mode to **Flexible**
|
||
(Cloudflare terminates HTTPS, talks HTTP to the VPS).
|
||
- That's it. `https://voxel.mxvs.art` serves the game.
|
||
|
||
**Option B — Caddy on the VPS for Let's Encrypt.**
|
||
|
||
If you want real end-to-end TLS instead of Cloudflare-terminated:
|
||
|
||
```yaml
|
||
# docker-compose.prod.yml addition
|
||
caddy:
|
||
image: caddy:2-alpine
|
||
restart: always
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
volumes:
|
||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||
- caddy_data:/data
|
||
- caddy_config:/config
|
||
|
||
volumes:
|
||
caddy_data:
|
||
caddy_config:
|
||
```
|
||
|
||
```caddy
|
||
# Caddyfile
|
||
voxel.mxvs.art {
|
||
reverse_proxy voxel:8080
|
||
}
|
||
```
|
||
|
||
Then keep `voxel` bound to `127.0.0.1:8080` (or use Compose's internal
|
||
network only — drop the `ports:` mapping on the `voxel` service and let
|
||
Caddy reach it via the service name). The DNS A record in Cloudflare
|
||
should be **DNS only** (grey cloud) in this case so Cloudflare doesn't
|
||
re-terminate TLS.
|
||
|
||
### 5. Deploy updates
|
||
|
||
```sh
|
||
git pull
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
|
||
```
|
||
|
||
Down-and-up time is a couple of seconds while the new container
|
||
swaps in.
|
||
|
||
## Local + Cloudflare Tunnel (no VPS)
|
||
|
||
If you don't want a VPS yet, the game can run on your machine and be
|
||
exposed through a Cloudflare named tunnel pointing at `voxel.mxvs.art`.
|
||
The Dockerfile is still useful for keeping the local environment
|
||
consistent — just `docker compose up` and then point a `cloudflared`
|
||
container at `host.docker.internal:8080`. See the Cloudflare Tunnel
|
||
docs for the named-tunnel setup; the credential file (`cert.pem` from
|
||
`cloudflared tunnel login`) needs to land at `~/.cloudflared/cert.pem`
|
||
on whichever host the tunnel runs on.
|