Customize app config
Override an app’s generated docker-compose.yml and app.env when you need host mounts or environment values the install form does not cover.
Example use cases
- Set an environment variable on an app, such as Pi-hole’s time zone
- Mount an extra host volume into a media app such as Jellyfin. By default, Jellyfin only sees its own
mediafolder,app-data/<app-store>/jellyfin/media.
Anything you mount is visible to the app, with the permissions of the user the container runs as. Mount only the folders the app needs.
How overrides are applied
Hub generates each app’s docker-compose.yml under apps/ from the app store’s docker-compose.json every time the app installs, updates, or starts, so edits there are lost. Your overrides live under user-config/ in a matching path, and Hub applies them on top when the app starts. Hub uses them while user config is enabled for the app, which is the default. This guide’s two examples look like this:
flowchart LR
subgraph APPS["apps/<app-store>/ — generated by Hub, overwritten on start"]
PD["pi-hole/docker-compose.yml<br/>references PIHOLE_TZ"]
JD["jellyfin/docker-compose.yml"]
end
subgraph UC["user-config/<app-store>/ — your overrides"]
PE["pi-hole/app.env<br/>PIHOLE_TZ=Europe/Berlin"]
JC["jellyfin/docker-compose.yml<br/>volumes: /cellar:/cellar"]
end
PD --> P["Pi-hole container"]
PE -- "sets the variable" --> P
JD --> J["Jellyfin container"]
JC -- "adds the mount" --> J
RS["Stop, then Start<br/>the app to apply"] -.- P
RS -.- JCreate custom Docker config
This example sets an environment variable for Pi-hole and mounts /cellar into Jellyfin.
Inspect <ROOT_FOLDER_HOST>/apps/<app-store>/pi-hole/docker-compose.yml to learn which variables the generated file references:
environment:
TZ: ${PIHOLE_TZ}Here, set PIHOLE_TZ. A variable you set in app.env wins over the value the install form saved.
Do not edit files under apps directly. Hub regenerates them and overwrites
your changes.
Create the folders
Under your Hub data root (ROOT_FOLDER_HOST), create user-config folders that match the app store and app IDs. Find the data root with cihub doctor:
cd "$ROOT_FOLDER_HOST"
mkdir -p user-config/<app-store>/jellyfin
mkdir -p user-config/<app-store>/pi-holeReplace <app-store> with your app store’s folder name. Apps from the
Companion App Store use ci-marketplace; apps migrated from earlier versions
use migrated. Check the apps folder in your data root for the exact name.
Override Jellyfin volumes
touch user-config/<app-store>/jellyfin/docker-compose.yml
nano user-config/<app-store>/jellyfin/docker-compose.ymlservices:
jellyfin:
volumes:
- /cellar:/cellar/cellar with the host path you want to mount.Override Pi-hole environment
touch user-config/<app-store>/pi-hole/app.env
nano user-config/<app-store>/pi-hole/app.envPIHOLE_TZ=Europe/BerlinReplace Europe/Berlin with your own time zone
name .
Confirm the layout
- docker-compose.yml
- app.env
Restart the apps and verify
On each app’s detail page in Companion Hub, select Stop, then Start.
- In Jellyfin, open library settings and confirm the mounted volume appears.
- For Pi-hole, find the container name with
cihub app list, then check the time zone it runs in:
docker exec <container-name> dateThe output shows the time in the zone you set:
Mon Sep 29 14:02:11 CEST 2026