Commit Graph
446 Commits
Author SHA1 Message Date
ahmza 3c5678f8a8 Run Hugo natively in build stage to skip QEMU emulation
Build Hugo / build (push) Successful in 6m31s
Build Hugo / deploy (push) Failing after 24s
Pin the build stage to $BUILDPLATFORM so Hugo runs once on the native
arch instead of once per target arch under QEMU. Hugo output is static
HTML and identical across arches, so the emulated arm64 Hugo run (~59s
vs ~12s native) plus emulated base-image extraction were pure waste.
The runtime stage stays on TARGETPLATFORM, so multi-arch amd64+arm64
images are still produced.
2026-08-03 15:40:22 +00:00
ahmza 319c8fa922 Add NetBird diagnostic checks to deploy job
Build Hugo / build (push) Successful in 7m23s
Build Hugo / deploy (push) Successful in 12s
Surface VPN connection status in the deploy job so netbird failures are
legible instead of a cryptic DeadlineExceeded:
- Pre-flight check for /dev/net/tun + NET_ADMIN before connecting
- id + timeout-minutes:3 on Netbird Connect to bound its wait loop
- Post-connect 'netbird status --detail' with a Management:Connected assert
- Always-run diagnostics + 'netbird down' teardown
2026-08-03 14:51:04 +00:00
ahmza b84843ca3d added footer links
Build Hugo / build (push) Successful in 11m23s
Build Hugo / deploy (push) Failing after 54s
added gitlab as well as gitea footer links.
2026-08-03 13:12:58 +00:00
ahmza 4b0b681302 Merge pull request 'Use dynamic cloudflare trusted_proxies IP source' (#5) from caddy-dynamic-cf-ip into main
Build Hugo / build (push) Successful in 1m37s
Build Hugo / deploy (push) Successful in 41s
Reviewed-on: #5
2026-07-25 04:09:11 +00:00
ahmza 2c6f20fbc3 docs: show dynamic cloudflare trusted_proxies as primary example
caddy-cf now bundles WeidiDeng/caddy-cloudflare-ip, so document
'trusted_proxies cloudflare { interval 12h; timeout 15s }' as the
primary (auto-refreshing) approach, with the static-list method noted
as the fallback for builds without the plugin. Also explains
client_ip_headers (Cf-Connecting-Ip preferred, X-Forwarded-For fallback).
2026-07-25 05:04:52 +01:00
ahmza b88828f92e Use dynamic cloudflare trusted_proxies IP source
caddy-cf now includes WeidiDeng/caddy-cloudflare-ip, so replace the
hardcoded 22-range static list with 'trusted_proxies cloudflare' which
auto-fetches and refreshes Cloudflare's IPv4/IPv6 ranges (interval 12h,
timeout 15s). No static list to keep in sync when Cloudflare updates.

Kept client_ip_headers Cf-Connecting-Ip X-Forwarded-For (prefer CF's
authoritative end-user IP, fall back to XFF) and documented why.

Validated + fmt-clean and tested end-to-end against the updated caddy-cf
image: starts cleanly, serves HTTP 200 with gzip + security headers.
2026-07-25 05:04:52 +01:00
ahmza 09780d9598 Merge pull request 'Fix blank page: add Cloudflare-fronted HTTP-only Caddyfile' (#4) from fix-caddy-cloudflare into main
Build Hugo / build (push) Successful in 1m34s
Build Hugo / deploy (push) Successful in 40s
Reviewed-on: #4
2026-07-25 03:56:07 +00:00
ahmza c24ed01e0a docs: document Cloudflare-fronted HTTP-only Caddy topology
The live production setup is Cloudflare -> Caddy (HTTP :80) -> SWS, which
differed from the DNS-01 topology the doc previously assumed. Add a
'Deployment topologies' overview and a dedicated Cloudflare-fronted
section pointing at the committed root Caddyfile, covering reverse_proxy,
encode, security headers, and Cloudflare trusted_proxies. Label the
existing Compose/K8s examples as the DNS-01 alternative.
2026-07-25 04:29:33 +01:00
ahmza 7e1728a037 Restrict Caddy trusted_proxies to Cloudflare IP ranges
Replace 'private_ranges' with Cloudflare's official published edge ranges
(15 IPv4 + 7 IPv6 from cloudflare.com/ips-v4 and /ips-v6). This ensures
Cf-Connecting-Ip / X-Forwarded-For are only honoured for requests that
genuinely originate from Cloudflare, preventing client-IP header spoofing
from any other source.

Validated + fmt-clean and tested at runtime against the caddy-cf image:
Caddy starts cleanly with all 22 ranges, serves HTTP 200 with gzip and
security headers.
2026-07-25 04:25:25 +01:00
ahmza 30ef38b143 Add HTTP-only Caddyfile for Cloudflare-fronted deployment
The live Caddy was returning a blank page (NOP, status 0) because its
site block had no responder \u2014 no reverse_proxy to the blog. This adds a
known-good HTTP-only Caddyfile matching the actual topology
(Cloudflare terminates TLS -> Caddy :80 -> SWS blog:80):

- reverse_proxy blog:80  (the missing responder that caused the blank page)
- encode zstd gzip        (fixes: origin was serving everything uncompressed)
- security headers        (fixes: HSTS/X-Frame-Options/etc were absent)
- trusted_proxies + client_ip_headers for correct Cloudflare visitor IPs
- http:// scheme so Caddy does not try to provision TLS (Cloudflare does)

Validated + fmt-clean against the caddy-cf image; tested end-to-end
locally (Caddy -> SWS) returning HTTP 200 with gzip and headers.
2026-07-25 04:19:34 +01:00
ahmza f927bc191c Merge pull request 'Fix codebase audit findings: bugs, security, perf, content' (#3) from fix-audit-findings into main
Build Hugo / build (push) Successful in 1m36s
Build Hugo / deploy (push) Successful in 39s
Reviewed-on: #3
2026-07-25 02:38:13 +00:00
ahmza f402556380 Fix audit findings: bugs, security, perf, content
Bugs:
- setup-wsl: fix broken /img/WSL/* image paths (now bundle-relative;
  images were broken on the published post) + better alt text
- pi-docker-swarm: remove broken missing cluster.webp reference
- archetypes/posts.md: fix malformed {{ }} template so 'hugo new' works
- rename arrstack/arrstack.md -> index.md so it's a proper leaf bundle
- static/admin/config.yml: fix 'htpps' -> 'https' site_url typo
- fix silently-dropped <placeholder> text (unsafe=false dropped them):
  wrap <distro>/<username>/<user>/<version>/<ip address> etc in backticks
  across setup-wsl, securing-ssh, pi-docker-swarm, mc-server-on-docker

Security:
- render-link.html: add rel=noopener noreferrer to external target=_blank
- extend-footer.html: fix rel='me' trapped in class attr (broke Mastodon
  verification); add proper rel/target
- static/admin/index.html: pin Sveltia CMS to 0.172.4 via jsDelivr + SRI

Performance:
- hugo.toml: ignoreFiles for *.aseprite/*.bak (stop shipping source art;
  non-page files 23 -> 13)
- video shortcode: preload=metadata; image shortcode: loading=lazy decoding=async
- sws.toml: drop SPA page-fallback so missing paths return real 404 (404.html)

Content/SEO:
- normalize tag casing (HomeLab/RemoteAccess/SSH/HUGO -> lowercase),
  fix 'prodcutivity' typo, arrstack tags:[""] -> [], add welcome description
- delete stray index.md.bak
2026-07-25 03:36:50 +01:00
ahmza 25b6e0575a Merge pull request 'Optimize webm videos and webp images' (#2) from optimize-media into main
Build Hugo / build (push) Successful in 1m31s
Build Hugo / deploy (push) Successful in 40s
Reviewed-on: #2
2026-07-25 02:22:43 +00:00
ahmza e133b01b00 Optimize webm videos and webp images
Re-encode all webm meme clips as VP9 at CRF 38 (audio stripped; they are
muted autoplay loops). Downscale oversized images: background.webp
3394->1920 wide q80, profile.webp 1920->512 q85 (animation preserved).

Results:
- webm: 3.2MB -> 1.37MB (-56%)
- webp: 1.2MB -> 0.70MB (-42%)
- Docker image: 23.1MB -> 18.7MB (~42% smaller than the original nginx image)

All videos verified valid/playable; profile.webp animation (5 frames)
kept intact.
2026-07-25 03:20:57 +01:00
ahmza b7145e1323 Remove temporary Netbird connectivity debug step
Build Hugo / build (push) Successful in 1m32s
Build Hugo / deploy (push) Successful in 39s
The deploy pipeline works end-to-end now (Gimli deploys successfully),
so the diagnostic step used to trace the WireGuard/TUN issue is no
longer needed. RPIC continue-on-error is kept until the cluster returns.
2026-07-25 03:07:00 +01:00
ahmza 87867b9f30 Point compose.yml at Gitea registry image with :latest tag
Build Hugo / build (push) Successful in 1m27s
Build Hugo / deploy (push) Successful in 40s
CI pushes to tea.ahmza.com/ahmza/blog-ahmza-com, not ghcr.io, and a
bare reference could resolve to the non-runnable :buildcache tag. Pin
the image to tea.ahmza.com/ahmza/blog-ahmza-com:latest so docker compose
pulls the actual runnable image.
2026-07-25 03:02:39 +01:00
ahmza 8a7833e8f5 Make RPIC deploy non-blocking while cluster is out of service
Build Hugo / build (push) Successful in 1m26s
Build Hugo / deploy (push) Failing after 38s
The Raspberry Pi cluster is temporarily out of service. Mark its deploy
step continue-on-error so its failure no longer skips the Gimli deploy
or fails the whole job. Revert once the cluster is back online.
2026-07-25 02:42:15 +01:00
ahmza 4426668518 Use registry build cache instead of gha cache
Build Hugo / build (push) Successful in 3m23s
Build Hugo / deploy (push) Failing after 39s
The GitHub-hosted 'gha' cache backend is unreachable from the
self-hosted Gitea runner (dial tcp 172.18.0.2:44181 i/o timeout), which
failed the build step even though the image pushed successfully. Switch
cache-from/cache-to to a registry-backed cache stored as a :buildcache
tag in the same Gitea registry, which works on self-hosted runners.
2026-07-25 02:21:38 +01:00
ahmza eacf71d676 Debug: check runner WireGuard capability instead of UDP ports
Build Hugo / build (push) Failing after 13m45s
Build Hugo / deploy (push) Skipped
Other Netbird peers connect fine, so the server and 51820/udp are OK --
the hang is specific to the Gitea runner. Replace the UDP port probes
with runner-side checks: /dev/net/tun presence, effective capabilities
(NET_ADMIN), WireGuard tooling/module, and a definitive 'ip tuntap add'
test. A runner container lacking TUN/NET_ADMIN cannot create the
WireGuard interface, which explains 'netbird up' timing out after the
control plane connects.
2026-07-25 01:53:09 +01:00
ahmza b05814980f Update Netbird debug to probe correct data-plane ports
Build Hugo / build (push) Successful in 1m47s
Build Hugo / deploy (push) Failing after 1m15s
The Netbird server multiplexes management + signal + dashboard behind
Traefik on :443 (no separate :10000 signal port). The tunnel data plane
is WireGuard on 51820/udp and STUN on 3478/udp. Update the debug step to
probe those UDP ports plus a general outbound-UDP check (public STUN) to
determine whether the runner network blocks UDP egress -- the likely
cause of 'netbird up' timing out after the control plane connects fine.
2026-07-25 01:46:28 +01:00
ahmza eb67d6361e Add Netbird connectivity debug step to deploy job
Build Hugo / build (push) Successful in 1m44s
Build Hugo / deploy (push) Failing after 1m8s
Temporary diagnostic step before 'Netbird Connect' that checks secret
presence (masked), DNS resolution, HTTPS reachability to the management
API, and the signal server TCP port from the runner. Helps distinguish
DNS/connectivity issues from auth/registration failures behind the
recurring 'netbird up' DeadlineExceeded error. Marked continue-on-error
so it never blocks the build.
2026-07-25 01:39:09 +01:00
ahmza 8062b9d208 Read Netbird management URL from secret
Build Hugo / build (push) Successful in 1m46s
Build Hugo / deploy (push) Failing after 58s
Switch the deploy job's Netbird Connect step to read management-url from
the NETBIRD_URL secret instead of a hardcoded value, so the URL can be
managed in the Gitea UI alongside the setup key.
2026-07-25 01:33:47 +01:00
ahmza aa01def998 Merge pull request 'Optimizations: switch to static-web-server + Caddy reverse proxy docs' (#1) from optimizations into main
Build Hugo / build (push) Successful in 1m51s
Build Hugo / deploy (push) Failing after 57s
Reviewed-on: #1
2026-07-25 00:19:53 +00:00
ahmza f23fe01f3c Fix GitLab/Gitea inconsistency in README
Build Hugo / deploy (push) Canceled after 0s
Build Hugo / build (push) Canceled after 48s
Update the README to reflect the actual infrastructure: CI/CD runs on
Gitea Actions (not GitLab), images live in the Gitea container registry,
and the clone URL points to tea.ahmza.com. Also clarify the Blowfish
theme is a Hugo module, so no submodules are needed.
2026-07-25 01:19:29 +01:00
ahmza 1ad79d40d8 Use caddy-cf image with Cloudflare DNS-01 challenge
Switch the Caddy doc to the custom caddy-cf image
(ghcr.io/ahmzaa/caddy-cf) which bundles the Cloudflare DNS module, so
TLS certs are issued via the ACME DNS-01 challenge instead of HTTP-01.
This removes the need to expose ports 80/443 to the public internet,
which suits the Netbird-only infrastructure.

- Add (cloudflare) snippet + import cloudflare to both Caddyfiles
- Read CF_API_TOKEN from env (.env for Docker, Secret for K8s)
- Document token scope (Zone:DNS:Edit) and Cloudflare-hosted DNS
  requirement
- Validated Caddyfile against the caddy-cf image (caddy adapt)
2026-07-25 01:17:35 +01:00
ahmza 7d4f1668a6 Add Caddy reverse proxy documentation
Document running Caddy in front of the SWS origin for both deployment
targets (Docker Compose on Gimli and the Kubernetes Pi cluster), with
Caddy handling automatic HTTPS, compression, and security headers.

Explains the layer separation: SWS serves static files + Cache-Control,
Caddy owns TLS/compression/security headers (matching sws.toml where
those are disabled). Caddyfile validated with 'caddy validate'.
2026-07-25 01:13:10 +01:00
ahmza 498231c160 Tune SWS config for running behind a reverse proxy
The site sits behind a reverse proxy that already handles compression
and security headers. Disable those in SWS to avoid redundant work and
duplicate/conflicting headers, letting each layer own one concern.

- compression / compression-static: off (proxy compresses)
- security-headers: off (proxy sets them)
- cache-control-headers, page-fallback, health: kept (origin concerns)
2026-07-25 01:09:42 +01:00
ahmza 898e3003a2 Switch static server from nginx to static-web-server
Replace nginx:alpine-slim with the scratch-based static-web-server
image, reducing the final image size ~32MB -> ~23MB (28% smaller).

- Dockerfile: serve from static-web-server:2, copy site to /public
- sws.toml: mirror previous nginx behavior (compression, cache-control,
  SPA index fallback) plus security headers and /health endpoint
- Remove now-unused nginx.conf
2026-07-25 01:04:17 +01:00
ahmza 0d425c0ed1 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Failing after 18m24s
Build Hugo / deploy (push) Has been cancelled
2026-03-06 01:31:33 +00:00
ahmza cd6f85f903 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Successful in 52s
Build Hugo / deploy (push) Failing after 1m14s
2026-03-06 00:58:29 +00:00
ahmza 0bef6a1907 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Successful in 52s
Build Hugo / deploy (push) Failing after 56s
2026-03-06 00:52:33 +00:00
ahmza 83ca9b61b8 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Successful in 54s
Build Hugo / deploy-to-gimli-blog (push) Has been cancelled
Build Hugo / deploy-to-rpic (push) Has been cancelled
2026-03-06 00:39:57 +00:00
ahmza e9bcafb64b Update Dockerfile
Build Hugo / build (push) Failing after 47s
Build Hugo / deploy-to-rpic (push) Has been skipped
Build Hugo / deploy-to-gimli-blog (push) Has been skipped
2026-03-06 00:36:04 +00:00
ahmza 2480790384 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Failing after 37s
Build Hugo / deploy-to-rpic (push) Has been skipped
Build Hugo / deploy-to-gimli-blog (push) Has been skipped
2026-03-06 00:30:19 +00:00
ahmza 22d3759756 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Failing after 8s
Build Hugo / deploy-to-rpic (push) Has been skipped
Build Hugo / deploy-to-gimli-blog (push) Has been skipped
2026-03-06 00:26:33 +00:00
ahmza 9a6555f1c3 Update .github/workflows/build-docker-images.yml
Build Hugo / build (push) Failing after 9s
Build Hugo / deploy-to-rpic (push) Has been skipped
Build Hugo / deploy-to-gimli-blog (push) Has been skipped
2026-03-06 00:24:26 +00:00
ahmza d71dc7a86b modified registry auth 2026-03-06 00:23:39 +00:00
ahmza da5d05404f whoknows
Build Hugo / build (push) Failing after 1m20s
Build Hugo / deploy-to-rpic (push) Has been skipped
Build Hugo / deploy-to-gimli-blog (push) Has been skipped
2026-02-15 23:42:18 +00:00
ahmza 3322229b97 Updated hardening-linux post 2026-02-15 23:41:22 +00:00
ahmza 1ccf4d3d72 added deployment to gimli 2026-02-12 23:14:20 +00:00
ahmza a433830d1d Remove DOCKER_BUILDKIT setting in workflow
Remove unnecessary environment variable setting for Docker Buildx.
2026-02-12 23:00:44 +00:00
ahmza 36dae5fdf7 added github actions cache 2026-02-12 22:58:17 +00:00
ahmza ba646f28f1 Update ssh-action version in workflow file 2026-02-12 22:51:22 +00:00
ahmza d0f304ef95 Update ssh-action version in deployment workflow 2026-02-12 22:43:50 +00:00
ahmza 311627d9c8 added deployment to gimli 2026-02-12 22:40:32 +00:00
ahmza 6d8f616bf0 added deployment to gimli 2026-02-12 22:39:40 +00:00
ahmza 4fb2156fa9 added image creation for linux/amd64 2026-02-12 22:01:27 +00:00
ahmza 12e43ef580 Update kubectl rollout command for blog deployment 2026-02-11 23:42:47 +00:00
ahmza e9d8e0fdf6 updated action to use netbird for deployment 2026-02-11 23:20:54 +00:00
ahmza e11a1adeb4 added mastodon verification 2026-02-11 22:17:31 +00:00