Tech note · Site ops

How to set up and publish a post on wslproxy.org

wslproxy.org is plain static HTML in this repo's html/ folder, published to GitHub Pages by one workflow. This note covers adding a post, previewing it locally, and shipping it, plus how the same pages reach the edges.

GitHub Pages · deploy-pages.yml · no build step

Where the site lives

1. Write the post

  1. Copy an existing post, for example html/blog/vpn-only-hosts.html, to html/blog/<slug>.html. Keep the <head>, header and footer as they are. They load /css/site.css and /js/theme.js, which give the post the site theme.
  2. Update <title>, meta description and og:title/og:image. Use absolute https://wslproxy.org/… URLs for og:image.
  3. Write the body inside <article class="blog-article"><div class="wrap wrap--read">. Available classes: kicker, lede, meta, callout, features, hero-shot, video-frame.
  4. Put images in html/images/ and reference them with root-relative paths (/images/…). Always set width, height and alt.
  5. Never publish real home or office IPs, keys or tokens in examples. Use 203.0.113.0/24 and example.com.

2. List it

3. Preview locally

cd html && python3 -m http.server 8000
# open http://localhost:8000/blog/<slug>.html

Serve from html/ so root-relative paths resolve the same way they do in production. Check both themes and a narrow (phone-width) window.

4. Publish

Open a PR and merge it to main. .github/workflows/deploy-pages.yml runs on any push to main that touches html/index.html, html/blog/**, html/css|js|images/**, html/waf/**, html/swagger/** or CNAME. It assembles site/, adds .nojekyll and the CNAME, and deploys to GitHub Pages. To re-publish without a code change, use Run workflow on the Actions tab.

gh workflow run deploy-pages.yml
gh run watch
curl -sI https://wslproxy.org/blog/<slug>.html | head -1   # HTTP/2 200
Only the listed paths are published. A new top-level folder, such as html/guides/, needs its own cp -R in the workflow's "Assemble static site" step and an entry in on.push.paths. Otherwise it never reaches Pages.

The same landing page on the edges

Each edge also serves html/index.html from its own default.conf landing vhost. The Ansible template infra/ansible/roles/wslproxy/templates/default.conf.j2 builds its server_name from nginx_default_server_frontend, host_lan_ip and host_public_ip, so http://<edge-ip>/ shows the landing page instead of "Host not configured". Edge copies are updated by a code deploy of the delivery pipeline, not by the Pages workflow.

Checklist