my-homelab-configs/apps/website
juvdiaz e10be77cc2 Add application egress NetworkPolicies 2026-06-29 17:09:45 -06:00
..
images migration: incorporate repository secrets and apply clean application definitions 2026-05-19 08:06:40 -05:00
lang Add generated docs config 2026-06-27 15:42:59 -06:00
ollama Add dedicated website translation model 2026-06-10 10:34:00 -06:00
partials Updating translation endpoint so its reachable 2026-05-29 12:05:30 -06:00
Dockerfile Update debian ip 2026-06-26 22:50:19 -06:00
README.md Update debian ip 2026-06-26 22:50:19 -06:00
blog.php Add generated docs config 2026-06-27 15:42:59 -06:00
buildkitd.toml Update debian ip 2026-06-26 22:50:19 -06:00
cv-theme.js Fixing theme button 2026-05-29 11:12:20 -06:00
cv.php Version website stylesheet asset 2026-06-10 15:53:50 -06:00
demos.php Version website stylesheet asset 2026-06-10 15:53:50 -06:00
gnu.webp migration: incorporate repository secrets and apply clean application definitions 2026-05-19 08:06:40 -05:00
homelab-tree.php Add generated docs config 2026-06-27 15:42:59 -06:00
httpd-php-fpm.conf Add cache headers for website static output 2026-06-04 10:59:23 -06:00
ideas_helper.php Collect visitor homelab ideas safely 2026-05-25 21:12:51 -06:00
index.php Version website stylesheet asset 2026-06-10 15:53:50 -06:00
kustomization.yaml Add application egress NetworkPolicies 2026-06-29 17:09:45 -06:00
lang_helper.php Version website stylesheet asset 2026-06-10 15:53:50 -06:00
namespace.yaml feat: add explicit website-production namespace manifest 2026-05-19 08:46:33 -05:00
network-policy.yaml Add application egress NetworkPolicies 2026-06-29 17:09:45 -06:00
opcache.ini Run website with Apache PHP-FPM and OPcache 2026-06-04 09:50:23 -06:00
php-fpm-runtime.conf Run website with Apache PHP-FPM and OPcache 2026-06-04 09:50:23 -06:00
render-static-pages.sh Pre-render website read pages 2026-06-04 10:42:21 -06:00
save_idea.php Collect visitor homelab ideas safely 2026-05-25 21:12:51 -06:00
save_lang.php Add homelab provisioning automation 2026-05-26 11:46:38 -06:00
start-website.sh Run website with Apache PHP-FPM and OPcache 2026-06-04 09:50:23 -06:00
styles.css Update website retro theme styles 2026-06-10 15:14:00 -06:00
translate.php Update debian ip 2026-06-26 22:50:19 -06:00
translation.js Updating translation endpoint so its reachable 2026-05-29 12:05:30 -06:00
visitor-ideas.js Pre-render website read pages 2026-06-04 10:42:21 -06:00
visitor_ideas.php Pre-render website read pages 2026-06-04 10:42:21 -06:00
web-app.yaml Allow website and demos to schedule on any node 2026-06-27 07:39:42 -06:00

README.md

Website Runtime

The portfolio website keeps Apache at the core while moving PHP execution to PHP-FPM.

Runtime Shape

  • Base image: php:8.5-fpm-alpine
  • Web server: Alpine Apache, listening on container port 8080
  • PHP runtime: PHP-FPM on 127.0.0.1:9000
  • PHP cache: OPcache enabled, with timestamp validation disabled for immutable image deploys
  • Dynamic storage: /var/www/localhost/htdocs/db mounted from the retained website-db PVC

Apache routes *.php through proxy_fcgi to PHP-FPM. The startup script starts PHP-FPM in the background and then runs Apache in the foreground.

Static Render Path

render-static-pages.sh runs during the image build and renders static HTML for the read-heavy pages:

  • /
  • /cv.php
  • /blog.php
  • /demos.php
  • /homelab-tree.php

Static output is generated for the committed static languages under /static-pages/<lang>/. Apache rewrites supported static-language requests to those generated HTML files. Requests for runtime-generated languages still fall through to PHP so the translation workflow continues to work.

blog.php no longer renders visitor ideas directly into the HTML. Recent ideas are served by visitor_ideas.php and loaded by visitor-ideas.js, which keeps the blog page cacheable while preserving the write path through save_idea.php.

Cache Path

The website sets cache headers for pre-rendered HTML:

Cache-Control: public, max-age=300, s-maxage=3600

Dynamic write and translation endpoints are marked no-store:

  • save_idea.php
  • visitor_ideas.php
  • translate.php
  • save_lang.php

The OCI edge nginx layer handles gzip, cache HITs, HTTP/2, TLS session reuse, client keepalive, and upstream keepalive to the Traefik backend. CSS and JavaScript keep the edge's longer immutable asset policy.

Translation Flow

Unsupported browser languages call the same-origin translate.php endpoint. The endpoint sanitizes and batches text, checks Redis per string, calls the custom website-translator Ollama model only for cache misses, writes fresh translations back to Redis with a TTL, then returns results in the original order. The browser never calls the private Ollama address directly.

n8n is deployed separately at https://n8n.lab2025.duckdns.org and receives OLLAMA_BASE_URL=http://192.168.100.73:11434 so workflows can prewarm translations or run batch jobs against the Debian-host Ollama API.

Translation Observability

translate.php emits one structured JSON log event for each valid translation request. The event name is website_translation and the payload does not include source text or translated text.

Useful fields:

  • cache_hits
  • cache_misses
  • ollama_latency_ms
  • failed_json_parse_count
  • timeout_count
  • status
  • reason

In Loki, filter website logs for "event":"website_translation" to inspect cache behavior, Ollama latency, JSON parse failures, and timeout failures.

Validation

Do not build images locally. The image is built and deployed by the Debian homelab path and Gitea Actions.

Local source validation that does not build the image:

shellcheck apps/website/start-website.sh apps/website/render-static-pages.sh
find apps/website -name "*.php" -print0 | xargs -0 -n1 php -l
node --check apps/website/visitor-ideas.js
kubectl kustomize apps/website >/tmp/website-kustomize.yaml

Static rendering can be checked without Docker by copying the app to a temporary directory and running:

sh render-static-pages.sh /path/to/copied/apps/website