Self-hosting
Run SuperFiles on your own infrastructure with Docker.
Self-hosting
SuperFiles runs as a single Docker container with no external runtime dependencies. SQLite is used for metadata; blobs are stored on a mounted volume.
Requirements
- Docker 24+ or Docker Compose 2.20+
- A Linux host (or any Docker-capable machine)
- At least 1 GB RAM and 10 GB free disk space (for blobs)
Quick start with Docker Compose
Create a docker-compose.yml:
services:
superfiles-api:
image: ghcr.io/miracleonyenma/proxmox-management/superfiles-api:latest
restart: unless-stopped
ports:
- "3100:3100"
environment:
NODE_ENV: production
PORT: "3100"
DATA_DIR: /data
BLOB_DIR: /data/blobs
SESSION_SECRET: "change-me-to-a-random-64-char-hex" # openssl rand -hex 32
PUBLIC_URL: "https://superfiles-api.example.com"
FRONTEND_URL: "https://superfiles.example.com"
MAIL_PROVIDER: console # or: resend / smtp
BOOTSTRAP_ADMIN_EMAILS: "admin@example.com"
volumes:
- superfiles_data:/data
superfiles-web:
image: ghcr.io/miracleonyenma/proxmox-management/superfiles-web:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
NODE_ENV: production
SUPERFILES_API_URL: "http://superfiles-api:3100"
NEXT_PUBLIC_SUPERFILES_API_URL: "https://superfiles-api.example.com"
volumes:
superfiles_data:
Start it:
docker compose up -d
The API is now running on port 3100 and the web dashboard on port 3000.
Environment variables
API (superfiles-api)
| Variable | Required | Default | Description |
|---|---|---|---|
SESSION_SECRET |
Yes | — | Secret for signing sessions. Generate with openssl rand -hex 32 |
DATA_DIR |
Yes | /data |
Root directory for the SQLite database |
BLOB_DIR |
Yes | $DATA_DIR/blobs |
Directory for content-addressed blob storage |
PUBLIC_URL |
Yes | — | Public URL of the API (used in email links) |
FRONTEND_URL |
Yes | — | Public URL of the web dashboard |
PORT |
No | 3100 |
Port to listen on |
MAIL_PROVIDER |
No | console |
resend | smtp | console |
RESEND_API_KEY |
If resend |
— | Resend API key |
MAIL_FROM_EMAIL |
No | — | Sender address for transactional emails |
MAIL_FROM_NAME |
No | SuperFiles |
Sender name |
BOOTSTRAP_ADMIN_EMAILS |
No | — | Comma-separated emails auto-promoted to platform_admin on startup |
PLAN_ENFORCEMENT_ENABLED |
No | false |
Set to true to enforce storage and feature quotas |
CDN_SIGNING_SECRET |
No | — | 32-char hex secret for signed CDN URLs (private buckets). openssl rand -hex 32 |
ERROR_REPORT_SECRET |
No | — | Token for the client-side error reporting endpoint |
PAY_DB_PATH |
No | $DATA_DIR/pay.db |
Path for the billing ledger SQLite database |
Web (superfiles-web)
| Variable | Required | Description |
|---|---|---|
SUPERFILES_API_URL |
Yes | Server-side API base URL (internal, e.g. http://superfiles-api:3100) |
NEXT_PUBLIC_SUPERFILES_API_URL |
Build-time | Client-side API base URL (baked into the JS bundle) |
NEXT_PUBLIC_APP_NAME |
No | Display name (default: SuperFiles) |
Reverse proxy with Caddy
Put SuperFiles behind Caddy for automatic TLS:
superfiles-api.example.com {
reverse_proxy localhost:3100
}
superfiles.example.com {
reverse_proxy localhost:3000
}
Reverse proxy with nginx
server {
listen 443 ssl;
server_name superfiles-api.example.com;
location / {
proxy_pass http://localhost:3100;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_request_buffering off; # required for streaming PUT uploads
client_max_body_size 0; # no limit; SuperFiles enforces plan quota
}
}
Initial setup
On first run, SuperFiles creates the SQLite schema automatically. If you set
BOOTSTRAP_ADMIN_EMAILS, the listed accounts are promoted to platform_admin
on every startup (idempotent).
Otherwise, register via the API:
curl -X POST http://localhost:3100/api/auth/sign-up \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "changeme",
"name": "Admin"
}'
Then sign into the web dashboard at http://localhost:3000 and navigate to the
Admin section to manage plans, users, and billing.
Upgrading
docker compose pull
docker compose up -d
SuperFiles applies schema migrations on startup. Always back up the DATA_DIR
volume before upgrading.
Backup
Back up both the database and the blob store:
# SQLite snapshot (safe while the API is running — uses SQLite's .backup API)
sqlite3 /path/to/data/superfiles.db ".backup /backups/superfiles.db.bak"
# Blob store (rsync-friendly; blobs are immutable once written)
rsync -a /path/to/data/blobs/ backup-host:/backups/superfiles-blobs/