manifest.toml can be seen as the ID card of the app. It declares various basic metadata such as the id, name, description of the app, its version, install questions to be asked to the admin prior to installation, etc.
In this page, the data are described according to a somewhat dummy app called
If you want to convert an application from the packaging v1 to v2 format, please see here!
packaging_format = 2 id = "helloworld" name = "Hello World" description.en = "A dummy basic app to illustrate YunoHost's app packaging." description.fr = "Une app simple et bidon pour illustrer comme le packaging d'app de YunoHost fonctionne" version = "0.1~ynh1" maintainers = ["alexAubin"]
int) is the packaging version format used to package this app. Newly packaged apps are strongly encouraged to use the new "v2" format (starting with YunoHost 11.1) while older apps may still be in "v1" format.
str) is expected to be lower-case alphanumeric (and possibly
-). This is what will be used for instance in the syntax
yunohost app install <app_id>. This will also be the name of various folder or conf files such as
/etc/nginx/conf.d/<domain>.d/<app_id>.conf(if applicable), and a dedicated system user.
str) is the display name of the app, shown for example in the webadmin UI or user portal. It is limited to 22 chars (though not sure why this number?).
str) contains short, concise descriptions of the app in different languages (at least
en). It is limited to 150 chars. It will be displayed on the app catalog and should allow people to understand what this app is about at a glance. A more extensive description of the app can be provided in
str) is composed of the upstream version of the app shipped, and an
~ynhXsuffix. Changing this version is what effectively triggers an available upgrade for YunoHost instances which installed this package (hence no upgrade will be displayed as available if you forget to change it). The point of the
~ynhXsuffix is to have a way to increment the version when commiting changes unrelated to the upstream but still trigger an upgrade.
str) may allow to declare which person should be the referring person for this package (though packages are often maintained collectively and not really used in practice). This should contain a list of easily identifiable persons (eg your Github or Matrix username)
This section is meant to provide various metadata about the app upstream such that YunoHost admins can easily obtain further information regarding this app (or, kinda important, try the upstream's demo before deciding to install it).
Apart from the license, all fields are optional and should only be provided if they are relevant (e.g. don't provide
website if the upstream project has no website...)
[upstream] license = "WTFPL" website = "https://www.hello-world.com/" code = "https://github.com/octocat/Hello-World" demo = ... admindoc = ... userdoc = ...
str) : the license code of the upstream project. (Note that only apps based on free software will be accepted in the official YunoHost app catalog.). The license code should be a valid SPDX identified.
url) : the url of the upstream project's website, if there is indeed a website (please don't just copypasta the git repo url)
url) : an url where people can try out the app before installing it (ideally maintained by the upstream project)
url) : the url of the upstream project's code repository, which is very much expected to exist for free software ... but may not exist for special "no upstream" apps ;)
url) : the url of the upstream project's admin documentation, which may help YunoHost admins with adminstrating the app (YunoHost-specific documentation can be provided in
url) : the url of the upstream project's user documentation, which may help YunoHost end-users with effectively using the app.
str) corresponds to the Common Platform Enumerations code in NIST db. For example for Wekan this is
cpe:2.3:a:wekan_project:wekan. Not really used at the moment, but may be used in the future to check for known vulnerabilities (CVE) in the app catalog.
This section is meant to contain info related to the relation between the app and YunoHost, or things like typical resource usage.
[integration] yunohost = ">= 11.1" architectures = "all" multi_instance = false ldap = "not_relevant" sso = "not_relevant" disk = "1M" ram.build = "1M" ram.runtime = "1M"
str) contains the minimum YunoHost version required for this app to work.
"all"OR a list of supported archs using the
dpkg --print-architecturenomenclature, i.e. among :
amd64(= x86 64bit),
i386(= x86 32bit),
armhf(= ARM 32bit),
arm64(= ARM 64bit)
bool) : wether or not the app supports being installed multiple time (in which case, during installation, the actual app id is not just the
idof the manifest, but something like
helloworld__3, etc. for subsequent installs)
"not_relevant") : not to confused with the
ssokey : this corresponds to wether or not the app is configured to use YunoHost's LDAP DB as the user account DB. This should be set to
"not_relevant"if and only if there is no notion of user account for this app (for example, Hextris). LDAP integration is often a prerequisite for the SSO to work.
"not_relevant") : not to be confused with the
ldapkey : this corresponds to wether or not a user is automatically logged-in on the app when logged-in on the YunoHost portal. This should be set to
"not_relevant"if and only if there is no notion of user account for this app (for example, Hextris).
disk(size) : an estimate minimum disk requirement. For example: 20M, 400M, 1G, ...
ram.build(size) : an estimate minimum ram requirement when building the app (this may be way different than
ram.runtimebecause some apps have a peak 1~2G RAM when building sometimes...). For example: 50M, 400M, 1G, ...
ram.runtime(size) : an estimate minimum ram requirement when the app is active and running. For example: 50M, 400M, 1G, ...
This section is completely optional and, for most apps, doesn't exist at all.
Some applications have limitations, they might be due to non-free dependencies, arbitrary limitations, etc. Yunohost provides UI in the catalog to show such antifeatures.
The declaration of antifeatures is a 3-steps process:
Describe the app's antifeature in its
[antifeatures] arbitrary-limitations.en = "Some description about the specific limitations of this app."
The format of this section is a
dict where keys are antifeature IDs, and the values
are translated strings (
This section contains questions that should be asked to the admin prior to starting the actual install
[install] [install.domain] # this is a generic question - ask strings are automatically handled by YunoHost's core type = "domain" [install.path] # this is a generic question - ask strings are automatically handled by YunoHost's core type = "path" default = "/helloworld" [install.init_main_permission] # this is a generic question - ask strings are automatically handled by YunoHost's core type = "group" default = "visitors" [install.prefered_pet] ask.en = "Do you prefer cats or dogs?" help.en = "Think carefully!" type = "string" choices.cat = "Cats :3 !" choices.dog = "Doggos <3" choices.both = "OMG Both ! I can't choose !"
type = "domain"/"path") are classic questions to allow the admin to choose where the app is installed (in terms of web url endpoint)
/foobar, the app will be available under
ask.enstrings that contain the actual question displayed in the UI along the line of "Choose a domain to install this app on"
init_main_permissionis also a classic question (similar to
is_publicin v1 packaging) and define what user group will be able to access the app after it is installed. Typical answer are :
visitors(= everybody including anonymous users, the app is "public"),
all_users(= only people with a YunoHost account, the app is "private"), or any custom user group that may have been defined by the YunoHost admins prior to the install.
prefered_petis a custom question:
ask.endefines the human-readable question to be asked (at least the english version)
help.enis an optional additional message to provide further info about this question
typeis the type of question, in this case
both(with proper human-readable versions of these choices)
$prefered_petwith the chosen value
FIXME : This should be way more documented in a separate section (and is also related to config panels...)
The full list of question types is :
password-type questions have special behavior and are NOT automatically saved as setting (user-chosen password should ideally not be stored, at least not hashed...)
Every install question is not necessarily mandatory (e.g. a question to propose to add an api key for a better user experience, although the app still works without). To make those questions optional, just write
optional = true.
The resource section corresponds to recurring app needs that are to be provisioned/deprovisioned by the core of YunoHost. They include for example: downloading the app's sources, creating a system user, installing apt dependencies, creating the install dir, creating the data dir, finding an available internal port, configuring permissions, initializing an SQL database... Each resource is to be provisioned before running the install script, deprovisioned after the remove script, and automatically upgraded if needed before running the upgrade script (or provisionned if introduced in the new app version, or deprovisioned if removed w.r.t. the previous app version)
[resources] ```toml [resources.sources.main] url = "https://some.domain/url/where/to/download/the/app/sources.tar.gz" sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" [resources.system_user] [resources.install_dir] [resources.permissions] main.url = "/" [resources.apt] packages = "nyancat, lolcat, sl"
In this example:
sources.main: the URL+checksum from which the app sources will be downloaded + validated
system_user: a system (unix) user will be created for this app, using the app id as username.
install_dir: an install dir will be initialized, named
/var/www/$appby default. Additional
groupproperty allow to change the owner/group and r/w/x permissions on the created folder.
permissions: an SSOwat
$app.mainpermission will be initialized such that the SSO allows access to the app's endpoint according to the chosen
main.url = "/"is here to tell that the main endpoint is the "root" of the app, that is
https://domain.tld/helloworld/if the app is installed with
apt: the packages
slwill be installed with
apt. These are just dummy apt dependencies to illustrate the syntax.
The full documentation on resources is available here.
Found errors? Think you can improve this documentation? Simply click the Edit link at the top of the page, and then the icon on Github to suggest changes.