Self-Hosting & Deployment
For teams that want to run the full Parsyn platform on their own infrastructure. Covers Docker Compose setup, environment configuration, reverse proxy, and production hardening.
Self-hosting is optional. Most users use the hosted platform at parsyn.progatis.com and connect their own workers to it. This guide is for organizations that need to run the entire platform in-house, typically for data sovereignty, compliance, or air-gapped environments.
What you're deploying
| Service | Purpose | Port |
|---|---|---|
| Backend API | FastAPI application + WebSocket server | 8000 |
| PostgreSQL 16 | Primary database (metadata, users, metrics) | 5432 |
| Redis 7 | Sessions, rate limiting, Celery broker | 6379 |
| MinIO | S3-compatible object storage (datasets, models, checkpoints) | 9000 / 9001 |
| Celery worker | Async tasks (statistics, preprocessing, notifications) | N/A |
| Frontend | Vue.js dashboard (served by nginx) | 80 |
Workers run on separate GPU machines and connect to the backend via WebSocket. They are not part of the Docker Compose stack.
Prerequisites
- Docker Engine 24+ and Docker Compose v2
- A server with at least 4 CPU cores and 8 GB RAM
- 50 GB+ disk space (more for datasets and model storage)
- A domain name pointed to your server (for HTTPS)
Setup
git clone https://github.com/Progatis/parsyn.git
cd parsyn
cp .env.example .envEdit .env with your configuration (see below), then:
# Development (with MinIO for local S3)
docker compose up -d
# Production (with Traefik routing)
docker compose -f docker-compose.prod.yml up -dVerify:
curl https://your-domain.com/health
# {"status": "ok"}Environment variables
Database
| Variable | Example | Description |
|---|---|---|
DATABASE_URL | postgresql+asyncpg://parsyn:secret@db:5432/parsyn | Async PostgreSQL connection string. |
DB_POOL_SIZE | 20 | Connection pool size. |
Redis
| Variable | Example |
|---|---|
REDIS_URL | redis://redis:6379/0 |
Object storage
| Variable | Example | Description |
|---|---|---|
S3_ENDPOINT | http://minio:9000 | S3 endpoint. Use https://s3.amazonaws.com for AWS. |
S3_BUCKET | parsyn-storage | Bucket for datasets, models, checkpoints. |
S3_ACCESS_KEY | minioadmin | S3 access key. |
S3_SECRET_KEY | minioadmin | S3 secret key. |
Authentication
| Variable | Description |
|---|---|
JWT_SECRET | Secret key for JWT signing. Generate with openssl rand -hex 32. Must be strong in production. |
JWT_ALGORITHM | Signing algorithm. Default: HS256. |
Always generate a random JWT_SECRET for production. If compromised, attackers can forge authentication tokens for any user.
Platform settings
| Variable | Default | Description |
|---|---|---|
ENVIRONMENT | development | Set to production for production. Affects CORS and debug mode. |
CORS_ORIGINS | Comma-separated allowed origins (e.g., https://app.yourdomain.com). | |
WORKER_HEARTBEAT_TIMEOUT | 90 | Seconds before a worker is marked offline. |
MAX_CONCURRENT_TRAININGS | 10 | Maximum simultaneous training jobs. |
MAX_UPLOAD_SIZE_BYTES | 10737418240 | Maximum file upload size (10 GB). |
Notifications (optional)
| Service | Variables |
|---|---|
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD | |
| Slack | SLACK_WEBHOOK_URL |
| Telegram | TELEGRAM_BOT_TOKEN |
| Teams | TEAMS_WEBHOOK_URL |
| SMS | TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER |
Billing (optional)
| Variable | Description |
|---|---|
STRIPE_SECRET_KEY | Stripe API key. |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret. |
STRIPE_SUCCESS_URL | Redirect after successful payment. |
STRIPE_CANCEL_URL | Redirect after cancelled payment. |
Reverse proxy (Traefik)
The production Docker Compose file includes Traefik labels for automatic HTTPS and routing. Each exposed service needs the traefik.docker.network label to prevent random connectivity issues.
When a container is on multiple Docker networks, Traefik can pick the wrong internal IP. This causes intermittent 502 errors after deploys. Always set traefik.docker.network explicitly on every exposed service.
# docker-compose.prod.yml (relevant labels)
services:
backend:
labels:
- "traefik.enable=true"
- "traefik.http.routers.parsyn-api.rule=Host(`api.yourdomain.com`)"
- "traefik.http.routers.parsyn-api.tls.certresolver=letsencrypt"
- "traefik.http.services.parsyn-api.loadbalancer.server.port=8000"
- "traefik.docker.network=${PROXY_NETWORK:-coolify}" Set PROXY_NETWORK to match your Traefik network. Common values: coolify (Coolify PaaS), dokploy-network (Dokploy), traefik or proxy (standalone).
Connecting workers to your instance
Workers connect to your self-hosted platform instead of parsyn.progatis.com:
PLATFORM_URL=wss://api.yourdomain.com/ws/worker
WORKER_ENROLLMENT_KEY=enroll_xyz789...Database management
The backend runs Alembic migrations automatically on startup. For manual migration:
# Apply pending migrations
docker compose exec backend alembic upgrade head
# Generate migration after model changes
docker compose exec backend alembic revision --autogenerate -m "add preferences table"
# Rollback one migration
docker compose exec backend alembic downgrade -1Backups
PostgreSQL
# Dump
docker compose exec db pg_dump -U parsyn parsyn > backup_$(date +%Y%m%d).sql
# Restore
cat backup.sql | docker compose exec -T db psql -U parsyn parsynObject storage
If using MinIO, back up its data directory. With AWS S3, enable versioning and cross-region replication.
Monitoring
Health checks
# Backend
curl https://api.yourdomain.com/health
# Detailed (database, redis, S3)
curl https://api.yourdomain.com/api/healthLogs
docker compose logs -f backend
docker compose logs --tail 100 celeryThe backend outputs structured JSON logs. Pipe them to your log aggregation system (ELK, Loki, Datadog).
Key metrics to watch
- Active workers: Alert if zero for more than 5 minutes.
- Stuck jobs:
runningwith no progress for 30+ minutes. - API latency: p95 should stay under 500ms.
- Database pool: Alert at 80% of
DB_POOL_SIZE. - Disk space: Alert at 80% on MinIO volume and PostgreSQL data.
Production security checklist
- Generate a strong
JWT_SECRET(at least 256 bits). - Change MinIO default credentials.
- Set
ENVIRONMENT=production. - Use HTTPS for all public endpoints (Traefik + Let's Encrypt).
- Don't expose database (5432) or Redis (6379) ports publicly.
- Enable 2FA for admin accounts.
- Set up regular database backups.
- Rotate worker API keys periodically.
- Set
TRUST_REMOTE_CODE=falseon workers.