game builds proxy
This commit is contained in:
5
Dockerfile
Normal file
5
Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
FROM nginx:alpine
|
||||||
|
COPY nginx.conf.template /etc/nginx/nginx.conf.template
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh && mkdir -p /var/cache/nginx/builds
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
91
README.md
Normal file
91
README.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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.
|
||||||
36
deploy.sh
Normal file
36
deploy.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Upload a build to Hetzner Object Storage.
|
||||||
|
# Usage: ./deploy.sh ./dist [version]
|
||||||
|
#
|
||||||
|
# If version is omitted, uses the current git short hash.
|
||||||
|
# Requires: s3cmd configured for Hetzner Object Storage.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BUILD_DIR="${1:?Usage: ./deploy.sh <build-dir> [version]}"
|
||||||
|
VERSION="${2:-$(git rev-parse --short HEAD 2>/dev/null || date +%s)}"
|
||||||
|
|
||||||
|
# Configure these for your setup
|
||||||
|
BUCKET="s3://your-builds-bucket"
|
||||||
|
PREFIX="builds"
|
||||||
|
SITE_URL="https://builds.kill.systems"
|
||||||
|
|
||||||
|
# Hetzner Object Storage endpoint
|
||||||
|
S3CMD_OPTS="--host=fsn1.your-objectstorage.com --host-bucket=%(bucket)s.fsn1.your-objectstorage.com"
|
||||||
|
|
||||||
|
if [[ ! -d "$BUILD_DIR" ]]; then
|
||||||
|
echo "ERROR: $BUILD_DIR is not a directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Uploading build $VERSION..."
|
||||||
|
s3cmd sync \
|
||||||
|
$S3CMD_OPTS \
|
||||||
|
--acl-public \
|
||||||
|
--no-mime-magic \
|
||||||
|
--guess-mime-type \
|
||||||
|
"$BUILD_DIR/" \
|
||||||
|
"${BUCKET}/${PREFIX}/${VERSION}/"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Build uploaded:"
|
||||||
|
echo " ${SITE_URL}/${VERSION}/"
|
||||||
6
entrypoint.sh
Normal file
6
entrypoint.sh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
envsubst '$BUCKET_ORIGIN $BUCKET_HOST' \
|
||||||
|
< /etc/nginx/nginx.conf.template \
|
||||||
|
> /etc/nginx/conf.d/default.conf
|
||||||
|
exec nginx -g 'daemon off;'
|
||||||
27
nginx.conf
Normal file
27
nginx.conf
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
proxy_cache_path /var/cache/nginx/builds levels=1:2
|
||||||
|
keys_zone=builds:10m max_size=2g
|
||||||
|
inactive=30d use_temp_path=off;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 3000;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass $BUCKET_ORIGIN;
|
||||||
|
proxy_cache builds;
|
||||||
|
proxy_cache_valid 200 30d;
|
||||||
|
proxy_cache_valid 404 1m;
|
||||||
|
proxy_intercept_errors on;
|
||||||
|
|
||||||
|
proxy_hide_header x-amz-request-id;
|
||||||
|
proxy_hide_header x-amz-id-2;
|
||||||
|
proxy_hide_header x-amz-meta-s3cmd-attrs;
|
||||||
|
proxy_hide_header Set-Cookie;
|
||||||
|
proxy_ignore_headers Set-Cookie;
|
||||||
|
|
||||||
|
proxy_set_header Host $BUCKET_HOST;
|
||||||
|
proxy_set_header Cookie "";
|
||||||
|
proxy_set_header Authorization "";
|
||||||
|
|
||||||
|
add_header X-Cache-Status $upstream_cache_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user