Session-gated MinIO save sync with AppImage GUI, CLI edit/session flow, and Gitea release helper. Co-authored-by: Cursor <[email protected]>
82 lines
3.2 KiB
Markdown
82 lines
3.2 KiB
Markdown
# MinIO + NGINX + Cloudflare
|
|
|
|
WAN path for SyncGames SSOT. Laptop and phone use this HTTPS endpoint only (no LAN/VPN requirement).
|
|
|
|
## Topology
|
|
|
|
```
|
|
Clients → https://syncgames-s3.<your-domain>
|
|
→ Cloudflare DNS (+ optional Access)
|
|
→ cloudflared Tunnel
|
|
→ NGINX on NAS
|
|
→ MinIO S3 API :9000
|
|
```
|
|
|
|
Keep MinIO Console (often `:9001`) on a separate vhost or LAN-only. SyncGames clients need the **S3 API** only.
|
|
|
|
## MinIO
|
|
|
|
Prefer Docker on the NAS: [deploy/docker/](../deploy/docker/) (`docker compose up -d`).
|
|
|
|
Manual checklist:
|
|
|
|
1. Bind API to `127.0.0.1:9000` (Compose does this).
|
|
2. Create bucket `syncgames` (private) — `docker compose --profile init run --rm createbuckets`.
|
|
3. Create an access key / secret for SyncGames devices (rotate periodically).
|
|
4. Set `MINIO_SERVER_URL=https://syncgames-s3.<your-domain>` so redirects/presigns use the public name if you use them (SyncGames prefers path-style without relying on redirects).
|
|
|
|
## NGINX (anti-grief checklist)
|
|
|
|
Example vhost: [deploy/nginx/syncgames-s3.conf](../deploy/nginx/syncgames-s3.conf)
|
|
|
|
Required behaviors:
|
|
|
|
| Setting | Why |
|
|
|---------|-----|
|
|
| Preserve `Host` as public hostname | SigV4 signing |
|
|
| `proxy_request_buffering off` | Avoid truncated large PUTs |
|
|
| `client_max_body_size 512m;` (or higher) | Emulator dumps |
|
|
| `proxy_http_version 1.1` | Keepalive / chunked |
|
|
| `ignore_invalid_headers off` | S3 headers with underscores |
|
|
| Forward `Authorization`, `X-Amz-*`, `Content-Length`, `X-Forwarded-Proto` | API correctness |
|
|
| **No** `auth_basic` | Breaks AWS SDKs — use Cloudflare Access instead |
|
|
|
|
## Cloudflare
|
|
|
|
1. Create Tunnel hostname `syncgames-s3.<domain>` → `http://127.0.0.1:80` (or whatever port NGINX listens on for that vhost).
|
|
2. Prefer Cloudflare Access (email OTP / your IdP) for defense-in-depth.
|
|
3. Orange-cloud proxy is fine for typical Souls/ER save sizes. If a huge upload fails (~100MB free-plan body limits can apply depending on product), check Cloudflare docs / plan or temporarily use a larger object split strategy.
|
|
|
|
## Client configuration
|
|
|
|
In `agent.toml`:
|
|
|
|
```toml
|
|
endpoint_url = "https://syncgames-s3.example.com"
|
|
bucket = "syncgames"
|
|
region = "us-east-1"
|
|
path_style = true
|
|
access_key = "..."
|
|
secret_key = "..."
|
|
```
|
|
|
|
Android settings screen uses the same values.
|
|
|
|
## Validation
|
|
|
|
```bash
|
|
syncgames doctor
|
|
```
|
|
|
|
Performs HEAD/list on the bucket and a tiny PUT/GET/DELETE probe object under `games/_probe/`. Failures usually mean Host/header/buffering misconfig on NGINX or Access blocking SDK traffic (use a Service Token or bypass path carefully for API clients if Access challenges browsers only — for programmatic S3, Access service tokens or skip Access on the API hostname and rely on MinIO keys + Cloudflare WAF IP restrictions).
|
|
|
|
### Cloudflare Access vs S3 SDKs
|
|
|
|
Browser Access login does **not** work for boto3/Android AWS SDK. Pick one:
|
|
|
|
1. **Access Service Auth** (service token headers) injected by agents — advanced, document if you enable it; or
|
|
2. **No Access on the S3 API hostname**, protect with strong MinIO keys + tunnel (not publicly documented); or
|
|
3. Separate hostname for human console only behind Access.
|
|
|
|
Recommended v1: tunnel + strong MinIO keys; optional IP allowlist / WAF; Access only on MinIO **Console** vhost if exposed.
|