Merge claude/1

This commit is contained in:
librelad 2026-07-05 20:25:21 +01:00
commit d96a9646bc
7 changed files with 44 additions and 44 deletions

View File

@ -3,11 +3,11 @@ networks:
external: true
services:
marketplace-service: #LIBREPORTAL|SERVICE_TAG_1|marketplace-service
container_name: marketplace-service
libreportal-catalog-service: #LIBREPORTAL|SERVICE_TAG_1|libreportal-catalog-service
container_name: libreportal-catalog-service
image: nginx:alpine
restart: unless-stopped
hostname: marketplace
hostname: libreportal-catalog
# GLUETUN_OFF_BEGIN
ports:
- "PORTS_DATA_1" #LIBREPORTAL|PORTS_TAG_1|PORTS_DATA_1
@ -18,12 +18,12 @@ services:
libreportal.backup.files: "data"
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.marketplace-service.entrypoints: web,websecure
traefik.http.routers.marketplace-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.marketplace-service.tls: true
traefik.http.routers.marketplace-service.tls.certresolver: production
traefik.http.services.marketplace-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.marketplace-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
traefik.http.routers.libreportal-catalog-service.entrypoints: web,websecure
traefik.http.routers.libreportal-catalog-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.libreportal-catalog-service.tls: true
traefik.http.routers.libreportal-catalog-service.tls.certresolver: production
traefik.http.services.libreportal-catalog-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.libreportal-catalog-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -10,14 +10,14 @@
# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote
# DEV_ONLY = if true, hidden from the App Center unless Developer Mode is on
#
CFG_MARKETPLACE_APP_NAME=marketplace
CFG_MARKETPLACE_BACKUP=true
CFG_MARKETPLACE_BACKUP_STRATEGY=auto
CFG_MARKETPLACE_COMPOSE_FILE=default
CFG_MARKETPLACE_HEALTHCHECK=false
CFG_MARKETPLACE_AUTHELIA=false
CFG_MARKETPLACE_HEADSCALE=false
CFG_MARKETPLACE_DEV_ONLY=true
CFG_LIBREPORTAL_CATALOG_APP_NAME=libreportal_catalog
CFG_LIBREPORTAL_CATALOG_BACKUP=true
CFG_LIBREPORTAL_CATALOG_BACKUP_STRATEGY=auto
CFG_LIBREPORTAL_CATALOG_COMPOSE_FILE=default
CFG_LIBREPORTAL_CATALOG_HEALTHCHECK=false
CFG_LIBREPORTAL_CATALOG_AUTHELIA=false
CFG_LIBREPORTAL_CATALOG_HEADSCALE=false
CFG_LIBREPORTAL_CATALOG_DEV_ONLY=true
#
# =============================================================================
# METADATA
@ -29,12 +29,12 @@ CFG_MARKETPLACE_DEV_ONLY=true
# URL = source repository or documentation URL
# ACTIONS = available actions for this application
#
CFG_MARKETPLACE_CATEGORY="system"
CFG_MARKETPLACE_TITLE="LibrePortal Marketplace"
CFG_MARKETPLACE_DESCRIPTION="App Catalog & Registry"
CFG_MARKETPLACE_LONG_DESCRIPTION="Host your own signed LibrePortal app catalog — browse and add apps from your own instance."
CFG_MARKETPLACE_URL="https://github.com/Webstar/LibrePortal"
CFG_MARKETPLACE_ACTIONS="configure|install|restart|shutdown|uninstall"
CFG_LIBREPORTAL_CATALOG_CATEGORY="system"
CFG_LIBREPORTAL_CATALOG_TITLE="LibrePortal Catalog"
CFG_LIBREPORTAL_CATALOG_DESCRIPTION="App Catalog & Registry"
CFG_LIBREPORTAL_CATALOG_LONG_DESCRIPTION="Host your own signed LibrePortal app catalog — browse and add apps from your own instance."
CFG_LIBREPORTAL_CATALOG_URL="https://github.com/Webstar/LibrePortal"
CFG_LIBREPORTAL_CATALOG_ACTIONS="configure|install|restart|shutdown|uninstall"
#
# =============================================================================
# NETWORK CONFIGURATION
@ -42,9 +42,9 @@ CFG_MARKETPLACE_ACTIONS="configure|install|restart|shutdown|uninstall"
# DOMAIN = number of domain from the general config, useful when using multiple domains
# WHITELIST = if true only allow whitelisted ips on traefik, if false allow all
#
CFG_MARKETPLACE_DOMAIN=1
CFG_MARKETPLACE_WHITELIST=false
CFG_MARKETPLACE_NETWORK=default
CFG_LIBREPORTAL_CATALOG_DOMAIN=1
CFG_LIBREPORTAL_CATALOG_WHITELIST=false
CFG_LIBREPORTAL_CATALOG_NETWORK=default
#
# =============================================================================
# PORT CONFIGURATION
@ -60,4 +60,4 @@ CFG_MARKETPLACE_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_MARKETPLACE_PORT_1="marketplace-service|webui|random:80|public|tcp|false|true|true|Marketplace|/|marketplace"
CFG_LIBREPORTAL_CATALOG_PORT_1="libreportal-catalog-service|webui|random:80|public|tcp|false|true|true|Catalog|/|libreportal-catalog"

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -3,11 +3,11 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>LibrePortal Marketplace</title>
<link rel="icon" type="image/svg+xml" href="marketplace.svg">
<title>LibrePortal Catalog</title>
<link rel="icon" type="image/svg+xml" href="libreportal_catalog.svg">
<style>
/* Standalone replica of the LibrePortal App Center — same nebula theme,
aurora background and app-card design, so the marketplace looks like the
aurora background and app-card design, so the catalog looks like the
App Center it feeds. Self-contained by design: no external assets. */
:root {
--gradient-from: #1a1442; --gradient-mid: #1b2a5e; --gradient-to: #0f3b6e;
@ -234,8 +234,8 @@
</head>
<body>
<div class="topbar">
<img src="marketplace.svg" alt="">
<span class="brand">Libre<b>Portal</b> Marketplace</span>
<img src="libreportal_catalog.svg" alt="">
<span class="brand">Libre<b>Portal</b> Catalog</span>
<span class="spacer"></span>
<span class="chip" id="topchip">loading…</span>
</div>
@ -275,7 +275,7 @@
'use strict';
var CHANNELS = ['stable', 'edge'];
// The catalog repository submissions are opened against. Operators running
// their own marketplace set this to their repo (a <meta name="lp-repo"> wins).
// their own catalog set this to their repo (a <meta name="lp-repo"> wins).
var REPO_URL = (document.querySelector('meta[name="lp-repo"]') || {}).content || 'https://github.com/librelad/LibrePortal';
// The hash is either a view (#view=submit) or an app focus (#<slug>).
@ -330,7 +330,7 @@
// ---- browse view ----
function card(a) {
var iconInner = a.icon ? '<img src="' + esc(a.icon) + '" alt="" onerror="this.style.display=\'none\'">' : '<img src="marketplace.svg" alt="">';
var iconInner = a.icon ? '<img src="' + esc(a.icon) + '" alt="" onerror="this.style.display=\'none\'">' : '<img src="libreportal_catalog.svg" alt="">';
var trust = a.trust === 'official' ? '<span class="app-tag trust-badge">Official</span>' : '<span class="app-tag community-badge">' + esc(a.trust) + '</span>';
var stateTag = a.installed ? '<span class="app-tag installed-tag">Installed</span>' : '<span class="app-tag available-tag">Available</span>';
var descTag = a.description ? '<span class="app-tag description-tag">' + esc(a.description) + '</span>' : '';
@ -365,7 +365,7 @@
});
if (focus) {
var one = state.apps.filter(function (a) { return a.slug === focus; })[0];
fb.innerHTML = '<span>Linked from the marketplace: <strong>' + esc(one ? one.title : focus) + '</strong></span><button id="showall">← Show all apps</button>';
fb.innerHTML = '<span>Linked from the catalog: <strong>' + esc(one ? one.title : focus) + '</strong></span><button id="showall">← Show all apps</button>';
fb.hidden = false;
}
grid.innerHTML = shown.map(card).join('');
@ -379,9 +379,9 @@
return '<div class="doc"><h1>How it works</h1>' +
'<p class="lead">This is a signed catalog of apps you can add to your LibrePortal box. Browsing happens here; adding happens on your box.</p>' +
'<div class="doc-card"><h2>Add an app</h2><p>Click a cards <strong>Add</strong> to copy its <code>libreportal app add &lt;slug&gt;</code> command and run it on your box. Or, once your box has scanned this catalog, the app shows up in your App Center grid as an “Available” card you can add with one click.</p></div>' +
'<div class="doc-card"><h2>Point your box at this marketplace</h2><p>Set <code>CFG_RELEASE_BASE_URL</code> to this sites address (Config → Developer Mode). Your box fetches and verifies this catalog on its next scan, and its App Center starts offering these apps.</p></div>' +
'<div class="doc-card"><h2>Point your box at this catalog</h2><p>Set <code>CFG_RELEASE_BASE_URL</code> to this sites address (Config → Developer Mode). Your box fetches and verifies this catalog on its next scan, and its App Center starts offering these apps.</p></div>' +
'<div class="doc-card"><h2>How trust works</h2><p>The catalog is signed with <a href="https://jedisct1.github.io/minisign/" target="_blank" rel="noopener noreferrer">minisign</a>. Your box verifies that signature against its own root-owned key <em>before</em> adding anything — a website, even this one, can never forge or tamper with an app. An unsigned catalog is browseable, but adds are refused.</p></div>' +
'<div class="doc-card"><h2>Run your own marketplace</h2><p>This entire site is the open-source <code>marketplace</code> app that ships with LibrePortal (enable Developer Mode to install it). Publish apps with <code>make_app.sh</code>, drop the output into its data directory, and point boxes at your <code>CFG_RELEASE_BASE_URL</code>. Boxes trust only the catalogs signature, never the website.</p></div>' +
'<div class="doc-card"><h2>Run your own catalog</h2><p>This entire site is the open-source <code>libreportal_catalog</code> app that ships with LibrePortal (enable Developer Mode to install it). Publish apps with <code>make_app.sh</code>, drop the output into its data directory, and point boxes at your <code>CFG_RELEASE_BASE_URL</code>. Boxes trust only the catalogs signature, never the website.</p></div>' +
'</div>';
}

View File

@ -1,11 +1,11 @@
#!/bin/bash
# Marketplace install hooks — seed the served docroot. The generic installApp
# Catalog install hooks — seed the served docroot. The generic installApp
# driver handles compose/start; this converges the browse-UI files on every
# (re)install (always refreshed from the definition), while published channel
# data (stable/, edge/ — the operator's signed catalog) is never touched.
marketplace_install_post_setup()
libreportal_catalog_install_post_setup()
{
local app_name="$1"
local def="${install_containers_dir%/}/$app_name"
@ -20,7 +20,7 @@ marketplace_install_post_setup()
runFileOp mkdir -p "$dest" || return 1
runFileOp cp -f "$def/resources/site/index.html" "$dest/index.html" || return 1
runFileOp cp -f "$def/$app_name.svg" "$dest/marketplace.svg" || return 1
runFileOp cp -f "$def/$app_name.svg" "$dest/libreportal_catalog.svg" || return 1
# Bundle the App Center's category icons so the site's sidebar matches the
# WebUI (same per-category glyphs). Copied from the live frontend so they
@ -30,5 +30,5 @@ marketplace_install_post_setup()
runFileOp mkdir -p "$dest/categories" || true
runFileOp cp -f "$cat_src"/*.svg "$dest/categories/" 2>/dev/null || true
fi
isSuccessful "Marketplace site seeded. Publish a catalog into it: rsync dist/<channel>/ $dest/<channel>/"
isSuccessful "Catalog site seeded. Publish a catalog into it: rsync dist/<channel>/ $dest/<channel>/"
}

View File

@ -583,6 +583,7 @@ declare -gA LP_FN_MAP=(
[kopiaSnapshotListFiles]="backup/engine/kopia_snapshots.sh"
[kopiaSnapshotsJson]="backup/engine/kopia_snapshots.sh"
[kopiaSystemSnapshotsJson]="backup/engine/kopia_snapshots.sh"
[libreportal_catalog_install_post_setup]="libreportal_catalog/scripts/libreportal_catalog_install_hooks.sh"
[_linkdingManage]="linkding/scripts/linkding_auth.sh"
[listDockerComposeFiles]="config/docker/docker_list_compose_files.sh"
[localDnsAppHosts]="network/dns/setup_local_dns.sh"
@ -632,7 +633,6 @@ declare -gA LP_FN_MAP=(
[manifestReadFromSnapshot]="backup/manifest/manifest_read.sh"
[manifestRemove]="backup/manifest/manifest_write.sh"
[manifestWrite]="backup/manifest/manifest_write.sh"
[marketplace_install_post_setup]="marketplace/scripts/marketplace_install_hooks.sh"
[mattermostToolsMenu]="menu/tools/manage_mattermost.sh"
[maybeRegenPoll]="task/crontab_task_processor.sh"
[menuContinue]="menu/message/continue.sh"
@ -1550,6 +1550,7 @@ declare -gA LP_FN_ROOT=(
[kopiaSnapshotListFiles]="scripts"
[kopiaSnapshotsJson]="scripts"
[kopiaSystemSnapshotsJson]="scripts"
[libreportal_catalog_install_post_setup]="containers"
[_linkdingManage]="containers"
[listDockerComposeFiles]="scripts"
[localDnsAppHosts]="scripts"
@ -1599,7 +1600,6 @@ declare -gA LP_FN_ROOT=(
[manifestReadFromSnapshot]="scripts"
[manifestRemove]="scripts"
[manifestWrite]="scripts"
[marketplace_install_post_setup]="containers"
[mattermostToolsMenu]="scripts"
[maybeRegenPoll]="scripts"
[menuContinue]="scripts"
@ -2538,6 +2538,7 @@ kopiaSnapshotLatestId() { source "${install_scripts_dir}backup/engine/kopia_snap
kopiaSnapshotListFiles() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSnapshotListFiles "$@"; }
kopiaSnapshotsJson() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSnapshotsJson "$@"; }
kopiaSystemSnapshotsJson() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSystemSnapshotsJson "$@"; }
libreportal_catalog_install_post_setup() { source "${install_containers_dir}libreportal_catalog/scripts/libreportal_catalog_install_hooks.sh"; libreportal_catalog_install_post_setup "$@"; }
_linkdingManage() { source "${install_containers_dir}linkding/scripts/linkding_auth.sh"; _linkdingManage "$@"; }
listDockerComposeFiles() { source "${install_scripts_dir}config/docker/docker_list_compose_files.sh"; listDockerComposeFiles "$@"; }
localDnsAppHosts() { source "${install_scripts_dir}network/dns/setup_local_dns.sh"; localDnsAppHosts "$@"; }
@ -2587,7 +2588,6 @@ manifestReadField() { source "${install_scripts_dir}backup/manifest/manifest_rea
manifestReadFromSnapshot() { source "${install_scripts_dir}backup/manifest/manifest_read.sh"; manifestReadFromSnapshot "$@"; }
manifestRemove() { source "${install_scripts_dir}backup/manifest/manifest_write.sh"; manifestRemove "$@"; }
manifestWrite() { source "${install_scripts_dir}backup/manifest/manifest_write.sh"; manifestWrite "$@"; }
marketplace_install_post_setup() { source "${install_containers_dir}marketplace/scripts/marketplace_install_hooks.sh"; marketplace_install_post_setup "$@"; }
mattermostToolsMenu() { source "${install_scripts_dir}menu/tools/manage_mattermost.sh"; mattermostToolsMenu "$@"; }
maybeRegenPoll() { source "${install_scripts_dir}task/crontab_task_processor.sh"; maybeRegenPoll "$@"; }
menuContinue() { source "${install_scripts_dir}menu/message/continue.sh"; menuContinue "$@"; }