Offline installation
This page installs navin-manager in a bank network without Internet access. The same steps work online: the only difference is where the artifacts come from.
1. Prerequisites
| Item | Requirement |
|---|---|
| Manager host | RHEL family 8, 9 or 10 (RHEL, Rocky Linux, AlmaLinux, Oracle Linux 8/9, CentOS Stream 9/10) with python3.12, or Ubuntu 24.04 with python3.12. Ubuntu 22.04 is a managed host only: it provides no maintained Python 3.11 or newer. 4 CPU, 8 GB of memory, 50 GB for the mirror. |
| Managed hosts | Certified systems: RHEL 8/9/10, Rocky Linux 8/9/10, AlmaLinux 8/9/10, Oracle Linux 8/9, CentOS Stream 9/10, Ubuntu 22.04/24.04, Debian 12, Arch Linux (rolling). A newer release of these families (for example Ubuntu 26.04, Debian 13, Oracle Linux 10) or a derivative of Arch Linux (Manjaro, EndeavourOS) passes the preflight with a warning; an end of life release (CentOS 7 and 8, RHEL 7, Ubuntu 20.04 and older, Debian 11 and older) or another family is blocked. x86_64 or aarch64. Python 3.9 or later, openssl, tar, a synchronized clock (chronyd or systemd-timesyncd). Podman 4 or later for the podman method. Host firewall: the agent opens the public ports with firewalld or ufw; with your own nftables or iptables ruleset, open the ports the installation preflight lists. |
| Manager database | PostgreSQL 14 or later run by the bank in its own cluster, a database navin_manager, a role navin_manager owning it, TLS with the CA of the bank. |
| Certificates | A server certificate for the manager host (bank PKI), with the DNS name used by operators and agents. |
| Network | Operators to the manager on 8460/tcp; managed hosts to the manager on 8460/tcp (registration) and 8461/tcp (agent API and mirror). Nothing opens towards managed hosts. |
2. Build the offline bundle (outside the bank)
On a build host connected to the Internet, from a checkout of navin-manager:
navin-manager/server/.venv/bin/python navin-manager/packaging/offline/build-bundle.py \
--catalog navin-manager/catalog --out /srv/navin-bundle/mirror \
--services all --methods binary,podman,python --arch x86_64 --python-versions 3.9,3.11,3.12 \
--gpg-key release@bank.example
The builder downloads every artifact named by the catalog, checks it against the checksum file published by its
project, saves the container images with podman save and records their digests, downloads the Python wheels, and
writes manifest.json with the sha256 of every file. An artifact without an upstream checksum is refused unless
--trust-on-first-download is given; the manifest then records that choice for the entry. The result is
bundle.tar, bundle.tar.sha256 and, with --gpg-key, a detached signature.
Behind a corporate proxy, set NM_MIRROR_PROXY=http://proxy.bank.example:3128 (and NM_MIRROR_NO_PROXY with the
hosts reached directly, for example nexus.bank.example,.bank.internal) or pass --proxy and --no-proxy. The
proxy carries the artifact and checksum downloads, pip download and podman pull; without it the standard
https_proxy and no_proxy variables apply. The agents and the Manager never use a proxy: they talk to each other
directly.
For hosts without access to a package repository, add --os-repo (with --gpg-key), and the package method when
it is used, on a machine of the release of the hosts (for example Ubuntu 24.04):
navin-manager/server/.venv/bin/python navin-manager/packaging/offline/build-bundle.py \
--catalog navin-manager/catalog --out /srv/navin-bundle/mirror \
--services all --methods binary,podman,python,package --os-repo \
--gpg-key release@bank.example
The builder then adds in os/<id>-<release>-<arch>/ a signed repository of the system packages the chosen methods
need: podman (with uidmap on Debian and Ubuntu), tar, every Python interpreter and its venv module, the
packages of the package method and those of --os-packages, with all their dependencies for a minimal host. On the
Debian family InRelease is signed and the index gives the sha256 of every package; on the RHEL family
repodata/repomd.xml.asc signs the index and every package keeps the signature of its publisher, checked by
rpmkeys --checksig during the build. For another release of the hosts (for example RHEL 9), copy the --out
directory to a machine of that release and run the builder again with the same --out: the intact repositories of
the earlier runs are kept. --os-apt-option and --os-dnf-option name the sources of the downloads, for example the
internal mirror of the bank. Once the mirror is loaded, the agent of a host of that release installs the
prerequisites and the packages of the package method from this repository alone, never disabling a signature
check; a host of another release, or a package the repository lacks, goes through the repositories configured on the
host.
The agent packages recommend podman (and uidmap on Debian and Ubuntu): apt and dnf install them with the
agent when the repositories of the host carry them. An agent without root (sandbox) installs no system package: the
validation of a podman installation then gives the command to run on the host.
Build the packages of navin-manager and of the agent with navin-manager/packaging/build-packages.sh (see
packaging/README.md (navin-manager/packaging/README.md)): the server RPM is built in a RHEL builder with python3.12 (one
RPM for the RHEL family 8, 9 and 10), the server DEB on Ubuntu 24.04, the agent packages anywhere.
3. Transfer and verify
Copy bundle.tar, its checksum, its signature and the packages through the transfer procedure of the bank, then on
the manager host:
sha256sum -c bundle.tar.sha256
gpg --import navin-bundle.pub
gpg --verify bundle.tar.asc bundle.tar
The bundle is unpacked into the mirror directory once the server is installed (step 7), where verify-bundle.py
checks the size and the sha256 of every file against manifest.json.
4. Install the server
RHEL, Rocky, AlmaLinux:
dnf install ./navin-manager-1.0.0-1.el9.x86_64.rpm
Ubuntu 24.04:
apt install ./navin-manager_1.0.0_amd64.deb
Arch Linux (the package depends on the Python of Arch Linux it was built for, pacman -S postgresql first for a local
database):
pacman -U ./navin-manager-1.0.0-1-x86_64.pkg.tar.zst
The package creates the system user navin-manager, the application environment in /opt/navin-manager, the
catalog in /usr/share/navin-manager/catalog, the SQL migrations in /usr/share/navin-manager/sql, the console in
/usr/share/navin-manager/ui, /var/lib/navin-manager, /var/log/navin-manager and the systemd unit
navin-manager.service.
5. Configure
Edit /etc/navin-manager/server.yaml (every key can be overridden by NM_<KEY> in /etc/navin-manager/server.env):
| Key | Value |
|---|---|
database_url | postgresql://navin_manager@<db-host>:5432/navin_manager?sslmode=verify-full&sslrootcert=/etc/navin-manager/tls/postgresql-ca.pem. Put the password in server.env (NM_DATABASE_URL, mode 0640) or in ~navin-manager/.pgpass, never in server.yaml. |
tls_cert_file, tls_key_file | Certificate and key of the manager. |
public_url | URL of the console, for example https://<manager-host>:8460. |
agent_url | URL of the agent API, for example https://<manager-host>:8461. |
NM_METRICS_TOKEN | In server.env: 32 characters or more, used by Prometheus to read /metrics. |
mirror_url, registry | Optional: a Nexus or Artifactory of the bank holding the mirror tree, a Harbor, Quay or Nexus registry holding the images. Without them the agents use the local mirror of the manager. |
The package created the master key /etc/navin-manager/master.key (32 random bytes, owned by navin-manager, mode
0600). Check the settings, then start the server (the unit applies the database migrations before serving):
navin-manager check
systemctl enable --now navin-manager
Keep a copy of /etc/navin-manager/master.key in the bank vault: every stored secret depends on it.
navin-manager check lists every setting that forbids a production start (TLS, client certificates, cookie flag,
metrics token, scrypt cost, master key, sslmode).
6. First sign in
Open https://<manager-host>:8460 and sign in with navin and the initial password the package wrote to
/etc/navin-manager/server.env (NM_ADMIN_PASSWORD). That password serves once: the console asks right away for your
own password (12 characters or more, lower and upper case letters, digits and symbols). Lost password:
navin-manager reset-admin
In Administration, Authentication connect the LDAP or Active Directory of the bank, or an OIDC provider (Keycloak, Entra ID), map the groups to roles and adjust the security policy.
7. Load the mirror
Unpack the verified bundle (it holds the mirror/ directory), check every file and give it to the service account:
tar -xf /media/transfer/bundle.tar -C /var/lib/navin-manager
python3 /usr/share/navin-manager/packaging/verify-bundle.py --mirror /var/lib/navin-manager/mirror
chown -R navin-manager:navin-manager /var/lib/navin-manager/mirror
Then in Administration, Mirror, select Reload (or call POST /api/v1/mirror/reload?verify=true). The page lists
the services whose artifacts are missing from the mirror: they cannot be installed until a bundle that holds them is
loaded.
Manifest signature (manifest.json.sig)
By default (NM_MIRROR_SIGNATURE=required) the server refuses a manifest.json without a valid detached Ed25519
signature manifest.json.sig: error mirror_manifest_unsigned (no signature) or mirror_manifest_signature_invalid
(manifest or signature altered, unknown key). The check runs at load and again at every delivery to the agents: a
manifest replaced after the load is refused. Without it, anyone who can write in the mirror replaces an archive and its
sha256.
- Build:
build-bundle.py ... --sign-key /secure/path/mirror-signing.pem(Ed25519 private key, PEM, never in the bundle). Create the key:openssl genpkey -algorithm ed25519 -out mirror-signing.pemthenopenssl pkey -in mirror-signing.pem -pubout -out mirror-signing.pub.pem. - Trusted keys of the server: PEM file
NM_MIRROR_TRUSTED_KEYS_FILEand/or the Hub settinghub.trusted_keys_pem. - Check outside the server:
verify-bundle.py --mirror ... --trusted-keys mirror-signing.pub.pem. - Migration of an existing unsigned mirror: verify it (
verify-bundle.py --mirror) thensign-manifest.py --mirror /var/lib/navin-manager/mirror --sign-key mirror-signing.pem, and reload. During the migration only,NM_MIRROR_SIGNATURE=unsigned-allowedaccepts an unsigned manifest; every load is then recorded in the audit (mirror.reload,signature.status = unsigned). verify-bundle.py --strictalso refuses the images without a digest pinned in the catalog (trust: first-download).
8. Add the hosts
Create a cluster, then add hosts in one of two ways.
Agent package. In Hosts, Add hosts, create a bootstrap token. Install the agent on each host and run the register command shown by the console (it carries the token and the sha256 fingerprint of the manager CA). The shipped agent is the static Go binary (no Python needed on the host, see Host agent); take the package of the host architecture:
dnf install ./navin-manager-agent-go-1.0.0-1.x86_64.rpm
nm-agent register --server https://<manager-host>:8460 --token <token> --ca-sha256 <fingerprint>
systemctl enable --now navin-manager-agent
On Ubuntu use apt install ./navin-manager-agent-go_1.0.0_amd64.deb, on Arch Linux
pacman -U ./navin-manager-agent-go-1.0.0-1-x86_64.pkg.tar.zst. The Python agent
(navin-manager-agent-1.0.0-1.noarch.rpm, navin-manager-agent_1.0.0_all.deb,
navin-manager-agent-1.0.0-1-any.pkg.tar.zst, Python 3.9 or newer) is still provided and uses the same command,
configuration and unit.
SSH bootstrap. Give the host names, an SSH user, the private key and the SHA256 fingerprint of each host key. The manager checks each fingerprint, copies the agent package from the mirror, installs it and registers the host. The key stays in memory during the operation and is never stored.
The preflight checks of a host appear as soon as it registers: operating system, architecture, memory, CPU, disks, clock, SELinux, systemd, Podman, OpenSSL, Python, open files limit.
9. Install the platform
In Clusters, Install services, choose the services, assign their components to hosts (the wizard shows the placement rules of each mode and validates them live), bind each dependency to a managed service or to an existing connection (the PostgreSQL of the bank in production), review the configuration (recommended values come from the host facts) and start the installation. The operation page shows each stage and the live logs of each task.
10. Serve the packages from a local repository
On a site without access to the Navin repositories, serve the packages of the bundle from a local repository so that
dnf, apt and pacman resolve them like any other package. <version> is the release, for example 1.0.0.
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream (createrepo_c comes from the RHEL mirror of your
organization):
dnf install -y createrepo_c
mkdir -p /srv/repo/navin && cp /var/lib/navin-manager/mirror/agent/*.rpm navin-manager-*.rpm /srv/repo/navin/
createrepo_c /srv/repo/navin
printf '[navin]\nname=Navin Enterprise\nbaseurl=file:///srv/repo/navin\ngpgcheck=0\nenabled=1\n' > /etc/yum.repos.d/navin.repo
dnf install -y navin-manager-agent-go
Expected result: dnf repolist lists navin. Set gpgcheck=1 once the packages are signed with the RPM key of your
organization (rpmsign --addsign).
Ubuntu, Debian:
mkdir -p /srv/repo/navin && cp *.deb /srv/repo/navin/ && cd /srv/repo/navin
dpkg-scanpackages --multiversion . > Packages && gzip -k -f Packages
echo 'deb [trusted=yes] file:/srv/repo/navin ./' > /etc/apt/sources.list.d/navin.list
apt-get update && apt-get install -y navin-manager-agent-go
Expected result: apt-cache policy navin-manager-agent-go shows the local repository.
Arch Linux: pacman -U installs the package files directly; the signed [navin] repository of os/repo.sh can also
be copied to an internal web server, its section SigLevel = Required DatabaseRequired refuses an unsigned package.
If it fails: dnf or apt cannot read the directory when SELinux or the permissions forbid it: run
restorecon -R /srv/repo/navin and give it mode 0755.
11. Offline archives of the guided installer
os/build.sh install-archive [debian|rhel|arch] builds one archive per family, navin-install-<version>-<family>.tar.gz
with its .sha256: the installer, the packages of that family with their SHA256SUMS, the guide. Copy the archive
with its checksum, then:
sha256sum -c navin-install-<version>-rhel.tar.gz.sha256
tar xzf navin-install-<version>-rhel.tar.gz && cd navin-install-<version>-rhel
sudo ./navin-install preflight manager
The installer checks the packages against SHA256SUMS before each installation and changes nothing while a check
fails. The steps are in Install the Navin Manager.
12. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
sha256sum -c reports FAILED | the file was altered during the transfer | copy it again from the build host |
gpg --verify reports BAD signature | the bundle or the key differs from the signed one | stop: check the origin of the bundle and of navin-bundle.pub |
| The Mirror page lists missing artifacts | the bundle does not hold these services or methods | build a bundle with them (--services, --methods) and load it |
An installation stops with artifact_missing | the mirror lacks the artifact of this version | load the bundle of this version, then Reload the manifest |
A task fails with checksum_mismatch | the file of the mirror differs from manifest.json | run verify-bundle.py --mirror, then unpack the verified bundle again |
The validation refuses the podman method with podman_missing | the agent runs without root (sandbox), or the host has neither dnf, apt-get nor pacman | run on the host the command given by the message (for example sudo apt-get install -y podman uidmap), then refresh the facts of the host |
apt-get update or dnf fails on the navin-os repository | a file of the embedded repository changed or its signature does not match the key of the bundle | run verify-bundle.py --mirror, unpack the verified bundle again, then Reload the manifest |