containers/marketplace — nginx:alpine app (standard drop-in contract: config + tagged compose + icon + install hook) whose docroot serves BOTH halves of the marketplace: the signed catalog channel tree (index.json / payloads, published into data/<channel>/ by the release tools) and a self-contained client-rendered browse site over the same file (search, category chips, trust badges, copyable 'libreportal app add <slug>' — no third-party assets, no backend, no build step). The official marketplace is an instance of this app; self-hosting one = installing it and pointing CFG_RELEASE_BASE_URL at it. Boxes only ever trust the minisign signature on the catalog, never the website. New generic gating convention: CFG_<APP>_DEV_ONLY=true keeps an app out of the App Center grid unless Developer Mode is on (CFG_DEV_MODE, the same flag the **DEV** config-field filter uses); an installed dev-only app always stays visible. The marketplace app is the first user. Cache policy: catalog/channel manifests no-cache; payloads short revalidating cache (same-id re-publish); version-pinned release artifacts immutable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
39 lines
1.5 KiB
Nginx Configuration File
39 lines
1.5 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";
|
|
}
|
|
|
|
# The signed catalog + channel manifests move on every publish — no cache.
|
|
location ~ /index\.json(\.minisig)?$ {
|
|
default_type application/json;
|
|
add_header Cache-Control "no-cache, must-revalidate";
|
|
}
|
|
location ~ /latest\.json$ {
|
|
default_type application/json;
|
|
add_header Cache-Control "no-cache, must-revalidate";
|
|
}
|
|
|
|
# Payloads keep their name across re-publishes (same-id upsert), so they
|
|
# are NOT immutable — short revalidating cache; boxes verify the sha256
|
|
# pinned in the fresh index anyway.
|
|
location ~ /payloads/ {
|
|
add_header Cache-Control "public, max-age=300, must-revalidate";
|
|
}
|
|
|
|
# Version-pinned release artifacts never change — 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 browse UI.
|
|
location / { try_files $uri $uri/ =404; }
|
|
}
|