Deployment reference
This page covers running the stack by hand. The installer does all of it automatically.
Docker Compose
Section titled “Docker Compose”cp .env.example .env # set TIFUSI_SECRET_KEY; set TIFUSI_PUBLIC_URL when behind a reverse proxydocker compose up -d --build| Service | Container | Ports |
|---|---|---|
| Panel API | tifusi-panel |
8000 (API, loopback only), 80 (ACME HTTP-01 challenge only) |
| Dashboard | tifusi-dashboard |
8080 (HTTP), 443 (HTTPS) |
Every port above is chosen during installation and changeable afterwards with tifusi panel port; answer r at any prompt for a random free one. The only exception is 80, which is fixed because the panel answers Let’s Encrypt’s HTTP-01 challenge there. The HTTPS port is TIFUSI_DASHBOARD_HTTPS_PORT and defaults to 443; set it to one of 2053, 2083, 2087, 2096 or 8443 for an origin behind Cloudflare’s proxy, and keep TIFUSI_PUBLIC_URL in step, since only 443 is implied by a bare https://host.
SQLite data is stored in ./data. TIFUSI_PUBLIC_URL defines the base URL used in subscription links; without it, links are derived from the request Host header, which is not reachable from clients when the panel runs behind a proxy. The value can later be changed from Settings at runtime.
TLS on the dashboard
Section titled “TLS on the dashboard”The dashboard container terminates TLS on port 443 and proxies /api/, /sub/, /code/ and /app/ to the panel. It reads fullchain.pem and privkey.pem from ./certs, which is watched continuously; certificate changes take effect without a restart. Certificates can be supplied by the installer, uploaded under Settings → SSL Certificate, or placed in ./certs manually.
Direct TLS on the API
Section titled “Direct TLS on the API”For deployments without the dashboard container, uvicorn can terminate TLS directly:
TIFUSI_SSL_CERTFILE=/app/certs/fullchain.pemTIFUSI_SSL_KEYFILE=/app/certs/privkey.pemMount ./certs:/app/certs:ro in docker-compose.yml. Both variables must be set together; setting only one aborts startup rather than falling back to plain HTTP.
Database migrations
Section titled “Database migrations”The schema is managed with Alembic, and alembic upgrade head runs on every startup. When a model changes, generate and review a migration:
cd backendalembic revision --autogenerate -m "describe the change"SQLite requires op.batch_alter_table(...) for column alterations that cannot be applied in place; review autogenerated revisions before committing. The test suite fails when the migration chain has more than one head, when a recent migration can’t be reversed, or when the migrated schema differs from the models.
