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:50:54 -04:00

Builds

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 ksys-builds
git init
git add .
git commit -m "game builds proxy"
git remote add origin https://src.kill.systems/<user>/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://ksys-builds.fsn1.your-objectstorage.com/builds/
    BUCKET_HOST=ksys-builds.fsn1.your-objectstorage.com
    
  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%