CapRover PaaS Installation and Configuration

CapRover is an open-source Platform-as-a-Service that runs on your own Linux server, providing one-click app deployments, Docker-based builds, automatic SSL via Let's Encrypt, and a built-in Nginx reverse proxy. It supports single-server and multi-node cluster deployments, making it a practical self-hosted alternative to Heroku or Render.

Prerequisites

  • A fresh Ubuntu 20.04+ or Debian 11+ VPS
  • Minimum 1 vCPU, 1 GB RAM (2 GB recommended)
  • A domain with a wildcard DNS record: *.apps.yourdomain.com → your server IP
  • Ports 80, 443, 3000, 996, 7946, 4789, and 2377 open
  • Root access

Installing CapRover

# Install Docker (required first)
curl -fsSL https://get.docker.com | sh

# Start Docker and enable on boot
sudo systemctl enable docker --now

# Install CapRover using Docker
docker run -p 80:80 -p 443:443 -p 3000:3000 \
  -e ACCEPTED_TERMS=true \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /captain:/captain \
  --name captain \
  --restart always \
  caprover/caprover

# Verify CapRover is running
docker ps | grep captain
docker logs captain --tail 50

Access the dashboard at http://your-server-ip:3000. Default password is captain42.

Firewall Setup

# Ubuntu/Debian with UFW
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3000/tcp
sudo ufw allow 996/tcp    # Docker registry
sudo ufw allow 7946/tcp   # Swarm manager
sudo ufw allow 7946/udp
sudo ufw allow 4789/udp   # Overlay network
sudo ufw allow 2377/tcp   # Swarm cluster management
sudo ufw enable

Configuring the CapRover CLI

The CLI is the primary way to deploy apps from your local machine:

# Install CapRover CLI globally
npm install -g caprover

# Log in to your CapRover instance
caprover login

# You will be prompted for:
# - CapRover URL: http://your-server-ip:3000
# - Password: captain42 (change this immediately)
# - Machine name: my-server (alias for this instance)

# Change the default password
caprover api --caproverUrl http://your-server-ip:3000 \
  --method POST \
  --path /api/v2/user/changepassword \
  --data '{"oldPassword":"captain42","newPassword":"SecureNewPassword"}'

After logging in, complete the initial setup in the dashboard:

  1. Set your root domain: apps.yourdomain.com
  2. CapRover will verify domain ownership
  3. Enable HTTPS for the dashboard

Deploying One-Click Apps

CapRover includes a marketplace of one-click apps (databases, monitoring tools, CMS platforms):

# List available one-click apps via CLI
caprover list

# Deploy from the dashboard:
# Apps → One-Click Apps/Databases → Select app

Common one-click apps:

  • PostgreSQL, MySQL, MariaDB, MongoDB, Redis
  • WordPress, Ghost, Nextcloud
  • Grafana, Prometheus, Portainer

After deploying, connect apps to databases using Docker internal networking:

# App containers can reach each other by service name
# PostgreSQL one-click app is accessible at:
# Host: srv-captain--postgres
# Port: 5432

# Example connection string in your app:
DATABASE_URL=postgresql://user:pass@srv-captain--postgres:5432/mydb

Custom Dockerfile Deployments

Deploy via CLI

# Navigate to your project directory
cd /path/to/myapp

# Create captain-definition file
cat > captain-definition << 'EOF'
{
  "schemaVersion": 2,
  "dockerfileLines": [
    "FROM node:20-alpine",
    "WORKDIR /app",
    "COPY package*.json ./",
    "RUN npm ci --only=production",
    "COPY . .",
    "RUN npm run build",
    "EXPOSE 3000",
    "CMD [\"node\", \"dist/server.js\"]"
  ]
}
EOF

# Or reference an existing Dockerfile
cat > captain-definition << 'EOF'
{
  "schemaVersion": 2,
  "dockerfilePath": "./Dockerfile"
}
EOF

# Deploy to CapRover
caprover deploy --appName my-app

# Deploy from a tar archive
tar -czf app.tar.gz .
caprover deploy --appName my-app --tarFile app.tar.gz

Deploy via GitHub/GitLab Webhooks

  1. Create the app in the CapRover dashboard
  2. Go to App SettingsDeployment tab
  3. Enable Webhook deployment
  4. Copy the webhook URL
  5. Add it to your repository's webhook settings
# Trigger deployment manually via webhook
curl -X POST "https://captain.apps.yourdomain.com/api/v2/user/apps/webhooks/triggerbuild?namespace=captain&token=YOUR_TOKEN"

SSL Management

CapRover manages SSL certificates automatically via Let's Encrypt:

# Enable SSL for an app in the dashboard:
# Apps → your-app → HTTP Settings → Enable HTTPS

# Or via API
curl -X POST "https://captain.apps.yourdomain.com/api/v2/user/apps/appData/my-app" \
  -H "x-captain-auth: YOUR_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"forceSsl": true, "websocketSupport": true}'

Custom Domains with SSL

# 1. Add CNAME record in DNS: myapp.com → apps.yourdomain.com
# 2. In CapRover dashboard: App → HTTP Settings → Add Custom Domain
# 3. Enter: myapp.com
# 4. Enable HTTPS for the custom domain
# 5. CapRover issues a Let's Encrypt certificate automatically

Cluster Mode

CapRover supports Docker Swarm for multi-node clusters:

# On the master node (existing CapRover server):
# Dashboard → Cluster → Add Node
# Copy the "join token" command shown

# On worker nodes, first install Docker:
curl -fsSL https://get.docker.com | sh
sudo systemctl enable docker --now

# Join the swarm (use the token from CapRover dashboard)
docker swarm join --token SWMTKN-1-xxxxxxxxxxxx \
  master-server-ip:2377

# Verify cluster status on master
docker node ls

Label nodes for targeted deployments:

# Add labels to worker nodes
docker node update --label-add role=worker node-id

# Deploy app to specific node
# In CapRover app settings: set node label selector

Build Pipeline Configuration

Environment Variables

# Set in CapRover dashboard: App → App Configs → Environmental Variables
# Or via CLI:
caprover api --caproverUrl https://captain.apps.yourdomain.com \
  --method POST \
  --path /api/v2/user/apps/appData/my-app \
  --data '{
    "envVars": [
      {"key": "NODE_ENV", "value": "production"},
      {"key": "DATABASE_URL", "value": "postgresql://..."},
      {"key": "SECRET_KEY", "value": "your-secret"}
    ]
  }'

Persistent Volumes

# Mount persistent storage in app settings:
# App → App Configs → Persistent Directories
# Host path: /captain/data/my-app
# App path: /app/uploads

# Or add to captain-definition:
{
  "schemaVersion": 2,
  "dockerfilePath": "./Dockerfile",
  "volumes": [
    {
      "hostPath": "/captain/data/my-app/uploads",
      "containerPath": "/app/uploads"
    }
  ]
}

Troubleshooting

Dashboard inaccessible on port 3000:

# Check if CapRover container is running
docker ps -a | grep captain

# Check container logs
docker logs captain --tail 100

# Ensure port 3000 is not blocked
netstat -tlnp | grep 3000

Deployment fails - build error:

# View build logs in dashboard: Apps → [app] → Deployment Logs
# Common causes:
# - Invalid Dockerfile syntax
# - Missing captain-definition file
# - Out of disk space
df -h /

SSL certificate not issuing:

# Verify wildcard DNS is propagated
dig *.apps.yourdomain.com

# Check Let's Encrypt rate limits
# CapRover logs will show ACME errors
docker logs captain 2>&1 | grep -i "let's encrypt\|acme"

App container keeps restarting:

# Check app logs
docker service logs captain--my-app --tail 50

# List all services
docker service ls | grep captain

Conclusion

CapRover provides a full PaaS experience on your own infrastructure with minimal setup — a single Docker command installs everything needed to deploy and manage applications at scale. Its Dockerfile-first approach gives you complete control over your build process, while the one-click app marketplace accelerates deployment of common services. With cluster mode, you can grow from a single VPS to a multi-node swarm without migrating away from the platform.