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 Restore
    • pypkg/: path for module Python packages, added to PYTHONPATH
  • ui/: it contains all UI source code of the module
  • build-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 allocation
  • org.nethserver.images: see Service images
  • org.nethserver.rootfull: can be 0 or 1, if set to 0 the module will run podman in rootless mode, if set to 1 the module will run podman in rootfull mode. See Rootless vs Rootfull
  • org.nethserver.authorizations: authorize the module to run actions of other modules. For instance traefik@any:routeadm allows 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 core
    • account_provider: if present, it marks a module as an account provider
    • no_data_backup: if present, the modules will need no data backup
    • rootless: if present, the module is rootless (calculated from org.nethserver.rootfull label)
    • rootfull: if present, the module is rootfull (calculated from org.nethserver.rootfull label)
  • org.nethserver.max-per-node: maximum number of module instances installed on the same node
  • org.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 label org.nethserver.min-from has value 2.0.0, an existing instance with version 1.3.0 cannot 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 label org.nethserver.min-core has value 2.7.0 it cannot be installed if the leader node running core has version 2.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 I is prepended
  • _IMAGE suffix is appended

Examples:

  • docker.io/library/mysql:10.3-alpine becomes MYSQL_IMAGE=docker.io/library/mysql:10.3-alpine
  • quay.io/prometheus/node-exporter:v1.5.0 becomes NODE_EXPORTER_IMAGE=quay.io/prometheus/node-exporter:v1.5.0
  • docker.io/2fauth/2fauth:5.2.0 becomes I2FAUTH_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 declares ghcr.io/nethserver/docker.io and ghcr.io/nethserver/quay.io as mirrors of the respective registries. The configuration applies to Podman, Buildah and Skopeo.

  • Image copy: the ns8-repomd workflow runs syncmirrors.sh every time it publishes the default repository metadata. The script reads the org.nethserver.images label of every module version and copies each missing docker.io and quay.io image to the mirror, for example quay.io/prometheus/prometheus:v3.13.2 becomes ghcr.io/nethserver/quay.io/prometheus/prometheus:v3.13.2. Short Docker Hub names are expanded, so docker.io/redis:7 is copied as ghcr.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.