--- 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-.sql.gz │ │ │ /backup/latest.sql.gz │ │ └─ sub2api (0.0.0.0:7860, talks to localhost PG/Redis)│ └─────────────────────────────────────────────────────────────┘ │ ▼ /backup is FUSE-mounted hf://buckets//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 /sub2api-pgdump --private hf spaces volumes set /myapi-hub \ -v hf://buckets//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 = JWT_SECRET = # MUST be stable TOTP_ENCRYPTION_KEY = # MUST be stable ADMIN_EMAIL = you@example.com ADMIN_PASSWORD = DATABASE_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 /sub2api-pgdump` - **Download latest dump locally:** `hf buckets cp hf://buckets//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 `. ## 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).