Yunohost App Packaging: Manifests, Hooks and LDAP That Make One-Click Installs Safe Enough
Yunohost makes one-click installs reliable by pairing a declarative manifest.json with root shell hooks and LDAP-backed SSO, keeping Debian hygiene while enabling upgrades, backups and multi-instance apps.
26 Dec 2025, 00:59 UTC

Self-hosting a dozen services on one Debian box quickly becomes a routing, authentication and backup problem. You want each app isolated on domain.tld/app with single sign-on, automatic nginx and firewall rules, and a reliable upgrade path, without turning the host into a collection of ad-hoc scripts.
Yunohost solves this with a packaging contract rather than containers: a declarative manifest.json plus a small set of root shell hooks, all built on Debian hygiene and local LDAP. The core provides the helpers, the app provides the intent.
The contract is manifest.json plus six shell hooks
An app is described by manifest.json and a scripts/ directory. The manifest declares metadata, dependencies, required ports, data_dir, and LDAP permissions. The hooks are install, upgrade, remove, backup, restore and change_url. They run as root inside a controlled environment provided by /usr/share/yunohost/helpers/ynh_*.
The helpers abstract the repetitive operations: opening firewall ports, writing an nginx snippet, creating a systemd unit, generating secrets, and provisioning LDAP users and groups. A maintainer writes ~100 lines of hook logic instead of re-implementing system integration.
During install the core registers the app in the local LDAP directory, creates a dedicated service account, and writes a per-app nginx snippet that is included by the main vhost. The app is reachable under a sub-path with SSO via SSOwat without any app-level code changes, because authentication is delivered as an HTTP Remote-User header.
Install and upgrade are staged and reversible
Installation is transactional. The new version’s install hook runs in a staging directory. Only on success does Yunohost switch the active symlink under /etc/yunohost/apps/ and run post-upgrade hooks. Rollback is a core operation, not a custom script.
Backup and restore follow a standardized tarball layout. The core handles encryption, compression and remote storage targets such as SFTP, S3 or Borg. The app hook only needs to dump its database and copy its data_dir. Restoring re-runs the install hook then the restore hook, which keeps system state consistent.
SSO and routing without touching the app
LDAP is the identity backbone. Apps that support header auth receive the authenticated user via Remote-User. The core creates per-app LDAP groups and namespaces them per instance, so permissions are managed centrally.
Routing is done via an nginx snippet model. Each app provides a snippet that is included by the main domain vhost. This gives predictable sub-paths like domain.tld/app and avoids per-app vhost sprawl. Running an app on a dedicated subdomain still requires a manual vhost override.
Multi-instance support via environment variables
The same app can be installed multiple times under different paths. Hooks receive $YNH_APP_INSTANCE_NAME and $YNH_APP_INSTANCE_NUMBER. LDAP groups and data directories are namespaced per instance, so two Nextcloud instances can coexist with separate users and storage.
Worked example: preview an install safely
Before changing state, preview validation and hook order on the Yunohost server as root or with sudo:
yunohost app install --dry-run <app_id>This checks manifest schema compatibility and lists the hooks that would execute, without writing files. After a real install, inspect the resolved manifest:
cat /etc/yunohost/apps/<app_id>/manifest.jsonReview the hook source before installing a community app. Level 7–8 apps in the catalog pass CI linting for manifest schema, idempotent hooks and no hard-coded paths. The app catalog index is generated from GitHub repos tagged yunohost.
Trade-offs and limits to plan for
Hook scripts run as root. A buggy or malicious community app can escalate. Only install level 7+ apps or audit the hook source in the app repository.
Manifest schema evolves across major Yunohost releases, for example v2 in Yunohost 11 and v3 in Yunohost 12. Older apps may need manual manifest migration before upgrading the host.
LDAP-backed SSO assumes header auth support. Apps lacking this need a custom auth plugin or public access workaround.
Backup tarballs can grow large. The default temporary backup location can fill on large data sets. Configure a dedicated backup partition and monitor size.
App helpers are internal APIs and change between major releases without semver guarantees.
Check the result by verifying the app appears in the admin UI, the nginx snippet exists under /etc/nginx/conf.d/domain.tld.d/, and the LDAP group is created for the app instance. Keep a dry-run habit and review hook changes before upgrades.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.