83d4468b6991f6f87e9917bc01bf17070847376a
Downscale to 2000px JPEG before rembg, random blend opacity, timeout retries, per-variant remix prefill, lightbox, and longer SFTP idle. Co-authored-by: Cursor <cursoragent@cursor.com>
live.f12.rocks
Event photo pep pipeline: guests upload a photo via SFTP, a worker runs it
through rembg (background removal) + gmic (random filter/blend
compositing, ported from make_random.py), and a small web UI shows the
results with a "remix" option to try different filters on the same photo.
No web auth. This is an event tool, not a DAM.
Services (compose.yml)
| Service | What | Port |
|---|---|---|
sftpgo |
SFTP drop point, drakkan/sftpgo |
12121 (host) -> 2022 |
worker |
Watches inbox, runs the compose pipeline | none published |
web |
FastAPI + Jinja UI, browse jobs, remix | via Traefik only |
All three share one host directory (DATA_HOST_DIR, default ./data),
mounted at different paths — see the comment at the top of compose.yml.
Data layout (./data)
inbox/ # SFTP drop — worker only ever reads/copies from here
jobs/<job_id>/
original.<ext> # private copy of the uploaded photo
rembg.png # background removed (computed once, reused)
intermediates/ # every intermediate step, kept for inspection
variants/ # final composed images
manifest.json # filter names/commands/blends per variant
status.json # pending | processing | done | error
processed.json # worker bookkeeping: which inbox files were handled
assets/ (filter lists + trimmed filters.json) lives in the repo and is
bind-mounted read-only into worker/web at /data/assets.
Running it
cp .env.example .env
# edit .env: set a real SFTP_PASSWORD, and DATA_HOST_DIR on the server
docker compose up -d --build
Upload a photo:
sftp -P 12121 livef12@<host>
put photo.jpg
After a few seconds (poll interval + processing time) it shows up on the web UI as a new job.
Configuration (.env, see .env.example)
| Var | Default | Notes |
|---|---|---|
SFTP_USER / SFTP_PASSWORD |
livef12 / changeme |
SFTP login, home dir is locked to the shared inbox |
DATA_HOST_DIR |
./data |
On the server: /home/frank/live.f12.rocks/data |
SFTP_HOST_PORT |
12121 |
Host-side SFTP port (121212 is invalid TCP) |
OUTPUT_COUNT |
3 |
Variants generated per uploaded photo |
BLEND_OPACITY |
30% |
Default blend opacity for auto-generated variants |
FILTER_TIMEOUT |
120 |
Seconds before a single gmic call is killed |
MAX_FILTER_ATTEMPTS |
8 |
Random-filter retry budget per bg/fg pick |
NICE_LEVEL |
18 |
nice -n level for gmic/rembg subprocesses |
Deploy notes / caveats
- Port note: Spec originally said
121212, which exceeds TCP max (65535). Production default is12121. - Firewall: open host port
12121(SFTP) and make sure Traefik already routeslive.f12.rocks— this repo only adds the router labels, it assumes the externaltraefikdocker network exists. - SFTPGo first run: the
sftpgoservice auto-creates the SFTP user fromSFTP_USER/SFTP_PASSWORDon every start viasftpgo/entrypoint.sh(usesjq, bundled in the official image, to build aloaddataJSON safely — no manual admin setup needed). Host SSH keys persist in thesftpgo_statenamed volume, not in./data. The SFTPGo web admin exists internally on port 8080 but is deliberately not published or routed — there's no need for it here. - rembg model download: first background-removal call downloads the
u2netONNX model (~176 MB) from GitHub. This needs outbound internet on first run and can take a minute or two depending on the link; the model is cached in therembg_cachenamed volume afterwards, so restarts don't re-download it. - Inbox is append-only: the worker only ever copies out of
inbox/and never deletes or moves anything there — plan disk space accordingly, or clean upinbox/manually between events. - Sequential processing: the worker handles one photo at a time
(
cpus: "1.0", no concurrency) — fine for an event pace, but a burst of uploads will just queue up and get processed in order. - Deploy itself (
docker compose up -don the server) is on you — this repo doesn't run it automatically.
Description
Languages
Python
77.7%
HTML
11.1%
CSS
8%
Dockerfile
3.2%