Pathforge tech documentation · HTML Pathforge - VPS Deployment Documentation
PATHFORGE
VPS Deployment Docs
Version 1.0

1. Overview

This document covers two complete ways to deploy PathForge (backend + frontend) on a VPS: using Docker Compose, or manually without Docker, served through Nginx.

Each setup video below is paired with the exact written steps used in it. Replace placeholders such as <VPS_IP>, <VPS_USER>, <BACKEND_REPO_URL> and <FRONTEND_REPO_URL> with your actual values throughout.

REQUIRES

A VPS with SSH access (Ubuntu 22.04 / 24.04 recommended) is required for both deployment paths.

2. Deployment with Docker

This path covers deploying both the backend and the frontend on a VPS using Docker Compose.

Service URL Port
Backend http://<VPS_IP>:8585 8585
Frontend http://<VPS_IP>:8485 8485

2.1 Prerequisites

  • A VPS with SSH access (Ubuntu 22.04 / 24.04 recommended)
  • SSH credentials (password or private key)
  • Git installed on the VPS
  • Docker Engine and the Docker Compose plugin installed on the VPS
  • Ports 8585 and 8485 open in the firewall / cloud provider security group

Verify (or install) the prerequisites

git --version
docker --version
docker compose version

Install Docker if missing:

sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg git
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker
▶ VIDEO WALKTHROUGH 1

2.2 Setting up Backend in VPS via Docker

Part 1 of the Docker deployment guide

Step 1 — SSH into the VPS

ssh <VPS_USER>@<VPS_IP>

Step 2 — Navigate to deployment root

cd /var/www

Step 3 — Clone the backend repository

git clone https://github.com/Ahmad-Mujtaba-Saeed/backendAndTechTrack.git

Step 4 — Enter project directory & configure .env

cd backendAndTechTrack
cp .env.example .env
nano .env

Step 5 — Build and run Docker containers

docker compose up --build -d

Step 6 — Verify backend service

Open in browser: http://<VPS_IP>}:8585

▶ VIDEO WALKTHROUGH 2

2.3 Setting up Frontend on VPS via Docker

Part 2 of the Docker deployment guide

Step 1 — Navigate to deployment root

cd /var/www

Step 2 — Clone frontend repository

git clone https://github.com/Ahmad-Mujtaba-Saeed/aTechTrackFrontend.git

Step 3 — Build and start frontend container

cd aTechTrackFrontend
docker compose up --build -d

Step 4 — Verify Frontend application

Open in browser: http://<VPS_IP>:8485

2.4 Post-Deployment Checklist (Docker)

  • Backend containers Up (`docker compose ps`)
  • Frontend containers Up (`docker compose ps`)
  • `http://:8585` loads backend
  • `http://:8485` loads frontend interface

2.5 Common Management Commands

Run these from inside the respective project directory.

# View running containers
docker compose ps
 
# View logs (all services)
docker compose logs -f
 
# View logs for one service
docker compose logs -f <service-name>
 
# Stop containers (keeps volumes/data)
docker compose down
 
# Stop containers AND delete volumes (destroys database data)
docker compose down -v
 
# Restart containers
docker compose restart
 
# Open a shell inside a container
docker compose exec <service-name> bash

2.6 Deploying Updates

cd /var/www/<project-folder>
git pull origin main
docker compose up --build -d

2.7 Troubleshooting

Port already in use

sudo lsof -i :8585
sudo lsof -i :8485

Stop whatever is holding the port, or change the host-side port mapping in docker-compose.yml.

Backend can't connect to the database

  • Confirm DB_HOST in .env matches the database service name in docker-compose.yml (not localhost)
  • Confirm the database container is running: docker compose ps
  • Check the database logs: docker compose logs <db-service-name>
  • Give the database a moment on first boot — it may need to initialize before the backend can connect

Site not reachable from the browser but curl localhost works on the VPS

This is a firewall issue, not a Docker issue:

sudo ufw status

Also check your cloud provider's security group / firewall rules for ports 8585 and 8485.

Build fails or behaves unexpectedly

Rebuild from scratch without the cache:

docker compose build --no-cache
docker compose up -d

Disk space filling up

docker system df
docker system prune -a

3. Manual Deployment (Without Docker)

Deploying Laravel (Backend) and Node.js (Frontend) directly on a VPS, served via Nginx.

3.1 Prerequisites

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl unzip nginx
▶ VIDEO WALKTHROUGH 3

3.2 Setting up Backend on VPS without Docker

Part 1 of the manual deployment guide — Laravel

Step 1 — Install PHP, Composer & Dependencies

sudo apt install -y php php-fpm php-cli php-mysql php-mbstring php-xml php-curl php-zip
composer install --no-dev --optimize-autoloader

Step 2 — Generate Key & Run Migrations

php artisan key:generate
php artisan migrate --force
php artisan db:seed --force

Step 3 — Set Storage Permissions

sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache

Step 4 — Configure Nginx Site

sudo nano /etc/nginx/sites-available/backend
sudo ln -s /etc/nginx/sites-available/backend /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
▶ VIDEO WALKTHROUGH 4

3.3 Setting up Frontend on VPS without Docker

Part 2 of the manual deployment guide — Node.js

Step 1 — Configure API Endpoint

nano src/config/config.js # Point VITE_API_URL to backend URL

Step 2 — Build Static Files

npm install
npm run build

Step 3 — Nginx Config & Reload

sudo nano /etc/nginx/sites-available/frontend
sudo ln -s /etc/nginx/sites-available/frontend /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

3.4 Optional — Domain and HTTPS

If you're using domains rather than raw ports, point the DNS A records at your VPS IP, change both configs to listen 80; with the appropriate server_name, then issue certificates:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d api.yourdomain.com -d app.yourdomain.com

Certbot edits the Nginx configs in place and sets up automatic renewal. Verify renewal works:

sudo certbot renew --dry-run

REMEMBER

Update APP_URL in the backend .env and the API URL in the frontend .env to the https:// addresses, then re-run npm run build for the frontend.

3.5 Post-Deployment Checklist (Manual)

  • PHP and Node v22 installed and configured correctly
  • Nginx configuration syntax test (`sudo nginx -t`) passes
  • Storage write permissions granted to `www-data`
  • Frontend build outputs successfully served on port 8485

3.6 Deploying Updates

Backend:

cd /var/www/<backend-project-folder>
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo chown -R www-data:www-data storage bootstrap/cache
sudo systemctl reload php8.2-fpm

Frontend:

cd /var/www/<frontend-project-folder>
git pull origin main
npm install
npm run build

No Nginx reload is needed for a frontend rebuild — it serves the files from disk.

3.7 Useful Commands

# Nginx
sudo nginx -t                                   # test the config
sudo systemctl reload nginx                     # apply config changes
sudo systemctl status nginx
sudo tail -f /var/log/nginx/backend-error.log
 
# PHP-FPM
sudo systemctl status php8.2-fpm
sudo systemctl restart php8.2-fpm
 
# Laravel
php artisan config:clear                        # after editing .env
php artisan cache:clear
php artisan route:clear
tail -f storage/logs/laravel.log
 
# MySQL
sudo systemctl status mysql
mysql -u app_user -p app_db

3.8 Troubleshooting

500 error or a blank white page on the backend

Check the Laravel log first — it names the actual cause:

tail -50 storage/logs/laravel.log
tail -50 /var/log/nginx/backend-error.log

The usual culprits, in order of likelihood: storage / bootstrap/cache permissions, a missing APP_KEY, or wrong database credentials.

"No application encryption key has been specified"

php artisan key:generate
php artisan config:clear

Config changes in .env aren't taking effect

Laravel caches the config. After any .env edit:

php artisan config:clear
php artisan config:cache

502 Bad Gateway

Nginx can't reach PHP-FPM. Confirm the socket path in your config matches reality:

ls /var/run/php/
sudo systemctl status php8.2-fpm

Database connection refused

sudo systemctl status mysql
mysql -u app_user -p -h 127.0.0.1 app_db

Confirm DB_HOST=127.0.0.1 in .env — not a Docker service name left over from another setup.

Python packages import but the feature still fails

Almost always the missing system binaries rather than the Python packages:

pdftoppm -v           # poppler-utils, needed by pdf2image
tesseract --version   # needed by pytesseract

Also check that the www-data user can run them — PHP shells out as www-data, not as your login user.

Frontend loads but shows a blank page

Check the browser console. If assets 404, the Nginx root is pointing at the wrong build directory — confirm whether the project builds to dist/ or build/.

Frontend routes 404 on refresh

The try_files $uri $uri/ /index.html; line is missing from the Nginx config.

Port not reachable from outside though curl localhost works

Firewall, not Nginx:

sudo ufw status

Also check your cloud provider's security group rules for ports 8585 and 8485.