CapRover is a free, open-source Platform as a Service (PaaS) that turns any Linux server into a fully functional app deployment platform – similar to Heroku but running on your own infrastructure. It uses Docker Swarm under the hood for container orchestration, Nginx for load balancing, and Let’s Encrypt for automatic SSL certificates.

This guide walks through setting up CapRover as a self-hosted PaaS on Ubuntu 24.04, covering installation, HTTPS configuration, app deployments via the web UI and CLI, one-click apps, custom Dockerfile builds, GitHub auto-deploy, scaling, persistent storage, monitoring, backups, and cluster mode with worker nodes.

Prerequisites

Before starting, make sure you have:

  • A server running Ubuntu 24.04 LTS with at least 1GB RAM (2GB+ recommended for running multiple apps)
  • Root or sudo access to the server
  • A domain name with DNS access (e.g., example.com)
  • A wildcard DNS A record pointing *.caprover.example.com to your server IP
  • Ports 80, 443, and 3000 (TCP) open on your firewall
  • Docker Engine installed on the server
  • Port 996, 7946, and 4789 open if you plan to add worker nodes for cluster mode

Step 1: Install Docker on Ubuntu 24.04

CapRover requires Docker to run. If you already have Docker installed on Ubuntu, skip to Step 2. Otherwise, install it from Docker’s official repository.

First, update the system packages and install dependencies:

$ sudo apt update
$ sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

Add Docker’s official GPG key and repository:

$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list

Install Docker Engine:

$ sudo apt update
$ sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Enable and start Docker, then verify the installation:

$ sudo systemctl enable --now docker
$ docker --version
Docker version 27.x.x, build xxxxxxx

Add your user to the docker group so you can run Docker commands without sudo:

$ sudo usermod -aG docker $USER
$ newgrp docker

Step 2: Configure Wildcard DNS for CapRover

CapRover creates subdomains for every app you deploy. For this to work, you need a wildcard DNS record pointing to your server. Go to your domain registrar or DNS provider and create an A record like this:

  • Type: A
  • Host: *.caprover (or *.apps – whatever subdomain you choose)
  • Points to: Your server’s public IP address (e.g., 203.0.113.50)
  • TTL: 300 (or default)

This means any request to anything.caprover.example.com will resolve to your server IP. CapRover’s built-in Nginx reverse proxy then routes requests to the correct container based on the subdomain.

Verify the DNS record propagated by querying a random subdomain:

$ dig +short randomtest.caprover.example.com
203.0.113.50

If the IP matches your server, DNS is configured correctly.

Step 3: Install CapRover with Docker on Ubuntu 24.04

CapRover runs as a Docker container and initializes a Docker Swarm on the host. Deploy it with a single command:

$ docker run -d \
  -p 80:80 \
  -p 443:443 \
  -p 3000:3000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /captain:/captain \
  caprover/caprover

This pulls the latest CapRover image and starts it with the necessary port bindings. Port 3000 is for the initial setup, while ports 80 and 443 handle HTTP/HTTPS traffic for your deployed apps.

Wait about 60 seconds for CapRover to initialize Docker Swarm and configure its internal services. Check the logs to confirm it started successfully:

$ docker logs $(docker ps -q --filter ancestor=caprover/caprover) --tail 20

You should see output indicating that CapRover is ready:

Captain Starting ...
Installing Captain Service ...
Installation of CapRover is starting...
>>> Checking System Compatibility <<<
   Docker Version passed.
   X86 CPU detected.
   Total RAM 2048 MB
*** CapRover is initialized and ready ***

If you are installing on a server without a public IP (e.g., a local VM), pass the private IP as an environment variable:

$ docker run -d \
  -p 80:80 \
  -p 443:443 \
  -p 3000:3000 \
  -e MAIN_NODE_IP_ADDRESS=192.168.1.100 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /captain:/captain \
  caprover/caprover

Also create the config override to skip domain verification for local setups:

$ sudo mkdir -p /captain/data/
$ echo '{"skipVerifyingDomains":"true"}' | sudo tee /captain/data/config-override.json

Step 4: Complete CapRover Initial Web UI Setup

Open your browser and navigate to http://captain.caprover.example.com:3000 (replace with your actual root domain). The default password is captain42.

After logging in, CapRover prompts you to:

  1. Set your root domain - Enter caprover.example.com (the wildcard domain you configured in DNS)
  2. Change the default password - Pick a strong password and save it somewhere secure

CapRover verifies that captain.caprover.example.com correctly resolves to the server. If DNS is misconfigured, you will see an error at this stage. Double-check your wildcard A record if that happens.

Once the root domain is set, CapRover's dashboard becomes available at http://captain.caprover.example.com (port 3000 is no longer needed). The dashboard provides sections for Apps, Monitoring, Cluster, and Settings.

Step 5: Enable HTTPS with Let's Encrypt

CapRover has built-in Let's Encrypt integration for automatic SSL certificate provisioning. Enable it from the dashboard:

  1. Go to Settings in the CapRover dashboard
  2. Under CapRover Root HTTPS, enter your email address
  3. Click Enable HTTPS

CapRover requests a certificate from Let's Encrypt and configures Nginx to serve HTTPS. After enabling, toggle Force HTTPS to redirect all HTTP requests to HTTPS. The dashboard URL changes to https://captain.caprover.example.com.

Every app you deploy from this point can also get its own SSL certificate. When creating or editing an app, click Enable HTTPS on the app's HTTP Settings page. CapRover handles certificate issuance and renewal automatically.

Step 6: Deploy Apps via the CapRover Web UI

The simplest way to deploy an app is through the web dashboard. Navigate to Apps and click Create a New App. Enter an app name (lowercase, no spaces) - this becomes the subdomain. For example, an app named myapp gets served at myapp.caprover.example.com.

After creating the app, go to the Deployment tab. You have several upload options:

  • Upload a tar file - Compress your project directory and upload it directly
  • Paste a Dockerfile - Paste a Dockerfile directly in the text area and deploy
  • Deploy from a Docker image - Specify an image name like nginx:latest and deploy it

For a quick test, create an app called test-nginx, go to the Deployment tab, select Deploy a Docker Image, enter nginx:latest, and click Deploy. Within seconds, your Nginx instance is live at test-nginx.caprover.example.com.

Step 7: Deploy Apps Using the CapRover CLI

The CapRover CLI gives you command-line deployment capabilities, which is ideal for CI/CD pipelines and scripted workflows. Install it globally with npm:

$ sudo npm install -g caprover

If you do not have Node.js installed, install it first:

$ curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
$ sudo apt install -y nodejs

Verify the CLI installation:

$ caprover --version

Log in to your CapRover instance from the CLI:

$ caprover login
? CapRover machine URL: https://captain.caprover.example.com
? CapRover admin password: [your-password]
? Name this Captain machine: my-server
Logged in successfully to my-server

To deploy an app, navigate to your project directory (which must contain a Dockerfile or a captain-definition file) and run:

$ caprover deploy
? Select the Captain Machine: my-server
? Select the app: myapp
Deploying to myapp...
Build started
Build finished successfully
Deploy finished successfully

The captain-definition file tells CapRover how to build your app. Here is a minimal example for a Node.js app:

{
  "schemaVersion": 2,
  "dockerfilePath": "./Dockerfile"
}

Or reference a pre-built image directly:

{
  "schemaVersion": 2,
  "imageName": "myregistry/myapp:latest"
}

Step 8: Deploy One-Click Apps (WordPress, PostgreSQL, Redis, GitLab)

CapRover includes a marketplace of one-click apps that deploy popular software with minimal configuration. Access it from Apps > One-Click Apps/Databases in the dashboard.

Available one-click apps include:

  • Databases: PostgreSQL, MySQL, MariaDB, MongoDB, Redis, CouchDB
  • CMS/Web: WordPress, Ghost, Strapi, Directus
  • DevOps: GitLab, Gitea, Drone CI, Jenkins
  • Monitoring: Grafana, Prometheus, Uptime Kuma
  • Other: Minio, Nextcloud, Portainer, n8n, and many more

Example: Deploy WordPress with One-Click

Search for "WordPress" in the one-click apps section. CapRover shows the required fields:

  1. Enter an app name (e.g., wp-blog)
  2. Set the MySQL root password, database name, and WordPress credentials
  3. Click Deploy

CapRover creates two containers - one for WordPress and one for MySQL. Your WordPress site is immediately available at wp-blog.caprover.example.com. Enable HTTPS from the app's HTTP Settings tab to secure it.

Example: Deploy PostgreSQL

Search for "PostgreSQL" in one-click apps. Set the database name, user, and password. After deployment, the PostgreSQL instance runs as a CapRover app. Other apps on the same CapRover instance can connect using the internal Docker network - the hostname is srv-captain--your-postgres-app-name and the default port is 5432.

Example: Deploy Redis

Redis deploys the same way. Search for "Redis" in one-click apps, set a password if needed, and deploy. Other apps connect to it at srv-captain--your-redis-app-name:6379.

Step 9: Deploy Custom Dockerfile Apps

For applications not in the one-click marketplace, write your own Dockerfile and deploy it. Here is an example for a Python Flask app.

Create a project directory with this structure:

my-flask-app/
  captain-definition
  Dockerfile
  app.py
  requirements.txt

The Dockerfile:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

The captain-definition file:

{
  "schemaVersion": 2,
  "dockerfilePath": "./Dockerfile"
}

Create the app in the CapRover dashboard first, then deploy using the CLI:

$ cd my-flask-app
$ caprover deploy

CapRover builds the Docker image on the server, creates a container, and routes traffic through Nginx. Set the container HTTP port in the app's HTTP Settings if your app listens on a port other than 80 (in this case, set it to 5000).

You can also paste the Dockerfile content directly in the web UI under the Deployment tab if you prefer not to use the CLI.

Step 10: Connect GitHub for Automatic Deployments

CapRover supports automatic deployments triggered by git push. You can set this up using webhooks or by connecting your GitHub repository directly.

Method 1: Webhook-Based Auto-Deploy

Every CapRover app has a unique webhook URL. Find it in the Deployment tab of your app. The URL looks like:

https://captain.caprover.example.com/api/v2/user/apps/webhooks/triggerbuild?namespace=captain&token=YOUR_APP_TOKEN

To set up GitHub webhooks:

  1. Go to your GitHub repository settings
  2. Navigate to Webhooks > Add webhook
  3. Paste the CapRover webhook URL as the Payload URL
  4. Set Content type to application/json
  5. Select Just the push event
  6. Click Add webhook

Now every push to the repository triggers a build and deploy on CapRover.

Method 2: Git Repository Direct Connection

In the app's Deployment tab, scroll to Method 3: Deploy from GitHub/Bitbucket/GitLab. Enter your repository URL, branch name, and credentials (use a personal access token for private repos). Set the build trigger to automatically deploy on push.

CapRover clones the repo, looks for the captain-definition file, builds the image, and deploys. Each deployment is logged, and you can roll back to any previous version from the Deployment tab.

Step 11: Scale Apps with Replicas

CapRover leverages Docker Swarm for container orchestration, making horizontal scaling straightforward. To scale an app:

  1. Go to your app in the dashboard
  2. Navigate to the HTTP Settings tab
  3. Set the Instance Count to the desired number of replicas
  4. Click Save & Update

CapRover tells Docker Swarm to run multiple replicas of the container, and Nginx automatically load-balances traffic across them using round-robin. If a replica crashes, Swarm replaces it automatically.

Keep in mind that scaling works best for stateless apps. If your app writes to the local filesystem, those writes are not shared across replicas unless you use persistent storage (covered next).

Step 12: Configure Persistent Storage

Containers are ephemeral by default - data inside a container is lost when it restarts. For databases and apps that store files, you need persistent volumes.

In the CapRover dashboard, open your app and go to the App Configs tab. Scroll to the Persistent Directories section. Add the path inside the container that needs persistence. For example, for a PostgreSQL database, the path is /var/lib/postgresql/data.

CapRover maps these directories to Docker volumes on the host machine. The data persists across container restarts and redeployments. You can verify volumes on the host:

$ docker volume ls
DRIVER    VOLUME NAME
local     captain--mydb--data

For apps that need to share files across replicas, consider deploying a shared storage solution like Minio (available as a one-click app) or mounting an NFS volume.

Step 13: Monitor Apps and View Logs

CapRover provides built-in monitoring and logging through its dashboard.

Application Logs

View real-time logs for any app from the Deployment tab by clicking View App Logs. This shows stdout/stderr output from the container, which is helpful for debugging deployment failures or runtime errors.

From the command line, you can also check logs directly through Docker:

$ docker service logs srv-captain--myapp --tail 100 --follow

System Monitoring

The Monitoring section of the dashboard shows CPU and memory usage for the CapRover node. For more detailed monitoring, deploy Grafana and Prometheus from the one-click apps marketplace and point them at Docker's metrics endpoint.

Enable Docker metrics by adding the following to /etc/docker/daemon.json:

{
  "metrics-addr": "0.0.0.0:9323",
  "experimental": true
}

Restart Docker to apply:

$ sudo systemctl restart docker

Then configure Prometheus to scrape http://localhost:9323/metrics for container-level metrics.

Step 14: Backup Strategy for CapRover

CapRover stores its configuration in /captain/data/ on the host machine. Back up this directory regularly to preserve your app definitions, environment variables, and SSL certificates.

Create a backup script that covers all critical data:

$ sudo tar czf /backups/caprover-config-$(date +%Y%m%d).tar.gz /captain/data/

For database backups, use the native dump tools inside the container. For example, to back up a PostgreSQL database deployed on CapRover:

$ docker exec $(docker ps -q --filter name=srv-captain--mydb) pg_dumpall -U postgres > /backups/postgres-$(date +%Y%m%d).sql

Automate these backups with a cron job:

$ sudo crontab -e

Add entries like:

# CapRover config backup - daily at 2 AM
0 2 * * * tar czf /backups/caprover-config-$(date +\%Y\%m\%d).tar.gz /captain/data/
# PostgreSQL dump - daily at 3 AM
0 3 * * * docker exec $(docker ps -q --filter name=srv-captain--mydb) pg_dumpall -U postgres > /backups/postgres-$(date +\%Y\%m\%d).sql

Store backups off-server using rsync, S3, or any remote storage. Keeping backups only on the same machine defeats the purpose.

Step 15: Add Worker Nodes for Cluster Mode

CapRover supports multi-node clusters using Docker Swarm. Adding worker nodes distributes your app containers across multiple servers for better availability and load handling.

Prepare the Worker Node

On each worker server (Ubuntu 24.04), install Docker using the same steps from Step 1. The worker node does not need CapRover installed - it only needs Docker.

Ensure the following ports are open between the manager and worker nodes:

  • TCP 2377 - Cluster management communication
  • TCP/UDP 7946 - Node discovery and communication
  • UDP 4789 - Overlay network traffic (VXLAN)

Join the Worker to the Cluster

In the CapRover dashboard, go to Cluster and click Add New Node. CapRover generates a Docker Swarm join command. Copy this command and run it on the worker node:

$ docker swarm join --token SWMTKN-1-xxxxxxxxxxxxx 203.0.113.50:2377
This node joined a swarm as a worker.

Back in the CapRover dashboard, the new node appears in the Cluster section. Docker Swarm now distributes container replicas across both the manager and worker nodes.

Verify the cluster status from the manager node:

$ docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS
abc123 *                      manager    Ready     Active         Leader
def456                        worker-1   Ready     Active

When you scale an app to multiple replicas, Swarm spreads them across available nodes automatically. This gives you high availability - if one node goes down, the remaining nodes continue serving traffic.

CapRover Environment Variables and App Configuration

Applications often need environment variables for database URLs, API keys, and runtime settings. In the CapRover dashboard, go to your app's App Configs tab to manage these.

Add environment variables as key-value pairs. For example, to connect a Node.js app to a CapRover-deployed PostgreSQL database:

DATABASE_URL=postgresql://user:password@srv-captain--mydb:5432/myapp
NODE_ENV=production
PORT=3000

Changes to environment variables trigger an automatic redeployment of the app. The srv-captain--appname hostname is the internal Docker network address that allows containers to communicate with each other without exposing ports publicly.

Custom Domain Names for Apps

By default, apps are accessible at appname.caprover.example.com. To use a custom domain like myapp.com:

  1. Point your custom domain's A record to the CapRover server IP
  2. In the app's HTTP Settings, click Connect New Domain
  3. Enter the custom domain and click Connect
  4. Click Enable HTTPS on the custom domain to get an SSL certificate

CapRover's Nginx configuration updates automatically to route the custom domain to the correct container.

Conclusion

You now have a fully functional self-hosted PaaS running on Ubuntu 24.04 with CapRover. From single-command Docker deployments to multi-node clusters with automatic SSL, CapRover handles the infrastructure plumbing so you can focus on shipping apps. For production environments, secure your server with UFW firewall rules, set up automated off-site backups, enable monitoring with Prometheus and Grafana, and consider running at least two worker nodes for high availability.

Related Guides

LEAVE A REPLY

Please enter your comment!
Please enter your name here