This guide covers deploying Blik to DigitalOcean using two approaches:
- App Platform - Managed PaaS (recommended for quick deployment)
- Droplet - VPS with Docker Compose (recommended for cost optimization and full control)
- Prerequisites
- Option 1: App Platform Deployment
- Option 2: Droplet Deployment
- Post-Deployment
- Troubleshooting
- Cost Comparison
- DigitalOcean account (sign up here)
- GitHub repository with your Blik code
- Domain name (optional but recommended)
- Email service credentials (Gmail, SendGrid, Amazon SES, etc.)
# SECRET_KEY
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
# ENCRYPTION_KEY
python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'The fastest way to deploy Blik to DigitalOcean:
- Click the Deploy Button in the README
- Authorize GitHub - Grant DigitalOcean access to your repository
- Configure Environment Variables - See App Platform Configuration
- Review and Deploy - Click "Create Resources"
If you prefer manual setup or need more control:
- Log in to DigitalOcean
- Navigate to Apps in the left sidebar
- Click Create App
- Choose GitHub as source
- Authorize and select your repository
- Select the
masterbranch - Click Next
- Source Directory:
/(root) - Dockerfile Path:
Dockerfile - Build Command: (leave default)
- Run Command: (leave default - uses Dockerfile CMD)
- Click Add Database
- Select PostgreSQL
- Choose Version 15
- Select Basic plan ($15/month)
- Name it
db
- Name:
web - Instance Type: Basic
- Instance Size: Basic XXS ($5/month) for testing, Basic XS ($12/month) for production
- HTTP Port: 8000
See App Platform Configuration section below.
- Review your configuration
- Click Create Resources
- Wait 5-10 minutes for deployment
- Your app will be available at
https://your-app-name.ondigitalocean.app
Set these in the Environment Variables section:
| Variable | Type | Value | Notes |
|---|---|---|---|
DEBUG |
Plain | False |
Never use True in production |
ALLOWED_HOSTS |
Plain | ${APP_DOMAIN} |
Auto-provided by DO |
CSRF_TRUSTED_ORIGINS |
Plain | https://${APP_DOMAIN} |
Use your domain if custom |
DATABASE_URL |
Plain | ${db.DATABASE_URL} |
Auto-provided when DB attached |
DATABASE_TYPE |
Plain | postgres |
|
SECRET_KEY |
Secret | <generated> |
Generate using command above |
ENCRYPTION_KEY |
Secret | <generated> |
Generate using command above |
SESSION_COOKIE_SECURE |
Plain | True |
|
CSRF_COOKIE_SECURE |
Plain | True |
|
SECURE_SSL_REDIRECT |
Plain | True |
|
ORGANIZATION_NAME |
Plain | Your Org Name |
Optional - can set via /setup/ |
| Variable | Type | Value |
|---|---|---|
EMAIL_BACKEND |
Plain | django.core.mail.backends.smtp.EmailBackend |
EMAIL_HOST |
Secret | Your SMTP host (e.g., smtp.gmail.com) |
EMAIL_PORT |
Plain | 587 |
EMAIL_USE_TLS |
Plain | True |
EMAIL_HOST_USER |
Secret | Your email address |
EMAIL_HOST_PASSWORD |
Secret | Your email password/app password |
DEFAULT_FROM_EMAIL |
Plain | noreply@yourdomain.com |
Only if using subscription features:
| Variable | Type | Value |
|---|---|---|
STRIPE_PUBLISHABLE_KEY |
Secret | pk_live_... |
STRIPE_SECRET_KEY |
Secret | sk_live_... |
STRIPE_WEBHOOK_SECRET |
Secret | whsec_... |
STRIPE_PRICE_ID_SAAS |
Plain | price_... |
STRIPE_PRICE_ID_ENTERPRISE |
Plain | price_... |
- Go to Settings → Domains
- Click Add Domain
- Enter your domain (e.g.,
feedback.yourdomain.com) - Add the CNAME record to your DNS provider:
Type: CNAME Name: feedback (or @) Value: <provided-by-digitalocean>.ondigitalocean.app - Wait for DNS propagation (5-30 minutes)
- SSL certificate is automatically provisioned
- Logs: Apps → Your App → Runtime Logs
- Metrics: Apps → Your App → Insights
- Alerts: Apps → Your App → Settings → Alerts
For more control and cost optimization.
- Log in to DigitalOcean
- Click Create → Droplets
- Choose an image: Ubuntu 24.04 LTS
- Choose a plan: Basic → $6/month (1GB RAM)
- Choose a datacenter region (closest to your users)
- Authentication: SSH keys (recommended) or Password
- Hostname:
blik-production - Click Create Droplet
SSH into your droplet:
ssh root@your-droplet-ipClone your repository:
cd /opt
git clone https://github.com/yourusername/blik.git
cd blikRun the setup script:
sudo .do/droplet/deploy.sh setupThis will:
- Update system packages
- Install Docker and Docker Compose
- Configure UFW firewall (ports 22, 80, 443)
- Create project directory structure
Copy and edit the environment file:
cp .env.digitalocean.template .env.production
nano .env.productionFill in all required values (see .env.digitalocean.template for details).
Secure the environment file:
chmod 600 .env.productionsudo .do/droplet/deploy.sh deployThis will:
- Pull latest code (if git repo)
- Build Docker images
- Start all services (web, db, nginx, certbot)
- Run database migrations
- Collect static files
Check service status:
sudo .do/droplet/deploy.sh statusView logs:
sudo .do/droplet/deploy.sh logs
# Or for specific service:
sudo .do/droplet/deploy.sh logs webYour app is now running at:
- HTTP:
http://your-droplet-ip - HTTPS: Not yet configured (next step)
Add an A record in your DNS provider:
Type: A
Name: @ (or feedback)
Value: your-droplet-ip
TTL: 300
Wait for DNS propagation (can take 5-30 minutes). Verify:
dig yourdomain.com
# or
nslookup yourdomain.comRun the SSL setup script:
sudo .do/droplet/deploy.sh sslThis will:
- Prompt for your domain and email
- Update nginx configuration
- Obtain Let's Encrypt SSL certificate
- Configure nginx for HTTPS
- Set up automatic renewal
Your app is now accessible at:
https://yourdomain.com
Check certificate:
sudo docker compose -f .do/droplet/docker-compose.production.yml exec nginx ls -la /etc/letsencrypt/live/Test renewal (dry run):
sudo docker compose -f .do/droplet/docker-compose.production.yml exec certbot certbot renew --dry-runsudo .do/droplet/deploy.sh backupBackups are stored in /opt/blik/backups/
sudo .do/droplet/deploy.sh restoreUncomment the backup service in .do/droplet/docker-compose.production.yml to enable daily backups with 7-day retention.
Alternatively, use DigitalOcean's managed PostgreSQL with automated backups:
- Create Managed Database → PostgreSQL 15
- Update
docker-compose.production.ymlto remove thedbservice - Update
.env.productionwith managed database credentials
cd /opt/blik
git pull
sudo .do/droplet/deploy.sh deployVisit your application URL and navigate to /setup/:
- App Platform:
https://your-app.ondigitalocean.app/setup/ - Droplet:
https://yourdomain.com/setup/
Complete the installation wizard:
- Set organization name
- Create admin user
- Configure email settings (if not set via environment)
- Test email delivery
- Log in as admin
- Go to Admin → Questionnaires
- Select a template or create custom questionnaire
- Create a review cycle
- Invite participants
- SSL/HTTPS is working
-
DEBUG=Falsein environment - Strong
SECRET_KEYandENCRYPTION_KEY - Database password is secure
- Email is configured and tested
- Firewall is enabled (Droplet only)
- Regular backups are scheduled
- Admin user has strong password
See Custom Domain section above.
- Set up SPF, DKIM, and DMARC records for your domain
- Use a dedicated email service (SendGrid, Amazon SES) for better deliverability
- Configure email reply-to address
- App Platform: Use built-in Insights and Alerts
- Droplet: Consider setting up monitoring (e.g., Uptime Robot, New Relic)
Check logs:
Apps → Your App → Runtime Logs
Common causes:
- Missing environment variables
- Database not attached
- Invalid
SECRET_KEYorENCRYPTION_KEY - SMTP credentials incorrect
Solution:
- Verify all required environment variables are set
- Check that database component is attached
- Review build logs for errors
Blik uses WhiteNoise to serve static files. This should work automatically.
Verify:
- Check that
STATIC_ROOT=/app/staticfilesis set (automatic in Dockerfile) - Review build logs for
collectstaticoutput - Ensure WhiteNoise is in
INSTALLED_APPS(already configured)
Check firewall:
sudo ufw statusEnsure ports are open:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcpCheck nginx configuration:
sudo docker compose -f .do/droplet/docker-compose.production.yml exec nginx nginx -tCommon causes:
- SSL certificate paths incorrect (before SSL setup)
- Domain name not updated in
nginx.conf
Solution for initial deployment:
Edit .do/droplet/nginx.conf and comment out SSL certificate lines until you run the SSL setup.
Check database status:
sudo docker compose -f .do/droplet/docker-compose.production.yml ps dbView database logs:
sudo docker compose -f .do/droplet/docker-compose.production.yml logs dbVerify credentials:
Check that DATABASE_PASSWORD in .env.production matches the POSTGRES_PASSWORD.
Test SMTP connection:
# App Platform
doctl apps logs <app-id> --type RUN
# Droplet
sudo docker compose -f .do/droplet/docker-compose.production.yml exec web python manage.py shellfrom django.core.mail import send_mail
send_mail('Test', 'Test message', 'from@example.com', ['to@example.com'])Common causes:
- Incorrect SMTP credentials
- Gmail: Using account password instead of app password
- Firewall blocking port 587 (Droplet)
- SMTP host requires TLS on different port
Gmail setup:
- Enable 2-factor authentication
- Generate app password: https://myaccount.google.com/apppasswords
- Use app password in
EMAIL_HOST_PASSWORD
Check logs:
# App Platform
Apps → Runtime Logs
# Droplet
sudo .do/droplet/deploy.sh logs webCommon causes:
ALLOWED_HOSTSdoesn't include your domainCSRF_TRUSTED_ORIGINSdoesn't include your domain- Database migration not run
- Missing static files
If you encounter issues not covered here:
- Check logs (see above for how to access logs)
- Review environment variables against
.env.digitalocean.template - Consult main deployment docs:
docs/DEPLOYMENT.md - GitHub Issues: https://github.com/yourusername/blik/issues
- DigitalOcean Community: https://www.digitalocean.com/community
| Component | Tier | Monthly Cost |
|---|---|---|
| Web Service | Basic XXS (512MB) | $5 |
| Web Service | Basic XS (1GB, recommended) | $12 |
| PostgreSQL | Basic (1GB, 10GB storage) | $15 |
| Total (Testing) | $20 | |
| Total (Production) | $27 |
Pros:
- Fully managed
- Auto-scaling
- Zero-downtime deployments
- Automatic SSL
- Built-in monitoring
- GitHub auto-deploy
Best for: Quick deployment, managed infrastructure, teams without DevOps
| Component | Tier | Monthly Cost |
|---|---|---|
| Droplet | Basic (1GB RAM, 25GB SSD) | $6 |
| Droplet | Basic (2GB RAM, 50GB SSD) | $12 |
| Backups | +20% of droplet cost | $1.20-$2.40 |
| Total (Small) | $7.20 | |
| Total (Production) | $14.40 |
Optional Add-ons:
- Managed PostgreSQL: +$15/month (high availability, automated backups)
- Spaces (object storage): $5/month (if needed for media files)
Pros:
- Lower cost
- Full control
- Can run multiple apps
- Local volume storage
Cons:
- Manual management
- No auto-scaling
- Responsible for security updates
- Manual SSL renewal monitoring
Best for: Cost optimization, full control, existing DevOps expertise
- Complete post-deployment checklist
- Set up monitoring and alerts
- Configure automated backups
- Plan scaling strategy
- Review security best practices
- Set up staging environment