myapi-hub / README.md
Looknicemm's picture
Update README + fix short_description length
1730f5f verified
|
Raw
History Blame Contribute Delete
5.01 kB
---
title: MyAPI Hub
emoji: πŸš€
colorFrom: indigo
colorTo: purple
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: sub2api + bundled PG/Redis sidecar with bucket dumps
---
# MyAPI Hub on Hugging Face Spaces
Single-container deployment of [Wei-Shaw/sub2api](https://github.com/Wei-Shaw/sub2api)
that bundles **PostgreSQL 18** and **Redis** as sidecars inside the same Space.
PGDATA lives on the Space's ephemeral disk; `pg_dump` runs on a timer and writes
to a mounted **Hugging Face bucket** for persistence across rebuilds.
## Architecture
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ HF Space container (single image) ─────────────┐
β”‚ supervisord β”‚
β”‚ β”œβ”€ postgres (127.0.0.1:5432, PGDATA=/var/lib/...) β”‚
β”‚ β”œβ”€ redis (127.0.0.1:6379, in-memory) β”‚
β”‚ β”œβ”€ backup.sh (every BACKUP_INTERVAL_MIN min) β”‚
β”‚ β”‚ pg_dump | gzip β†’ /backup/pg-<ts>.sql.gz β”‚
β”‚ β”‚ /backup/latest.sql.gz β”‚
β”‚ └─ sub2api (0.0.0.0:7860, talks to localhost PG/Redis)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό /backup is FUSE-mounted
hf://buckets/<you>/sub2api-pgdump
```
On cold boot, if PGDATA is empty *and* `/backup/latest.sql.gz` exists, the
entrypoint restores it before launching the app.
## Why not mount the bucket as PGDATA directly?
HF buckets are S3-style storage exposed via a FUSE filesystem. PostgreSQL
requires real `fsync` semantics for durability; running PGDATA on FUSE risks
silent corruption. We therefore keep live PGDATA on the Space disk and only
write **dumps** to the bucket (a workload FUSE handles safely).
## 1. Prerequisites
```bash
hf auth login # HF token with write to your namespace
hf buckets create <you>/sub2api-pgdump --private
hf spaces volumes set <you>/myapi-hub \
-v hf://buckets/<you>/sub2api-pgdump:/backup
```
Free accounts get **100 GB private storage**, far more than needed for dump
snapshots (a hobby DB compresses to a few MB).
## 2. Required Space secrets
In **Settings β†’ Variables and secrets** add as **secrets**:
```
POSTGRES_PASSWORD = <strong random β€” used by both PG and sub2api>
JWT_SECRET = <openssl rand -hex 32> # MUST be stable
TOTP_ENCRYPTION_KEY = <openssl rand -hex 32> # MUST be stable
ADMIN_EMAIL = you@example.com
ADMIN_PASSWORD = <leave empty to auto-generate; check logs>
DATABASE_PASSWORD = <same value as POSTGRES_PASSWORD>
```
Optional **variables** (defaults in parentheses):
```
POSTGRES_USER = sub2api
POSTGRES_DB = sub2api
BACKUP_INTERVAL_MIN = 30 # how often to dump
BACKUP_KEEP = 24 # how many timestamped dumps to retain
DATABASE_USER = sub2api # same as POSTGRES_USER
DATABASE_DBNAME = sub2api # same as POSTGRES_DB
LOG_LEVEL = info
```
Do **not** override `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_SSLMODE`,
`REDIS_HOST`, `REDIS_PORT`, `REDIS_ENABLE_TLS` β€” they are set in the Dockerfile
for the in-container loopback.
## 3. Deploy
Push `Dockerfile`, `entrypoint.sh`, `backup.sh`, `supervisord.conf`, `README.md`
to the Space repo. First build runs `initdb`, creates the database, and starts
the four sidecar processes. Subsequent rebuilds will restore from the latest
bucket dump if the ephemeral disk was wiped.
## 4. Operating
- **List dumps:** `hf buckets list <you>/sub2api-pgdump`
- **Download latest dump locally:** `hf buckets cp hf://buckets/<you>/sub2api-pgdump/latest.sql.gz ./`
- **Force a manual dump:** restart the Space (next cycle fires after `BACKUP_WARMUP_SEC`), or open a shell via dev mode and run `/usr/local/bin/backup.sh once`.
- **Disaster recovery:** download `latest.sql.gz`, restore into any Postgres with `gunzip -c latest.sql.gz | psql -d <db>`.
## 5. Caveats
- **RPO β‰ˆ BACKUP_INTERVAL_MIN.** Crash between dumps loses up to that many minutes of writes.
- **No external PG access.** Postgres binds `127.0.0.1` inside the Space; only the bundled sub2api can reach it. For psql from outside, use the dump file or run a tunnel (cloudflared/chisel) β€” not provided here.
- **Cold start = potential restore.** Free Spaces sleep after inactivity and may evict the ephemeral disk on hardware moves. The restore step runs only when PGDATA is empty, so warm restarts are fast.
- **Redis is non-persistent.** AOF/RDB disabled by design (sessions are cheap to re-create). Restart logs users out.
- **Pin secrets.** `JWT_SECRET` / `TOTP_ENCRYPTION_KEY` must not change across rebuilds, or all sessions / 2FA invalidate.
## License
Apache-2.0 (inherits from upstream sub2api).