Overview

Dokku is a Docker-powered PaaS that implements Heroku’s buildpack approach on your own server. It’s the most mature open-source PaaS, first released in 2013.
Best for: Teams wanting Heroku-like git-push deployments with proven stability and extensive plugin ecosystem.

Why Dokku?

Git-Push Deploys

git push dokku main to deploy

Mature & Stable

10+ years of development, battle-tested

Heroku Compatible

Uses Heroku buildpacks and Procfiles

Plugin Ecosystem

100+ official plugins for every need

Comparison with Other Methods

FeatureDokkuDokployCoolifyCapRover
Maturity★★★★★ (2013)★★★☆☆ (2023)★★★★☆ (2021)★★★★☆ (2018)
Git Push✅ Native❌ No✅ Yes✅ Yes
Web UI⚠️ Plugin✅ Yes✅ Yes✅ Yes
Buildpacks✅ Heroku❌ No✅ Nixpacks✅ Yes
Plugins✅ 100+❌ Limited⚠️ Some⚠️ Some
SSL✅ Let’s Encrypt✅ Built-in✅ Built-in✅ Built-in
Learning CurveMediumLowLowLow
Resource UsageLowMediumMedium-HighMedium
CommunityVery LargeGrowingLargeMedium
Verdict: Dokku is the most proven and stable option, but lacks native web UI (plugin available).

Prerequisites

  • Hetzner CPX32 (4 vCPU, 8GB RAM)
  • Ubuntu 24.04 or 22.04 LTS
  • Domain with DNS access
  • Comfortable with terminal/SSH

Installation

Step 1: Install Dokku

# SSH into VPS
ssh root@46.224.2.100

# Download and run installer
wget -NP . https://dokku.com/install/v0.34.3/bootstrap.sh
sudo DOKKU_TAG=v0.34.3 bash bootstrap.sh

# Installation takes ~5 minutes

Step 2: Initial Setup

Visit http://46.224.2.100 in browser to complete setup:
  1. Add SSH Public Key - Paste your ~/.ssh/id_rsa.pub
  2. Hostname - Enter your domain: dokku.yourdomain.com
  3. Virtualhost Naming - Enable (allows app.yourdomain.com)
Or via command line:
# Add your SSH key
cat ~/.ssh/id_rsa.pub | dokku ssh-keys:add admin

# Set global domain
dokku domains:set-global yourdomain.com

# Enable vhost-based routing
dokku domains:enable

Step 3: Install Essential 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 SSL
dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

# Optional: Web UI
dokku plugin:install https://github.com/dokku/dokku-graphite.git

Create RippleCore Apps

1. Create PostgreSQL Database

# Create database
dokku postgres:create ripplecore-db

# Verify
dokku postgres:info ripplecore-db

2. Create Redis Cache

# Create Redis
dokku redis:create ripplecore-cache

# Verify
dokku redis:info ripplecore-cache

3. Create Main App

# Create app
dokku apps:create app

# Set domain
dokku domains:set app app.yourdomain.com

# Link to PostgreSQL
dokku postgres:link ripplecore-db app

# Link to Redis
dokku redis:link ripplecore-cache app

# Set environment variables
dokku config:set app \
  BETTER_AUTH_SECRET="your_secret_32_chars" \
  BETTER_AUTH_URL="https://app.yourdomain.com" \
  BETTER_AUTH_TRUST_HOST="true" \
  NEXT_PUBLIC_APP_URL="https://app.yourdomain.com" \
  NEXT_PUBLIC_WEB_URL="https://yourdomain.com" \
  NODE_ENV="production"

# Enable SSL
dokku letsencrypt:enable app

4. Create API App

dokku apps:create api
dokku domains:set api api.yourdomain.com
dokku postgres:link ripplecore-db api
dokku redis:link ripplecore-cache api
dokku config:set api NODE_ENV="production"
dokku letsencrypt:enable api

5. Create Web App

dokku apps:create web
dokku domains:set web yourdomain.com www.yourdomain.com
dokku config:set web \
  NEXT_PUBLIC_APP_URL="https://app.yourdomain.com" \
  NEXT_PUBLIC_WEB_URL="https://yourdomain.com" \
  NODE_ENV="production"
dokku letsencrypt:enable web

Deploy with Git

Local Setup

# Add Dokku remote to your repo
cd /path/to/ripplecore-forge

git remote add dokku-app dokku@your-vps-ip:app
git remote add dokku-api dokku@your-vps-ip:api
git remote add dokku-web dokku@your-vps-ip:web

Configure for Monorepo

Since RippleCore is a monorepo, configure Dokku to build specific apps: Option 1: Dockerfile-based (Recommended) Create .dokku directory in monorepo root:
mkdir -p .dokku/app .dokku/api .dokku/web
.dokku/app/Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN corepack enable pnpm
RUN pnpm install --frozen-lockfile
RUN pnpm --filter @repo/app build
WORKDIR /app/apps/app
CMD ["pnpm", "start"]
Option 2: Buildpack with app.json Create app.json in each app directory:
{
  "name": "ripplecore-app",
  "description": "RippleCore Main Application",
  "buildpacks": [
    {
      "url": "heroku/nodejs"
    }
  ]
}

Deploy

# Deploy main app
git push dokku-app main:main

# Deploy API
git push dokku-api main:main

# Deploy web
git push dokku-web main:main
Dokku will:
  1. Detect buildpack or use Dockerfile
  2. Build the application
  3. Run database migrations (if configured)
  4. Deploy with zero-downtime
  5. Generate SSL certificate

Run Migrations

One-time Migration

# SSH into VPS
ssh root@your-vps-ip

# Run migration via dokku run
dokku run app "cd packages/database && pnpm db:push"

Auto-migrate on Deploy

Add to Procfile:
release: cd packages/database && pnpm db:push
web: cd apps/app && pnpm start
Dokku will run release command before each deployment.

Management Commands

App Management

# View all apps
dokku apps:list

# View app logs
dokku logs app -t

# Restart app
dokku ps:restart app

# Scale app (multiple containers)
dokku ps:scale app web=2

# Enter app container
dokku enter app

# Run one-off command
dokku run app node --version

Database Management

# Backup PostgreSQL
dokku postgres:export ripplecore-db > backup.sql

# Restore from backup
dokku postgres:import ripplecore-db < backup.sql

# Connect to database
dokku postgres:connect ripplecore-db

# View database info
dokku postgres:info ripplecore-db

SSL Management

# Enable auto-renewal
dokku letsencrypt:cron-job --add

# Force renewal
dokku letsencrypt:renew app

# View certificate info
dokku letsencrypt:list

Monitoring

# View resource usage
dokku ps:report app

# View all config
dokku config app

# View domains
dokku domains:report app

# Check app status
dokku ps:inspect app

Advanced Configuration

Zero-Downtime Deployments

Enable health checks in app.json:
{
  "healthchecks": {
    "web": [
      {
        "type": "startup",
        "name": "web check",
        "path": "/api/health",
        "attempts": 3
      }
    ]
  }
}

Custom Domains

# Add additional domains
dokku domains:add app app2.yourdomain.com

# Remove domain
dokku domains:remove app old.yourdomain.com

Environment Variables

# Set multiple vars at once
dokku config:set app \
  VAR1="value1" \
  VAR2="value2"

# Set from file
dokku config:set --no-restart app $(cat .env)

# View all config
dokku config app

Persistent Storage

# Create storage directory
mkdir -p /var/lib/dokku/data/storage/app-uploads

# Mount to app
dokku storage:mount app /var/lib/dokku/data/storage/app-uploads:/app/uploads

# Verify
dokku storage:list app

Plugins Ecosystem

Essential Plugins

# Automated backups
dokku plugin:install https://github.com/dokku/dokku-postgres.git

# Monitoring (metrics)
dokku plugin:install https://github.com/dokku-community/dokku-prometheus-pushgateway.git

# HTTP redirects
dokku plugin:install https://github.com/dokku/dokku-redirect.git

# Maintenance mode
dokku plugin:install https://github.com/dokku/dokku-maintenance.git

Useful Plugins

  • dokku-graphite - Web UI dashboard
  • dokku-event-listener - Event notifications
  • dokku-http-auth - Basic auth for apps
  • dokku-scheduler-k3s - K3s scheduler (alternative to Docker)
View all: https://dokku.com/docs/community/plugins/

Migration from Dokploy

1. Export Data

# From Dokploy VPS
docker exec ripplecore-postgres pg_dump -U ripplecore > backup.sql

2. Install Dokku

Follow installation steps above on new or same VPS.

3. Import Data

# On Dokku VPS
dokku postgres:create ripplecore-db
cat backup.sql | dokku postgres:import ripplecore-db

4. Deploy Apps

# Add Dokku remotes
git remote add dokku-app dokku@your-vps:app

# Deploy
git push dokku-app main:main

5. Update DNS

Point A records to Dokku VPS IP. Migration time: 3-4 hours

Troubleshooting

Issue: Buildpack detection failingFix:
  • Specify Dockerfile: Create .dokku/Dockerfile
  • Check buildpack: dokku buildpacks:list app
  • Set buildpack manually:
    dokku buildpacks:set app heroku/nodejs
    
Issue: App can’t connect to databaseFix:
  • Verify link: dokku postgres:list
  • Re-link: dokku postgres:link ripplecore-db app
  • Check env: dokku config app | grep DATABASE
Issue: Let’s Encrypt failingFix:
  • Check DNS: dig app.yourdomain.com
  • Verify port 80 open: ufw status
  • Check logs: dokku letsencrypt:list
  • Force renewal: dokku letsencrypt:renew app
Issue: git push hangs during deploymentFix:
  • Check VPS resources: htop
  • View logs: dokku logs app
  • Increase timeout: dokku config:set app DOKKU_WAIT_TO_RETIRE=60

Automated Backups

Database Backup Script

# Create backup script
cat > /usr/local/bin/dokku-backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/var/backups/dokku"
DATE=$(date +%Y%m%d-%H%M)

mkdir -p $BACKUP_DIR

# Backup PostgreSQL
dokku postgres:export ripplecore-db > $BACKUP_DIR/postgres-$DATE.sql
gzip $BACKUP_DIR/postgres-$DATE.sql

# Backup Redis (optional)
dokku redis:export ripplecore-cache > $BACKUP_DIR/redis-$DATE.rdb

# Keep last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete

# Optional: Upload to S3
# aws s3 cp $BACKUP_DIR/postgres-$DATE.sql.gz s3://your-bucket/
EOF

chmod +x /usr/local/bin/dokku-backup.sh

Schedule with Cron

# Add to crontab
crontab -e

# Add line:
0 2 * * * /usr/local/bin/dokku-backup.sh

Performance Optimization

Resource Limits

# Set memory limit (1GB)
dokku resource:limit app --memory 1024m

# Set CPU limit (1 core)
dokku resource:limit app --cpu-quota 100000

# Reserve resources
dokku resource:reserve app --memory 512m

Scaling

# Scale to 2 web processes
dokku ps:scale app web=2

# Auto-scale with autoscaler plugin
dokku plugin:install https://github.com/dokku/dokku-autoscaler
dokku autoscaler:set app --min 1 --max 5 --target-cpu 70

Pros & Cons

Advantages

  • Proven Stability (10+ years)
  • Git-push deployments
  • Heroku-compatible
  • 100+ plugins
  • Low resource overhead
  • Large community
  • Excellent docs

Limitations

  • No native web UI
  • CLI-focused
  • Steeper learning curve
  • Manual plugin setup
  • Less beginner-friendly

When to Choose Dokku

Choose Dokku over other methods if:
  • ✅ You want Heroku-like git-push deployments
  • ✅ Need proven stability (10+ years production use)
  • ✅ Comfortable with CLI tools
  • ✅ Want extensive plugin ecosystem
  • ✅ Low resource overhead matters
  • ✅ Planning long-term self-hosted PaaS
Stick with Dokploy/Coolify if:
  • ⚠️ You prefer web UI over CLI
  • ⚠️ Want simpler setup process
  • ⚠️ Need built-in monitoring dashboard

Cost Comparison

Hetzner CPX32 (€11.99/month): Dokku Overhead:
  • Platform: ~200MB RAM
  • Available for apps: ~7.8GB RAM
  • Most efficient PaaS option
vs Dokploy: -300MB overhead vs Coolify: -1.3GB overhead vs CapRover: -800MB overhead

Real-World Usage

Dokku powers thousands of production applications including:
  • Smaller SaaS companies
  • Development agencies
  • Side projects and startups
  • Educational platforms
  • Internal tools
Notable Users: Many Ruby on Rails and Node.js projects migrated from Heroku to Dokku post-pricing changes.

Next Steps

Resources

Dokku is the most mature and stable self-hosted PaaS, perfect for teams comfortable with CLI who want Heroku-like deployments with proven reliability.