tidy: docs + Nextcloud APCu + container-side file-capture rollout
Three closeouts in one pass: 1. DEVELOPMENT.md — consolidated hook-conventions table covering all 8 per-app hook types (tools / update-specifics / compose-tags / webui-refresh / the two traefik markers / the two network-provider hooks). One place to look instead of inferring from the codebase. 2. Nextcloud APCu wired alongside Redis: appUpdateSpecifics_nextcloud now sets memcache.local=\OC\Memcache\APCu too (was deferred from the fpm switch). APCu = cheap in-process cache; the fpm-alpine image ships the extension. CLI mode may emit a harmless "no memory cache" notice on `occ` runs — Nextcloud is graceful, the FPM worker still uses APCu fine. 3. Container-side file-capture rollout to 3 confident cases: - bookstack: lscr.io/linuxserver/bookstack with PUID=1000 → /config (1000:1000) - gitea: gitea/gitea with USER_UID=1000 → /data (1000:1000) - owncloud: owncloud/server (Apache/PHP) → /mnt/data (33:33, www-data) Snapshots are now complete for these (the dir's excluded from the raw restic pass and captured live through the container as a tar → libreportal-owned staging, same proven pattern as Nextcloud). Less-evidenced candidates left for live verification: linkding, mastodon, jellyfin, trilium, focalboard, invidious, vaultwarden, headscale-service — each needs its in-container uid confirmed before labeling (wrong uid won't break backup, but restore would chown to the wrong owner). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
95207905a9
commit
af23488df1
@ -33,6 +33,7 @@ services:
|
||||
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
|
||||
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
|
||||
libreportal.backup.db: "mariadb:bookstack_db:db:"
|
||||
libreportal.backup.files: "bookstack:/config:data:1000:1000"
|
||||
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
|
||||
# TRAEFIK_PORT_1_BEGIN
|
||||
traefik.http.routers.bookstack-service.entrypoints: web,websecure
|
||||
|
||||
@ -65,6 +65,7 @@ services:
|
||||
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
|
||||
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
|
||||
libreportal.backup.db: "sqlite:::data/gitea/gitea/gitea.db"
|
||||
libreportal.backup.files: "gitea-service:/data:data/gitea:1000:1000"
|
||||
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
|
||||
# TRAEFIK_PORT_1_BEGIN
|
||||
traefik.http.routers.gitea-service.entrypoints: web,websecure
|
||||
|
||||
@ -24,16 +24,21 @@ appUpdateSpecifics_nextcloud() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
isNotice "Wiring Redis caching into Nextcloud..."
|
||||
isNotice "Wiring Redis caching + APCu into Nextcloud..."
|
||||
local rc=0
|
||||
# APCu = in-process local cache (cheap, fast). The fpm image ships with the
|
||||
# apcu PHP extension; under CLI mode it isn't enabled by default which makes
|
||||
# `occ` emit a harmless "memory cache not available" notice — Nextcloud's
|
||||
# graceful, the FPM worker still uses APCu fine.
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set memcache.local --value '\OC\Memcache\APCu' >/dev/null 2>&1 || rc=1
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set memcache.distributed --value '\OC\Memcache\Redis' >/dev/null 2>&1 || rc=1
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set memcache.locking --value '\OC\Memcache\Redis' >/dev/null 2>&1 || rc=1
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set redis host --value nextcloud-redis >/dev/null 2>&1 || rc=1
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set redis port --value 6379 --type=integer >/dev/null 2>&1 || rc=1
|
||||
runFileOp docker exec -u www-data nextcloud-service php occ config:system:set filelocking.enabled --value true --type=boolean >/dev/null 2>&1 || rc=1
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
isSuccessful "Nextcloud → Redis caching + file-locking wired."
|
||||
isSuccessful "Nextcloud → APCu (local) + Redis (distributed + file-locking) wired."
|
||||
else
|
||||
isNotice "Redis wiring had errors (non-fatal; Nextcloud still functions without it)"
|
||||
isNotice "Cache wiring had errors (non-fatal; Nextcloud still functions without it)"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ services:
|
||||
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
|
||||
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
|
||||
libreportal.backup.db: "mariadb:owncloud-mariadb:mysql:"
|
||||
libreportal.backup.files: "owncloud-service:/mnt/data:files:33:33"
|
||||
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
|
||||
# TRAEFIK_PORT_1_BEGIN
|
||||
traefik.http.routers.owncloud-service.entrypoints: web,websecure
|
||||
|
||||
@ -192,6 +192,27 @@ is a dev-only escape hatch.
|
||||
`./config`, …) or nest them under `resources/`. (The scan is `maxdepth 3`, so
|
||||
one sourced subfolder level is the cap — keep `scripts/` flat; name files
|
||||
`<app>_<purpose>.sh` instead of nesting.)
|
||||
- **Per-app hook conventions.** Every per-app extension is a conventionally-named
|
||||
function the central code dispatches via `declare -F` — define it, the
|
||||
framework picks it up; don't, you're a clean no-op. All hooks live in
|
||||
`containers/<app>/scripts/<app>_*.sh` unless noted. The hooks the framework
|
||||
currently dispatches:
|
||||
|
||||
| Hook function | When it runs | Notes |
|
||||
|---|---|---|
|
||||
| `app<App><PascalToolId>` | a Tools-tab button is clicked | declared in `tools/<app>.tools.json`; function in `tools/<app>_<tool_id>.sh`. Dispatched by `dockerAppRunTool`. |
|
||||
| `appUpdateSpecifics_<app>($app)` | end of every install / update | post-install fixups, side-effects. May set `shouldrestart=true` to request a restart. |
|
||||
| `appSetupComposeTags_<app>($file)` | during compose templating | fill computed (non-CFG) compose tags. CFG_`<APP>`_* tags are filled generically — only needed for tags that require computation. |
|
||||
| `appWebuiRefresh_<app>` | every `webuiLibrePortalUpdate` while the app is installed | data that needs ongoing refresh (e.g. gluetun's provider list snapshot). |
|
||||
| `appTraefikSkipsDefaultMiddleware_<app>` | router setup | **marker only** — function presence means "opt out of `default@file` middleware." |
|
||||
| `appTraefikExtraMiddlewares_<app>` | router setup | echo extra middleware entries (one per line) to append to this app's chain. |
|
||||
| `appNetworkApplyMode_<provider>($file)` | templating, when an app sets `CFG_<APP>_NETWORK=<provider>` | switch the routed app's compose to the provider's networking (e.g. toggle the `GLUETUN_OFF`/`ON` regions). The `<provider>` is the provider's app slug; the hook lives in `containers/<provider>/scripts/`. |
|
||||
| `appNetworkRegisterPorts_<provider>` | templating + uninstall, for any provider with a hook | refresh the provider's forwarded-port wiring (so a routed app's ports appear / removed apps drop out). Self-skip when the provider isn't installed. |
|
||||
|
||||
None of these need to be wired anywhere — the container scan live-sources
|
||||
`containers/<app>/scripts/*.sh` (depth 3, only `resources/` pruned), and the
|
||||
central dispatchers find the hook by name. So new apps adopting any of these
|
||||
is just "create the file + define the function."
|
||||
- **What gets backed up** (so you know what's safe to regenerate vs. preserve):
|
||||
per-app backups capture only the live data dir `<containers>/<app>/` — the
|
||||
deployed compose, the live `<app>.config` (settings + secrets), and the mounted
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user