TL;DR: CapRover simplifies deployment. Build a Docker image, add a captain-definition file, push to your VPS, and deploy via CLI. Your Astro site runs behind Nginx with automatic HTTPS in minutes. Perfect alternative to Vercel if you prefer self-hosted control.
What is CapRover?
CapRover is a Platform-as-a-Service (PaaS) platform you run on your own VPS. It handles:
- Docker container orchestration
- Automatic SSL/TLS with Let’s Encrypt
- Automatic Nginx reverse proxy
- Simple deployment via Git push or CLI
- Persistent volumes and environment variables
- One-click app deployment
Think of it as “Heroku on your VPS.” You get the convenience of Vercel/Netlify but with full control and lower cost (just VPS fees, no per-app costs).
Prerequisites
Before you start, you need:
-
A VPS running a supported OS (Ubuntu 20.04+ recommended)
- DigitalOcean, Linode, AWS EC2, etc.
- SSH access to root or sudo user
- At least 2GB RAM, 10GB disk minimum
-
A domain name (if you want a custom domain)
-
Docker knowledge (basic understanding of images and containers)
-
Git installed locally
Step 1: Install CapRover on Your VPS
SSH into your VPS:
ssh deploy@your-vps-ip
Install CapRover (as root or with sudo):
# Download and run the installation script
curl -fsSL https://raw.githubusercontent.com/caprover/caprover/master/scripts/install.sh | sudo /bin/bash
# Wait for installation to complete (5-10 minutes)
After installation, CapRover tells you the login URL:
CapRover is installed successfully!
CapRover is running at http://your-vps-ip:3000
Default password: captain42
Step 2: Access CapRover Dashboard and Configure
Open http://your-vps-ip:3000 in your browser.
First login:
- Username:
captain - Password:
captain42(change this immediately in Settings)
Configure your domain:
- Go to Settings (⚙️ icon)
- Enter your root domain:
example.com - CapRover will configure automatic HTTPS via Let’s Encrypt
Create an API token for CLI:
- Settings → API Tokens
- Create a new token
- Copy the token (you’ll use it in CLI)
Step 3: Prepare Your Astro Project for CapRover
Create a captain-definition file in your project root. This tells CapRover how to build and run your app:
{
"schemaVersion": 2,
"containerName": "personal-blog",
"imageName": "personal-blog:latest",
"dockerfileLines": [
"FROM node:18-alpine AS builder",
"WORKDIR /app",
"COPY package*.json ./",
"RUN npm ci",
"COPY . .",
"RUN npm run build",
"",
"FROM node:18-alpine",
"WORKDIR /app",
"RUN npm install -g serve",
"COPY --from=builder /app/dist ./dist",
"EXPOSE 3000",
"HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\",
" CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1",
"CMD [\"serve\", \"-s\", \"dist\", \"-l\", \"3000\"]"
]
}
Alternative: If you already have a Dockerfile, reference it instead:
{
"schemaVersion": 2,
"containerName": "personal-blog",
"imageName": "personal-blog:latest",
"dockerfilePath": "./Dockerfile"
}
Commit this file to Git:
git add captain-definition
git commit -m "Add CapRover deployment config"
git push origin main
Step 4: Install CapRover CLI
On your local machine:
npm install -g caprover
Log in to your CapRover instance:
caprover login
When prompted:
- Hostname:
your-vps-iporcaptain.example.com - API Token: Paste the token from Step 2
CapRover saves credentials locally.
Step 5: Create an App in CapRover
In the CapRover dashboard:
- Click “New App”
- Enter app name:
blog(becomesblog.example.com) - Click “Create New App”
- In app settings:
- Enable HTTPS: Yes
- Set domain:
blog.example.comor your preferred subdomain
Step 6: Deploy via CLI
From your project root (where captain-definition is):
# Deploy the app
caprover deploy
# When prompted:
# - Select the app: blog
# - Confirm deployment: yes
CapRover will:
- Build the Docker image
- Push to the in-VPS registry
- Run the container
- Configure Nginx
- Deploy HTTPS certificate
Watch the logs in the dashboard or CLI. Deployment usually takes 2-3 minutes.
After success, visit https://blog.example.com—your site is live.
Step 7: Configure App Settings (Optional)
In CapRover dashboard, app settings:
Enable “Persistent Directories” (if you need persistent storage):
- Path:
/app/data - Mount point: Optional
Environment Variables:
- No env vars needed for a static Astro site, but you can add them for:
- Build arguments
- Future backend integrations
SSL/HTTPS:
- Auto-generated via Let’s Encrypt
- Renews automatically
Step 8: Automate Deployments with GitHub Actions
Create .github/workflows/deploy-caprover.yml:
name: Deploy to CapRover
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install CapRover CLI
run: npm install -g caprover
- name: Deploy to CapRover
run: |
caprover deploy \
--caproverUrl "https://captain.example.com" \
--caproverPassword "${{ secrets.CAPROVER_PASSWORD }}" \
--appName "blog" \
--imageName "personal-blog:latest"
env:
CAPROVER_URL: "https://captain.example.com"
Set GitHub Secret:
- Repository → Settings → Secrets and variables → Actions
- New Repository Secret:
- Name:
CAPROVER_PASSWORD - Value: Your CapRover API token
- Name:
Now every push to main automatically deploys.
Step 9: Set Up Custom Domain
If you have a domain (example.com), point it to your VPS:
Update DNS records:
A record: example.com → your-vps-ip
A record: *.example.com → your-vps-ip (wildcard for subdomains)
Wait for DNS to propagate (can take minutes to hours).
In CapRover app settings, update HTTP domain to blog.example.com.
Monitoring and Maintenance
Check app logs:
- Dashboard: App page → View Logs
Monitor resources:
- Dashboard: Monitoring tab (CPU, memory, disk)
Backup:
- CapRover doesn’t backup databases (you don’t have any for a static site)
- Backup your code in Git (you already do)
- Backup VPS files periodically (manual SSH or automated rsync)
Update CapRover:
- Dashboard: Settings → Update CapRover
- Usually safe; test on staging first if critical
Troubleshooting
App won’t start:
- Check logs in dashboard
- Common cause: port not exposed in Dockerfile
- Ensure
EXPOSE 3000is in Dockerfile
Certificate errors:
- Wait 5 minutes for Let’s Encrypt to issue
- Check domain DNS resolves to VPS IP
Slow deploys:
- First deploy builds image from scratch (slow)
- Subsequent deploys re-use cache (faster)
- Building takes 2-3 minutes, expected
App exits immediately:
- Often a startup error
- Check logs: Dashboard → App → View Logs
- Common: missing dependencies (ensure
npm ciruns in Dockerfile)
Cost Comparison
CapRover (self-hosted):
- VPS: $5-20/month (DigitalOcean, Linode, etc.)
- Total: $5-20/month for unlimited apps
Vercel/Netlify:
- Free tier: OK for small projects
- Pro: $20/month per account
- Team: $35+ per team member
For a personal blog, CapRover is cheaper. For multiple projects, it’s significantly better value.
Summary: Deploy from Git Push
Once set up, your workflow is simple:
# Make changes
echo "New post" >> content.md
# Push to main
git add content.md
git commit -m "Add new post"
git push origin main
# GitHub Actions triggers automatically
# Your blog updates live in 3-5 minutes
No manual deployments, no secrets in your code, full control of your infrastructure.
Next Steps
- Backup strategy: Set up automated VPS snapshots
- Multiple apps: Deploy other projects to same CapRover instance
- Custom Nginx config: CapRover allows per-app Nginx rules
- Email alerts: Set up monitoring for app downtime
CapRover is powerful enough for production but simple enough to use daily. It’s a solid choice for engineers who want control without the overhead of manual Docker/Kubernetes management.