Deployment
Deploy ReadyKit to production.
Overview
ReadyKit provides multiple deployment options:
- Docker Compose - Full stack on any server
- Fly.io - Quick cloud deployment with CI/CD
- Railway - Simple cloud deployment with CI/CD
- Traditional - Manual setup on Ubuntu/Debian
Docker Compose (Recommended)
The simplest way to deploy. One command starts everything:
docker compose up --build -dThis starts:
- Flask app via uWSGI
- PostgreSQL database
- Redis for sessions and Celery
- Nginx reverse proxy on HTTP port 80; configure HTTPS separately
- Celery worker for background tasks
The web container uses an HTTP health check. The Celery container overrides it with a ping to its own worker through Redis. An unresponsive worker or unavailable broker causes this check to fail. Docker reports the health status; it does not restart an unhealthy container automatically.
The supplied Fly.io and Railway configs run only the web app. The systemd worker does not use Docker health checks. If you run a separate worker from the Docker image, override its HTTP health check as shown in docker-compose.yml.
Configuration
- Generate the Docker environment:
./setup.sh # Answer y to Docker configuration
# Review .env and configure HTTPS before serving users- Key production settings:
FLASK_DEBUG=0
SECRET_KEY=your_secure_random_key
SQLALCHEMY_DATABASE_URI=postgresql://user:pass@postgres:5432/readykit
# Billing (Stripe or Chargebee)
BILLING_PROVIDER=stripe # or chargebee
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...- Start the stack:
docker compose up --build -d- Initialize a fresh database and create an admin user:
docker compose exec website flask create-db
docker compose exec website flask installFor an existing database, use docker compose exec website flask db upgrade. create-db initializes tables and stamps migrations; it does not apply schema changes.
Fly.io Deployment
Quick cloud deployment with automatic CI/CD. See Fly.io Guide for detailed setup.
Use the Fly.io guide to configure the database, required secrets, and app name before deploying. The checked-in workflow runs manually by default.
Railway Deployment
Use the Railway guide to configure the services, environment, and deployment token. The checked-in workflow also runs manually by default.
Traditional Deployment
For manual setup on Ubuntu/Debian servers.
Prerequisites
- Python 3.11+
- PostgreSQL
- Redis
- Nginx
- Systemd
Server Setup
# Update system
sudo apt update && sudo apt upgrade -y
# Install dependencies
sudo apt install -y python3-pip python3-venv nginx redis-server postgresql
# Install uv
pip install uvApplication Setup
# Clone repository
git clone https://github.com/level09/readykit.git
cd readykit
# Setup environment
./setup.sh --full
# Configure production settings
nano .env # Update with production values
# Initialize database
source .venv/bin/activate
flask create-db
flask installSystemd Service
Create /etc/systemd/system/readykit.service:
[Unit]
Description=ReadyKit Web Application
After=network.target
[Service]
User=www-data
WorkingDirectory=/path/to/readykit
Environment="PATH=/path/to/readykit/.venv/bin"
ExecStart=/path/to/readykit/.venv/bin/gunicorn -w 4 -b 127.0.0.1:5000 run:app
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable readykit
sudo systemctl start readykitCelery Worker
Create /etc/systemd/system/readykit-celery.service:
[Unit]
Description=ReadyKit Celery Worker
After=network.target
[Service]
User=www-data
WorkingDirectory=/path/to/readykit
Environment="PATH=/path/to/readykit/.venv/bin"
ExecStart=/path/to/readykit/.venv/bin/celery -A enferno.tasks worker --loglevel=info
[Install]
WantedBy=multi-user.targetNginx Configuration
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static {
alias /path/to/readykit/enferno/static;
expires 30d;
}
}SSL with Let's Encrypt
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.comProduction Checklist
Security
- [ ] Set
FLASK_DEBUG=0 - [ ] Use strong
SECRET_KEY - [ ] Enable HTTPS only
- [ ] Set secure cookie flags
- [ ] Configure firewall (allow 80, 443, 22)
Billing (Stripe/Chargebee)
- [ ] Use live API keys (not test)
- [ ] Configure webhook endpoint
- [ ] Test webhook authentication
- [ ] Verify pricing displays correctly
Database
- [ ] Use PostgreSQL (not SQLite)
- [ ] Set up automated backups
- [ ] Configure connection pooling
Monitoring
- [ ] Set up error tracking (Sentry)
- [ ] Configure logging
- [ ] Set up uptime monitoring
- [ ] Monitor billing webhooks
Environment Variables
Essential production variables:
# Core
FLASK_DEBUG=0
SECRET_KEY=your_64_char_hex_key
SECURITY_PASSWORD_SALT=your_secure_salt
# Database
SQLALCHEMY_DATABASE_URI=postgresql://user:pass@localhost/readykit
# Redis
REDIS_SESSION=redis://localhost:6379/1
CELERY_BROKER_URL=redis://localhost:6379/2
# Billing (Stripe or Chargebee)
BILLING_PROVIDER=stripe # or chargebee
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PRO_PRICE_ID=price_...
STRIPE_WEBHOOK_SECRET=whsec_...
# OAuth (if using)
GOOGLE_AUTH_ENABLED=true
GOOGLE_OAUTH_CLIENT_ID=...
GOOGLE_OAUTH_CLIENT_SECRET=...Troubleshooting
Application Not Starting
# Check service status
sudo systemctl status readykit
# View logs
sudo journalctl -u readykit -fDatabase Connection Issues
# Test PostgreSQL connection
psql -U user -h localhost -d readykit
# Check environment variable
echo $SQLALCHEMY_DATABASE_URIBilling Webhooks Not Working
# Check webhook logs in your billing provider's dashboard
# Verify webhook secrets are set correctly
# For Stripe, test locally with:
stripe listen --forward-to localhost:5000/stripe/webhook