Premier League Predictor: Astro — Chapter 11, Exercise 3 ==================================================== TASK Build the project, run it as a standalone Node server behind an nginx reverse proxy with Basic Auth gating /admin/, and confirm directly: an unauthenticated request to a real admin API route under /admin/ is rejected by nginx before it ever reaches the Node process, while a request to the public league table route succeeds with no credentials at all. SOLUTION Steps to complete the hands-on part: 1. Run npm run build, confirm ./dist/server/entry.mjs exists, then run it directly: HOST=0.0.0.0 PORT=4321 node ./dist/server/entry.mjs and confirm /api/health still returns {"status":"ok"} when hit directly on port 4321. 2. Create /etc/nginx/.htpasswd with a real username/password using htpasswd -c /etc/nginx/.htpasswd admin. 3. Configure nginx with the two location blocks from the chapter — auth_basic on /admin/, no auth on the plain / location — both proxying to http://127.0.0.1:4321, then reload nginx. 4. From a separate machine or a fresh, unauthenticated curl session, request an admin route through nginx with no credentials, e.g.: curl -i http://your-server/admin/seasons Confirm the response is a real 401 Unauthorized with a WWW-Authenticate header, returned by nginx itself. 5. Confirm this rejection never reaches the app at all: check the Node process's own logs (or add a temporary console.log at the top of the relevant route) and confirm nothing is logged for the rejected request — nginx's own auth_basic check happens before proxy_pass is ever invoked, so a failed check never forwards the request to port 4321 in the first place. 6. Retry the same request with real credentials: curl -i -u admin:yourpassword http://your-server/admin/seasons Confirm this one succeeds with a real 200 and the actual JSON response, and this time does show up in the Node process's own logs. 7. Request a plain, non-admin route (e.g. /api/health or /) with no credentials at all and confirm it succeeds normally — proving the Basic Auth gate is scoped specifically to /admin/, not applied site-wide. WHY THIS WORKS AS AN ANSWER ---------------------------- It completes the real, hands-on deployment setup end to end (build, run, reverse proxy, Basic Auth), and explicitly verifies the one detail that actually matters for this chapter's own claim — that an unauthenticated admin request is rejected by nginx itself, before the Node process ever sees it at all, confirmed directly by the absence of any log entry for the rejected request versus a real log entry once valid credentials are supplied — rather than just confirming a 401 status code came back from somewhere.