sojorn/sojorn_docs/deployment/VPS_SETUP_GUIDE.md

10 KiB

Sojorn VPS Setup Guide

Complete guide to deploy Sojorn Flutter Web app to your VPS with Nginx.

Note: You mentioned MariaDB, but since you're using Supabase (PostgreSQL) for your database, you don't need MariaDB on your VPS. This guide focuses on hosting the static Flutter web files.


Prerequisites

  • VPS with Ubuntu 20.04/22.04 (or Debian-based distro)
  • Root or sudo access
  • Domain name (sojorn.net) pointed to your VPS IP
  • SSH access to your VPS

Part 1: Initial VPS Setup

1. Connect to your VPS

ssh root@your-vps-ip
# or if you have a non-root user
ssh your-username@your-vps-ip

2. Update system packages

apt update
apt upgrade -y

3. Set up firewall

# Allow SSH
ufw allow OpenSSH

# Allow HTTP and HTTPS
ufw allow 'Nginx Full'

# Enable firewall
ufw enable

# Check status
ufw status

Note: If you're logged in as root, you don't need sudo. If you're using a non-root user, prefix commands with sudo.


Part 2: Install Nginx

1. Install Nginx

apt install nginx -y

2. Start and enable Nginx

systemctl start nginx
systemctl enable nginx
systemctl status nginx

3. Test Nginx

Visit http://your-vps-ip in a browser. You should see the default Nginx welcome page.


Part 3: SSL Certificate (Let's Encrypt)

1. Install Certbot

apt install certbot python3-certbot-nginx -y

2. Obtain SSL certificate

Important: Make sure your domain DNS is already pointing to your VPS IP before running this.

certbot --nginx -d sojorn.net -d www.sojorn.net

Follow the prompts:

  • Enter your email address
  • Agree to terms of service
  • Choose whether to redirect HTTP to HTTPS (recommended: Yes)

3. Test auto-renewal

certbot renew --dry-run

Certbot will automatically renew your certificate before it expires.


Part 4: Configure Nginx for Flutter Web

1. Create web root directory

mkdir -p /var/www/sojorn
chmod -R 755 /var/www/sojorn

2. Create Nginx configuration

nano /etc/nginx/sites-available/sojorn

Paste this configuration:

# Redirect www to non-www
server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name www.sojorn.net;

    ssl_certificate /etc/letsencrypt/live/sojorn.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sojorn.net/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    return 301 https://sojorn.net$request_uri;
}

# Main server block
server {
    listen 80;
    listen [::]:80;
    server_name sojorn.net;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name sojorn.net;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/sojorn.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sojorn.net/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # Root directory
    root /var/www/sojorn;
    index index.html;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;

    # Flutter Web routing
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Cache control for Flutter assets
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Don't cache index.html or service worker
    location ~* (index\.html|flutter_service_worker\.js)$ {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        expires 0;
    }

    # Security: deny access to hidden files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Logging
    access_log /var/log/nginx/sojorn_access.log;
    error_log /var/log/nginx/sojorn_error.log;
}

3. Enable the site

# Create symbolic link
ln -s /etc/nginx/sites-available/sojorn /etc/nginx/sites-enabled/

# Test configuration
nginx -t

# Reload Nginx
systemctl reload nginx

Part 5: Build and Deploy Flutter Web

On your local machine (Windows):

1. Build Flutter for web

cd C:\Webs\Sojorn\sojorn_app

# Build for production
flutter build web --release --web-renderer canvaskit

Build options:

  • --web-renderer canvaskit: Best for mobile-first apps (better compatibility)
  • --web-renderer html: Lighter weight, faster initial load (alternative)
  • --web-renderer auto: Flutter decides based on device (default)

2. The build output is in: sojorn_app/build/web/


Part 6: Transfer Files to VPS

Option A: Using SCP (from Windows PowerShell or WSL)

# From your local machine
cd C:\Webs\Sojorn\sojorn_app\build

# Upload web directory
scp -r web/* your-username@your-vps-ip:/var/www/sojorn/

Option B: Using SFTP

# Connect via SFTP
sftp your-username@your-vps-ip

# Navigate to local build directory
lcd C:\Webs\Sojorn\sojorn_app\build\web

# Navigate to remote directory
cd /var/www/sojorn

# Upload files
put -r *

# Exit
exit

On your VPS:

cd /var/www/sojorn

# Initialize git repo
git init
git remote add origin https://github.com/yourusername/sojorn-web.git

# Pull latest
git pull origin main

On your local machine:

# Create a separate repo for web builds
cd C:\Webs\Sojorn\sojorn_app\build\web

git init
git add .
git commit -m "Initial Flutter web build"
git remote add origin https://github.com/yourusername/sojorn-web.git
git push -u origin main

Part 7: Set Correct Permissions

On your VPS:

# Set ownership (Nginx runs as www-data user)
chown -R www-data:www-data /var/www/sojorn

# Set permissions
chmod -R 755 /var/www/sojorn

Part 8: Test Your Deployment

  1. Visit https://sojorn.net - you should see your app
  2. Test deep linking: https://sojorn.net/username should route to a profile
  3. Check SSL: Look for the padlock icon in the browser

Part 9: Set Up Automatic Deployments (Optional)

Create a deployment script on your VPS:

nano ~/deploy-sojorn.sh

Paste:

#!/bin/bash

echo "Deploying Sojorn..."

# Navigate to web directory
cd /var/www/sojorn

# Pull latest changes (if using Git)
git pull origin main

# Set permissions
chown -R www-data:www-data /var/www/sojorn
chmod -R 755 /var/www/sojorn

# Reload Nginx
systemctl reload nginx

echo "Deployment complete!"

Make it executable:

chmod +x ~/deploy-sojorn.sh

Run deployments:

~/deploy-sojorn.sh

Part 10: Monitoring and Maintenance

Check Nginx logs

# Access logs
tail -f /var/log/nginx/sojorn_access.log

# Error logs
tail -f /var/log/nginx/sojorn_error.log

Check Nginx status

systemctl status nginx

Restart Nginx if needed

systemctl restart nginx

Update SSL certificate (automatic, but manual command)

certbot renew

Troubleshooting

Issue: "502 Bad Gateway"

  • Check Nginx error logs: tail -f /var/log/nginx/sojorn_error.log
  • Verify file permissions
  • Restart Nginx: systemctl restart nginx

Issue: Routes not working (404 on /u/username)

  • Verify try_files directive in Nginx config
  • Make sure index.html exists in /var/www/sojorn
  • Check Nginx configuration: nginx -t

Issue: SSL certificate issues

  • Verify DNS is pointing to correct IP
  • Run: certbot certificates to check status
  • Renew manually: certbot renew --force-renewal

Issue: Assets not loading

  • Check browser console for CORS errors
  • Verify file permissions: ls -la /var/www/sojorn
  • Clear browser cache

Performance Optimization Tips

1. Enable HTTP/2 (already in config)

HTTP/2 is enabled with http2 directive in listen statements.

2. Add Brotli compression (optional)

# Install brotli module
sudo apt install nginx-module-brotli -y

# Add to nginx.conf
sudo nano /etc/nginx/nginx.conf

Add to http block:

brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json;

Consider using Cloudflare for:

  • Global CDN
  • DDoS protection
  • Free SSL
  • Automatic minification

Next Steps

  1. Set up monitoring: Use tools like UptimeRobot or Pingdom to monitor uptime
  2. Configure backups: Regularly backup your VPS
  3. Set up CI/CD: Automate deployments with GitHub Actions or GitLab CI
  4. Analytics: Add Google Analytics or Plausible to track usage
  5. Performance monitoring: Use tools like Lighthouse to monitor performance

Quick Reference Commands

# Restart Nginx
systemctl restart nginx

# Reload Nginx (without downtime)
systemctl reload nginx

# Test Nginx configuration
nginx -t

# Check Nginx status
systemctl status nginx

# View error logs
tail -f /var/log/nginx/sojorn_error.log

# Deploy new version
~/deploy-sojorn.sh

# Renew SSL
certbot renew

Summary

You now have: Nginx web server installed and configured SSL certificate for HTTPS Flutter Web app served at https://sojorn.net Deep linking support for URLs like /username Gzip compression for better performance Proper security headers Caching for static assets

Your app is now live and accessible at https://sojorn.net! 🎉