Two Problems, One Morning

This morning I pushed a blog post about the M2M Job Application Protocol — 23 D2 diagrams, 740 lines of markdown, the whole thing. The build succeeded locally. I committed. I pushed. And then:

  1. The blog post never appeared. The GitLab CI/CD pipeline had silently failed.
  2. https://nurazhar.com/ didn’t work. TLS handshake completed but the connection hung.

Two unrelated issues, same root cause: assumptions about the build environment.

Problem 1: The Hardcoded Resume Path

The Fabricate SSG (our 253-line Babashka static site generator) had one line that only worked on my laptop:

Architecture Diagram

The Error

In the GitLab CI runner (Alpine Linux Docker container), the build script tried to copy a file at an absolute path that only exists on my local machine:

java.io.FileNotFoundException:
  /home/nurazhar/Work/lifestyle/Job Hunting/...
  Supabase_IT_Systems_Administrator_Resume.pdf (No such file or directory)

The entire build crashed. No HTML files were generated. GitLab Pages served the stale deployment from the previous successful pipeline.

The Fix

The fix is defensive: check if the file exists before copying, and continue gracefully if it doesn’t. This is a one-line change with a three-line guard:

Architecture Diagram

The principle: a static site generator should never crash because a non-essential asset is missing. The resume PDF is a convenience copy, not a build-critical artifact. CI builds skip it; local builds include it.

Problem 2: HTTPS on the Custom Domain

The second issue was invisible until I looked at the response headers:

Architecture Diagram

The Mechanism

GitLab Pages has a project-level setting for custom domains. When you set nurazhar.com as the custom domain, GitLab automatically:

  1. Issues a Let’s Encrypt SSL certificate for the domain
  2. Redirects all traffic from the default GitLab Pages URL to the custom domain
  3. Handles both HTTP and HTTPS on the custom domain

The 308 redirect from nurazhar.gitlab.io/homepage/ to http://nurazhar.com/ works. But HTTPS on nurazhar.com hangs because the SSL certificate verification wasn’t completed.

GitLab Pages SSL Flow

Architecture Diagram

The missing step was likely the DNS TXT verification record. GitLab Pages requires you to add a TXT record to your domain’s DNS to prove ownership before it issues the SSL certificate. Without it, Let’s Encrypt can’t complete the challenge, and HTTPS stays broken.

The Fix

This needs to be fixed in GitLab project settings, not in code:

  1. Go to your GitLab project → Settings → Pages
  2. Verify the custom domain nurazhar.com is listed
  3. If SSL status shows “not verified”, add the DNS TXT record to your domain
  4. Wait for Let’s Encrypt to issue the certificate
  5. Check: curl -sI https://nurazhar.com/ should return 200 OK

DNS A records must point to GitLab Pages IPs:

Architecture Diagram

Lessons Learned

1. Never Hardcode Absolute Paths in Build Scripts

Any path that starts with /home/ is a ticking time bomb. Build scripts should:

2. CI/CD ≠ Local Dev Environment

The rules are simple but easy to forget:

Architecture Diagram

My laptop has the resume PDF. The CI runner doesn’t. My laptop has environment variables in .env. The CI runner has them in GitLab CI variables. The fix is to simulate the CI environment locally before pushing.

3. HTTPS is Not Automatic

GitLab Pages says “automatic SSL” but there’s a manual DNS verification step:

4. The Diagnostic Toolkit

Here’s the checklist I ran through:

Architecture Diagram

Check 6 was the smoking gun. Simulating the CI environment locally with Docker revealed the hardcoded path issue immediately.

The Actual Fixes Applied

Architecture Diagram

Fix 1 is code (already committed). Fix 2 requires a trip to the GitLab project settings page — verify the domain and ensure the DNS TXT record exists.

Verdict

Two bugs, both from the same category: assuming the build environment matches the development environment.

The hardcoded path fix is straightforward defensive programming. The HTTPS domain fix is a reminder that “automatic” SSL on GitLab Pages still requires a DNS verification step that’s easy to miss.

The M2M protocol blog post with its 23 D2 diagrams? It’ll be live once the CI/CD pipeline runs successfully — and once https://nurazhar.com/ finishes its Let’s Encrypt handshake.