Capstone: Secure, Monitor, and Back Up

July 16, 2026 ยท View on GitHub

The public HTTP site works. This stage turns it into an operable HTTPS service.

Step 1: Issue a Certificate

Before issuance, confirm:

dig A example.dpdns.org
dig AAAA example.dpdns.org
dig A www.example.dpdns.org
curl -I http://example.dpdns.org

Use a maintained ACME client supported by the server environment. Request names only after both reach the intended server.

Do not copy private keys into notes or screenshots.

Step 2: Verify HTTPS Directly

curl -I https://example.dpdns.org
curl -I https://www.example.dpdns.org

Inspect the certificate:

openssl s_client -connect example.dpdns.org:443 -servername example.dpdns.org </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

Expected:

  • Current validity dates
  • Root and www in the subject alternative names
  • A chain trusted by the intended clients

Step 3: Configure Canonical Redirects

Choose the root domain as canonical for this project.

HTTP redirect:

server {
    listen 80;
    listen [::]:80;
    server_name example.dpdns.org www.example.dpdns.org;
    return 308 https://example.dpdns.org$request_uri;
}

Add an HTTPS redirect virtual host for www using the certificate configuration produced by the reviewed ACME workflow, then serve the content from the root hostname.

Validate and reload:

sudo nginx -t
sudo systemctl reload nginx

Step 4: Verify the Redirect Path

curl -IL http://www.example.dpdns.org/about.html

The response should reach the canonical HTTPS URL without loops or unnecessary chains.

Step 5: Test Certificate Renewal

Run the documented dry-run or test-renewal command for the installed ACME client. Verify the scheduled timer or task and review its latest status.

Create an independent expiration alert. The same client that fails renewal should not be the only system expected to report the failure.

Step 6: Apply Server Baseline

  • Confirm only required public ports are open.
  • Confirm website files are not broadly writable.
  • Confirm Nginx and the operating system are updated.
  • Confirm SSH recovery access before tightening authentication.
  • Confirm logs rotate.
  • Confirm time synchronization.
  • Remove default pages and unused services.

Re-run:

sudo ss -lntup
sudo nginx -t

Step 7: Create a Website Backup

sudo tar -C /var/www -czf /tmp/example-site-backup.tar.gz example.dpdns.org
tar -tzf /tmp/example-site-backup.tar.gz | sed -n '1,80p'

Copy the verified archive to a protected system separate from the server. Back up the Nginx site configuration and the source repository as separate recovery inputs.

Step 8: Restore in Isolation

On a safe test system or isolated directory:

mkdir restore-test
tar -xzf example-site-backup.tar.gz -C restore-test
find restore-test -maxdepth 3 -type f -print

Serve the restored files on 127.0.0.1 and verify Home, About, and CSS. Record the restore duration.

Step 9: Create Monitors

At minimum:

  • Domain expiration reminder
  • Canonical HTTPS status and content check
  • TLS expiration check
  • Backup job result
  • Server disk-space alert
  • Unexpected nameserver or address change check

Every alert needs an owner and a first-response instruction.

Step 10: Run a Failure Drill

Temporarily use a safe test environment to simulate one failure, such as a missing static file or stopped local test server. Confirm that:

  • Monitoring detects it.
  • The operator follows the runbook.
  • Recovery restores the expected page.
  • The incident is recorded.

Do not intentionally break public DNS or production certificates for a learning drill.

Continue to Final Acceptance and Handover.