2026-03-15 19:47:44 -04:00
2026-03-15 19:47:44 -04:00
2026-03-15 19:26:37 -04:00
2026-03-15 19:26:37 -04:00
2026-03-15 19:26:37 -04:00
2026-03-15 19:26:37 -04:00

Game Builds Service

Nginx reverse proxy to Hetzner Object Storage with local caching. Upload builds with s3cmd, testers access them at https://builds.kill.systems/<version>/.

Setup

1. Create a public bucket for builds

In Hetzner Console → Object Storage, create a new bucket (e.g. kill-builds). Set visibility to public so Nginx can proxy to it without authentication.

Generate S3 credentials if you haven't already (Security → S3 Credentials).

2. Configure s3cmd locally

# Install
brew install s3cmd  # or apt install s3cmd

# Configure
s3cmd --configure \
  --host=fsn1.your-objectstorage.com \
  --host-bucket='%(bucket)s.fsn1.your-objectstorage.com'

Enter your Hetzner S3 access key and secret key when prompted.

3. Push this repo to Gitea

cd game-builds
git init
git add .
git commit -m "game builds proxy"
git remote add origin https://src.kill.systems/<user>/game-builds.git
git push -u origin main

4. Deploy in Dokploy

  1. Create a new project (e.g. "builds")
  2. Add a new Application service (not Docker Compose)
  3. Set source to your Gitea repo
  4. In Environment Variables, add:
    BUCKET_ORIGIN=https://kill-builds.fsn1.your-objectstorage.com/builds/
    BUCKET_HOST=kill-builds.fsn1.your-objectstorage.com
    
    Replace kill-builds with your actual bucket name.
  5. Set the port to 3000
  6. Deploy

5. Add the domain

In the Domains tab, add builds.kill.systems with HTTPS and Let's Encrypt on port 3000.

DNS at Squarespace:

Host: builds
Type: A
Data: 46.224.133.129

Uploading Builds

Edit deploy.sh and set your bucket name, then:

# Upload current build (uses git hash as version)
./deploy.sh ./dist

# Upload with a specific version name
./deploy.sh ./dist v1.2.3

# Upload with a custom label
./deploy.sh ./dist beta-march15

Testers visit https://builds.kill.systems/<version>/ to play.

How it works

Tester → builds.kill.systems → Nginx (cache) → Hetzner Object Storage
                                  ↓
                          Cached for 30 days
                          (builds are immutable)

First request fetches from Object Storage and caches locally. Subsequent requests are served from the Nginx cache. The X-Cache-Status response header shows HIT or MISS.

Since each build has a unique path (the git hash), cache invalidation is never needed — new builds go to new paths.

Description
No description provided
Readme 32 KiB
Languages
Shell 84.6%
Dockerfile 15.4%