librelad 63b53c7751 feat(hosting): getlibreportal as a first-class LibrePortal app (phase E)
Redo the download/website host as a normal app under containers/ (dogfooded — the
project hosts its own downloads on LibrePortal), instead of the bespoke repo-root
thing. Modeled on speedtest: standard getlibreportal.{config,sh,svg} +
docker-compose.yml (tagged template) so it plugs into the app scan + install
dispatch (installGetlibreportal) like every other app. nginx serves ./data (the
app data dir) — no special /web.

- getlibreportal.config: features category, public (login=false — it's a download
  host), no backup (regenerable), healthcheck on.
- docker-compose.yml: nginx:alpine, ./data:ro docroot + ./nginx.conf, traefik tags.
- nginx.conf: install.sh + latest.json no-cache; tarball/.sha256/.minisig immutable.
- publish.sh: assembles the docroot (built site + install.sh + dist/<channel>) into
  a target data dir; run on a full repo checkout (site/ + dist/ are host-side).
- exec bits set on the run-directly scripts (make_release.sh, install.sh, publish.sh).
- .gitattributes: dropped the stray 'getlibreportal export-ignore' (the no-slash
  pattern would also have excluded containers/getlibreportal — the app must ship);
  data/ gitignored.

Verified: app discovered by the site catalog (32 apps), installGetlibreportal matches
the dispatch name, and the full release->publish flow yields a docroot with the
website + install.sh + the signed/checksummed stable channel. The actual app-install
run + DNS/TLS for get.libreportal.org are operational steps (need a real host).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-25 20:02:47 +01:00

28 lines
1.1 KiB
Nginx Configuration File

server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# The bootstrap installer: served as a shell script, never cached, so
# `curl … | sudo bash` always gets the current one.
location = /install.sh {
default_type text/x-shellscript;
add_header Cache-Control "no-cache, must-revalidate";
}
# Channel manifests change every release — don't cache.
location ~ /latest\.json$ {
default_type application/json;
add_header Cache-Control "no-cache, must-revalidate";
}
# Release artifacts are immutable (version-pinned names) — cache hard.
location ~ \.tar\.gz$ { default_type application/gzip; add_header Cache-Control "public, max-age=31536000, immutable"; }
location ~ \.sha256$ { default_type text/plain; add_header Cache-Control "public, max-age=31536000, immutable"; }
location ~ \.minisig$ { default_type text/plain; add_header Cache-Control "public, max-age=31536000, immutable"; }
# The static website.
location / { try_files $uri $uri/ =404; }
}