Deploying a Nuxt 3 application with Server-Side Rendering (SSR) on Laravel Forge requires specific configurations to ensure that Nuxt is properly served. This guide provides a step-by-step walkthrough to deploy your Nuxt 3 SSR app on Forge, configure Nginx, and manage Nuxt processes using PM2.
Step 1: Prepare Your Nuxt 3 App for Deployment
Before deploying, ensure your Nuxt app is properly configured for SSR. Update your nuxt.config.js
file:
export default defineNuxtConfig({ ssr: true, // Enable Server-Side Rendering nitro: { prerender: { crawlLinks: false, // Prevent Nitro from crawling and generating routes routes: [], // No pre-rendered routes }, }, // ... other config here })
Why this matters?
- When SSR is enabled, Nuxt does not serve static files from
/dist
. - Instead, the SSR application is served from
.output/public/server
. - This means all requests are handled dynamically by Nuxt.
- We need PM2 to manage the Nuxt server, ensuring it runs continuously.
Step 2: Create a New Static App on Laravel Forge
- Log in to your Laravel Forge account.
- Create a new site and select Static App as the site type.
- Add your domain (e.g.,
yourdomain.com
). - Assign an SSL certificate (Let's Encrypt or manually).
- Once SSL is active, edit the Nginx configuration file.
Editing Nginx Configuration on Forge
Rather than editing the Nginx config directly on the server, follow these steps:
- Navigate to your site on Forge.
- Locate the Edit Files dropdown on the top-right side of the page.
- Select Edit Nginx Configuration.
- Replace the existing configuration with the following, ensuring you replace:
-
YOUR_DOMAIN_NAME
with your actual domain. -
YOUR_DOMAIN_FOLDER
with the correct site directory. - Keep the SSL ID values assigned by Forge for your certificate.
-
Example:
# FORGE CONFIG (DO NOT REMOVE!) include forge-conf/YOUR_DOMAIN_FOLDER/before/*; map $sent_http_content_type $expires { "text/html" epoch; "text/html; charset=utf-8" epoch; default off; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name YOUR_DOMAIN_NAME; # FORGE SSL (DO NOT REMOVE!) ssl_certificate /etc/nginx/ssl/YOUR_DOMAIN_NAME/YOUR_SSL_ID/server.crt; ssl_certificate_key /etc/nginx/ssl/YOUR_DOMAIN_NAME/YOUR_SSL_ID/server.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_dhparam /etc/nginx/dhparams.pem; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; gzip on; gzip_types text/plain application/xml text/css application/javascript; gzip_min_length 1000; # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/YOUR_DOMAIN_FOLDER/server/*; location / { expires $expires; 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_redirect off; proxy_read_timeout 1m; proxy_connect_timeout 1m; proxy_pass http://127.0.0.1:3000; # Set the address of the Node.js server } access_log off; error_log /var/log/nginx/YOUR_DOMAIN_NAME-error.log error; location ~ /\.(?!well-known).* { deny all; } } # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/YOUR_DOMAIN_FOLDER/after/*;
After saving changes in Forge, restart Nginx by clicking Apply Changes.
Step 3: Set Up Deployment Script on Forge
Navigate to your site on Laravel Forge and go to the Deployment tab. Update the deployment script with the following:
#!/bin/bash cd /home/forge/YOUR_DOMAIN_NAME # Pull latest changes git pull origin $FORGE_SITE_BRANCH # Clean installation files rm -rf node_modules rm package-lock.json # Install dependencies with platform-specific flags export ROLLUP_SKIP_NODE_CHECK=true npm install --platform=linux --arch=x64 # Build for SSR npm run build # Restart Nuxt using PM2 pm2 delete nuxt-app || true # Ensure old process is removed pm2 start .output/server/index.mjs --name "nuxt-app" # Save PM2 process so it persists after a reboot pm2 save # Restart PHP-FPM (if needed for other Laravel services) ( flock -w 10 9 || exit 1 echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock
Click Save and then Deploy Now to start the process.
Step 4: Finalizing Your Deployment
- Ensure that your Web Directory in Laravel Forge is set to:
/public
- Manually restart all services to ensure everything is working:
sudo service nginx restart pm2 restart nuxt-app
Open your domain in the browser (
https://yourdomain.com
) and check that the app is loading correctly.Monitor logs if there are any issues:
tail -f /var/log/nginx/YOUR_DOMAIN_NAME-error.log pm2 logs nuxt-app
Conclusion
By following these steps, you have successfully deployed a Nuxt 3 SSR application on Laravel Forge. This setup ensures:
- Nuxt 3 runs in server-side rendering mode.
- Nginx properly proxies requests to the Nuxt SSR server.
- PM2 keeps the Nuxt process running reliably.
This guide should serve as a complete reference for anyone deploying Nuxt 3 SSR on Laravel Forge. 🚀
Top comments (0)