document media hosting in readme and usecases

This commit is contained in:
2026-03-19 22:34:47 -04:00
parent 4516ed7bab
commit 6b1e78350f
2 changed files with 78 additions and 3 deletions
+47
View File
@@ -80,6 +80,9 @@ and verifies the site is live.
installed. Uses the deploy SSH key from Bitwarden Secrets Manager -- no
personal server access needed. See USECASES.md for full details.
`new-app.sh` also creates a Garage media bucket for the domain, allowing
media files to be served at `https://www.<domain>/media/`.
After the site is live, clone the app repo and customize it:
```bash
@@ -119,6 +122,47 @@ docker exec garage /garage layout apply --version 1
This only needs to be done once. If only hantim is reprovisioned, argento
retains the layout and hantim reconnects automatically.
## Media hosting
Media files (images, videos) are stored in Garage and served via nginx at
`/media/` on each domain. This keeps large files out of git repos.
**Endpoints:**
- `s3.hantim.net` — S3 API for uploads (authenticated with `media-key`)
- `garage.hantim.net` — Admin API for bucket management
- `https://www.<domain>/media/<path>` — public file access
**Uploading media:**
```bash
# Configure AWS CLI (one-time)
aws configure # key ID, secret key from bws, region: garage
aws configure set default.endpoint_url https://s3.hantim.net
# Upload files
aws s3 cp photo.jpg s3://example.com/photo.jpg
aws s3 sync static/media/ s3://example.com/
```
**Local development:** Store media in `static/media/` (gitignored) so files
are accessible at `/media/` when serving locally.
**Creating buckets manually** (for existing domains without buckets):
```bash
# Get admin token and media key ID from bws
# Create bucket
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"globalAlias": "example.com"}' https://garage.hantim.net/v2/CreateBucket
# Note the bucket ID from the response, then:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"bucketId": "BUCKET_ID", "accessKeyId": "MEDIA_KEY_ID", "permissions": {"read": true, "write": true, "owner": false}}' \
https://garage.hantim.net/v2/AllowBucketKey
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"websiteAccess": {"enabled": true, "indexDocument": "index.html"}}' \
"https://garage.hantim.net/v2/UpdateBucket?id=BUCKET_ID"
```
## Restoring from backup
Run the same three commands as provisioning. `bootstrap.sh` is idempotent:
@@ -139,6 +183,9 @@ Bitwarden Secrets Manager (project: `hantim`, fetched via `bws` CLI on the serve
| `hantim-vultr-api-key` | Vultr API key for DNS management | `new-app.sh` |
| `hantim-garage-rpc-secret` | Garage cluster RPC secret | `deploy.sh` |
| `hantim-garage-argento-node-id` | Argento's Garage node ID + address | `deploy.sh` |
| `hantim-garage-admin-token` | Garage admin API token | `deploy.sh`, `new-app.sh` |
| `hantim-garage-media-key-id` | S3 access key ID for media uploads | `new-app.sh`, `aws` CLI |
| `hantim-garage-media-secret-key` | S3 secret key for media uploads | `aws` CLI |
Machine accounts: `hantim-server` (token at `/etc/bws-token`), `hantim-ci` (reserved).
+31 -3
View File
@@ -62,9 +62,10 @@ From your dev machine (single command):
- `.gitea/workflows/deploy-example.com.yml`
- `docker/nginx/conf.d/example.com.conf` (HTTP->HTTPS, bare->www, proxy)
7. SSHes to server as deploy user, issues SSL cert via webroot (zero downtime)
8. Commits and pushes hantim-server (triggers deploy)
9. Triggers initial build of the app repo via Gitea API
10. Polls `https://www.example.com` until it responds (up to 3 minutes)
8. Creates Garage media bucket via admin API (create, allow media-key, enable website)
9. Commits and pushes hantim-server (triggers deploy)
10. Triggers initial build of the app repo via Gitea API
11. Polls `https://www.example.com` until it responds (up to 3 minutes)
After the site is live, clone the app repo and customize:
@@ -148,3 +149,30 @@ triggers automatically.
- Existing certs are skipped
- Brief nginx downtime (seconds) while certbot checks run
- Services are restarted
## 8. Upload media files
Media files (images, videos) are stored in Garage and served at `/media/`
on each domain.
```bash
# One-time setup
aws configure # key ID + secret from bws, region: garage
aws configure set default.endpoint_url https://s3.hantim.net
# Upload a single file
aws s3 cp photo.jpg s3://example.com/photo.jpg
# Sync a directory
aws s3 sync static/media/ s3://example.com/
```
**What happens:**
1. File is uploaded to the Garage S3 API via `s3.hantim.net`
2. Garage replicates the file to both nodes (hantim + argento)
3. File is accessible at `https://www.example.com/media/photo.jpg`
**Local development:** Store media in `static/media/` (gitignored). The app's
nginx serves these locally, matching the `/media/` path used in production.
**Reference in HTML:** Use absolute paths like `/media/photo.jpg`.