Deployment¶
paxx generates 12-factor apps that are deployable to any container platform. The Dockerfile is the universal interface - every platform knows how to run a container.
Quick Start¶
Add a deployment configuration to your project:
This generates deployment scripts, Docker Compose configuration, and a CI/CD pipeline.
Environment Variables¶
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
SECRET_KEY |
Yes | Cryptographic signing key (min 32 chars) |
ENVIRONMENT |
No | development, staging, production |
LOG_LEVEL |
No | DEBUG, INFO, WARNING, ERROR (default: INFO) |
LOG_FORMAT |
No | json or console (default: json in production) |
Generate a secret key:
Building the Container¶
The generated Dockerfile uses a multi-stage build for minimal image size.
Health Checks¶
The app exposes /health which returns:
200 OKwhen healthy503 Service Unavailablewhen database is unreachable
Configure your platform's liveness/readiness probes to hit this endpoint.
Database Migrations¶
Local¶
In Production¶
Access production environment, eg.:
Execute the same command as during local development:
Rollback¶
paxx db downgrade # Revert last migration
paxx db downgrade -2 # Revert last 2 migrations
paxx db downgrade abc123 # Downgrade to specific revision
Backwards-Compatible Migrations¶
For zero-downtime deploys, migrations should be backwards-compatible:
- Add nullable columns, not required ones
- Add new tables before removing old ones
- Use multi-phase migrations for breaking changes:
- Deploy: add new column (nullable)
- Backfill data
- Deploy: code uses new column
- Deploy: remove old column
Linux Server Deployment¶
Add the deployment configuration:
Generated Files¶
deploy/linux-server/
├── deploy.sh # Main deployment script
├── deploy-init.sh # Initial server setup
├── deploy-if-changed.sh # Deploy only if image changed
├── deploy-purge.sh # Clean up deployment
├── get-status.sh # Check deployment status
├── server-setup.sh # Server configuration
├── docker-compose.yml # Production compose file
├── traefik-dynamic.yml # Traefik routing config
├── .env.example # Production env template
├── README.md # Deployment documentation
└── certs/ # TLS certificates directory
.github/workflows/
└── build.yml # CI/CD pipeline
Setup Process¶
- Configure environment:
cp deploy/linux-server/.env.example deploy/linux-server/.env
# Edit .env with your production values
- Push to GitHub:
- Create a release tag:
This triggers the GitHub Actions build workflow.
- Initial server deployment:
Architecture¶
The linux-server deployment uses:
- Traefik - Reverse proxy with automatic HTTPS
- Docker Compose - Container orchestration
- systemd - Process management and auto-restart
- GitHub Actions - CI/CD pipeline
Server Requirements¶
- Ubuntu 22.04+ or Debian 12+
- Docker and Docker Compose installed
- SSH access with key-based authentication
- Domain name pointing to server IP
TLS Certificates¶
Place your certificates in deploy/linux-server/certs/:
Or use Let's Encrypt with Traefik's automatic certificate management.
Deployment Commands¶
# Initial deployment to a new server
./deploy/linux-server/deploy-init.sh user@server
# Standard deployment (pulls and restarts)
./deploy/linux-server/deploy.sh user@server
# Deploy only if image has changed
./deploy/linux-server/deploy-if-changed.sh user@server
# Check deployment status
./deploy/linux-server/get-status.sh user@server
# Remove deployment completely
./deploy/linux-server/deploy-purge.sh user@server
CI/CD Pipeline¶
The generated .github/workflows/build.yml provides:
- Build - Creates Docker image on tag push
- Push - Pushes to GitHub Container Registry
- Deploy - Optionally triggers deployment
Triggering Builds¶
Builds are triggered by version tags:
GitHub Secrets¶
Configure these secrets in your repository:
| Secret | Description |
|---|---|
DEPLOY_HOST |
Server hostname or IP |
DEPLOY_USER |
SSH username |
DEPLOY_KEY |
SSH private key |
Scaling¶
The production Dockerfile runs uvicorn with multiple workers:
Adjust workers based on CPU cores (2 * cores + 1 is a common formula).
For horizontal scaling, run multiple container instances behind a load balancer.
Platform-Specific Examples¶
Fly.io¶
# Create app
fly launch --no-deploy
# Create and attach Postgres
fly postgres create
fly postgres attach
# Run migrations
fly ssh console -C "paxx db upgrade"
# Deploy
fly deploy
Railway¶
- Create project with Postgres addon
DATABASE_URLis automatically set from the addon- Deploy via GitHub or
railway up - Run migrations:
railway run paxx db upgrade
AWS ECS¶
- Push image to ECR
- Create task definition with environment variables
- Run migration as one-off task before deploying
- Update service with new task definition
Generic Docker Host¶
# Build and push
docker build -t myregistry/myapp:latest .
docker push myregistry/myapp:latest
# On server
docker pull myregistry/myapp:latest
docker run -d \
-e DATABASE_URL="postgresql://..." \
-e SECRET_KEY="..." \
-p 8000:8000 \
myregistry/myapp:latest
Monitoring¶
Logs¶
View application logs:
# Local development
docker compose logs -f app
# Production (linux-server)
ssh user@server
cd /opt/myapp
docker compose logs -f app
Health Status¶
Metrics¶
Add the metrics infrastructure component for Prometheus and OpenTelemetry:
See Infrastructure for details.
Next Steps¶
Read the CLI Reference for all available commands