Skip to content

[NEXT] Keep configuration, uploads and themes on the mounted data volume - #28

Open
luke- wants to merge 1 commit into
developfrom
enh/core-1.20-config-directory
Open

luke- wants to merge 1 commit into
developfrom
enh/core-1.20-config-directory

Conversation

@luke-

@luke- luke- commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Prepares the image for HumHub 1.20. Not urgent for 1.19, but two of the three cases below mean data loss the moment the image is built against 1.20, so this should land before that happens.

What 1.20 changes

1.20 serves from a public/ directory and anchors paths on the installation root instead of on the document root (humhub/humhub#8459). This image relocates the document root to /app/public via HUMHUB_ALIASES__WEBROOT, which is exactly why uploads and themes were on the volume at all:

1.19 1.20 in this image
uploads @webroot/uploads @root/uploads /app/public/uploads/opt/humhub/uploads
themes @webroot/themes <root>/themes /app/public/themes/opt/humhub/themes
assets @webroot/assets @webroot/assets /app/public/assets — unchanged
config protected/config <root>/config see below

So under 1.20 uploads are written into the container layer and vanish when the container is recreated, and custom themes in /data/themes are no longer found. The configuration directory additionally moved out of protected/ (humhub/humhub#8483).

The configuration directory was already broken

Independent of 1.20: /data/config is created by the entrypoint, seeded from the image and included in humhub-backup.sh — but HumHub never read it. BootstrapService loads common.php, web.php, console.php and dynamic.php through the real path of the installation, not through @config, so HUMHUB_ALIASES__CONFIG=/data/config only ever redirected what actually goes through the alias (@config/messages, @config/views, and the dynamicConfigFile parameter). Anything an operator put in /data/config/common.php was silently ignored.

That is why this is a link and not another environment override.

The change

/opt/humhub/{config,uploads,themes} become links into /data, and what the release ships in them is kept as /opt/humhub-defaults/ — the template the entrypoint seeds /data from, exactly as it did before.

The config link is resolved at build time and covers both layouts (/opt/humhub/config on 1.20, /opt/humhub/protected/config before), so the image keeps working against 1.19 and this can sit on develop while HUMHUB_GIT_BRANCH still defaults to develop.

HUMHUB_ALIASES__CONFIG=/data/config is kept. It is redundant now that the real path leads there, but it is the explicit statement of intent and it keeps the alias correct if the link is ever absent.

Behaviour change to be aware of

On 1.19 an operator may have a /data/config/common.php that has been sitting there with no effect — seeded as return [];, possibly edited. After this change it is loaded. The seeded file is empty and the path is undocumented, so the practical risk is small, but it is a real change.

Testing

cd image
DOCKER_BUILDKIT=1 docker build --build-arg HUMHUB_GIT_BRANCH=enh/root-config-directory -t humhub:next-test .

enh/root-config-directory is the core branch of humhub/humhub#8483; use next once it is merged. Verify that /opt/humhub/{config,uploads,themes} are links into /data, that a fresh start seeds /data/config with the *.example.php files 1.20 ships, and that an upload survives docker compose down && up.

Not covered here

ln -s /opt/humhub/static/ /app/public/static is a dangling link — static/ moved into protected/humhub/ back in 1.19 (humhub/humhub#8102). Pre-existing and unrelated to the directories above, so it is left for its own change.

HumHub 1.20 anchors these three directories on the installation root. Uploads
and themes used to hang off the document root, which this image relocates to
/app/public and which therefore already put them on the volume - under 1.20
they resolve to /opt/humhub/{uploads,themes} inside the container layer, so
uploads are lost when the container is recreated and custom themes are not
found. The configuration directory additionally moved out of protected/.

All three are now linked into /data, which also fixes a case that was broken
before 1.20: the configuration directory is read through the real path of the
installation, not through the @config alias, so /data/config was created,
seeded and backed up but never loaded. HUMHUB_ALIASES__CONFIG only ever
redirected what goes through the alias.

Both directory layouts are linked, so the image keeps working against 1.19.
@luke-

luke- commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Built and ran locally against the core branch (--build-arg HUMHUB_GIT_BRANCH=enh/root-config-directory, i.e. 1.20 with the configuration move).

Image layout:

/opt/humhub/config  -> /data/config
/opt/humhub/themes  -> /data/themes
/opt/humhub/uploads -> /data/uploads

/opt/humhub-defaults/config: common.example.php  console.example.php  web.example.php
/opt/humhub/protected/config: absent (correct for 1.20)

First start against an empty volume seeds /data/config with the three *.example.php files and /data/uploads with the shipped skeleton (.gitignore, .htaccess, file/, index.html, profile_image/), as before.

Resolution inside the running image, with a common.php dropped into /data/config:

app name from config     = LOADED FROM /data/config      <- was silently ignored before
params.dynamicConfigFile = /opt/humhub/config/dynamic.php
  -> realpath of its dir = /data/config
fs uploads mount         = @root/uploads
  -> realpath            = /data/uploads                 <- was the container layer
aliases.@themes          = /opt/humhub/themes
  -> realpath            = /data/themes                  <- was the container layer

Note on the build: buildx was not available here, so the build ran against a context whose only difference is FROM debian:bookworm AS builder without --platform=$BUILDPLATFORM. Nothing this PR touches is affected by that line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant