Deployment

Deploy wherever you want:

  • Platform services: Railway, Render, Vercel, Fly.io
  • VPS: Any server with SSH and Node.js

Platform Deployment

Services like Railway and Render make deployment trivial. Connect your Git repo and push. Follow their Astro SSR deployment guides.

VPS Deployment

For those who prefer running on a private VPS with SSH access, here’s how to set up with PM2.

Prerequisites

On your server:

  1. SSH access as a non-root user
  2. Node.js via nvm
  3. PM2 process manager
Terminal window
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# Install PM2
npm install pm2 -g

PM2 Configuration

Create ecosystem.config.cjs in your project:

module.exports = {
apps: [
{
name: "myapp",
cwd: "/home/myuser/myapp",
script: "dist/server/entry.mjs",
instances: 1,
exec_mode: "fork",
watch: false,
interpreter: "/home/myuser/.nvm/versions/node/v20.19.4/bin/node",
env: {
NODE_ENV: "production",
HOST: "127.0.0.1",
PORT: "3000",
},
max_memory_restart: "1G",
error_file: "logs/error.log",
out_file: "logs/out.log",
log_file: "logs/combined.log",
time: true,
},
],
};

Initial Setup

Terminal window
# Clone and build
git clone your-repo
cd your-repo
npm install
npm run build
# Add production .env
# Start with PM2
pm2 start ecosystem.config.cjs
pm2 save

PM2 Startup (Auto-restart on Reboot)

Terminal window
pm2 startup
# Run the command it outputs as root
pm2 save

Apache .htaccess Proxy

If using Apache, add to your document root:

DirectoryIndex disabled
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}e"
RewriteRule ^/?(.*)$ http://localhost:3000/$1 [P,L]

Deploy Script

Create a deploy.sh script for easy deployments:

#!/bin/bash
GIT_BRANCH="main"
COMMIT_MESSAGE="Updates - $(date +"%Y-%m-%d %T")"
SSH_USER="myuser"
SSH_SERVER="myserver.com"
SSH_PORT="22"
DEPLOYMENT_PATH="/home/myuser/myapp"
PM2_APP_NAME="myapp"
git add --all
echo "Enter Git commit message (default: $COMMIT_MESSAGE)"
read NEW_MESSAGE
[ -n "$NEW_MESSAGE" ] && COMMIT_MESSAGE=$NEW_MESSAGE
git commit -am "$COMMIT_MESSAGE"
git push origin $GIT_BRANCH
ssh $SSH_USER@$SSH_SERVER -p $SSH_PORT -t "cd $DEPLOYMENT_PATH && git pull origin $GIT_BRANCH && npm install && npm run build && npm run migrate && pm2 reload $PM2_APP_NAME"
exit

Make it executable and add to .gitignore:

Terminal window
touch deploy.sh
chmod +x deploy.sh
echo "/deploy.sh" >> .gitignore

Monitoring Script

For quick access to PM2 logs:

#!/bin/bash
SSH_USER="myuser"
SSH_SERVER="myserver.com"
SSH_PORT="22"
ssh $SSH_USER@$SSH_SERVER -p $SSH_PORT -t "pm2 logs"

Recovery

If the app goes offline:

Terminal window
cd /path/to/your/app
pm2 start ecosystem.config.cjs
pm2 save