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.
Where the site lives
html/index.html: the landing page.docs/index.htmlis a mirror, so keep both identical.html/blog/index.html: the blog list. Each post is one file,html/blog/<slug>.html.html/css/site.css,html/js/theme.js: shared styles and the light/dark toggle.html/images/: post images.docs/blog/<slug>.md: the Markdown version of each post, for reading on GitHub.CNAME: holdswslproxy.org. The workflow copies it into the published site so Pages keeps the custom domain.
1. Write the post
- Copy an existing post, for example
html/blog/vpn-only-hosts.html, tohtml/blog/<slug>.html. Keep the<head>, header and footer as they are. They load/css/site.cssand/js/theme.js, which give the post the site theme. - Update
<title>,meta descriptionandog:title/og:image. Use absolutehttps://wslproxy.org/…URLs forog:image. - Write the body inside
<article class="blog-article"><div class="wrap wrap--read">. Available classes:kicker,lede,meta,callout,features,hero-shot,video-frame. - Put images in
html/images/and reference them with root-relative paths (/images/…). Always setwidth,heightandalt. - Never publish real home or office IPs, keys or tokens in examples. Use
203.0.113.0/24andexample.com.
2. List it
- Add a
post-cardat the top ofhtml/blog/index.htmlso the newest post comes first. - Add a
media-rowto the#blogsection ofhtml/index.html, then copy the file over the mirror:cp html/index.html docs/index.html. - Add
docs/blog/<slug>.mdwith a link to the live article.
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
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
- Post file,
<title>and meta tags - Card in
blog/index.html, row in the landing#blogsection,docs/index.htmlmirror updated - Markdown copy in
docs/blog/ - Previewed in light, dark and phone-width
- Merged to
main, workflow green, URL returns 200