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.comto 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:
- Set your root domain - Enter
caprover.example.com(the wildcard domain you configured in DNS) - 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:
- Go to Settings in the CapRover dashboard
- Under CapRover Root HTTPS, enter your email address
- 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:latestand 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:
- Enter an app name (e.g.,
wp-blog) - Set the MySQL root password, database name, and WordPress credentials
- 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:
- Go to your GitHub repository settings
- Navigate to Webhooks > Add webhook
- Paste the CapRover webhook URL as the Payload URL
- Set Content type to
application/json - Select Just the push event
- 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:
- Go to your app in the dashboard
- Navigate to the HTTP Settings tab
- Set the Instance Count to the desired number of replicas
- 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:
- Point your custom domain's A record to the CapRover server IP
- In the app's HTTP Settings, click Connect New Domain
- Enter the custom domain and click Connect
- 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
- How To Install Docker CE on Ubuntu
- How To Install Docker Swarm On Ubuntu
- Run GitLab in Docker Containers using Docker Compose
- Install Docker Registry on Ubuntu
- Run Docker/Podman Containers as Systemd Service




































































