Skip to main content

Overview

This guide walks through deploying inspir to a production Ubuntu server with:
  • nginx as a reverse proxy and static file server
  • SSL/TLS via Let’s Encrypt (free certificate)
  • PM2 or systemd for process management
  • Domain name configured with DNS
Production deployment requires server administration knowledge. Ensure you understand Linux, nginx, and security best practices before proceeding.

Prerequisites

  • Ubuntu 20.04+ server with root/sudo access
  • Domain name pointed to your server’s IP address
  • Supabase project with database schema configured
  • Anthropic API key
  • Git installed on the server

Step 1: Server Setup

1

Update system packages

sudo apt update
sudo apt upgrade -y
2

Install Node.js 18+

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# Verify installation
node --version  # Should be 18.x or higher
npm --version
3

Install nginx

sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
4

Install PM2 (recommended)

sudo npm install -g pm2
Alternatively, you can use systemd instead of PM2 (see below).

Step 2: Clone and Configure the Application

1

Clone the repository

cd /root
git clone https://github.com/yourusername/inspir.git
cd inspir
2

Configure backend environment

cd backend
cp .env.example .env
nano .env  # or vim .env
Update with production values:
# Server Configuration
PORT=3000
HOST=0.0.0.0
FRONTEND_URL=https://yourdomain.com  # Your actual domain

# Anthropic API
ANTHROPIC_API_KEY=sk-ant-api03-...

# Supabase Configuration
SUPABASE_URL=https://xxxxxxxxxxx.supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# JWT Secret - Generate a strong random string
JWT_SECRET=$(openssl rand -base64 32)
3

Configure frontend environment

cd ../frontend
cp .env.example .env
nano .env
Update with production values:
# Supabase Configuration
VITE_SUPABASE_URL=https://xxxxxxxxxxx.supabase.co
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# API Configuration - Use your actual domain
VITE_API_URL=https://yourdomain.com/api
4

Install dependencies

# Backend
cd /root/inspir/backend
npm install --production

# Frontend
cd /root/inspir/frontend
npm install
5

Build the frontend

cd /root/inspir/frontend
npm run build
This creates an optimized production build in dist/.

Step 3: Configure nginx

1

Create nginx configuration

Create a new site configuration:
sudo nano /etc/nginx/sites-available/inspir.conf
Paste the following (replace yourdomain.com with your actual domain):
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    # Serve the built frontend
    root /var/www/inspir;
    index index.html;

    # Reverse proxy API requests to the backend
    location /api/ {
        proxy_pass http://127.0.0.1:3000/api/;
        proxy_http_version 1.1;
        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_set_header Connection "";
        proxy_read_timeout 90;
        client_max_body_size 15m;
    }

    # Single-page app routing
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Enable gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript application/ld+json application/xml text/xml image/svg+xml;
}
2

Copy frontend build to web directory

sudo mkdir -p /var/www/inspir
sudo cp -r /root/inspir/frontend/dist/* /var/www/inspir/
sudo chmod -R 755 /var/www/inspir
3

Enable the site

sudo ln -s /etc/nginx/sites-available/inspir.conf /etc/nginx/sites-enabled/
sudo nginx -t  # Test configuration
sudo systemctl reload nginx

Step 4: Set Up SSL with Let’s Encrypt

1

Install Certbot

sudo apt install certbot python3-certbot-nginx -y
2

Obtain SSL certificate

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Follow the prompts to:
  • Enter your email address
  • Agree to terms of service
  • Choose to redirect HTTP to HTTPS (recommended)
3

Verify auto-renewal

Certbot automatically sets up certificate renewal. Test it:
sudo certbot renew --dry-run

Step 5: Start the Backend

1

Start the backend with PM2

cd /root/inspir/backend
pm2 start server.js --name inspir-backend
pm2 save
2

Configure PM2 to start on boot

pm2 startup
# Follow the command it outputs
pm2 save
3

Verify it's running

pm2 status
pm2 logs inspir-backend

Option B: Using systemd

1

Create systemd service file

sudo nano /etc/systemd/system/inspirquiz.service
Paste the following:
[Unit]
Description=InspirQuiz Backend Service
After=network.target

[Service]
Type=simple
WorkingDirectory=/root/inspir/backend
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=HOST=0.0.0.0
EnvironmentFile=-/root/inspir/backend/.env
ExecStart=/usr/bin/node /root/inspir/backend/server.js
Restart=on-failure
RestartSec=5
User=root
Group=root

[Install]
WantedBy=multi-user.target
2

Enable and start the service

sudo systemctl daemon-reload
sudo systemctl enable inspirquiz
sudo systemctl start inspirquiz
3

Check service status

sudo systemctl status inspirquiz
sudo journalctl -u inspirquiz -f  # View logs

Step 6: Verify Deployment

1

Test the website

Open https://yourdomain.com in your browser.
  • βœ… HTTPS should be enabled (green padlock)
  • βœ… Homepage should load
  • βœ… Sign up/login should work
2

Test the API

curl https://yourdomain.com/api/health
Should return a health check response.
3

Monitor logs

PM2:
pm2 logs inspir-backend
systemd:
sudo journalctl -u inspirquiz -f

Deployment Script

Create a script to automate future deployments:
sudo nano /root/deploy.sh
Paste the following:
#!/bin/bash

echo "πŸš€ Starting inspir deployment..."

# Navigate to project directory
cd /root/inspir || exit 1

# Pull latest code
echo "πŸ“₯ Pulling latest code..."
git pull origin main

# Install backend dependencies
echo "πŸ“¦ Installing backend dependencies..."
cd /root/inspir/backend
npm install --production

# Build the frontend
echo "πŸ“¦ Building frontend..."
cd /root/inspir/frontend
npm install
npm run build

if [ $? -ne 0 ]; then
    echo "❌ Frontend build failed!"
    exit 1
fi

# Copy build to web directory
echo "πŸ“‚ Copying build to web directory..."
sudo rm -rf /var/www/inspir/*
sudo cp -r dist/* /var/www/inspir/
sudo chmod -R 755 /var/www/inspir/

# Reload nginx
echo "πŸ”„ Reloading nginx..."
sudo systemctl reload nginx

# Restart backend with PM2
echo "πŸ”„ Restarting backend..."
cd /root/inspir/backend
pm2 restart inspir-backend || pm2 start server.js --name inspir-backend
pm2 save

echo "βœ… Deployment complete!"
echo "🌐 Live at: https://yourdomain.com"
Make it executable:
chmod +x /root/deploy.sh
Run future deployments with:
/root/deploy.sh

Security Best Practices

Production security is critical. Follow these best practices:

Firewall Configuration

# Install ufw (Uncomplicated Firewall)
sudo apt install ufw

# Allow SSH, HTTP, HTTPS
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Enable firewall
sudo ufw enable
sudo ufw status

Secure Environment Variables

# Restrict .env file permissions
chmod 600 /root/inspir/backend/.env
chmod 600 /root/inspir/frontend/.env

Keep Dependencies Updated

# Check for vulnerabilities
cd /root/inspir/backend
npm audit
npm audit fix

cd /root/inspir/frontend
npm audit
npm audit fix

Enable fail2ban (Optional)

Protect against brute-force attacks:
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Monitoring and Logs

View Application Logs

PM2:
pm2 logs inspir-backend
pm2 monit  # Live monitoring
systemd:
sudo journalctl -u inspirquiz -f
sudo journalctl -u inspirquiz --since "1 hour ago"

View nginx Logs

sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

Monitor Server Resources

htop  # Install: sudo apt install htop
df -h  # Disk usage
free -h  # Memory usage

Troubleshooting

502 Bad Gateway

Cause: Backend is not running or unreachable. Fix:
# Check if backend is running
pm2 status  # or sudo systemctl status inspirquiz

# Restart backend
pm2 restart inspir-backend  # or sudo systemctl restart inspirquiz

# Check logs for errors
pm2 logs inspir-backend

SSL Certificate Issues

Renew certificate manually:
sudo certbot renew
sudo systemctl reload nginx

Frontend Not Updating

Clear build and redeploy:
cd /root/inspir/frontend
rm -rf dist node_modules
npm install
npm run build
sudo cp -r dist/* /var/www/inspir/

Database Connection Errors

Check Supabase project status: Test connection from server:
curl -I https://xxxxxxxxxxx.supabase.co

Backup Strategy

Regularly backup your environment variables and application data.

Backup Environment Variables

cp /root/inspir/backend/.env /root/inspir/backend/.env.backup
cp /root/inspir/frontend/.env /root/inspir/frontend/.env.backup

Backup Database

Supabase provides automatic backups. For manual backups:
  1. Go to Supabase Dashboard
  2. Navigate to Database β†’ Backups
  3. Download manual backup or use pg_dump via connection string

Next Steps

Your production deployment is complete! Consider:
  • Setting up monitoring (e.g., UptimeRobot, Datadog)
  • Configuring automated backups
  • Setting up CI/CD for automated deployments
  • Adding a CDN (e.g., Cloudflare) for better performance
Database Setup β†’

Build docs developers (and LLMs) love