# VPS Debugging Lab

Practice diagnosing a static site on a VPS by separating DNS, HTTP, HTTPS, Nginx routing, release files, and permissions.

## How to use the lab

Read the clue, choose the smallest safe command, predict the expected output pattern, then compare your answer to the key.

## Scenario 1: Domain still shows the registrar parking page

Clue: The domain loads, but it shows a parked or default registrar page instead of your static site.

Commands:
- `dig +short example.com A`
- `dig +short @1.1.1.1 example.com A`
- `curl -I http://example.com`
- `curl -I -H 'Host: example.com' http://SERVER_IP`

Expected output pattern: DNS returns a registrar, parking, or old hosting IP, or the direct Host-header check reaches different content than the domain.

Diagnosis: The request is not consistently reaching the intended VPS for that hostname.

Fix checklist:
- Correct the A record for the exact hostname.
- Record the resolver answer before changing another record.
- Retest HTTP only after DNS returns the intended IP.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 2: www works but the root domain fails

Clue: https://www.example.com loads, but https://example.com does not, or the reverse happens.

Commands:
- `dig +short www.example.com A`
- `dig +short example.com A`
- `curl -I https://www.example.com`
- `curl -I https://example.com`

Expected output pattern: One hostname resolves or redirects correctly while the other is missing, stale, or routed differently.

Diagnosis: The root and www hostnames are not configured as one intentional pair.

Fix checklist:
- Choose the canonical hostname.
- Add or correct the missing record.
- Verify both hostnames and their redirect behavior.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 3: HTTPS fails after HTTP starts working

Clue: http://example.com returns a response, but https://example.com shows a certificate or connection failure.

Commands:
- `curl -I http://example.com`
- `curl -I https://example.com`
- `certbot certificates`
- `openssl s_client -connect example.com:443 -servername example.com </dev/null`

Expected output pattern: HTTP reaches the server, but HTTPS shows a missing, wrong, expired, or unmatched certificate.

Diagnosis: The web route exists, but certificate coverage or TLS routing is not correct yet.

Fix checklist:
- Confirm DNS and HTTP first.
- Check certificate names and expiry.
- Fix the TLS server block or request the right certificate once prerequisites are true.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 4: Nginx default page appears

Clue: The browser reaches Nginx, but it shows the default welcome page instead of your project.

Commands:
- `sudo nginx -t`
- `systemctl status nginx --no-pager`
- `grep -RInE 'server_name|root|listen' /etc/nginx/sites-enabled /etc/nginx/conf.d 2>/dev/null`
- `curl -I -H 'Host: example.com' http://127.0.0.1`

Expected output pattern: Nginx is alive, but the matching server block or root path does not select your release.

Diagnosis: The request reaches Nginx but falls through to the wrong server block or document root.

Fix checklist:
- Fix the intended server_name/listen/root block.
- Run nginx -t before reload.
- Retest with the Host header and the public domain.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 5: 403 forbidden after deploy

Clue: The route exists, but Nginx returns 403 when loading the static site.

Commands:
- `namei -l /srv/www/example.com/current/index.html`
- `stat -c '%A %U:%G %n' /srv/www/example.com/current/index.html`
- `sudo tail -80 /var/log/nginx/error.log`
- `id www-data`

Expected output pattern: A parent directory lacks execute permission, the file is unreadable, or Nginx logs name a permission issue.

Diagnosis: Nginx found the path but cannot traverse or read the file as the service user.

Fix checklist:
- Fix the specific path component shown by namei.
- Avoid broad recursive permission edits.
- Retest after the smallest owner or mode correction.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 6: 404 after a fresh deploy

Clue: The domain loads but a page that should exist returns 404.

Commands:
- `find /srv/www/example.com/current -maxdepth 2 -type f | sort | head -50`
- `readlink -f /srv/www/example.com/current`
- `curl -I https://example.com/missing-page/`
- `grep -RIn 'root' /etc/nginx/sites-enabled /etc/nginx/conf.d 2>/dev/null`

Expected output pattern: The generated file is missing, the URL path differs, or Nginx points at a release without that file.

Diagnosis: The web server is responding, but the requested path does not map to a generated file in the active release.

Fix checklist:
- Confirm the file exists in the current release.
- Regenerate or deploy the missing route.
- Retest the exact URL path.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 7: Stale release is still live

Clue: You deployed new content, but the live page still shows old text or an old asset version.

Commands:
- `readlink -f /srv/www/example.com/current`
- `curl -sS https://example.com/ | grep -n 'expected text'`
- `curl -I 'https://example.com/?v=check'`
- `ls -lah /srv/www/example.com/releases | tail`

Expected output pattern: The current symlink, page body, or asset version does not match the release you expected.

Diagnosis: The deploy artifact exists, but the live symlink, cache, or generated asset reference is stale.

Fix checklist:
- Flip the current symlink to the intended release.
- Use a cache-busting URL to verify.
- Record the live release path in the project note.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.

## Scenario 8: Certificate renewal failed

Clue: The site worked before, but the browser now warns about an expired or invalid certificate.

Commands:
- `certbot certificates`
- `sudo certbot renew --dry-run`
- `journalctl -u certbot --since '7 days ago' --no-pager`
- `curl -I http://example.com/.well-known/acme-challenge/test`

Expected output pattern: The certificate list, dry run, or logs name the failing domain, challenge route, or renewal hook.

Diagnosis: Renewal cannot prove domain control or cannot run its configured renewal path.

Fix checklist:
- Fix the named DNS or HTTP challenge issue.
- Confirm port 80 reaches the right host.
- Run a dry run before relying on automatic renewal.

Answer key: choose the first command that separates the failing layer, compare actual output to the expected pattern, then follow the fix checklist without broad edits.
