Prerequisites
- A RamNode VPS running Ubuntu 24.04 LTS (recommended: 1 GB RAM minimum — available starting at $5/month)
- SSH access to your VPS (terminal on macOS/Linux, or PuTTY/Windows Terminal on Windows)
- A registered domain name (optional but recommended for SSL)
- Basic familiarity with the Linux command line
Recommended Plans
| Use Case | Plan | RAM | Best For |
|---|---|---|---|
| Static blog / portfolio | $5/mo | 1 GB | Personal sites, landing pages |
| SSR application | $10/mo | 2 GB | Dynamic sites, API routes |
| Multi-site hosting | $15/mo | 3 GB | Multiple Astro projects |
| High-traffic SSR | $20/mo+ | 4 GB+ | E-commerce, dashboards |
Initial Server Setup
ssh root@YOUR_SERVER_IP
# Update system packages
apt update && apt upgrade -yCreate a Deploy User
Running applications as root is a security risk. Create a dedicated user for your Astro deployment:
adduser astro
usermod -aG sudo astro
# Switch to the new user
su - astroConfigure the Firewall
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw statusInstall Node.js
Astro requires Node.js 18.17.1 or later. We recommend Node.js 22 LTS for the best performance and long-term support.
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
# Verify the installation
node -v
npm -vCreate Your Astro Project
cd ~
npm create astro@latest my-astro-siteThe CLI will prompt you with several options. For a production deployment, recommended selections are:
- Template: Use the "Include sample files" starter for a working baseline
- TypeScript: Choose "Strict" for type safety in production
- Install dependencies: Yes
- Initialize git: Yes
cd my-astro-site
npm run dev -- --host 0.0.0.0
# Visit http://YOUR_SERVER_IP:4321 to confirm
# Press Ctrl+C to stop⚠️ Warning: The --host 0.0.0.0 flag binds to all interfaces for remote access. Do not leave the dev server running in production — it is not optimized for security or performance.
Build for Production (Static)
By default, Astro generates a fully static site. This is the recommended approach for blogs, documentation, portfolios, and marketing pages.
# Build for production
npm run build
# This compiles into optimized HTML, CSS, and JS in the dist/ directory
# Preview the build locally
npm run preview -- --host 0.0.0.0
# Confirm everything renders at http://YOUR_SERVER_IP:4321
# Press Ctrl+C once confirmedConfigure Nginx as Web Server
Nginx serves your static Astro files with high performance and low memory overhead — ideal for a RamNode VPS.
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginxserver {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;
root /home/astro/my-astro-site/dist;
index index.html;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Cache Astro's hashed assets aggressively
location /_astro/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Serve static files with fallback
location / {
try_files $uri $uri/ $uri.html =404;
}
# Gzip compression
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 256;
error_page 404 /404.html;
}sudo ln -s /etc/nginx/sites-available/astro /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginxSecure with SSL Using Let's Encrypt
sudo apt install -y certbot python3-certbot-nginx
# Obtain and install the SSL certificate
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
# Verify auto-renewal is configured
sudo certbot renew --dry-runCertbot automatically modifies your Nginx configuration to handle HTTPS and redirect HTTP traffic. Certificates renew automatically via a systemd timer — no cron jobs needed.
Server-Side Rendering (Optional)
If your project requires dynamic routes, API endpoints, or per-request rendering, configure Astro for SSR using the Node.js adapter.
Install the Node.js Adapter
npx astro add nodeVerify Configuration
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone',
}),
});npm run build
node dist/server/entry.mjs
# SSR server starts on port 4321 — confirm it responds
# Press Ctrl+C to stopCreate a systemd Service
Manage the Astro SSR process with systemd for automatic startup and crash recovery:
[Unit]
Description=Astro SSR Application
After=network.target
[Service]
Type=simple
User=astro
WorkingDirectory=/home/astro/my-astro-site
ExecStart=/usr/bin/node dist/server/entry.mjs
Restart=on-failure
RestartSec=5
Environment=HOST=127.0.0.1
Environment=PORT=4321
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable astro
sudo systemctl start astroUpdate Nginx for SSR Reverse Proxy
Replace your static Nginx config with a reverse proxy configuration:
server {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
proxy_pass http://127.0.0.1:4321;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
}
# Still cache Astro's hashed assets directly
location /_astro/ {
alias /home/astro/my-astro-site/dist/client/_astro/;
expires 1y;
add_header Cache-Control "public, immutable";
}
}sudo nginx -t
sudo systemctl reload nginxAutomated Deployments
#!/bin/bash
set -e
cd /home/astro/my-astro-site
git pull origin main
npm ci
npm run build
# For SSR deployments, restart the service:
# sudo systemctl restart astro
echo "Deployment complete!"chmod +x ~/deploy.sh
# Run whenever you push updates
~/deploy.shFor fully automated CI/CD, add a GitHub Actions workflow that SSHs into your RamNode VPS and runs the deploy script on every push to main.
Performance Optimization
Enable Brotli Compression
Brotli provides better compression ratios than Gzip for text-based assets:
sudo apt install -y libnginx-mod-http-brotli-filterbrotli on;
brotli_types text/plain text/css application/json
application/javascript text/xml application/xml
image/svg+xml;HTTP/2
HTTP/2 is enabled automatically when you configure SSL with Certbot. If your site includes many assets, HTTP/2 multiplexing significantly reduces load times.
Swap File for Low-Memory Plans
On the $5/month plan with 1 GB RAM, add swap to prevent out-of-memory errors during builds:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabMonitoring & Maintenance
# Service status
sudo systemctl status nginx
sudo systemctl status astro # If using SSR
# Nginx access and error logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
# Astro SSR service logs (if using SSR)
sudo journalctl -u astro -fAutomatic Security Updates
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgradesTroubleshooting
Build fails with out-of-memory error
Add a swap file (see Step 10) or upgrade to a plan with more RAM. Node.js builds can spike to 512 MB+ during compilation.
Nginx returns 403 Forbidden
Ensure the astro user's home directory and the dist/ folder have correct permissions: chmod 755 /home/astro && chmod -R 755 /home/astro/my-astro-site/dist
Port 4321 not accessible externally
Check UFW rules with sudo ufw status. The dev/preview server port is intentionally not exposed in production — use Nginx as your public-facing server.
SSL certificate not renewing
Run sudo certbot renew --dry-run to diagnose. Common causes include DNS misconfiguration or port 80 being blocked.
SSR service crashes on startup
Check logs with sudo journalctl -u astro -n 50. Common causes include missing environment variables or a failed npm run build.
Astro Site Deployed Successfully!
Your Astro site is now running in production on a RamNode VPS with Nginx, SSL encryption, and a deployment workflow. Astro's zero-JavaScript-by-default architecture combined with RamNode's SSD-backed infrastructure delivers near-instant page loads — starting at just $4/month.
