Images
General
NS8 modules are distributed as packages that are implemented as Podman container images. A package is pulled from a remote software repository, implemented by a registry service, like GitHub Packages. Each package can be seen much like a tar archive.
When installing a rootless module, the corresponding image is extracted
inside the home of the module Unix user, i.e. /home/<module_id>.
Rootfull modules are extracted under /var/lib/nethserver/<module_id>.
In both cases the module UI is extracted to
/var/lib/nethserver/cluster/ui/apps/<module_id>.
Source tree
The sources repository of a module can be structured as follow:
imageroot/: it contains module scripts and configuration. Everything inside this directory is copied under the module installation directory. Common subdirs include:systemd/user: where Systemd units are stored.actions/: each subdirectory implements an action.bin/: it contains additional binaries for the module. It is added to PATH in the agent environment.etc/: to store additional configuration for Backup and Restorepypkg/: path for module Python packages, added toPYTHONPATH
ui/: it contains all UI source code of the modulebuild-images.sh: a script to manually build one or more images of the module and push them inside the image registry.README.md: a Markdown file describing the module purpose and implementation
Image labels
Module images can use a list of well-known labels to configure the system:
org.nethserver.tcp-ports-demand: see Port allocationorg.nethserver.images: see Service imagesorg.nethserver.rootfull: can be0or1, if set to0the module will run podman in rootless mode, if set to1the module will run podman in rootfull mode. See Rootless vs Rootfullorg.nethserver.authorizations: authorize the module to run actions of other modules. For instancetraefik@any:routeadmallows setting Traefik routes. See Roles and authorizations.org.nethserver.flags: a space-separated list of well-known flags. Currently available flags are:core_module: if present, it marks a module as coreaccount_provider: if present, it marks a module as an account providerno_data_backup: if present, the modules will need no data backuprootless: if present, the module is rootless (calculated fromorg.nethserver.rootfulllabel)rootfull: if present, the module is rootfull (calculated fromorg.nethserver.rootfulllabel)
org.nethserver.max-per-node: maximum number of module instances installed on the same nodeorg.nethserver.min-from: the image can be used to install a new application instance, or to update an existing instance provided it has a version greater than or equal to the label value. E.g. if the image labelorg.nethserver.min-fromhas value2.0.0, an existing instance with version1.3.0cannot be updated with it.org.nethserver.min-core: the image can be used to install a new application instance, or update an existing one, if the core version is greater than or equal to the label value. E.g. if the image labelorg.nethserver.min-corehas value2.7.0it cannot be installed if the leader node running core has version2.6.2.org.nethserver.volumes: space-separated list of named volumes. When the node provides additional disks, the Sysadmin is prompted to assign these volumes one of them. See Volumes.
Labels are set by build-images.sh, when the images are built.
Service images
Most modules run software from additional Podman images. The
org.nethserver.images takes a space-separated list of image URLs that
will be automatically downloaded by the create-module base action.
Information about the downloaded images are stored in the agent
environment, so they can be referenced in unit .service files and action
scripts.
Environment variables names are set as follow:
- one variable for each image
- variable name is the uppercase value of the image name
- symbols are mapped to
_(underscore) - if the image name begins with a digit, a
Iis prepended _IMAGEsuffix is appended
Examples:
docker.io/library/mysql:10.3-alpinebecomesMYSQL_IMAGE=docker.io/library/mysql:10.3-alpinequay.io/prometheus/node-exporter:v1.5.0becomesNODE_EXPORTER_IMAGE=quay.io/prometheus/node-exporter:v1.5.0docker.io/2fauth/2fauth:5.2.0becomesI2FAUTH_IMAGE=docker.io/2fauth/2fauth:5.2.0
Registry mirrors
NethServer keeps a copy of some public images on its own registry,
ghcr.io/nethserver. Nodes are configured to pull images hosted on
docker.io and quay.io from this mirror first: if the image is
missing there, or the mirror cannot be reached, it is pulled from the
original registry. Image references in org.nethserver.images and in
the agent environment do not change: always use the original registry
URL.
The mirror was introduced to work around Docker Hub pull rate limits.
Docker Hub counts anonymous pulls by IPv6 /64 prefix, so many servers
sharing the same prefix, like VPSs of a cloud provider, reach the
limit quickly and image downloads fail during module installation and
updates (see NethServer/dev#7160).
The same mechanism was later extended to quay.io images (see
NethServer/dev#8231).
The mirror is made of two parts:
-
Node configuration: the core installs
/etc/containers/registries.conf.d/800-nethserver.conf, which declaresghcr.io/nethserver/docker.ioandghcr.io/nethserver/quay.ioas mirrors of the respective registries. The configuration applies to Podman, Buildah and Skopeo. -
Image copy: the ns8-repomd workflow runs
syncmirrors.shevery time it publishes the default repository metadata. The script reads theorg.nethserver.imageslabel of every module version and copies each missingdocker.ioandquay.ioimage to the mirror, for examplequay.io/prometheus/prometheus:v3.13.2becomesghcr.io/nethserver/quay.io/prometheus/prometheus:v3.13.2. Short Docker Hub names are expanded, sodocker.io/redis:7is copied asghcr.io/nethserver/docker.io/library/redis:7.
Only images of modules published in the default repository are mirrored. Images of other repositories, like NethForge, and images from other registries are always pulled from their original location.