BLiNQ NetworksNetLiNQ · On-Prem Install All guides/Before you begin

Customer Installation Guide

Install NetLiNQ on your own servers.

The installer builds your Kubernetes cluster and deploys the full NetLiNQ platform for you. You fill in a few settings, answer a handful of prompts, and confirm everything is running — about 30 minutes end to end.

~30 minutes 3 setup types Secure by default One command

Before you begin

Requirements

Choose the setup you're installing. The requirements and example values throughout this guide update to match your choice.

CPU
24vCPU
Memory
48GB
Disk
750GB

Master nodesrun the control planemaster_ip
Worker nodesrun the workloadsworker_ip
Storagewhere platform data lives 

The storage figures are an estimate and still need to be validated. Real usage depends on how many devices you manage and how long you retain telemetry and log data. Confirm sizing with BLiNQ before you provision or order hardware.

You'll also need

  • A server running Ubuntu 22.04 or 24.04 with root access.
  • Internet access — the installer downloads software and container images.
  • At least 250 GB of local disk on each node, plus one shared 1500 GB NFS volume.
  • Your EMS and SpC serial numbers (provided by BLiNQ).
  • The certificate file from BLiNQ — only for manual-certificate installs (most installs use automatic certificates and skip this).

Step 1

Prepare the server

Log in and update the system. Enter your password when asked.

prepare
# Make package downloads use IPv4
$ echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4
# Become root and update the system
$ sudo -i
$ apt update
$ apt full-upgrade -y
Ubuntu 22.04 only: install the newer kernel, then reboot. On Ubuntu 24.04, just reboot.
kernel
$ apt install -y linux-generic-hwe-22.04   # Ubuntu 22.04 only
$ reboot

Step 2

Get the install package

BLiNQ support sends you the install package. After the reboot, log back in, copy the package onto the server and unpack it — everything from here runs inside the folder it creates.

unpack
# from your own machine, if the package is not on the server yet
$ scp netlinq-onprem-package.tar.gz blinq@<server>:~/

# on the server — the file name follows your release
$ tar -xzf netlinq-onprem-package.tar.gz
$ cd blinq-ems-autom-configs
No package yet? Ask BLiNQ support for the release that matches your order. Do not pull the installer from a public source — the package you are sent is the one supported for your deployment.

If BLiNQ gave you the certificate ZIP (manual-certificate installs only), copy it onto the server now and note where you put it.

Step 3

Enter your settings

Open the settings file and fill in the values for your environment.

edit-settings
$ cd blinq-ems-autom-configs
$ nano netlinq_onprem_install.vars

The settings you'll set

typesinglenode — your setup type (set by your choice above).
master_ipThe IP address of your server. For multinode, list all master IPs separated by spaces.
username_nodesYour login user — usually blinq.
endpointYour NetLiNQ web address, e.g. ems.example.org.
EMS_SERIALNUMBERYour EMS serial number from BLiNQ.
SPC_SERIALNUMBERYour SpC serial number from BLiNQ.
subnetnoHow many IP addresses your network uses — 1, 2, or 3. See below.
worker_ipYour worker server IPs, separated by spaces.
nfs_server_ipThe server that holds shared storage (NFS).
nfs_allowed_subnetYour network — must be a /24.

Choosing your IP layout (subnetno)

NetLiNQ uses up to three addresses. subnetno tells the installer how many separate addresses you're giving it — pick the option that matches your network, then copy the matching example.

Primary managementems-ui, dieselngf_external_ip
Secondary managementkeycloak, grafanangf_internal_ip
Deviceshow devices reach EMSdevice_lb

example — subnetno 1

      

Complete example for your setup type

Each setup type needs a slightly different set of values. Pick yours to see a complete, copy-ready example.

example — singlenode

      

Generator

Build your vars file

Enter the real values for this deployment and a complete netlinq_onprem_install.vars file is written below — every setting the installer reads, including the ones that must not be left unset. Download it and hand it to the customer ready to use.

Advanced options›

These have safe defaults and rarely need changing. Everything else the installer reads is written out with its documented default, so no setting is ever left unset.

netlinq_onprem_install.vars

      
This file holds addresses and serial numbers, not passwords — passwords are entered separately in the Secrets Console (Step 5). Still, send it over a trusted channel.

Step 4

Run the installer

run-installer
$ cd installation
$ sudo su
$ chmod +x install_kubespray.sh
$ ./install_kubespray.sh
Keep your VPN or SSH session connected for the whole run — the install takes about 30 minutes.

What happens next

The installer runs through these stages automatically:

Read settings
Pre-flight checks
Build cluster
Network & storage
Deploy platform
Ready

Step 5

Answer the prompts

The installer asks a few questions. Anything you already filled in above won't be asked again.

Low on resources — proceed?
Type y to continue.
How do you want to configure secrets?
Choose 1 Browser UI or 2 CLI editor — see below.
Proceed to initialization?
Enter 1 for yes (or 2 to cancel).
Sudo password
Enter your server login password.
Confirm values? [Y/N]
Check the values match what you entered, then type Y.
[NFS] sudo password for NFS server
Enter the login password of the NFS server (nfs_server_ip). Asked late in the install, once the cluster is up and NFS storage is set up. Not echoed as you type; the installer verifies it over SSH before changing anything, so a wrong password stops the NFS step immediately.

Entering your secrets

When the installer reaches the secrets step, it asks how you'd like to enter your usernames, passwords, and SMTP settings. Both options do the same thing — pick whichever you prefer:

Option 1 · Easiest

Browser form

The installer prints a web address. Open it in your browser, fill in the form, then click Validate to check your entries and Done to finish. It's secured with a one-time token and closes itself when finished.

Option 2

Text editor

A text editor (vi by default) opens the secrets file. Each field carries a comment showing what it needs, for example # REQUIRED; min 8 chars; letters, digits and @ -. Fill in your values, then save and close.

If anything is wrong, the editor reopens. Validation runs when you quit, lists every problem it found, then reopens the same file so you can fix them. This repeats until all fields are valid, so you cannot continue the install with a bad value. Nothing is saved until it passes — press Ctrl-C to abort instead.

With the browser form, the installer — or sudo secretsctl ui later — prints two addresses. Open the one that fits where your browser is:

secrets-console
$ sudo secretsctl ui
  Opened temporary firewall allow for TCP 41863 (removed when UI exits).

  ==============================================
    NetLiNQ Secrets Console
  ==============================================

  On this host, open:
    https://127.0.0.1:41863/?t=1c345353...8895f59a
  From your laptop browser (no SSH tunnel), open:
    https://192.168.5.130:41863/?t=1c345353...8895f59a

  Click Done when finished; Cancel or Ctrl-C aborts install.
Expect a one-time browser security warning. The page uses a certificate created just for this session, so your browser flags it once — choose Advanced → Proceed / Accept to continue. The address, certificate, and token all expire when the session ends.
NetLiNQ Secrets Console in the browser, showing all secrets ready with Validate and Done actions
The Secrets Console in your browser — fill in the external fields, then click Validate and Done. Internal secrets are auto-generated for you; the completion bar shows when everything is ready.
Changing secrets later? No reinstall needed. Run secretsctl edit (or secretsctl ui for the form), then secretsctl apply to push changes to the cluster.
Email/SMTP is skipped by default. That's fine — you can set it up afterwards in Step 7.

Step 6

Check that it worked

List the platform pods. Every pod should reach Running or Completed — give it up to 20 minutes after the installer finishes.

verify
$ sudo kubectl get pods -A

A healthy result settles like this:

If pods are still in another state after 20 minutes, the install didn't complete — contact BLiNQ support with the output of kubectl describe pod <name> -n <namespace>.

Step 7 · Optional

Customize

Set the default user password or email (SMTP). Use the values file that matches your setup.

customize
$ cd blinq-ems-autom-configs/installation/netlinq-deployment-values/
$ nano custom-singlenode-values.yml
values.yml
user_default_password: ""

smtp:
  Server: ""
  Port: 587
  User: ""
  Password: ""          # for Gmail, use an app password
  encryption: STARTTLS

Apply your changes, then add the NetLiNQ web addresses to your DNS so people can reach them.

apply
$ ./custom_values_apply.sh
$ kubectl get httproutes -n netlinq   # addresses to add to DNS

Branding

brand_name in your vars file decides which brand the platform wears. Supported values are blinq and agil; the comment on that line in your own vars file is the authoritative list for your release.

netlinq_onprem_install.vars
### Enter brand name
brand_name="blinq"   # currently supported blinq and agil

That one value reaches two places during the install:

keycloak.brand_nameThe sign-in page. Keycloak's init container copies /blinq/themes/<brand_name> into its theme directory, so people see that brand when they log in.
global.BRAND_NAMEThe NetLiNQ applications, which read it for their own logos and titles.
Set it before you install. The value is read from the vars file and handed to Helm as the charts go on, so changing the brand later means re-applying those charts with the new value.

Branding does not change any address. What people type in the browser comes from endpoint and ui_subdomain, which stay the same whichever brand you pick.

Step 8 · Optional

Shutting down and restarting

NetLiNQ ships two systemd units that scale the platform down in dependency order before the machine stops, drain the nodes, and then restore everything after boot. They are armed by default — the shipped vars file sets enable_netlinq_shutdown_service="true". Set it to "false" to leave them off.

Full reference: NetLiNQ Lifecycle Service guide — enabling and disabling the units, preparing an existing cluster, what happens at shutdown and at boot, the replicas.json order, and how to scale the platform down by hand.

Help

Quick troubleshooting

Installer stops on the kernel check›
On Ubuntu 22.04, install the HWE kernel and reboot (Step 1): apt install -y linux-generic-hwe-22.04 && reboot.
Installer stops on resources›
You're below the minimums shown in Requirements for your setup type — add CPU, RAM, or disk and re-run.
Some pods never reach Running›
Wait up to 20 minutes. If still stuck, run kubectl describe pod <name> -n <namespace> and share the output with BLiNQ support.
Web pages don't load›
Make sure your DNS points to the correct IPs (Step 7) and that they match your subnetno layout. List them with kubectl get httproutes -n netlinq.
Browser warns the Secrets Console isn't secure›
Expected. The console uses a certificate generated for that session only — choose Advanced → Proceed / Accept. The address and certificate expire when you click Done.

Danger

Removing NetLiNQ

dev_tools/uninstall_netlinq.sh permanently deletes every database, Kafka topic and stored file. It runs kubectl delete pvc --all in the netlinq and kafka namespaces, destroying every PersistentVolumeClaim and all persisted state. There is no undo, and the script takes no backup.

Only run it when you intend to wipe the installation completely — for example before rebuilding a lab server. Take a backup first: once the PVCs are gone the data cannot be recovered from the cluster.

The script asks you to confirm by typing DELETE in full. Anything else aborts without changing a thing. It also asks separately whether to reset the secrets and GPG configuration — answering y (or Y, yes, YES) removes the encrypted protected_config.yaml.gpg, the decrypted protected_config.yaml if one was left behind, the sealed secrets and all GPG keys for the current user, so GPG must be set up again before the next install.

Old passwords reappearing after a reinstall? That prompt was answered "no" — the encrypted config survived and the next install reused it. Re-run the uninstall and answer y. Answering anything else now prints Keeping local secrets… so it is never silent.

If there is no terminal to prompt on, the script refuses to run rather than assume you meant it. For a deliberately scripted teardown, and only then:

teardown
$ ./dev_tools/uninstall_netlinq.sh --yes
  no confirmation prompt — use with care

Appendix

secretsctl reference

secretsctl manages every credential NetLiNQ uses — database passwords, Keycloak clients, SMTP, Grafana, TLS material and registry credentials. You met it in Step 5; this appendix covers everything it can do afterwards.

The installer places a wrapper at /usr/local/bin/secretsctl, so the command works from any directory on the server. Your encrypted values live in protected_config.yaml.gpg at the root of the cloned repository. Kubernetes Secret names are unchanged from earlier releases: the config key external_ems_aoa_client becomes the Secret external-ems-aoa-client.

The one rule to remember

Editing secrets and pushing them to the cluster are two separate steps.

Editingchanges the encrypted file onlyedit, set, save, generate disk only
Applyingseals, applies, restarts consumersapply live cluster

If you change a password and skip apply, the cluster keeps running with the old value. This is the most common point of confusion.

Secret requirements

Every value you type is checked. The browser form shows the rule under each box and turns it red as you type; the text editor puts the rule in a comment beside the field and refuses to save until it is met.

The general rule: passwords need at least 8 characters. Each field also limits which characters are allowed — these values end up in connection strings, URLs and config files, where certain characters break downstream services.

The EMS login

If your provider issues the password, check it against these rules first. For credentials you choose, simply pick one that fits. For credentials issued by an external service — most often SMTP — the provider decides the format, and some issue values containing characters NetLiNQ currently rejects, such as + / = ! or %. Amazon SES SMTP passwords and base64-style API keys are the common examples. Do not edit such a credential to make it fit — it will stop working. Raise it with the NetLiNQ team so the allowed set can be widened; the restriction is NetLiNQ policy, not a limit of the mail server.

This is the account you sign in to the NetLiNQ web interface with, so it is the one you will use most.

ems-usernameRequired. Maximum 20 characters. Letters, digits and _.
ems-passwordRequired. Minimum 8 characters. Letters, digits, @ and - only.
Leave the password blank and a readable one is generated for you, for example NetLiNQ-CoralHarbor-42. Kubernetes Secret: external-ems-aoa-client.

Everything else you enter

keycloak-usernameMust be admin. Do not change this — the platform depends on it.
keycloak-passwordRequired. Minimum 8 characters. Letters, digits and @ . _ -.
smtp-usernameRequired. Letters, digits and @ . _ -.
smtp-passwordRequired. Minimum 8 characters. Letters, digits and @ . _ -.
smtp-client-idRequired. Provided by your mail provider.
smtp-client-secretRequired. Provided by your mail provider.
sftp-usernameRequired. Letters, digits and @ . _ -.
sftp-passwordRequired. Minimum 8 characters. Letters, digits and @ . _ -.
mongodb-root-passwordRequired. Minimum 8 characters. Letters and digits only — no punctuation at all.
mongodb-replica-set-keyRequired. Minimum 8 characters. Letters and digits only.
mongo-usernameRequired on each of the three databases. Letters, digits and _. All three must be different from each other.
mongo-passwordRequired on each of the three databases. Minimum 8 characters. Letters and digits only.
The MongoDB fields reject punctuation entirely, including @ and -. A password with a special character there will fail to save.

Values generated for you

Elasticsearch, Grafana, PostgreSQL, the Keycloak client IDs and secrets, and the device-admin encryption key are all created automatically with strong random values. They are marked protected: the browser form shows them read-only, and if you change one in the text editor your edit is discarded and the original restored. You never need to invent these.

Certificate fields

When certificate automation is off, the Spark, SPC TLS and SAS entries hold file paths rather than passwords, so the length and character rules do not apply. They are filled in for you from your certificate bundle.

Upgrading an existing system

These requirements arrived after some systems were already installed. If a stored password predates them, secretsctl prints a warning naming the field but does not block the upgrade. The rules apply the moment you change that value. To list everything non-compliant at once, run secretsctl validate and rotate whatever it reports.

Three ways to work

Easiest

Browser form

See every secret at once and fill them in a form. Run sudo secretsctl ui.

Terminal

CLI editor

No browser needed. Run secretsctl edit to open the config in your editor.

For automation and repeatable builds, use the scripted commands: set, save, generate and apply.

Every command

manifestPrints the secret schema. Names and field types only, never values. Add --json for machine output.
statusPer-secret summary of what is configured and what is still empty. Add --json.
validateDecrypts and validates everything. Exits 0 if valid, 1 if not — useful in a pre-install check.
initEnsures the GPG key and a template config exist. Run once on a fresh machine.
getDecrypts and prints the whole config. Add --json or --yaml. Handle with care.
setset <secret> <field> <value> — updates one field and re-encrypts.
saveReads JSON from standard input, merges it and re-encrypts. Add --skip-validate to bypass checks.
generategenerate <secret> fills that secret's empty auto-generated fields. generate --all does every secret; adding --external also invents external passwords, for lab use only.
editOpens the config in your $EDITOR, vi by default. No browser required.
applySeals and applies to the cluster, then restarts consumers. Repeat --secret NAME to target individual secrets; --no-restart leaves pods running.
sealBuilds and seals the sealed-secret manifests. Add --apply to push them as well.
uiLaunches the browser console. Accepts --port N and --bind ADDR, and builds itself on first use.
Most commands also accept --cert-automation true|false, which tells them whether to expect certificate paths in the config.

What is stored

Secrets fall into three groups. Only the first needs your input.

ExternalSMTP, Keycloak admin, EMS login, SFTP, four MongoDB passwordsexternal_* you fill in
InternalElasticsearch, Keycloak clients, Grafana, PostgreSQL, Spark materialinternal_* generated
Certificatesonly when automatic certificates are offspc_tls, sas, regcred conditional

Internal secrets are read-only in the browser form — you can reveal and copy them, but not change them. That is how you retrieve the generated Grafana password.

The browser console

secretsctl ui
$ sudo secretsctl ui                    # LAN-reachable, random port
$ sudo secretsctl ui --bind 127.0.0.1   # only on the server itself
$ sudo secretsctl ui --port 8765        # fixed port
Builds itselfOn first use it compiles the console, installing Go if needed. There is no separate build step.
Binds to LANReachable from your laptop with no SSH tunnel. Use --bind 127.0.0.1 to restrict it to the server.
One-time tokenThe port is random each run and a token is required. Both die when the session ends.
Session TLSThe certificate is generated for that session only, so the browser warns once. Choose Advanced → Proceed.
Temporary firewallAn opening is created for the port and removed when the console exits.
FinishingClick Validate to check your entries, then Done. Cancel or Ctrl-C aborts.

Scripted installs

These environment variables drive the secrets step without answering the prompt.

SECRETS_MODE=uiForce the browser console.
SECRETS_MODE=cliForce the terminal editor.
SECRETS_MODE=legacyUse the older set_secret_values.sh editor.
SECRETS_UI=0Same as SECRETS_MODE=cli.
SECRETS_UI_BIND=127.0.0.1Bind the console to the server only.

Common tasks

change SMTP and push it live
$ secretsctl edit
$ secretsctl apply --secret external_smtp_default_user_client
check what is missing
$ secretsctl status     # configured vs empty, per secret
$ secretsctl validate   # exits 0 if everything is valid
fresh lab machine
$ secretsctl init
$ secretsctl generate --all
$ secretsctl apply --no-restart   # push without bouncing pods

Safety behaviour

No values in logsOnly secret names and status are recorded, never the values themselves.
Temp files locked downCreated owner-only and removed when the command exits.
Protected fieldsCannot be overwritten by save, the browser form or edit. Prior values are restored instead.
Namespace-boundSealed secrets are tied to both the secret name and its namespace, so a value cannot be moved elsewhere.
secretsctl get prints every secret in clear text. Only run it when you genuinely need the values, and never paste its output into a ticket, chat message or log.
MANIFEST_FILE, CONFIG_GPG, PLAIN_CONFIG, YQ_BIN and the KUBESEAL_* variables exist for testing and for pointing the tool at alternate files. Leave them unset for normal use.