Deployment
Website Rebuild with Next.js
Chapter 11 · Deployment
This chapter's own deployment story is genuinely different from three of its five already-complete siblings — Laravel, Rails, and Astro all found a way to reuse the site's own already-live Apache. This course stands up entirely new infrastructure instead, the same real situation Django Rebuild 11 independently faced.
Two Real Paths: Vercel or Self-Hosted
vercel deploy gets a working production URL with essentially zero configuration, precisely because the platform and the framework share an owner. That's the genuinely easiest real path for a real Next.js project. This chapter goes self-hosted instead, deliberately: it's the only way to give this course a genuine, comparable production deployment story against its own siblings, on the same kind of server the real site this whole series rebuilds actually runs on.
Building for Production
next build produces the production bundle; next start serves it. Neither of these alone stays running after the terminal session ends — that's the next problem.
PM2: Keeping the Server Running
pm2 startup registers PM2 itself to relaunch on server reboot — without it, a reboot would silently take the whole site down until someone noticed.
gunicorn needed a process supervisor for: a production server process that must keep running unattended, restart itself if it crashes, and survive a reboot. Different runtime, same real requirement.
nginx: A Fresh Reverse Proxy
mod_php or PHP-FPM) — but nothing for proxying to a plain Node process on a local port. Rather than bolt an unfamiliar module onto Apache, this chapter stands up a fresh nginx instance instead, exactly the same call Django Rebuild 11 made for the identical reason.
The Upgrade/Connection headers matter specifically because Next.js's own dev-time hot-reload and certain runtime features rely on WebSocket upgrades — worth proxying correctly even in production, not just for local development.
certbot: TLS for the New Proxy
certbot's own nginx plugin edits the site's config in place, adding the certificate paths and a redirect from port 80 to 443 automatically — the same Let's Encrypt mechanism behind every genuinely free HTTPS setup on a self-hosted server.
Secrets: A Plain .env
AUTH_SECRET, the direct equivalent of a name every sibling course already hasAUTH_SECRET is what Auth.js uses to sign the JWT sessions Chapter 9 introduced — the exact same job Django's SECRET_KEY, Laravel's APP_KEY, and Rails' master.key each do in their own frameworks. A plain .env file is the simplest secrets story of the whole series — matching Django and Laravel's own convention exactly, not Rails' own reversed, encrypted-commit-to-the-repo approach.
Deployment, Compared Across the Series
| Next.js | Django | Laravel | Rails | Astro | Express | |
|---|---|---|---|---|---|---|
| Approach | Stood up fresh — PM2 + nginx + certbot | Stood up fresh — gunicorn + nginx | Modernize in place — Apache mod_proxy_fcgi | Modernize in place — Apache mod_passenger | Modernize in place — Apache mod_proxy_http | Stood up fresh — reuses Astro's own PM2 + mod_proxy_http unchanged |
| Secrets | Plain .env | Plain .env | Plain .env | Encrypted, committed (master.key) | Plain .env | Plain .env (via dotenv, an explicit package) |
| First-party zero-config platform? | Yes — Vercel (not used here, named honestly) | No | Paid, AWS-specific (Vapor) | No | No | No |
Hands-On Exercises
Run next build, start the result with PM2 using this chapter's own ecosystem.config.js, and confirm pm2 status shows the process running and pm2 startup is registered.
📄 View solutionConfigure the nginx reverse proxy from this chapter, run certbot against it, and confirm the site is reachable over HTTPS with a valid certificate — not just HTTP on port 3000 directly.
📄 View solutionExplain why this course's own deployment chapter had to stand up nginx from nothing, while Laravel Rebuild's, Rails Rebuild's, and Astro Rebuild's own Chapter 11s could all reuse the site's already-live Apache instead.
📄 View solutionChapter 11 Quick Reference
- Vercel or self-hosted — Vercel is genuinely easier; this chapter goes self-hosted for a comparable production story across the series
- PM2 — keeps
next startrunning unattended and across reboots, the same real job as Django'sgunicorn - nginx, stood up fresh — the existing Apache has no path for a plain Node process; certbot handles TLS
AUTH_SECRETin a plain.env— the direct equivalent of Django'sSECRET_KEY/Laravel'sAPP_KEY/Rails'master.key- Next chapter: Capstone: A Complete, Working Flexible-Routing Site