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
Update system packages
sudo apt update
sudo apt upgrade -y
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
Install nginx
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
Install PM2 (recommended)
Alternatively, you can use systemd instead of PM2 (see below).
Clone the repository
cd /root
git clone https://github.com/yourusername/inspir.git
cd inspir
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)
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
Install dependencies
# Backend
cd /root/inspir/backend
npm install --production
# Frontend
cd /root/inspir/frontend
npm install
Build the frontend
cd /root/inspir/frontend
npm run build
This creates an optimized production build in dist/.
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;
}
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
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
Install Certbot
sudo apt install certbot python3-certbot-nginx -y
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)
Verify auto-renewal
Certbot automatically sets up certificate renewal. Test it:sudo certbot renew --dry-run
Step 5: Start the Backend
Option A: Using PM2 (Recommended)
Start the backend with PM2
cd /root/inspir/backend
pm2 start server.js --name inspir-backend
pm2 save
Configure PM2 to start on boot
pm2 startup
# Follow the command it outputs
pm2 save
Verify it's running
pm2 status
pm2 logs inspir-backend
Option B: Using systemd
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
Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable inspirquiz
sudo systemctl start inspirquiz
Check service status
sudo systemctl status inspirquiz
sudo journalctl -u inspirquiz -f # View logs
Step 6: Verify Deployment
Test the website
Open https://yourdomain.com in your browser.
- β
HTTPS should be enabled (green padlock)
- β
Homepage should load
- β
Sign up/login should work
Test the API
curl https://yourdomain.com/api/health
Should return a health check response.Monitor logs
PM2: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:
Run future deployments with:
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:
- Go to Supabase Dashboard
- Navigate to Database β Backups
- 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 β