astro SSR deployemnt
Deploying a dynamic (SSR) Astro site to an EC2 instance with Nginx is different from a static deployment. For SSR, Astro must run as a Node server (or another adapter like Deno/Cloudflare), and Nginx acts as a reverse proxy.
Below is the correct, production-ready guide for Ubuntu EC2 + Nginx + Astro SSR (Node adapter).
✅ STEP 1 — Build your Astro project for SSR
Section titled “✅ STEP 1 — Build your Astro project for SSR”In astro.config.mjs you must use:
import node from "@astrojs/node";
export default { output: "server", adapter: node({ mode: "standalone", // recommended on servers }),};Then build:
npm installnpm run buildThis produces a server-ready folder:
/dist└── server.mjs└── package.json└── node_modules (light version)✅ STEP 2 — Upload your dist folder to the EC2 instance
Section titled “✅ STEP 2 — Upload your dist folder to the EC2 instance”From your machine:
rsync -avz dist/ ubuntu@your-ec2:/var/www/myastroOr via Git pull directly on EC2.
✅ STEP 3 — Install dependencies on the EC2 server
Section titled “✅ STEP 3 — Install dependencies on the EC2 server”SSH into EC2:
ssh ubuntu@your-ec2cd /var/www/myastronpm install --production⚠️ If you used
mode: "standalone", the server bundle already includes dependencies, and you don’t need npm install.
✅ STEP 4 — Run your Astro SSR server
Section titled “✅ STEP 4 — Run your Astro SSR server”Test manually:
node ./server.mjsIt usually runs on port 3000, unless configured otherwise.
Check it’s working: http://your-ec2:3000
✅ STEP 5 — Create a PM2 service for Astro
Section titled “✅ STEP 5 — Create a PM2 service for Astro”Install PM2:
sudo npm i -g pm2Start the Astro server:
pm2 start server.mjs --name astro-sitepm2 savepm2 startupThis ensures your Astro server runs permanently after reboot.
✅ STEP 6 — Configure Nginx as a reverse proxy
Section titled “✅ STEP 6 — Configure Nginx as a reverse proxy”Create your site config:
sudo nano /etc/nginx/sites-available/astroPaste:
server { listen 80; server_name your-domain.com;
location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }}Enable it:
sudo ln -s /etc/nginx/sites-available/astro /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginx✅ STEP 7 — (Optional but recommended) Install HTTPS with Certbot
Section titled “✅ STEP 7 — (Optional but recommended) Install HTTPS with Certbot”sudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d your-domain.com🚀 Your Astro SSR site is now live behind Nginx!
Section titled “🚀 Your Astro SSR site is now live behind Nginx!”🧪 Quick test
Section titled “🧪 Quick test”curl -I http://localhostYou should get:
HTTP/1.1 200 OKserver: nginx📌 Summary
Section titled “📌 Summary”| Component | Role |
|---|---|
| Astro SSR | Runs as Node server (PM2) |
| Port 3000 | Internal server port |
| Nginx | Reverse proxy in front |
| HTTPS | Managed by Certbot |
If you want, I can prepare a complete ready-to-copy server config, a deployment bash script, or help you fix errors (proxy, permissions, PM2, Nginx).
Perfect — here is Option A: a full ready-to-copy deployment script that installs everything on a fresh Ubuntu EC2 instance and deploys an Astro SSR (Node) site behind Nginx + PM2.
🚀 FULL DEPLOYMENT SCRIPT FOR ASTRO SSR ON UBUNTU + NGINX + PM2
Section titled “🚀 FULL DEPLOYMENT SCRIPT FOR ASTRO SSR ON UBUNTU + NGINX + PM2”✔️ Installs Node
Section titled “✔️ Installs Node”✔️ Installs Nginx
Section titled “✔️ Installs Nginx”✔️ Installs PM2
Section titled “✔️ Installs PM2”✔️ Sets up your Astro SSR server
Section titled “✔️ Sets up your Astro SSR server”✔️ Configures reverse proxy
Section titled “✔️ Configures reverse proxy”✔️ Enables HTTPS (optional)
Section titled “✔️ Enables HTTPS (optional)”🔧 Before running the script
Section titled “🔧 Before running the script”Replace the variables:
your_domain.com/var/www/myastro3000(if you use another port)
📦 DEPLOYMENT SCRIPT (copy & paste in EC2)
Section titled “📦 DEPLOYMENT SCRIPT (copy & paste in EC2)”#!/bin/bash
# -----------------------------# CONFIG - CHANGE THESE VALUES# -----------------------------DOMAIN="your_domain.com"PROJECT_DIR="/var/www/myastro"ASTRO_PORT=3000NODE_VERSION="20"
# -----------------------------# UPDATE SYSTEM# -----------------------------sudo apt update && sudo apt upgrade -y
# -----------------------------# INSTALL NODE# -----------------------------curl -fsSL https://deb.nodesource.com/setup_$NODE_VERSION.x | sudo -E bash -sudo apt install -y nodejs
# -----------------------------# INSTALL NGINX# -----------------------------sudo apt install -y nginxsudo systemctl enable nginxsudo systemctl start nginx
# -----------------------------# INSTALL PM2# -----------------------------sudo npm install -g pm2
# -----------------------------# CREATE PROJECT DIRECTORY# -----------------------------sudo mkdir -p $PROJECT_DIRsudo chown -R $USER:$USER $PROJECT_DIR
# -----------------------------# PULL OR COPY YOUR ASTRO BUILD# (You must rsync or git clone before running PM2)# -----------------------------echo "⚠️ Make sure your Astro 'dist/' folder is inside $PROJECT_DIR"
# -----------------------------# START ASTRO SSR SERVER# -----------------------------cd $PROJECT_DIRpm2 stop astro-site || truepm2 delete astro-site || truepm2 start server.mjs --name astro-sitepm2 savepm2 startup -u $USER --hp $HOME
# -----------------------------# CREATE NGINX REVERSE PROXY# -----------------------------sudo bash -c "cat >/etc/nginx/sites-available/astro <<EOFserver { listen 80; server_name $DOMAIN;
location / { proxy_pass http://127.0.0.1:$ASTRO_PORT; proxy_http_version 1.1; proxy_set_header Upgrade \\\$http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host \\\$host; proxy_cache_bypass \\\$http_upgrade; }}EOF"
sudo ln -sf /etc/nginx/sites-available/astro /etc/nginx/sites-enabled/astrosudo nginx -t && sudo systemctl reload nginx
echo "---------------------------------------------------"echo "🚀 Deployment done. Your Astro SSR app should be live."echo "🌐 http://$DOMAIN"echo "---------------------------------------------------"
# OPTIONAL ---------------------# ENABLE HTTPS USING CERTBOT# -----------------------------echo ""echo "To enable HTTPS, run:"echo "sudo apt install certbot python3-certbot-nginx -y"echo "sudo certbot --nginx -d $DOMAIN"🧪 AFTER RUNNING THE SCRIPT
Section titled “🧪 AFTER RUNNING THE SCRIPT”1️⃣ Upload your Astro build to the server:
Section titled “1️⃣ Upload your Astro build to the server:”From your local machine:
rsync -avz dist/ ubuntu@YOUR_SERVER:/var/www/myastro2️⃣ Restart Astro server
Section titled “2️⃣ Restart Astro server”cd /var/www/myastropm2 restart astro-site3️⃣ Check that it works:
Section titled “3️⃣ Check that it works:”curl -I http://localhostYou should get:
HTTP/1.1 200 OK⚠️ Important Notes
Section titled “⚠️ Important Notes”✔️ Your astro.config.mjs MUST have:
Section titled “✔️ Your astro.config.mjs MUST have:”export default { output: 'server', adapter: node({ mode: 'standalone' }),};✔️ Your server.mjs is generated inside /dist
Section titled “✔️ Your server.mjs is generated inside /dist”✔️ Nginx does NOT serve Astro files directly in SSR mode
Section titled “✔️ Nginx does NOT serve Astro files directly in SSR mode”It only proxies to the Node server.
Want the script customized to your domain + folder + EC2 setup?
Section titled “Want the script customized to your domain + folder + EC2 setup?”Tell me:
- Your domain
- Your project folder
- Your adapter mode
- Your EC2 Linux version (probably Ubuntu 22.04)
I will generate a tailored deployment script.