terainia/DEPLOY.md
Maximus Gorog f239a939ce Add Docker + Caddy deploy for voxel.mxvs.art
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).
2026-05-23 18:45:05 -06:00

113 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 ~58 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.