---
title: App helpers (v2.1)
template: docs
taxonomy:
    category: docs
routes:
  default: '/packaging_apps_helpers_v2.1'
---

Doc auto-generated by [this script](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/doc/generate_helper_doc.py) on 03/07/2024 (YunoHost version 11.2.20.2)



## Sources

<p>This is coupled to the 'sources' resource in the manifest.toml</p>

    

### SOURCES
        
#### ynh_setup_source

[details summary="<i>Download, check integrity, uncompress and patch upstream sources</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_setup_source --dest_dir=dest_dir [--source_id=source_id] [--keep="file1 file2"] [--full_replace]`

**Arguments**:
- `--dest_dir=`: Directory where to setup sources
- `--source_id=`: Name of the source, defaults to `main` (when the sources resource exists in manifest.toml) or (legacy) `app` otherwise
- `--keep=`: Space-separated list of files/folders that will be backup/restored in $dest_dir, such as a config file you don't want to overwrite. For example 'conf.json secrets.json logs' (no trailing `/` for folders)
- `--full_replace=`: Remove previous sources before installing new sources (can be 1 or 0, default to 0)

**Details**:  
This helper will read infos from the 'sources' resources in the `manifest.toml` of the app
and expect a structure like:

```toml
[resources.sources]
    [resources.sources.main]
    url = "https://some.address.to/download/the/app/archive"
    sha256 = "0123456789abcdef"    # The sha256 sum of the asset obtained from the URL
```

(See also the resources documentation which may be more complete?)

##### Optional flags in the 'sources' resource

```text
format    = "tar.gz"/xz/bz2/tar # automatically guessed from the extension of the URL, but can be set explicitly. Will use `tar` to extract
            "zip"               # automatically guessed from the extension of the URL, but can be set explicitly. Will use `unzip` to extract
            "docker"            # useful to extract files from an already-built docker image (instead of rebuilding them locally). Will use `docker-image-extract` to extract
            "whatever"          # an arbitrary value, not really meaningful except to imply that the file won't be extracted

in_subdir = true    # default, there's an intermediate subdir in the archive before accessing the actual files
            false   # sources are directly in the archive root
            n       # (special cases) an integer representing a number of subdirs levels to get rid of

extract   = true    # default if file is indeed an archive such as .zip, .tar.gz, .tar.bz2, ...
          = false   # default if file 'format' is not set and the file is not to be extracted because it is not an archive but a script or binary or whatever asset.
                    #    in which case the file will only be `mv`ed to the location possibly renamed using the `rename` value

rename    = "whatever_your_want"   # to be used for convenience when `extract` is false and the default name of the file is not practical
platform  = "linux/amd64"          # (defaults to "linux/$YNH_ARCH") to be used in conjonction with `format = "docker"` to specify which architecture to extract for
```

You may also define assets url and checksum per-architectures such as:
```toml
[resources.sources]
    [resources.sources.main]
    amd64.url = "https://some.address.to/download/the/app/archive/when/amd64"
    amd64.sha256 = "0123456789abcdef"
    armhf.url = "https://some.address.to/download/the/app/archive/when/armhf"
    armhf.sha256 = "fedcba9876543210"
```

In which case `ynh_setup_source --dest_dir="$install_dir"` will automatically pick the appropriate source depending on the arch

The helper will:
- Download the specific URL if there is no local archive
- Check the integrity with the specific sha256 sum
- Uncompress the archive to `$dest_dir`.
  - If `in_subdir` is true, the first level directory of the archive will be removed.
  - If `in_subdir` is a numeric value, the N first level directories will be removed.
- Patches named `patches/${src_id}/*.patch` will be applied to `$dest_dir`
- Apply sane default permissions (see _ynh_apply_default_permissions)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/sources#L63)
[/details]
        
---
    

## App Technologies

<p>These allow to install specific version of the technology required to run some apps</p>

    

### NODEJS
        
#### ynh_nodejs_install

[details summary="<i>Install a specific version of nodejs, using 'n'</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_nodejs_install`

**Details**:  
The installed version is defined by `$nodejs_version` which should be defined as global prior to calling this helper

`n` (Node version management) uses the `PATH` variable to store the path of the version of node it is going to use.
That's how it changes the version

The helper adds the appropriate, specific version of nodejs to the `$PATH` variable (which
is preserved when calling ynh_exec_as_app). Also defines:
- `$path_with_nodejs` to be used in the systemd config (`Environment="PATH=__PATH_WITH_NODEJS__"`)
- `$nodejs_dir`, the directory containing the specific version of nodejs, which may be used in the systemd config too (e.g. `ExecStart=__NODEJS_DIR__/node foo bar`)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/nodejs#L42)
[/details]
        
#### ynh_nodejs_remove

[details summary="<i>Remove the version of node used by the app.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_nodejs_remove`

**Details**:  
This helper will check if another app uses the same version of node.
- If not, this version of node will be removed.
- If no other app uses node, n will be also removed.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/nodejs#L107)
[/details]
        
---
    

### RUBY
        
#### ynh_ruby_install

[details summary="<i>Install a specific version of Ruby using rbenv</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_ruby_install`

**Details**:  
The installed version is defined by `$ruby_version` which should be defined as global prior to calling this helper

The helper adds the appropriate, specific version of ruby to the `$PATH` variable (which
is preserved when calling ynh_exec_as_app). Also defines:
- `$path_with_ruby` to be used in the systemd config (`Environment="PATH=__PATH_WITH_RUBY__"`)
- `$ruby_dir`, the directory containing the specific version of ruby, which may be used in the systemd config too (e.g. `ExecStart=__RUBY_DIR__/ruby foo bar`)

This helper also creates a /etc/profile.d/rbenv.sh that configures PATH environment for rbenv


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/ruby#L44)
[/details]
        
#### ynh_ruby_remove

[details summary="<i>Remove the version of Ruby used by the app.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_ruby_remove`

**Details**:  
This helper will also cleanup unused Ruby versions


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/ruby#L185)
[/details]
        
---
    

### GO
        
#### ynh_go_install

[details summary="<i>Install a specific version of Go using goenv</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_go_install`

**Details**:  
The installed version is defined by `$go_version` which should be defined as global prior to calling this helper

The helper adds the appropriate, specific version of go to the `$PATH` variable (which
is preserved when calling `ynh_exec_as_app`). Also defines:
- `$path_with_go` (the value of the modified `$PATH`, but you dont really need it?)
- `$go_dir` (the directory containing the specific go version)

This helper also creates a /etc/profile.d/goenv.sh that configures PATH environment for goenv


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/go#L42)
[/details]
        
#### ynh_go_remove

[details summary="<i>Remove the version of Go used by the app.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_go_remove`

**Details**:  
This helper will also cleanup Go versions


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/go#L129)
[/details]
        
---
    

### COMPOSER
        
#### ynh_composer_install

[details summary="<i>Install and initialize Composer in the given directory</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_composer_install`

**Details**:  
The installed version is defined by `$composer_version` which should be defined
as global prior to calling this helper.

Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/composer#L11)
[/details]
        
#### ynh_composer_exec

[details summary="<i>Execute a command with Composer</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_composer_exec commands`

**Details**:  
Will use `$install_dir` as workdir unless `$composer_workdir` exists (but that shouldnt be necessary)

You may also define `composer_user=root` prior to call this helper if you
absolutely need composer to run as root, but this is discouraged...


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/composer#L37)
[/details]
        
---
    

## Databases

<p>This is coupled to the 'database' resource in the manifest.toml - at least for mysql/postgresql. Mongodb/redis may have better integration in the future.</p>

    

### MYSQL
        
#### ynh_mysql_db_shell

[details summary="<i>Run SQL instructions in a database ($db_name by default)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mysql_db_shell [database] <<< "instructions"`

**Arguments**:
- `database=`: the database to connect to (by default, $db_name)

**Examples**:
    
        
- `   ynh_mysql_db_shell $db_name <<< "UPDATE ...;"`
        
    
        
- `   ynh_mysql_db_shell < /path/to/file.sql`
        
    
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mysql#L12)
[/details]
        
#### ynh_mysql_dump_db

[details summary="<i>Dump a database</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mysql_dump_db database`

**Arguments**:
- `database`: the database name to dump (by default, $db_name)

**Returns**: The mysqldump output

**Example**: `ynh_mysql_dump_db "roundcube" > ./dump.sql`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mysql#L65)
[/details]
        
---
    

### POSTGRESQL
        
#### ynh_psql_db_shell

[details summary="<i>Run SQL instructions in a database ($db_name by default)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_psql_db_shell database <<< "instructions"`

**Arguments**:
- `database`: the database to connect to (by default, $db_name)

**Examples**:
    
        
- `   ynh_psql_db_shell $db_name <<< "UPDATE ...;"`
        
    
        
- `   ynh_psql_db_shell < /path/to/file.sql`
        
    
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/postgresql#L15)
[/details]
        
#### ynh_psql_dump_db

[details summary="<i>Dump a database</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_psql_dump_db database`

**Arguments**:
- `database`: the database name to dump (by default, $db_name)

**Returns**: the psqldump output

**Example**: `ynh_psql_dump_db 'roundcube' > ./dump.sql`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/postgresql#L70)
[/details]
        
---
    

### MONGODB
        
#### ynh_mongo_exec

[details summary="<i>Execute a mongo command</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_exec [--database=database] --command="command"`

**Arguments**:
- `--database=`: The database to connect to
- `--command=`: The command to evaluate

**Example**: `ynh_mongo_exec --command='db.getMongo().getDBNames().indexOf("wekan")' example: ynh_mongo_exec --command="db.getMongo().getDBNames().indexOf(\"wekan\")"`

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L13)
[/details]
        
#### ynh_mongo_dump_db

[details summary="<i>Dump a database</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_dump_db --database=database`

**Arguments**:
- `--database=`: The database name to dump

**Returns**: the mongodump output

**Example**: `ynh_mongo_dump_db --database=wekan > ./dump.bson`

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L64)
[/details]
        
#### ynh_mongo_database_exists

[details summary="<i>Check if a mongo database exists</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_database_exists --database=database
| exit: Return 1 if the database doesn't exist, 0 otherwise`

**Arguments**:
- `--database=`: The database for which to check existence

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L107)
[/details]
        
#### ynh_mongo_restore_db

[details summary="<i>Restore a database</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_restore_db --database=database`

**Arguments**:
- `--database=`: The database name to restore

**Example**: `ynh_mongo_restore_db --database=wekan < ./dump.bson`

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L130)
[/details]
        
#### ynh_mongo_setup_db

[details summary="<i>Create a database, an user and its password. Then store the password in the app's config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_setup_db --db_user=user --db_name=name [--db_pwd=pwd]`

**Arguments**:
- `--db_user=`: Owner of the database
- `--db_name=`: Name of the database
- `--db_pwd=`: Password of the database. If not provided, a password will be generated

**Details**:  
After executing this helper, the password of the created database will be available in $db_pwd
It will also be stored as "mongopwd" into the app settings.




[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L171)
[/details]
        
#### ynh_mongo_remove_db

[details summary="<i>Remove a database if it exists, and the associated user</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_mongo_remove_db --db_user=user --db_name=name`

**Arguments**:
- `--db_user=`: Owner of the database
- `--db_name=`: Name of the database

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L198)
[/details]
        
#### ynh_install_mongo

[details summary="<i>Install MongoDB and integrate MongoDB service in YunoHost</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_install_mongo`

**Details**:  
The installed version is defined by $mongo_version which should be defined as global prior to calling this helper


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L222)
[/details]
        
#### ynh_remove_mongo

[details summary="<i>Remove MongoDB
Only remove the MongoDB service integration in YunoHost for now
if MongoDB package as been removed</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_remove_mongo`

**Details**:  



[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/mongodb#L263)
[/details]
        
---
    

### REDIS
        
#### ynh_redis_get_free_db

[details summary="<i>get the first available redis database</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_redis_get_free_db`

**Returns**: the database number to use
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/redis#L7)
[/details]
        
#### ynh_redis_remove_db

[details summary="<i>Create a master password and set up global settings
Please always call this script in install and restore scripts</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_redis_remove_db database`

**Arguments**:
- `database`: the database to erase
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/redis#L36)
[/details]
        
---
    

## Configurations / Templating



    

### TEMPLATING
        
#### ynh_config_add

[details summary="<i>Create a dedicated config file from a template</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add --template="template" --destination="destination"`

**Arguments**:
- `--template=`: Template config file to use
- `--destination=`: Destination of the config file
- `--jinja`: Use jinja template instead of the simple `__MY_VAR__` templating format

**Examples**:
    
        
- `ynh_add_config --template=".env" --destination="$install_dir/.env"   # (use the template file "conf/.env" from the app's package)`
        
    
        
- `ynh_add_config --jinja --template="config.j2" --destination="$install_dir/config"    # (use the template file "conf/config.j2" from the app's package)`
        
    

**Details**:  
The template can be 1) the name of a file in the `conf` directory of
the app, 2) a relative path or 3) an absolute path.

This applies a simple templating format which covers a good 95% of cases,
where patterns like `__FOO__` are replaced by the bash variable `$foo`, for example:
  `__DOMAIN__`   by `$domain`
  `__PATH__`     by `$path`
  `__APP__`      by `$app`
  `__VAR_1__`    by `$var_1`
  `__VAR_2__`    by `$var_2`

Special case for `__PATH__/` which is replaced by `/` instead of `//` if `$path` is `/`

##### When --jinja is enabled

This option is meant for advanced use-cases where the "simple" templating
mode ain't enough because you need conditional blocks or loops.

For a full documentation of jinja's syntax you can refer to:
https://jinja.palletsprojects.com/en/3.1.x/templates/

Note that in YunoHost context, all variables are from shell variables and therefore are strings

##### Keeping track of manual changes by the admin

The helper will verify the checksum and backup the destination file
if it's different before applying the new template.

And it will calculate and store the destination file checksum
into the app settings when configuration is done.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/templating#L44)
[/details]
        
#### ynh_read_var_in_file

[details summary="<i>Get a value from heterogeneous file (yaml, json, php, python...)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_read_var_in_file --file=PATH --key=KEY`

**Arguments**:
- `--file=`: the path to the file
- `--key=`: the key to get
- `--after=`: the line just before the key (in case of multiple lines with the name of the key in the file)

**Details**:  
This helpers match several var affectation use case in several languages
We don't use jq or equivalent to keep comments and blank space in files
This helpers work line by line, it is not able to work correctly
if you have several identical keys in your files

Example of line this helpers can managed correctly
.yml
    title: YunoHost documentation
    email: 'yunohost@yunohost.org'
.json
    "theme": "colib'ris",
    "port": 8102
    "some_boolean":     false,
    "user": null
.ini
    some_boolean = On
    action = "Clear"
    port = 20
.php
    $user=
    user => 20
.py
    USER = 8102
    user = 'https://donate.local'
    CUSTOM['user'] = 'YunoHost'


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/templating#L172)
[/details]
        
#### ynh_write_var_in_file

[details summary="<i>Set a value into heterogeneous file (yaml, json, php, python...)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_write_var_in_file --file=PATH --key=KEY --value=VALUE`

**Arguments**:
- `--file=`: the path to the file
- `--key=`: the key to set
- `--value=`: the value to set
- `--after=`: the line just before the key (in case of multiple lines with the name of the key in the file)
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/templating#L247)
[/details]
        
---
    

### NGINX
        
#### ynh_config_add_nginx

[details summary="<i>Create a dedicated nginx config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add_nginx`

**Details**:  
This will use a template in `../conf/nginx.conf`
See the documentation of `ynh_config_add` for a description of the template
format and how placeholders are replaced with actual variables.

Additionally, ynh_config_add_nginx will replace:
- `#sub_path_only`      by empty string if `path` is not `'/'`
- `#root_path_only`     by empty string if `path`  *is*  `'/'`

This allows to enable/disable specific behaviors dependenging on the install
location


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/nginx#L17)
[/details]
        
#### ynh_config_remove_nginx

[details summary="<i>Remove the dedicated nginx config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_remove_nginx`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/nginx#L37)
[/details]
        
#### ynh_config_change_url_nginx

[details summary="<i>Regen the nginx config in a change url context</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_change_url_nginx`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/nginx#L46)
[/details]
        
---
    

### PHP
        
#### ynh_config_add_phpfpm

[details summary="<i>Create a dedicated PHP-FPM config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add_phpfpm`

**Details**:  
This will automatically generate an appropriate PHP-FPM configuration for this app.

The resulting configuration will be deployed to the appropriate place:
`/etc/php/$php_version/fpm/pool.d/$app.conf`

If the app provides a `conf/extra_php-fpm.conf` template, it will be appended
to the generated configuration. (In the vast majority of cases, this shouldnt
be necessary)

$php_version should be defined prior to calling this helper, but there should
be no reason to manually set it, as it is automatically set by the apt
helpers/resources when installing phpX.Y dependencies (PHP apps should at
least install phpX.Y-fpm using the `apt` helper/resource)

`$php_group` can be defined as a global (from `_common.sh`) if the worker
processes should run with a different group than `$app`

Additional "pm" and "php_admin_value" settings which are meant to be possibly
configurable by admins from a future standard config panel at some point,
related to performance and availability of the app, for which tweaking may be
required if the app is used by "plenty" of users and other memory/CPU load
considerations....

If you have good reasons to be willing to use different
defaults than the one set by this helper (while still allowing admin to
override it) you should use `ynh_app_setting_set_default`

- `$php_upload_max_filezise`: corresponds upload_max_filesize and post_max_size. Defaults to 50M
- `$php_process_management`: corresponds to "pm" (ondemand, dynamic, static). Defaults to ondemand
- `$php_max_children`: by default, computed from "total RAM" divided by 40, cf `_default_php_max_children`
- `$php_memory_limit`: by default, 128M (from global php.ini)

Note that if $php_process_management is set to "dynamic", then these
variables MUST be defined prior to calling the helper (no default value) ...
Check PHP-FPM's manual for more info on what these are (: ...

- `$php_start_servers`
- `$php_min_spare_servers`
- `$php_max_spare_servers`


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/php#L50)
[/details]
        
#### ynh_config_remove_phpfpm

[details summary="<i>Remove the dedicated PHP-FPM config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_remove_phpfpm`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/php#L126)
[/details]
        
---
    

### SYSTEMD
        
#### ynh_config_add_systemd

[details summary="<i>Create a dedicated systemd config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add_systemd [--service=service] [--template=template]`

**Arguments**:
- `--service=`: Service name (optionnal, `$app` by default)
- `--template=`: Name of template file (optionnal, this is 'systemd' by default, meaning `../conf/systemd.service` will be used as template)

**Details**:  
This will use the template `../conf/<templatename>.service`.

See the documentation of `ynh_config_add` for a description of the template
format and how placeholders are replaced with actual variables.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemd#L13)
[/details]
        
#### ynh_config_remove_systemd

[details summary="<i>Remove the dedicated systemd config</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_remove_systemd service`

**Arguments**:
- `service`: Service name (optionnal, $app by default)
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemd#L33)
[/details]
        
#### ynh_systemctl

[details summary="<i>Start (or other actions) a service,  print a log in case of failure and optionnaly wait until the service is completely started</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_systemctl [--service=service] [--action=action] [ [--wait_until="line to match"] [--log_path=log_path] [--timeout=300] [--length=20] ]`

**Arguments**:
- `--service=`: Name of the service to start. Default : `$app`
- `--action=`: Action to perform with systemctl. Default: start
- `--wait_until=`: The pattern to find in the log to attest the service is effectively fully started.
- `--log_path=`: Log file - Path to the log file. Default : `/var/log/$app/$app.log`
- `--timeout=`: Timeout - The maximum time to wait before ending the watching. Default : 60 seconds.
- `--length=`: Length of the error log displayed for debugging : Default : 20
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemd#L52)
[/details]
        
---
    

### FAIL2BAN
        
#### ynh_config_add_fail2ban

[details summary="<i>Create a dedicated fail2ban config (jail and filter conf files)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add_fail2ban --logpath=log_file --failregex=filter`

**Arguments**:
- `--logpath=`: Log file to be checked by fail2ban
- `--failregex=`: Failregex to be looked for by fail2ban

**Details**:  
If --logpath / --failregex are provided, the helper will generate the appropriate conf using these.

Otherwise, it will assume that the app provided templates, namely
`../conf/f2b_jail.conf` and `../conf/f2b_filter.conf`

They will typically look like (for example here for synapse):
```
f2b_jail.conf:
    [__APP__]
    enabled = true
    port = http,https
    filter = __APP__
    logpath = /var/log/__APP__/logfile.log
    maxretry = 5
```
```
f2b_filter.conf:
    [INCLUDES]
    before = common.conf
    [Definition]

# Part of regex definition (just used to make more easy to make the global regex)
    __synapse_start_line = .? \- synapse\..+ \-

# Regex definition.
   failregex = ^%(__synapse_start_line)s INFO \- POST\-(\d+)\- <HOST> \- \d+ \- Received request\: POST /_matrix/client/r0/login\??<SKIPLINES>%(__synapse_start_line)s INFO \- POST\-\1\- Got login request with identifier: \{u'type': u'm.id.user', u'user'\: u'(.+?)'\}, medium\: None, address: None, user\: u'\5'<SKIPLINES>%(__synapse_start_line)s WARNING \- \- (Attempted to login as @\5\:.+ but they do not exist|Failed password login for user @\5\:.+)$

ignoreregex =
```

##### Regarding the the `failregex` option:

regex to match the password failure messages in the logfile. The host must be
matched by a group named "`host`". The tag "`<HOST>`" can be used for standard
IP/hostname matching and is only an alias for `(?:::f{4,6}:)?(?P<host>[\w\-.^_]+)`

You can find some more explainations about how to make a regex here :
https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Filters

To validate your regex you can test with this command:
```
fail2ban-regex /var/log/YOUR_LOG_FILE_PATH /etc/fail2ban/filter.d/YOUR_APP.conf
```


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/fail2ban#L52)
[/details]
        
#### ynh_config_remove_fail2ban

[details summary="<i>Remove the dedicated fail2ban config (jail and filter conf files)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_remove_fail2ban`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/fail2ban#L114)
[/details]
        
---
    

### LOGROTATE
        
#### ynh_config_add_logrotate

[details summary="<i>Add a logrotate configuration to manage log files / log directory</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_config_add_logrotate [/path/to/log/file/or/folder]`

**Details**:  
If not argument is provided, `/var/log/$app/*.log` is used as default.

The configuration is autogenerated by YunoHost
(ie it doesnt come from a specific app template like nginx or systemd conf)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logrotate#L13)
[/details]
        
#### ynh_config_remove_logrotate

[details summary="<i>Remove the app's logrotate config.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_remove_logrotate`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logrotate#L71)
[/details]
        
---
    

## Misc Tools



    

### UTILS
        
#### ynh_exec_as_app

[details summary="<i>Execute a command after sudoing as $app</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_exec_as_app COMMAND [ARG ...]`

**Details**:  
Note that the $PATH variable is preserved (using --preserve-env=PATH)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L60)
[/details]
        
#### ynh_local_curl

[details summary="<i>Curl abstraction to help with POST requests to local pages (such as installation forms)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_local_curl "page_uri" "key1=value1" "key2=value2" ...`

**Arguments**:
- `page_uri`: Path (relative to `$path`) of the page where POST data will be sent
- `key1=value1`: (Optionnal) POST key and corresponding value
- `key2=value2`: (Optionnal) Another POST key and corresponding value
- `...`: (Optionnal) More POST keys and values

**Example**: `ynh_local_curl "/install.php?installButton" "foo=$var1" "bar=$var2"`

**Details**:  
For multiple calls, cookies are persisted between each call for the same app

`$domain` and `$path` should be defined externally (and correspond to the domain.tld and the /path (of the app?))


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L77)
[/details]
        
#### ynh_safe_rm

[details summary="<i>Remove a file or a directory, checking beforehand that it's not a disastrous location to rm such as entire /var or /home</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_safe_rm path_to_remove`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L145)
[/details]
        
#### ynh_read_manifest

[details summary="<i>Read the value of a key in the app's manifest</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_read_manifest "key"`

**Arguments**:
- `key`: Name of the key to find

**Returns**: the value associate to that key
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L171)
[/details]
        
#### ynh_app_upstream_version

[details summary="<i>Return the app upstream version, deduced from `$YNH_APP_MANIFEST_VERSION` and strippig the `~ynhX` part</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_app_upstream_version`

**Returns**: the version number of the upstream app

**Details**:  
For example, if the manifest contains `4.3-2~ynh3` the function will return `4.3-2`


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L181)
[/details]
        
#### ynh_app_upstream_version_changed

[details summary="<i>Return 0 if the "upstream" part of the version changed, or 1 otherwise (ie only the ~ynh suffix changed)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `if ynh_app_upstream_version_changed; then ...`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L188)
[/details]
        
#### ynh_app_upgrading_from_version_before

[details summary="<i>Compare the current package version is strictly lower than another version given as an argument</i>" class="helper-card-subtitle text-muted"]

**Usage**: ``

**Example**: `if ynh_app_upgrading_from_version_before 2.3.2~ynh1; then ...`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L196)
[/details]
        
#### ynh_app_upgrading_from_version_before_or_equal_to

[details summary="<i>Compare the current package version is lower or equal to another version given as an argument</i>" class="helper-card-subtitle text-muted"]

**Usage**: ``

**Example**: `if ynh_app_upgrading_from_version_before_or_equal_to 2.3.2~ynh1; then ...`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L206)
[/details]
        
#### ynh_validate_ip

[details summary="<i>Validate an IP address</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_validate_ip --family=family --ip_address=ip_address`

**Returns**: 0 for valid ip addresses, 1 otherwise

**Example**: `ynh_validate_ip 4 111.222.333.444`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L284)
[/details]
        
#### ynh_in_ci_tests

[details summary="<i>Check if the scripts are being run by the package_check in CI</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_in_ci_tests`

**Details**:  
Return 0 if in CI, 1 otherwise


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L348)
[/details]
        
#### ynh_user_get_info

[details summary="<i>Retrieve a YunoHost user information</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_user_get_info --username=username --key=key`

**Arguments**:
- `--username=`: the username to retrieve info from
- `--key=`: the key to retrieve

**Returns**: the value associate to that key

**Example**: `mail=$(ynh_user_get_info --username="toto" --key=mail)`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L360)
[/details]
        
#### ynh_user_list

[details summary="<i>Get the list of YunoHost users</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_user_list`

**Returns**: one username per line as strings

**Example**: `for u in $(ynh_user_list); do ... ; done`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/utils#L377)
[/details]
        
---
    

### SETTING
        
#### ynh_app_setting_get

[details summary="<i>Get an application setting</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_app_setting_get --key=key`

**Arguments**:
- `--app=`: the application id (global $app by default)
- `--key=`: the setting to get
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/setting#L8)
[/details]
        
#### ynh_app_setting_set

[details summary="<i>Set an application setting</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_app_setting_set --key=key --value=value`

**Arguments**:
- `--app=`: the application id (global $app by default)
- `--key=`: the setting name to set
- `--value=`: the setting value to set
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/setting#L27)
[/details]
        
#### ynh_app_setting_set_default

[details summary="<i>Set an application setting but only if the "$key" variable ain't set yet</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_app_setting_set_default --key=key --value=value`

**Arguments**:
- `--app=`: the application id (global $app by default)
- `--key=`: the setting name to set
- `--value=`: the default setting value to set

**Details**:  
Note that it doesn't just define the setting but ALSO define the $foobar variable

Hence it's meant as a replacement for this legacy overly complex syntax:

if [ -z "${foo:-}" ]
then
    foo="bar"
    ynh_app_setting_set --key="foo" --value="$foo"
fi


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/setting#L57)
[/details]
        
#### ynh_app_setting_delete

[details summary="<i>Delete an application setting</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_app_setting_delete --key=key`

**Arguments**:
- `--app=`: the application id (global $app by default)
- `--key=`: the setting to delete
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/setting#L79)
[/details]
        
---
    

### STRING
        
#### ynh_string_random

[details summary="<i>Generate a random string</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_string_random [--length=string_length]`

**Arguments**:
- `--length=`: the string length to generate (default: 24)
- `--filter=`: the kind of characters accepted in the output (default: 'A-Za-z0-9')

**Returns**: the generated string

**Example**: `pwd=$(ynh_string_random --length=8)`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/string#L11)
[/details]
        
#### ynh_replace

[details summary="<i>Substitute/replace a string (or expression) by another in a file</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_replace --match=match --replace=replace --file=file`

**Arguments**:
- `--match=`: String to be searched and replaced in the file
- `--replace=`: String that will replace matches
- `--file=`: File in which the string will be replaced.

**Details**:  
As this helper is based on sed command, regular expressions and references to
sub-expressions can be used (see sed manual page for more information)


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/string#L35)
[/details]
        
#### ynh_replace_regex

[details summary="<i>Substitute/replace a regex in a file</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_replace_regex --match=match --replace=replace --file=file`

**Arguments**:
- `--match=`: String to be searched and replaced in the file
- `--replace=`: String that will replace matches
- `--file=`: File in which the string will be replaced.

**Details**:  
This helper will use ynh_replace, but as you can use special
characters, you can't use some regular expressions and sub-expressions.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/string#L63)
[/details]
        
#### ynh_normalize_url_path

[details summary="<i>Normalize the url path syntax</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_normalize_url_path path_to_normalize`

**Examples**:
    
        
- `    url_path=$(ynh_normalize_url_path $url_path)`
        
    
        
- `    ynh_normalize_url_path example    # -> /example`
        
    
        
- `    ynh_normalize_url_path /example   # -> /example`
        
    
        
- `    ynh_normalize_url_path /example/  # -> /example`
        
    
        
- `    ynh_normalize_url_path /          # -> /`
        
    

**Details**:  
Handle the slash at the beginning of path and its absence at ending
Return a normalized url path


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/string#L118)
[/details]
        
---
    

### BACKUP
        
#### ynh_backup

[details summary="<i>Add a file or a directory to the list of paths to backup</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_backup /path/to/stuff`

**Details**:  
NB : note that this helper does *NOT* perform any copy in itself, it only
declares stuff to be backuped via a CSV which is later picked up by the core

NB 2 : there is a specific behavior for $data_dir (or childs of $data_dir) and
/var/log/$app which are *NOT* backedup during safety-backup-before-upgrade,
OR if the setting "do_not_backup_data" is equals 1 for that app

The rationale is that these directories are usually too heavy to be integrated in every backup
(think for example about Nextcloud with quite a lot of data, or an app with a lot of media files...)

This is coupled to the fact that $data_dir and the log dir won't be (and
should NOT) be deleted during remove, unless --purge is used. Hence, if the
upgrade fails and the script is removed prior to restoring the backup, the
data/logs are not destroyed.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L24)
[/details]
        
#### ynh_restore

[details summary="<i>Restore a file or a directory from the backup archive</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_restore /path/to/stuff`

**Examples**:
    
        
- `    ynh_restore "/etc/nginx/conf.d/$domain.d/$app.conf"`
        
    

**Details**:  
If the file or dir to be restored already exists on the system and is lighter
than 500 Mo, it is backed up in `/var/cache/yunohost/appconfbackup/`.
Otherwise, the existing file or dir is removed.

if `apps/$app/etc/nginx/conf.d/$domain.d/$app.conf` exists, restore it into
`/etc/nginx/conf.d/$domain.d/$app.conf`
otheriwse, search for a match in the csv (eg: conf/nginx.conf) and restore it into
`/etc/nginx/conf.d/$domain.d/$app.conf`


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L131)
[/details]
        
#### ynh_restore_everything

[details summary="<i>Restore all files that were previously backuped in an app backup script</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_restore_everything`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L189)
[/details]
        
#### ynh_store_file_checksum

[details summary="<i>Calculate and store a file checksum into the app settings</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_store_file_checksum /path/to/file`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L211)
[/details]
        
#### ynh_backup_if_checksum_is_different

[details summary="<i>Verify the checksum and backup the file if it's different</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_backup_if_checksum_is_different /path/to/file`

**Details**:  
This helper is primarily meant to allow to easily backup personalised/manually
modified config files.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L242)
[/details]
        
#### ynh_delete_file_checksum

[details summary="<i>Delete a file checksum from the app settings</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_delete_file_checksum /path/to/file`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/backup#L273)
[/details]
        
---
    

### LOGGING
        
#### ynh_die

[details summary="<i>Print a message to stderr and terminate the current script</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_die "Some message"`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L6)
[/details]
        
#### ynh_print_info

[details summary="<i>Print an "INFO" message</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_print_info "Some message"`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L22)
[/details]
        
#### ynh_print_warn

[details summary="<i>Print a warning on stderr</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_print_warn "Some message"`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L29)
[/details]
        
#### ynh_hide_warnings

[details summary="<i>Execute a command and redirect stderr to stdout</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_hide_warnings your command and args`

**Arguments**:
- `command`: command to execute
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L38)
[/details]
        
#### ynh_exec_and_print_stderr_only_if_error

[details summary="<i>Execute a command and redirect stderr in /dev/null. Print stderr on error.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_exec_and_print_stderr_only_if_error your command and args`

**Arguments**:
- `command`: command to execute

**Details**:  
Note that you should NOT quote the command but only prefix it with ynh_exec_and_print_stderr_only_if_error


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L49)
[/details]
        
#### ynh_return

[details summary="<i>Return data to the YunoHost core for later processing
(to be used by special hooks like app config panel and core diagnosis)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_return somedata`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L65)
[/details]
        
#### ynh_script_progression

[details summary="<i>Print a progress bar showing the progression of an app script</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_script_progression "Some message"`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/logging#L83)
[/details]
        
---
    

### MULTIMEDIA
        
#### ynh_multimedia_build_main_dir

[details summary="<i>Initialize the multimedia directory system</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_multimedia_build_main_dir`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/multimedia#L9)
[/details]
        
#### ynh_multimedia_addfolder

[details summary="<i>Add a directory in yunohost.multimedia</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_multimedia_addfolder --source_dir="source_dir" --dest_dir="dest_dir"`

**Arguments**:
- `--source_dir=`: Source directory - The real directory which contains your medias.
- `--dest_dir=`: Destination directory - The name and the place of the symbolic link, relative to "/home/yunohost.multimedia"

**Details**:  
This "directory" will be a symbolic link to a existing directory.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/multimedia#L60)
[/details]
        
#### ynh_multimedia_addaccess

[details summary="<i>Add an user to the multimedia group, in turn having write permission in multimedia directories</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_multimedia_addaccess user_name`

**Arguments**:
- `user_name`: The name of the user which gain this access.
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/multimedia#L86)
[/details]
        
---
    

## Deprecated Or Handled By The Core / App Resources Since V2



    

### PERMISSION
        
#### ynh_permission_delete

[details summary="<i>Remove a permission for the app (note that when the app is removed all permission is automatically removed)</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_permission_delete --permission="permission"`

**Arguments**:
- `--permission=`: the name for the permission (by default a permission named "main" is removed automatically when the app is removed)

**Example**: `ynh_permission_delete --permission=editors`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/permission#L149)
[/details]
        
#### ynh_permission_exists

[details summary="<i>Check if a permission exists</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_permission_exists --permission=permission
| exit: Return 1 if the permission doesn't exist, 0 otherwise`

**Arguments**:
- `--permission=`: the permission to check
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/permission#L164)
[/details]
        
#### ynh_permission_url

[details summary="<i>Redefine the url associated to a permission</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
                                                    [--auth_header=true|false] [--clear_urls]`

**Arguments**:
- `--permission=`: the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
- `--url=`: (optional) URL for which access will be allowed/forbidden. Note that if you want to remove url you can pass an empty sting as arguments ("").
- `--add_url=`: (optional) List of additional url to add for which access will be allowed/forbidden.
- `--remove_url=`: (optional) List of additional url to remove for which access will be allowed/forbidden
- `--auth_header=`: (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
- `--clear_urls`: (optional) Clean all urls (url and additional_urls)
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/permission#L185)
[/details]
        
#### ynh_permission_update

[details summary="<i>Update a permission for the app</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]`

**Arguments**:
- `--permission=`: the name for the permission (by default a permission named "main" already exist)
- `--add=`: the list of group or users to enable add to the permission
- `--remove=`: the list of group or users to remove from the permission
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/permission#L248)
[/details]
        
#### ynh_permission_has_user

[details summary="<i>Check if a permission has an user</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_permission_has_user --permission=permission --user=user
| exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise`

**Arguments**:
- `--permission=`: the permission to check
- `--user=`: the user seek in the permission

**Example**: `ynh_permission_has_user --permission=main --user=visitors`
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/permission#L289)
[/details]
        
---
    

### APT
        
#### ynh_apt_install_dependencies

[details summary="<i>Define and install dependencies with a equivs control file</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_install_app_dependencies dep [dep [...]]`

**Arguments**:
- `dep`: the package name to install in dependence.
- `"dep1|dep2|…"`: You can specify alternatives. It will require to install (dep1 or dep2, etc).

**Details**:  
example : ynh_install_app_dependencies dep1 dep2 "dep3|dep4|dep5"


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/apt#L13)
[/details]
        
#### ynh_apt_remove_dependencies

[details summary="<i>Remove fake package and its dependencies</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_apt_remove_dependencies`

**Details**:  
Dependencies will removed only if no other package need them.


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/apt#L159)
[/details]
        
#### ynh_apt_install_dependencies_from_extra_repository

[details summary="<i>Install packages from an extra repository properly.</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_apt_install_dependencies_from_extra_repository --repo="repo" --package="dep1 dep2" --key=key_url`

**Arguments**:
- `--repo=`: Complete url of the extra repository.
- `--package=`: The packages to install from this extra repository
- `--key=`: url to get the public key.
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/apt#L191)
[/details]
        
---
    

### SYSTEMUSER
        
#### ynh_system_user_exists

[details summary="<i>Check if a user exists on the system</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_system_user_exists --username=username`

**Arguments**:
- `--username=`: the username to check

**Returns**: 0 if the user exists, 1 otherwise.
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemuser#L8)
[/details]
        
#### ynh_system_group_exists

[details summary="<i>Check if a group exists on the system</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_system_group_exists --group=group`

**Arguments**:
- `--group=`: the group to check

**Returns**: 0 if the group exists, 1 otherwise.
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemuser#L23)
[/details]
        
#### ynh_system_user_create

[details summary="<i>Create a system user</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_system_user_create --username=user_name [--home_dir=home_dir] [--use_shell] [--groups="group1 group2"]`

**Arguments**:
- `--username=`: Name of the system user that will be create
- `--home_dir=`: Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home
- `--use_shell`: Create a user using the default login shell if present. If this argument is omitted, the user will be created with /usr/sbin/nologin shell
- `--groups`: Add the user to system groups. Typically meant to add the user to the ssh.app / sftp.app group (e.g. for borgserver, my_webapp)

**Details**:  
Create a nextcloud user with no home directory and /usr/sbin/nologin login shell (hence no login capability) :
```
ynh_system_user_create --username=nextcloud
```
Create a discourse user using /var/www/discourse as home directory and the default login shell :
```
ynh_system_user_create --username=discourse --home_dir=/var/www/discourse --use_shell
```


[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemuser#L49)
[/details]
        
#### ynh_system_user_delete

[details summary="<i>Delete a system user</i>" class="helper-card-subtitle text-muted"]

**Usage**: `ynh_system_user_delete --username=user_name`

**Arguments**:
- `--username=`: Name of the system user that will be create
[Dude, show me the code!](https://github.com/YunoHost/yunohost/blob/5d15c00d921927825a0bf98b0c5d872dac57d1b7/helpers/helpers.v2.1.d/systemuser#L87)
[/details]
        
---
    
