- Add TASK_REMINDER_HOUR, TASK_REMINDER_MINUTE, OVERDUE_REMINDER_HOUR, DAILY_DIGEST_HOUR config - Document schedule times in UTC with explanation table - Add worker verification steps to check logs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
11 KiB
11 KiB
Dokku Deployment Guide for Casera API
This guide provides step-by-step instructions for deploying the Casera Go API to a remote server using Dokku.
Table of Contents
- Prerequisites
- Server Setup
- Install Dokku
- Create the App
- Configure PostgreSQL
- Configure Redis
- Set Environment Variables
- Configure Storage
- Deploy the Application
- Configure SSL
- Set Up Worker Process
- Push Notifications (Optional)
- Maintenance Commands
- Troubleshooting
Prerequisites
Server Requirements
- Ubuntu 22.04 LTS (recommended) or 20.04 LTS
- Minimum 2GB RAM (4GB+ recommended for production)
- 20GB+ disk space
- Root or sudo access
- Domain name pointed to your server's IP
Local Requirements
- Git installed
- SSH key configured for server access
Server Setup
1. Connect to Your Server
ssh root@your-server-ip
2. Update System Packages
apt update && apt upgrade -y
3. Set Up Swap (Recommended for servers with limited RAM)
# Create 2GB swap file
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# Make permanent
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab
4. Configure Firewall
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Install Dokku
1. Download and Install Dokku
# Download the installation script
wget -NP . https://dokku.com/install/v0.34.4/bootstrap.sh
# Run the installer (takes 5-10 minutes)
sudo DOKKU_TAG=v0.34.4 bash bootstrap.sh
2. Configure Dokku
# Set your domain (replace with your actual domain)
dokku domains:set-global casera.treytartt.com
# Add your SSH public key for deployments
# Run this from your LOCAL machine:
cat ~/.ssh/id_rsa.pub | ssh root@your-server-ip dokku ssh-keys:add admin
3. Install Required Plugins
# PostgreSQL plugin
dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
# Redis plugin
dokku plugin:install https://github.com/dokku/dokku-redis.git redis
# Let's Encrypt plugin (for SSL)
dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
Create the App
1. Create the Dokku App
dokku apps:create casera-api
2. Set the Domain
dokku domains:add casera-api api.casera.treytartt.com
3. Configure Buildpack (if needed)
The app uses a Dockerfile, so Dokku will auto-detect it. If you need to force Docker builds:
dokku builder:set casera-api build-dir .
dokku builder-dockerfile:set casera-api dockerfile-path Dockerfile
Configure PostgreSQL
1. Create PostgreSQL Service
# Create the database service
dokku postgres:create casera-db
# Link to the app (automatically sets DATABASE_URL)
dokku postgres:link casera-db casera-api
2. Verify Connection
# Check the connection info
dokku postgres:info casera-db
# Connect to the database
dokku postgres:connect casera-db
3. Set Individual Database Variables
Dokku sets DATABASE_URL automatically, but the app expects individual variables:
# Get the database credentials
dokku postgres:info casera-db
# Set individual variables (replace with actual values from info command)
dokku config:set casera-api \
DB_HOST=dokku-postgres-casera-db \
DB_PORT=5432 \
POSTGRES_DB=casera_db \
POSTGRES_USER=postgres \
POSTGRES_PASSWORD=1mJPfu6rzG9r6xukcGbUOU5NoCg0jKfa
Configure Redis
1. Create Redis Service
# Create the Redis service
dokku redis:create casera-redis
# Link to the app (automatically sets REDIS_URL)
dokku redis:link casera-redis casera-api
2. Verify Connection
dokku redis:info casera-redis
Set Environment Variables
1. Required Variables
dokku config:set casera-api \
PORT=5000 \
DEBUG=false \
ALLOWED_HOSTS=api.casera.treytartt.com,localhost \
TIMEZONE=UTC \
SECRET_KEY=8553813eda361017a02677ed504abdd331537cfe6f7cc407345f037cc22c75fc
2. Email Configuration
dokku config:set casera-api \
EMAIL_HOST=smtp.fastmail.com \
EMAIL_PORT=587 \
EMAIL_USE_TLS=true \
EMAIL_HOST_USER=treytartt@fastmail.com \
EMAIL_HOST_PASSWORD=2t9y4n4t497z5863 \
DEFAULT_FROM_EMAIL="Casera <treytartt@fastmail.com>"
3. Apple Sign In (Optional)
dokku config:set casera-api \
APPLE_CLIENT_ID=com.tt.casera.CaseraDev \
APPLE_TEAM_ID=V3PF3M6B6U
4. Push Notifications (Optional)
dokku config:set casera-api \
GORUSH_CORE_PORT=8080 \
GORUSH_IOS_ENABLED=true \
GORUSH_IOS_KEY_PATH=/push_certs/AuthKey_R9N3SM2WD5.p8 \
GORUSH_IOS_KEY_ID=R9N3SM2WD5 \
GORUSH_IOS_TEAM_ID=V3PF3M6B6U \
GORUSH_IOS_TOPIC=com.tt.casera.CaseraDev \
GORUSH_IOS_PRODUCTION=true \
GORUSH_ANDROID_ENABLED=false
// GORUSH_ANDROID_APIKEY=your-firebase-server-key
5. Admin Panel URL
dokku config:set casera-api \
NEXT_PUBLIC_API_URL=https://api.casera.treytartt.com
6. View All Configuration
dokku config:show casera-api
Configure Storage
1. Create Persistent Storage Directory
# Create storage directory on host
mkdir -p /var/lib/dokku/data/storage/casera-api/uploads
# Set permissions
chown -R 32767:32767 /var/lib/dokku/data/storage/casera-api
2. Mount Storage to App
dokku storage:mount casera-api /var/lib/dokku/data/storage/casera-api/uploads:/app/uploads
Deploy the Application
1. Add Dokku Remote (Local Machine)
cd /path/to/myCribAPI-go
git remote add dokku dokku@your-server-ip:casera-api
2. Deploy
git push dokku master:main
# Or if your branch is already 'main':
git push dokku main
3. Watch Deployment Logs
# On server
dokku logs casera-api -t
4. Verify Deployment
# Check app status
dokku ps:report casera-api
# Check app is running
curl https://api.casera.treytartt.com/api/health/
Configure SSL
1. Set Let's Encrypt Email
dokku letsencrypt:set casera-api email admin@treytartt.com
2. Enable Let's Encrypt
dokku letsencrypt:enable casera-api
3. Set Up Auto-Renewal
dokku letsencrypt:cron-job --add
Set Up Worker Process
The worker process handles background jobs (task reminders, overdue alerts, daily digests, email sending, etc.).
1. Configure Worker Environment Variables
dokku config:set casera-api \
TASK_REMINDER_HOUR=20 \
TASK_REMINDER_MINUTE=0 \
OVERDUE_REMINDER_HOUR=9 \
DAILY_DIGEST_HOUR=11
Schedule times are in UTC:
| Variable | Default | Description |
|---|---|---|
TASK_REMINDER_HOUR |
20 | Hour to send "task due soon" notifications (8 PM UTC) |
TASK_REMINDER_MINUTE |
0 | Minute for task reminder |
OVERDUE_REMINDER_HOUR |
9 | Hour to send overdue task alerts (9 AM UTC) |
DAILY_DIGEST_HOUR |
11 | Hour to send daily summary (11 AM UTC) |
2. Scale Worker Process
# Scale to 1 worker
dokku ps:scale casera-api worker=1
# Verify processes
dokku ps:report casera-api
3. Verify Worker is Running
# Check worker logs
dokku logs casera-api -p worker
# Should see:
# "Registered task reminder job"
# "Registered overdue reminder job"
# "Registered daily digest job"
# "Starting worker server..."
7. Set Proxy Port
dokku proxy:ports-set gorush http:80:8080
8. Restart Gorush
dokku ps:restart gorush
9. Configure Casera API to Use Gorush
dokku config:set casera-api GORUSH_URL=http://gorush.web:8080
10. Verify Gorush is Running
# Check status
dokku ps:report gorush
# Check logs
dokku logs gorush
# Test health endpoint (if you have a domain set)
curl http://gorush.yourdomain.com/api/stat/go
Option B: Use External Push Service
Configure the app to use an external push notification service instead.
Maintenance Commands
View Logs
# Real-time logs
dokku logs casera-api -t
# Last 100 lines
dokku logs casera-api -n 100
# Worker logs
dokku logs casera-api -p worker
Database Operations
# Connect to database
dokku postgres:connect casera-db
# Export database backup
dokku postgres:export casera-db > backup.sql
# Import database backup
dokku postgres:import casera-db < backup.sql
Run Migrations Manually
# Enter the app container
dokku enter casera-api web
# Migrations run automatically on startup, but if needed:
/app/api migrate
Restart App
dokku ps:restart casera-api
Scale App
# Scale web process
dokku ps:scale casera-api web=2 worker=1
# View current scale
dokku ps:report casera-api
Stop/Start App
dokku ps:stop casera-api
dokku ps:start casera-api
Troubleshooting
Check App Status
dokku ps:report casera-api
dokku logs casera-api -n 200
Common Issues
1. App Won't Start
# Check logs for errors
dokku logs casera-api -n 500
# Verify environment variables
dokku config:show casera-api
# Check if ports are available
dokku proxy:ports casera-api
2. Database Connection Failed
# Verify link
dokku postgres:linked casera-api casera-db
# Check database is running
dokku postgres:info casera-db
# Re-link if needed
dokku postgres:unlink casera-db casera-api
dokku postgres:link casera-db casera-api
3. Redis Connection Failed
# Verify link
dokku redis:linked casera-api casera-redis
# Check Redis is running
dokku redis:info casera-redis
4. Storage/Upload Issues
# Check mounts
dokku storage:report casera-api
# Verify permissions
ls -la /var/lib/dokku/data/storage/casera-api/
5. SSL Certificate Issues
# Check certificate status
dokku letsencrypt:list
# Renew manually
dokku letsencrypt:enable casera-api
View Resource Usage
# Docker stats for all containers
docker stats
# Disk usage
dokku storage:report casera-api
df -h
Quick Reference
| Command | Description |
|---|---|
dokku apps:list |
List all apps |
dokku logs casera-api -t |
Tail logs |
dokku ps:restart casera-api |
Restart app |
dokku config:show casera-api |
Show env vars |
dokku postgres:connect casera-db |
Connect to DB |
dokku enter casera-api web |
Shell into container |
dokku ps:scale casera-api web=2 |
Scale processes |
Environment Variables Reference
| Variable | Required | Description |
|---|---|---|
SECRET_KEY |
Yes | 32+ character secret key |
DEBUG |
Yes | Set to false in production |
ALLOWED_HOSTS |
Yes | Comma-separated list of domains |
DATABASE_URL |
Auto | Set by postgres:link |
REDIS_URL |
Auto | Set by redis:link |
EMAIL_HOST |
Yes | SMTP server |
EMAIL_PORT |
Yes | SMTP port (587) |
EMAIL_HOST_USER |
Yes | SMTP username |
EMAIL_HOST_PASSWORD |
Yes | SMTP password |
APPLE_CLIENT_ID |
No | iOS Bundle ID |
APPLE_TEAM_ID |
No | Apple Developer Team ID |
GORUSH_URL |
No | Push notification server URL |
APNS_AUTH_KEY_PATH |
No | Path to APNs .p8 key |
APNS_AUTH_KEY_ID |
No | APNs Key ID |
APNS_TEAM_ID |
No | APNs Team ID |