Deploying Node.js + Laravel Together
Laravel backend + Node for realtime/SSR/assets deployed reliably.
A compact, practical, production-ready recipe that covers two common approaches
- Docker Compose + self-managed server
- Integration tips (broadcasting, queues, SSL, CI/CD, scaling)
You can pick a deployment style below:
Docker Compose (recommended for reproducibility) — everything containerized, single server or multiple, easy CI/CD. Good for small→medium projects.
Traditional (Nginx + PHP-FPM + PM2 for Node) — if you prefer not to use Docker and like systemd/supervisor.
Cloud managed (ECS / Fargate / Kubernetes / DigitalOcean Apps) — use when you need autoscaling. Concepts below still apply.
Prerequisites (server/local)
Ubuntu 20.04+ (or similar) or Docker-compatible host
SSH access + domain name (example.com)
Git, Docker & Docker Compose (if using Docker)
PHP 8.0+/Composer, Node 16+/npm or pnpm (if not using Docker)
MySQL/Postgres, Redis (for sessions, queues, broadcasting)
Certbot or a reverse proxy with Let’s Encrypt (Traefik) for TLS
A — Docker Compose approach (complete example)
1. Repo layout (monorepo recommended)
2. Laravel Dockerfile (/backend/Dockerfile)
3. Node Dockerfile (/node-app/Dockerfile)
4. docker-composer.yml (basic, extend as needed)
5. Nginx config (/nginx/conf.d/app.conf)
6. Environment (.env important keys for Docker)
7. Build & run
8. TLS / Let’s Encrypt
Option A: Put Traefik as a reverse proxy with automatic ACME in front of nginx.
Option B: Run certbot on the host and configure nginx to serve certs (if not fully containerized).
For production, Traefik + Docker labels or annginx-proxy+letsencrypt-companionare solid choices.
B — Non-Docker (Nginx + PHP-FPM + PM2)
If you prefer bare metal:
1. PHP & Laravel
- Install PHP-FPM, PHP extensions, Composer.
- Nginx config similar to above, with
fastcgi_pass unix:/run/php/php8.1-fpm.sock;or127.0.0.1:9000depending on your PHP-FPM setup. - Run
php artisan migrate --force, etc.
2. Node process manager (PM2)
- Install PHP-FPM, PHP extensions, Composer.
- Nginx config similar to above, with
fastcgi_pass unix:/run/php/php8.1-fpm.sock;or127.0.0.1:9000depending on your PHP-FPM setup. - Run
php artisan migrate --force, etc.
3. Supervisor for Laravel queue worker
/etc/supervisor/conf.d/laravel-worker.conf:
Then supervisorctl reread && supervisorctl update.
4. Cron scheduler
Integrating realtime: Laravel Node (Socket.io) via Redis
Use Redis as a bridge:
Node (socket.io + redis-adapter)
Laravel
.env:BROADCAST_DRIVER=redisCreate an
ShouldBroadcastevent — Laravel will publish to Redis channels.Node’s redis-adapter will receive broadcasts and forward to connected clients.
Alternative: use beyondcode/laravel-websockets or laravel-echo-server if you want PHP to serve WebSockets itself.
CI/CD (GitHub Actions → server via SSH + Docker Compose)
Simple flow: build images → push (or build on server) → ssh to server → docker-compose pull && docker-compose up -d --build.
Sample deploy step (in a GH Actions job):
Production hardening checklist
Run
php artisan config:cache&route:cache&optimize.APP_DEBUG=falsein.env.Periodic DB backups + offsite storage.
Set file permissions:
chown -R www-data:www-data storage bootstrap/cache.Use Redis for sessions & queue for worker scalability.
Use HTTPS + HSTS.
Logging & error tracking: Sentry, Papertrail, or ELK stack.
Monitor processes (PM2 / Prometheus + Grafana / UptimeRobot).
Use
--forceflag for migrations in automation only.
Troubleshooting commands
docker-compose logs -f nginx/docker-compose exec php tail -f storage/logs/laravel.logdocker ps/docker exec -it <container> bashpm2 logs/pm2 statusss -ltnp | grep 3000(check Node port)journalctl -u nginx -f
Quick 10-step executable checklist
Clone repo on server.
Create
.env.productionwith production values.docker-compose build --paralleldocker-compose up -ddocker-compose exec php php artisan key:generatedocker-compose exec php php artisan migrate --forcedocker-compose exec php php artisan config:cachedocker-compose exec php php artisan route:cacheEnable SSL (Traefik or certbot).
docker-compose exec worker supervisorctl status(verify queue worker)

