- Removed ssl-redirect annotation (now proper HTTPS)
- Added tls section matching other service patterns
- Updated home.junv.cc DNS to use Cloudflare proxy
- Certificate issued by letsencrypt-prod via HTTP-01 through Cloudflare
When an HTML page references static files (images, CSS, JS) via
relative URLs, the browser resolves them as root-level paths
(e.g. /image.jpg from page /site-name). Without a trailing slash
on the page URL, these resolve to /image.jpg instead of
/site-name/image.jpg.
The API's /site-content/{path} handler interprets the first path
segment as the site name, so /dule_yuan_15k.jpg was treated as a
site name lookup rather than a file within the dule-yuan site.
Added _find_static_file() fallback: when no site matches the first
path segment, search all site directories for a matching filename.
Only triggered for common static file extensions to avoid
ambiguous lookups.
- Both /api/* and catch-all handlers now use quoted Caddy placeholder
syntax (e.g. "{http.request.header.X-Forwarded-For}") so Caddy evaluates
them in 'set' mode instead of failing silently in 'replace' mode.
- demo-service-caddy.yaml ConfigMap: also added missing X-Forwarded-For
header_up in the catch-all handler (was entirely absent).
- Caddy was overwriting X-Forwarded-For with {remote_host} (nginx
ingress pod IP), losing the original client IP from nginx ingress
- Fix: preserve upstream X-Forwarded-For and append Caddy's remote
- Add X-Real-IP fallback in is_internal_ip() for extra safety
- Clean up the caddy-config ConfigMap accordingly
- Replace old enabled/published fields with single visibility field:
- disabled → 404 for everyone (admin sees in admin UI only)
- internal → 192.168.1.x access without auth; external → 404
- public → anyone can access
- Admin users can see all sites via admin UI regardless of visibility
- Add /api/sites/{name}/visibility endpoint to change visibility
- Keep backward-compat enable/disable/publish/unpublish endpoints
- Database auto-migration from old enabled+published to new visibility
- NFS-safe sync_visibility hides/shows index.html per mode
The site_content endpoint only checked for .html suffix to render
inline. Hidden HTML fallbacks (.index.html.draft, .index.html.bak)
have .draft or .bak suffixes, so they fell through to FileResponse
which triggered browser download instead of rendering.
Fix: also check for .draft and .bak suffixes.
- Add subtle 'Log in' link to 401/403/404 error page
- Link redirects through pass.junv.cc OAuth with return URL
- Mount error-page-html ConfigMap into API container too (so both
Caddy and API serve the same updated error page)
- Define error-page-html ConfigMap in repo for ArgoCD management
- Hermes Agent instance running as Discord bot WhatToDo#3542
- Restricted tools: only web/search, no terminal/file/system access
- DISCORD_ALLOW_ALL_USERS=true + require_mention for access control
- NetworkPolicy restricts egress to internet only (no internal network)
- Secret removed from manifest — managed via kubectl create secret
- New _db.py module with sqlite3-based persistence
- Auto-migrate from sites.json on first run
- All writes now use _db.insert/update/delete directly
- Sites default to draft (published: false) on creation
The sites.json file is kept as .json.migrated for safety
- Extract Caddyfile from demo-service.yaml into demo-service-caddy.yaml
- ArgoCD auto-applies both files; Caddyfile changes are tracked in git
- Fixes issue where Caddyfile updates in the source dir weren't reaching the pod
- ArgoCD 'home-apps' app tracks the home-apps/ directory at root level only
- Move k8s-manifest.yaml to home-apps/demo-service.yaml (sibling of other apps)
- Keep source code (Dockerfile, service.py, etc.) in home-apps/demo-service/ subdirectory
- Update workflow to update the new path
- Also fix imagePullSecrets placement (pod-level not container-level)
- .github/workflows/build-demo-service.yml builds on push when home-apps/demo-service/**
- Pushes to ghcr.io/wahyd4/demo-manager with git SHA tag + :latest
- Updates k8s-manifest.yaml with new image tag
- ArgoCD picks up the new image on next sync
k8s-manifest changes:
- image: ghcr.io/wahyd4/demo-manager (was docker.io/library/demo-manager)
- imagePullPolicy: Always
- imagePullSecrets: github-image-pull-secret (auth for ghcr.io)
- admin-ui.html extracted from git history
- Caddy handle_errors serves canvas page for all HTML errors
- Error page served directly by Caddy (correct status code preserved)
- Republished hermes-stats and my-awesome-demo
- Modular file structure: _config.py, _loaders.py, admin-ui.html, error-page.html