diff --git a/docs/architecture/package-system.md b/docs/architecture/package-system.md index 4f7edd5..e9aa881 100644 --- a/docs/architecture/package-system.md +++ b/docs/architecture/package-system.md @@ -11,28 +11,43 @@ Packaging containers as `.deb` files provides several advantages over Docker Com - **Clean removal**: `apt remove` stops containers and cleans up - **Automatic updates**: Standard `apt upgrade` workflow - **System integration**: systemd services, icons, dashboard tiles — all in one package -- **Repository distribution**: Published to `apt.hatlabs.fi` like any APT package +- **Repository distribution**: Published to `apt.halos.fi` like any APT package ## What's in a Container App Package? -Each container app package contains: +A container app package installs the files under `/var/lib`, `/etc/systemd` and `/usr/share`. Its maintainer scripts and service create the rest: ``` -/var/lib/container-apps/{app-name}/ +/var/lib/container-apps/{package}/ ├── docker-compose.yml # Docker Compose definition -├── runtime.env # Environment variables -└── icon.png # Application icon +├── compose # Wrapper that runs docker compose with the overrides +├── compose.d/ # Local Compose overrides (empty when installed) +├── prestart.sh # Runs before each start; writes the runtime environment +├── metadata.yaml # App metadata +├── env.user-template # Template for the local env file +├── config.yml # User-configurable settings +├── env.template # Default environment values +└── data/ # Persistent app data, kept on remove and purge + +/etc/container-apps/{package}/ +├── env.defaults # Created by postinst from env.template on each install and upgrade +└── env # Created by postinst once; local overrides, kept across upgrades + +/run/container-apps/{package}/ +└── runtime.env # Environment generated by prestart.sh at each start /etc/systemd/system/ -└── {app-name}-container.service # systemd service unit +└── {package}.service # systemd service unit /usr/share/pixmaps/ -└── {app-name}.png # Icon for store and dashboard +└── {package}.{svg,png} # Icon for store and dashboard (extension of the source icon) ``` The package is intentionally lightweight — it does **not** contain the Docker image itself. The actual container image is pulled from the registry when the service starts for the first time. This keeps packages small (a few kilobytes) and ensures you always get the exact image version specified in the compose file. -The systemd service runs `docker compose up -d` on start and `docker compose down` on stop. +The systemd service runs Compose through the `compose` wrapper, which passes `docker-compose.yml`, then the generated routing-labels file for routed apps, then any files in `compose.d/`. Before starting, the service runs `prestart.sh` and `compose config --quiet`, so an invalid project fails the start. It then runs `compose up` in the foreground, and on stop runs `docker compose -p down --remove-orphans`. The stop uses only the project name, so it does not depend on the files in `compose.d/`. + +`compose.d/` holds local overrides written by the administrator. See [App Data and Migration — Customising an app with compose.d](../user-guide/app-data.md#customising-an-app-with-composed). ## App Definition Format @@ -75,9 +90,9 @@ See the [Container Metadata Reference](../reference/container-metadata.md) for t Standard Docker Compose file. The `container-packaging-tools` adds Traefik labels and Homarr labels automatically based on `metadata.yaml`. -### config.yml (optional) +### config.yml -User-configurable settings that are exposed as environment variables in `runtime.env`. +User-configurable settings that are exposed as environment variables through `/etc/container-apps/{package}/env.defaults`, and overridable in `/etc/container-apps/{package}/env`. ## container-packaging-tools @@ -85,7 +100,7 @@ The `generate-container-packages` command converts app definitions into Debian p ``` apps/grafana/ generate-container-packages -├── metadata.yaml ──────────────────────────► grafana-container_12.3.2-1_all.deb +├── metadata.yaml ──────────────────────────► marine-grafana-container_12.3.2-1_all.deb ├── docker-compose.yml ├── config.yml └── icon.png @@ -136,7 +151,7 @@ New categories appear automatically when a package uses a new `category::*` tag ## APT Repository -Container app packages are published to `apt.hatlabs.fi`: +Container app packages are published to `apt.halos.fi`: | Channel | Purpose | Tag format | |---------|---------|-----------| @@ -153,7 +168,7 @@ The CI/CD pipeline builds packages on push to main, publishes to unstable, and p apt install marine-grafana-container → dpkg extracts files (seconds — package is small) → postinst creates data directories, generates secrets - → systemd starts grafana-container.service + → systemd starts marine-grafana-container.service → prestart.sh computes runtime configuration → docker compose up → Docker pulls image layers from registry (may take minutes on first install) @@ -166,7 +181,7 @@ apt install marine-grafana-container ``` apt remove marine-grafana-container - → prerm stops grafana-container.service + → prerm stops marine-grafana-container.service → docker compose down → Traefik removes route → Homarr adapter detects removal @@ -177,10 +192,10 @@ apt remove marine-grafana-container ``` apt upgrade - → dpkg extracts updated files + → dpkg extracts updated files, overwriting docker-compose.yml → systemd restarts the service → docker compose pulls new image (only if upstream version changed) and recreates container - → Persistent data in /var/lib/container-apps/{app}/ is preserved + → compose.d/ overrides and persistent data in /var/lib/container-apps/{package}/data/ are preserved ``` ## Version Management diff --git a/docs/developer-guide/adding-apps.md b/docs/developer-guide/adding-apps.md index 4c29da9..4c83c61 100644 --- a/docs/developer-guide/adding-apps.md +++ b/docs/developer-guide/adding-apps.md @@ -163,7 +163,7 @@ settings: description: "Application timezone" ``` -These become environment variables in `runtime.env`, editable through the Cockpit configuration UI. +Their defaults land in `/etc/container-apps//env.defaults` and local values in `/etc/container-apps//env`, editable through the Cockpit configuration UI. The service reads both as environment variables. ## Step 4: Add an Icon diff --git a/docs/developer-guide/development-workflow.md b/docs/developer-guide/development-workflow.md index 69fb7a2..72ca64a 100644 --- a/docs/developer-guide/development-workflow.md +++ b/docs/developer-guide/development-workflow.md @@ -149,7 +149,7 @@ git commit --no-verify -m "WIP: message" 1. CI builds the Debian package 2. Creates a pre-release tag (`v{version}+{N}_pre`) -3. Publishes `.deb` to `apt.hatlabs.fi` unstable channel +3. Publishes `.deb` to the unstable channel of `apt.halos.fi` (`apt.hatlabs.fi` for repos in the `hatlabs` organisation) 4. Creates a draft GitHub release ### Publishing Stable Releases @@ -157,7 +157,7 @@ git commit --no-verify -m "WIP: message" 1. Test the unstable package on a device 2. Publish the draft release in GitHub UI 3. CI copies the `.deb` to the stable release -4. CI publishes to `apt.hatlabs.fi` stable channel +4. CI publishes to the stable channel of the same repository ## Development Environments diff --git a/docs/user-guide/app-data.md b/docs/user-guide/app-data.md index 43fef6d..165ef5f 100644 --- a/docs/user-guide/app-data.md +++ b/docs/user-guide/app-data.md @@ -1,6 +1,6 @@ # App Data and Migration -Every container app in HaLOS stores its persistent data on the host filesystem in a predictable location. This page explains where that data lives and how to migrate or back it up. +Every container app in HaLOS stores its persistent data on the host filesystem in a predictable location. This page explains where that data lives, how to migrate or back it up, and how to customise an app's Compose settings. ## Where app data is stored @@ -10,7 +10,7 @@ All container apps store data under: /var/lib/container-apps//data/ ``` -Each app gets its own isolated directory. Data persists across container restarts and app updates. Removing an app with `apt remove` preserves the data; `apt purge` deletes it. +Each app gets its own isolated directory. Data persists across container restarts and app updates. Removing an app with `apt remove` or `apt purge` preserves the data. `apt purge` deletes only the app's configuration in `/etc/container-apps//`; for a clean reinstall, delete `/var/lib/container-apps//` by hand after purging. ### Finding an app's data path @@ -103,3 +103,43 @@ sudo tar xzf backup.tar.gz -C / # Start the app sudo systemctl start ``` + +## Customising an app with compose.d + +Each container app is defined by a `docker-compose.yml` in `/var/lib/container-apps//`. Do not edit that file: the next package upgrade overwrites it. To change an app's Compose settings, put your own Compose file in the app's `compose.d/` directory: + +``` +/var/lib/container-apps//compose.d/ +``` + +Files ending in `.yml` or `.yaml` are applied in byte order of filename, after `docker-compose.yml` and, for apps with a web address, after the generated routing labels. A file in `compose.d/` can therefore override any setting of the app. Package upgrades and `apt purge` leave these files in place. + +The files merge with the app's definition by Docker Compose's [merge rules](https://docs.docker.com/reference/compose-file/merge/). Lists such as `group_add` add to the existing entries. To clear a setting, tag it with `!reset`; to replace it entirely, tag it with `!override`. HaLOS ships Compose 2.26, which supports both. + +### Example: adding a supplementary group + +To give the process in one of the app's services an extra group, create for example `compose.d/10-groups.yml`: + +```yaml +services: + : + group_add: + - "" +``` + +`` is the service name from the app's `docker-compose.yml`. Use the numeric group ID from the host (`getent group ` shows it); a group name is looked up inside the container, where it may not exist. + +Relative paths in a `compose.d/` file resolve against the app directory, `/var/lib/container-apps//`. A top-level `name:` in a `compose.d/` file has no effect, because the service sets the project name itself. + +### Applying the change + +Changes take effect when the app restarts. Check the result first, then restart: + +```bash +sudo /var/lib/container-apps//compose check +sudo systemctl restart +``` + +`compose check` validates the app's Compose configuration with the same environment the service uses, and lists the active `compose.d/` files. Part of that environment is generated when the service starts, so run the check while the app is running or after it has started at least once since boot. It needs `sudo` because the app's `runtime.env` is readable only by root. + +If a `compose.d/` file makes the configuration invalid, the app does not start. See [App fails to start after adding a compose.d file](troubleshooting.md#app-fails-to-start-after-adding-a-composed-file). diff --git a/docs/user-guide/installing-apps.md b/docs/user-guide/installing-apps.md index 3d4b98d..9239c4d 100644 --- a/docs/user-guide/installing-apps.md +++ b/docs/user-guide/installing-apps.md @@ -38,12 +38,12 @@ The store shows apps from all configured stores. The Marine variant adds a dedic ## Managing installed apps -**Start/Stop/Restart**: Open Cockpit → Services. Find the service (named `-container.service`) and use the controls to start, stop, or restart it. +**Start/Stop/Restart**: Open Cockpit → Services. Find the service (named `.service`) and use the controls to start, stop, or restart it. **View logs**: Open Cockpit → Services → select the service → Logs tab. Or use the terminal: ```bash -sudo journalctl -u -container.service -f +sudo journalctl -u .service -f ``` **Check container status**: Via the Cockpit terminal: diff --git a/docs/user-guide/system-management.md b/docs/user-guide/system-management.md index b16606b..baf3f85 100644 --- a/docs/user-guide/system-management.md +++ b/docs/user-guide/system-management.md @@ -33,7 +33,7 @@ A full command-line terminal in the browser. Useful for running commands without ### Services -View and manage systemd services. You can start, stop, restart, and enable/disable services. Container apps run as systemd services (e.g., `signalk-server-container.service`), so you can manage them here. +View and manage systemd services. You can start, stop, restart, and enable/disable services. Container apps run as systemd services (e.g., `marine-signalk-server-container.service`), so you can manage them here. ### Logs diff --git a/docs/user-guide/troubleshooting.md b/docs/user-guide/troubleshooting.md index 7bafe07..c3f402c 100644 --- a/docs/user-guide/troubleshooting.md +++ b/docs/user-guide/troubleshooting.md @@ -199,6 +199,33 @@ sudo systemctl restart avahi-daemon sudo systemctl status docker ``` +## App fails to start after adding a compose.d file + +**Symptom**: After you add or change a file in an app's `compose.d/` directory, the app's service fails to start. + +**Cause**: The service validates the app's Compose configuration, including every `compose.d/` file, before it starts the containers. An invalid file fails the start. + +**Solution**: + +1. Find the error in the service log: + ```bash + sudo journalctl -u -e + ``` + A `compose.d fragments: ...` line lists the active files, followed by Compose's error. The error names the service or the YAML line but not the file, so check each listed file. + +2. Fix or remove the file, then check the configuration: + ```bash + sudo /var/lib/container-apps//compose check + ``` + +3. Clear the failed state and start the service: + ```bash + sudo systemctl reset-failed + sudo systemctl start + ``` + +See [Customising an app with compose.d](app-data.md#customising-an-app-with-composed) for how these files are applied. + ## Getting help - **[GitHub Discussions](https://github.com/halos-org/halos-distro/discussions)** — Ask questions and share ideas with the community