Back to Blog
vps Mar 3, 2026 6 min read

How to Deploy Open-Source Apps to a VPS (The Easy Way)

H

HowToDeploy Team

Lead Engineer @ howtodeploy

How to Deploy Open-Source Apps to a VPS (The Easy Way)

Deploying an open-source app to a VPS (Virtual Private Server) is one of the most cost-effective ways to run software. You get a dedicated server, full root access, and predictable monthly pricing — typically $4-12/month.

But the setup process has always been the barrier. This guide covers both the manual approach and a faster alternative.


The manual approach: step by step

Here's what it takes to deploy an open-source app (like Ghost, Chatwoot, or an AI agent) to a VPS from scratch.

Step 1: Choose a VPS provider

Popular options in 2026:

ProviderStarting priceBest for
Hetzner€3.79/moBest price-to-performance in Europe
DigitalOcean$6/moDeveloper-friendly UI and docs
Vultr$5/moWide global region coverage
Linode (Akamai)$5/moSolid performance, good support
AWS EC2~$8/mo (t3.micro)Enterprise compliance requirements

For most open-source apps, a 2GB RAM / 1 vCPU server is sufficient. Ghost runs comfortably on 1GB. Most AI agents need 1-2GB.

Step 2: Provision the server

  1. Create an account with your chosen provider
  2. Spin up a new server (Ubuntu 22.04 LTS recommended)
  3. Choose a region close to your users
  4. Add your SSH public key

Step 3: SSH into the server

ssh root@your-server-ip

First-time setup:

# Update the system
apt update && apt upgrade -y
 
# Create a non-root user
adduser deploy
usermod -aG sudo deploy
 
# Set up SSH for the new user
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh

Step 4: Install dependencies

Every app needs different system packages. For example, Ghost needs Node.js and MySQL:

# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
 
# Install MySQL
sudo apt install -y mysql-server
sudo mysql_secure_installation
 
# Create a database
sudo mysql -e "CREATE DATABASE ghost;"
sudo mysql -e "CREATE USER 'ghost'@'localhost' IDENTIFIED BY 'your-password';"
sudo mysql -e "GRANT ALL ON ghost.* TO 'ghost'@'localhost';"

For Chatwoot, you'd need PostgreSQL and Redis instead. For AI agents, you might need Python or Go runtimes.

This is where most people get stuck. Every app has different dependencies, different configuration files, and different ways to break.

Step 5: Install the application

# Clone the repo
git clone https://github.com/TryGhost/Ghost.git /var/www/ghost
cd /var/www/ghost
 
# Install dependencies
npm install --production
 
# Configure
cp .env.example .env
nano .env  # Edit with your database credentials, URL, etc.
 
# Run database migrations
npx knex-migrator init
 
# Start the app
npm start

Step 6: Set up a reverse proxy with SSL

You need a reverse proxy to serve your app on port 80/443 with HTTPS. The two main options:

Option A: Nginx + Certbot

# Install Nginx
sudo apt install -y nginx
 
# Create config
sudo nano /etc/nginx/sites-available/ghost
server {
    listen 80;
    server_name yourdomain.com;
 
    location / {
        proxy_pass http://localhost:2368;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
 
# Install Certbot for SSL
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com

Option B: Caddy (simpler)

# Install Caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
# /etc/caddy/Caddyfile
yourdomain.com {
    reverse_proxy localhost:2368
}

Caddy handles SSL automatically — no Certbot needed.

Step 7: Set up a process manager

Your app needs to restart on crashes and server reboots:

# Using systemd
sudo nano /etc/systemd/system/ghost.service
[Unit]
Description=Ghost CMS
After=network.target
 
[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/ghost
ExecStart=/usr/bin/node index.js
Restart=always
 
[Install]
WantedBy=multi-user.target
sudo systemctl enable ghost
sudo systemctl start ghost

Step 8: Configure firewall

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'  # or 80,443 for Caddy
sudo ufw enable

Total time: 30-90 minutes

And that's for a single app, assuming nothing goes wrong. Common issues include:

  • Wrong Node.js version
  • Database connection errors
  • Permission problems
  • SSL certificate failures
  • Port conflicts
  • Missing system dependencies
  • Process manager configuration issues

Every app has its own set of gotchas. Multiply this by every app you want to deploy.


The easy way: skip all of that

HowToDeploy automates every step above. Instead of 30-90 minutes of SSH and configuration:

  1. Connect your cloud provider — paste your API key (one-time setup)
  2. Pick an app from the catalog
  3. Fill in the essentials — admin email, password, domain (optional)
  4. Click Deploy

Behind the scenes, AI generates a custom provisioning script that handles server setup, dependency installation, app configuration, Caddy reverse proxy, SSL certificates, and process management — all tailored to your specific configuration.

You still get a VPS on your own cloud account. You still have full SSH access. You still pay your cloud provider directly at their standard rates. You just skip the ops work.

What happens when you click Deploy

  1. Server is provisioned via your cloud provider's API
  2. SSH key pair is generated for secure access
  3. AI generates a complete installation script based on the app manifest and your config
  4. Script runs on the server — progress is streamed to your browser in real time
  5. Caddy is configured for your domain (if provided) with automatic SSL
  6. App is live — URL appears in your dashboard

The whole process takes 3-5 minutes.


When to go manual vs. automated

Go manual when:

  • You want to deeply understand the deployment process
  • You have custom infrastructure requirements (load balancers, private networks)
  • You enjoy DevOps and want full hands-on control

Use HowToDeploy when:

  • You want the app running, not the learning experience
  • You're deploying multiple apps across different servers
  • You don't have DevOps expertise on your team
  • You value your time over the DIY satisfaction

Both approaches put you in control of your infrastructure. The difference is how much time you spend getting there.

Deploy your first app in 3 minutes →