TopicLadder
Practice lab

VPS Debugging Lab

Practice diagnosing a static site that is live on a VPS but not loading the way a maker expects.

How to practice

  1. Read the starting clue.
  2. Choose the first command before opening the answer.
  3. Predict what output would prove the likely cause.
  4. Open the answer key and write the next fix in a project note.

What counts as a good answer

A good answer names the layer being tested, the command that tests it, the output pattern that would confirm or reject the hypothesis, and the next safe action. Do not stop at “DNS problem” or “Nginx problem.” Say what evidence made you think that.

For example, if the domain returns the wrong IP, the answer should stay in DNS. If DNS is correct and HTTP reaches Nginx, the answer should move to server-block routing, file paths, or certificates depending on the visible symptom.

Scoring your run

  • 1 point: you picked an inspection command before a change command.
  • 1 point: you predicted the expected output pattern before opening the answer.
  • 1 point: your next action matches the evidence instead of the browser symptom alone.
  • 1 point: you wrote the command, actual output, and next action into a project note.

A perfect score is less important than the habit: separate layers, read output, and avoid broad fixes until the evidence narrows the problem.

Scenario index

Use the table to pick a failure mode, then open the scenario and choose the smallest command that separates that layer.

# Scenario Likely layer
1 Domain still shows the registrar parking page The request is not consistently reaching the intended VPS for that hostname.
2 www works but the root domain fails The root and www hostnames are not configured as one intentional pair.
3 HTTPS fails after HTTP starts working The web route exists, but certificate coverage or TLS routing is not correct yet.
4 Nginx default page appears The request reaches Nginx but falls through to the wrong server block or document root.
5 403 forbidden after deploy Nginx found the path but cannot traverse or read the file as the service user.
6 404 after a fresh deploy The web server is responding, but the requested path does not map to a generated file in the active release.
7 Stale release is still live The deploy artifact exists, but the live symlink, cache, or generated asset reference is stale.
8 Certificate renewal failed Renewal cannot prove domain control or cannot run its configured renewal path.

Scenarios

1. Domain still shows the registrar parking page

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The request is not consistently reaching the intended VPS for that hostname.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

2. www works but the root domain fails

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The root and www hostnames are not configured as one intentional pair.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

3. HTTPS fails after HTTP starts working

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The web route exists, but certificate coverage or TLS routing is not correct yet.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

4. Nginx default page appears

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The request reaches Nginx but falls through to the wrong server block or document root.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

5. 403 forbidden after deploy

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: Nginx found the path but cannot traverse or read the file as the service user.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

6. 404 after a fresh deploy

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The web server is responding, but the requested path does not map to a generated file in the active release.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

7. Stale release is still live

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: The deploy artifact exists, but the live symlink, cache, or generated asset reference is stale.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

8. Certificate renewal failed

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

Commands to run
  • 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.
Show answer key

Start by proving this layer: Renewal cannot prove domain control or cannot run its configured renewal path.

Use the expected output pattern above to decide whether the problem stays in this layer or moves to the next check. Do not apply the checklist until the output supports it.

Common mistakes this lab is trying to prevent

  • Treating a browser cache as proof that DNS is still wrong.
  • Assuming www and the root domain share the same record.
  • Fixing HTTPS before proving port 80 reaches the VPS.
  • Reloading Nginx after a failed config test.
  • Using broad chmod or chown when one parent directory is the issue.
  • Assuming a generated page exists in the active release without checking.
  • Reading certbot output without checking which domain failed.
  • Changing multiple layers at once and losing the evidence trail.

Safety notes

  • Replace example.com and SERVER_IP before running any command.
  • Record the current DNS answer before editing records again.
  • Check plain HTTP before spending time on certificates.
  • Run nginx -t before reloads or service restarts.
  • Use namei and stat before changing permissions.
  • Verify the current release symlink before blaming cache.
  • Do not request certificates repeatedly when DNS is wrong.
  • Write the actual output, not just the symptom you saw in the browser.

Project note template

Use the same small template for every scenario: clue, layer tested, command, expected output, actual output, diagnosis, and next action. This makes the lab useful later when a real VPS issue happens.

Clue:
Layer tested:
Command:
Expected output:
Actual output:
Diagnosis:
Next action:

Answer key discipline

The answer key is not a script to paste. It is the evidence you should expect and the next safe fix direction. If your output differs, write down the difference before trying stronger commands.

When you use this lab with a real site, replace example domains and paths with your actual domain, server path, service name, and release folder. If the result is surprising, pause and inspect one layer closer instead of jumping to a larger edit.

Buy me a coffee for more maker ladders

TopicLadder is free to read. Support helps turn rough project paths into useful notes, cards, videos, and practice tasks.

Support this project

Last reviewed: July 5, 2026. TopicLadder pages are curated for practical learning and may be updated as examples improve.