Appearance
Deployment
This guide covers a typical VPS production setup:
exchangepro.com→ Nuxt (Node)api.exchangepro.com→ Laravel (PHP-FPM + Nginx)
Pre-deployment checklist
- [ ]
APP_DEBUG=falseon backend - [ ]
APP_KEYgenerated - [ ] Migrations run on production database
- [ ]
FRONTEND_URLandAPI_URLset correctly - [ ] CORS and Sanctum domains configured
- [ ] SSL certificates installed
- [ ] Cron entry for Laravel scheduler (
* * * * * … schedule:run) - [ ] Queue:
syncor Supervisor runningqueue:workifQUEUE_CONNECTION=database - [ ] Mail SMTP working
Backend — Nginx + PHP-FPM
Document root
nginx
server {
listen 443 ssl http2;
server_name api.exchangepro.com;
root /var/www/exchangepro/backend/public;
index index.php;
ssl_certificate /etc/letsencrypt/live/api.exchangepro.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.exchangepro.com/privkey.pem;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
client_max_body_size 12M;
}client_max_body_size helps proof file uploads (5 MB limit per file in app).
Optimize Laravel
bash
cd /var/www/exchangepro/backend
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan view:cacheFrontend — Node SSR
Build on server (or CI)
bash
cd /var/www/exchangepro/frontend
npm ci
npm run buildsystemd service example
/etc/systemd/system/exchangepro-frontend.service:
ini
[Unit]
Description=ExchangePro Nuxt SSR
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/exchangepro/frontend
Environment=HOST=127.0.0.1
Environment=PORT=3000
Environment=FRONTEND_URL=https://exchangepro.com
Environment=API_URL=https://api.exchangepro.com
ExecStart=/usr/bin/node .output/server/index.mjs
Restart=on-failure
[Install]
WantedBy=multi-user.targetbash
sudo systemctl enable --now exchangepro-frontendNginx reverse proxy to Nuxt
nginx
server {
listen 443 ssl http2;
server_name exchangepro.com www.exchangepro.com;
ssl_certificate /etc/letsencrypt/live/exchangepro.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exchangepro.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}Alternative: PM2
bash
npm install -g pm2
cd frontend
FRONTEND_URL=https://exchangepro.com API_URL=https://api.exchangepro.com \
pm2 start .output/server/index.mjs --name exchangepro-web
pm2 saveFile uploads & persistence
Ensure these survive deploys and are backed up:
text
backend/public/transaction-proofs/
backend/public/images/Do not wipe public/images on deploy if it contains production uploads.
Admin cache clear
Admins can clear caches from Admin → Extra → Cache, or run:
bash
php artisan optimize:clearZero-downtime tips
- Put site in maintenance:
php artisan downduring DB migrations - Run
php artisan migrate --forcebefore switching traffic - Rebuild frontend after env changes
Shared hosting note
If your host only supports PHP (no Node):
- Host API on subdomain
- Build Nuxt locally and host SSR on Vercel, Netlify, Railway, or a small VPS
- Point
API_URLto PHP backend
Pure cPanel without Node cannot run the default Nuxt SSR output.