Skip to content

Installing in an Air-Gapped Environment

Use this installation process when your cluster cannot reach the internet. You mirror Sovereign Home Cloud's images from Solace's registry into a registry inside your network, then install the chart with every image pointed at that registry. Once installed, Sovereign Home Cloud needs nothing from the internet to start, onboard datacenters, and create and upgrade event broker services.

How you move images and the chart across the air gap is up to you: a registry replication tool, an image mirroring tool such as crane or skopeo, or exported archives carried in. This page lists what to mirror and how to install from it.

Prerequisites

What Details
Private registry An OCI registry inside your network that the cluster nodes trust (its TLS chain installed on the nodes), holding the mirrored images and chart
Kubernetes cluster A StorageClass that provisions ReadWriteOnce volumes, an ingress controller already running in the cluster, and the capacity in Compute Resources
Workstation kubectl and helm 3, with network access to the private registry and the Kubernetes API
Event broker A Solace event broker for the control plane's own messaging, with a message VPN, a client username and a SEMP administrator, serving TLS with a valid certificate for its hostname. You need one before you install; to run one in Kubernetes, use the Solace Event Broker Operator Quick Start, and mirror its images too. Or use the chart's embedded broker, at your own risk.
CA certificate and key A CA, with its certificate and its private key, that signs your event broker services' certificates and that the control plane trusts. Every datacenter uses the same CA; see The CA Certificate.
Hostnames One each for the Cloud Console and the Ops User Interface (UI), and optionally one for the API, with DNS records pointing at your ingress controller's address
TLS certificate One certificate from your own PKI covering those hostnames
Data stores Recommended: your own PostgreSQL, OpenSearch, Redis-compatible cache and S3-compatible object store, meeting the requirements in Before You Begin. OpenSearch and the cache take only a hostname and port: they are used without credentials.

Plan Network Connectivity

Inbound

From To Port
Users' browsers The Cloud Console, Ops UI and API hostnames, through your ingress controller 443
Messaging applications Each event broker service's client ports; see Event Broker Service Exposure Per event broker service
Workstation The Kubernetes API and the private registry Your cluster's API port, and the registry's port
Cluster nodes The private registry The registry's port

Outbound

None. A few calls can still be attempted; none is needed, and blocking them breaks nothing. Before You Begin lists them.

Mirror the Images

You must mirror the following from Solace's registry, registry.solace.com/solace/home-cloud-control-plane/<image>, into your private registry, keeping each image's name and tag:

Image Used by Tag
home-cloud-control-plane The control plane Set by the chart version
maas-cloud-agent-k8s Each datacenter's agent Set by the chart version
solace-pubsub-enterprise Event broker services Every event broker version you create or upgrade event broker services with; see below
solace-datadog-agent The monitoring sidecar in every event broker service pod latest
busybox Maintenance jobs that run before an event broker service upgrade latest
postgres Bundled PostgreSQL Only if you bundle it
opensearch Bundled OpenSearch Only if you bundle it
valkey Bundled cache Only if you bundle it
chrislusf/seaweedfs Bundled object store Only if you bundle it

Mirror the chart too: oci://registry.solace.com/solace/home-cloud-control-plane/charts/home-cloud-control-plane, at the version you install.

To print the exact image references for your values, render the chart on a machine that can reach Solace's registry:

helm template home-cloud-control-plane oci://registry.solace.com/solace/home-cloud-control-plane/charts/home-cloud-control-plane --version <chart version> -f values.local.yaml \
  | grep -E '^\s+image:' | sort -u

The render does not include the event broker, sidecar and busybox images, because the datacenter agent pulls them only when it creates or upgrades an event broker service. Add them to your list yourself.

Event broker versions

Each Sovereign Home Cloud release offers a set of event broker versions. An event broker version's image tag is the version without its -<n> revision: for example, version 10.26.0.9054-18 uses solace-pubsub-enterprise:10.26.0.9054.

Mirror every version you create event broker services with, and every version you upgrade them to. If an image is missing, creating or upgrading an event broker service to that version fails with ImagePullBackOff.

Write Your Values File

Create one values file, for example values.local.yaml. It holds secrets, so keep it out of version control or encrypt it.

Point every image at your registry

Five values do this, and the chart refuses to install if only some of them are changed:

imageRegistry: <registry>
persistence-layer:
  postgresql:
    image:
      registry: <registry>
  seaweedfs:
    image:
      registry: <registry>
solace-cloud-ca:
  image:
    cloudAgent:
      repository: <registry>/maas-cloud-agent-k8s
  k8s:
    imageRepository: <registry>

global:
  imagePullSecrets:
    - <pull secret name>

The pull secret holds your private registry's credentials.

Identity and secrets

global:
  persistence:
    storageClassName: ""       # blank: the cluster's default StorageClass
    namespaceId: <prefix>      # always the same value as maasPrefix

maasPrefix: <prefix>           # names your stored data; fixed at installation

organization:
  operator:
    username: <Ops UI administrator email>
    password: <Ops UI administrator password>

secrets:
  values:
    VAULT_LOCAL_KEY: <64 hexadecimal characters>   # openssl rand -hex 32

Warning! Keep the encryption key. VAULT_LOCAL_KEY encrypts sensitive values in the database. Losing it loses every value encrypted under it, even if the database survives. Store a copy outside the cluster.

The Ops UI administrator defaults to admin@company.com with the password admin; set your own.

Event broker for the control plane

Use your own event broker, or one the chart deploys for you.

Give the connection details of the event broker you are running. broker.enabled stays false, its default.

ivmr:
  smfHost: tcps://broker.example.internal:55443
  mgmtHost: https://broker.example.internal:943
  msgVpn: <message VPN>
  username: <client username>
  mgmtUsername: <SEMP admin username>
secrets:
  values:
    EXTERNAL_IVMR_PASSWORD: <client password>
    EXTERNAL_IVMR_MGMT_PASSWORD: <SEMP admin password>

Every datacenter connects to this event broker at the smfHost address, so it must be reachable from the control plane and from every datacenter.

The event broker must present a valid TLS certificate: unexpired, with the smfHost and mgmtHost hostname in its subject alternative names, and signed by a CA the control plane trusts. Sign it with the CA from The CA Certificate, or add the CA that signed it under Other private CAs. Every other client of the broker, such as the Event Management Agents, must trust that CA too.

The chart deploys a single-node event broker in the release's namespace and sets up the control plane's connection to it. Leave every ivmr.* value unset: the chart refuses them alongside the embedded event broker. It generates the event broker's passwords and keeps them across upgrades. It runs the solace-pubsub-enterprise image at the tag the chart sets, so mirror that tag too.

broker:
  enabled: true
  networkPolicy:
    extraIngress:              # admits the datacenter namespaces you label
      - from:
          - namespaceSelector:
              matchLabels:
                solace.com/home-cloud-mca: "true"
        ports:
          - { protocol: TCP, port: 55555 }

Warning! Use it at your own risk. The embedded event broker has no redundancy, so it is down while its pod restarts, and monitoring it is up to you. It speaks plain text, without TLS, and only clients inside the cluster can reach it.

Only datacenters in the same cluster can use it. When you onboard each datacenter, label its namespace so the event broker's NetworkPolicy admits it, and give its agent the event broker's full in-cluster address; see step 5.

This is an installation-time choice. Moving the control plane to another event broker later, including from the embedded event broker to your own, is a reinstall, not an upgrade.

Hostnames and TLS

ingress:
  enabled: true
  className: <ingress class>       # blank: the cluster's default IngressClass
  consoleHost: console.example.internal
  opsHost: ops.example.internal
  apiHost: api.example.internal    # optional
  tls:
    - secretName: home-cloud-control-plane-tls
      hosts: [console.example.internal, ops.example.internal, api.example.internal]

Every hostname must be covered by the certificate. Renewing it is your responsibility.

Your own data stores

For each data store you run yourself, turn off the bundled one and give its endpoint:

persistence-layer:
  postgresql:
    enabled: false
  seaweedfs:
    enabled: false
dataLayer:
  opensearch:
    enabled: false
  redis:
    enabled: false
  external:
    postgresHost: pg.example.internal
    postgresPort: 5432
    postgresUsername: hosted_fleet
    opensearchHost: search.example.internal
    opensearchPort: 443
    opensearchProtocol: https
    redisHost: cache.example.internal
    redisPort: 6379
objectStorage:
  enabled: false
  bucket: <bucket>
  region: <region>
  external:
    endpoint: https://s3.example.internal
    forcePathStyle: true
secrets:
  values:
    HOSTED_FLEET_POSTGRES_PASSWORD: <password>
    HOSTED_FLEET_S3_ACCESS_KEY: <access key>
    HOSTED_FLEET_S3_SECRET_KEY: <secret key>

OpenSearch and the cache are used without credentials, so restrict access to them by network. Installing for Production has the details of each block.

No datacenter or organization at installation

The installation creates no datacenter and no Cloud Console organization. After you install, the Ops UI administrator creates the organizations and their users (Administering with the Ops UI), then onboards each datacenter (Onboarding a Datacenter). Point each datacenter's event broker images at your private registry when you do.

The CA Certificate

One CA serves the whole installation: each datacenter's agent signs event broker service certificates with it, so it needs the CA's certificate and private key, and the control plane trusts it, so it needs only the certificate.

The CA must use an RSA key, be marked CA:TRUE, and have at least seven days of validity left. Use an intermediate CA dedicated to event broker services, not your root.

  1. Get the CA's certificate as ca.crt and its private key as ca.key, in PKCS#8 format.

    To use an existing CA, export its certificate, followed by its chain, and its private key.

    To create a new CA instead:

    openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
      -subj "/CN=Broker Issuing CA" \
      -addext "basicConstraints=critical,CA:TRUE" \
      -addext "keyUsage=critical,keyCertSign,cRLSign" \
      -keyout ca.key -out ca.crt
    

    This writes the key in PKCS#8 format and a certificate valid for 10 years (-days 3650). Event broker service certificates never outlive the CA, so plan to replace it before then.

  2. Encrypt the key. This is optional and recommended: anyone who has ca.key can issue certificates your clients trust.

    openssl pkcs8 -topk8 -v2 aes-256-cbc -in ca.key -out ca.enc.key -passout pass:"$PASSPHRASE"
    
  3. Create the Secret, after the namespace exists (see Deploy):

    kubectl create secret generic broker-issuing-ca -n home-cloud-control-plane \
      --from-file=ca.crt=ca.crt \
      --from-file=ca.key=ca.enc.key \
      --from-file=passphrase=<(printf '%s' "$PASSPHRASE")
    

    For an unencrypted key, use --from-file=ca.key=ca.key and leave out passphrase.

  4. Add to your values file, so the control plane trusts only the certificate:

    composite:
      trustedCA:
        existingSecret: broker-issuing-ca
        keys: [ca.crt]
    

If your data stores or your event broker service present certificates from another private CA, add it under composite.trustedCA.certificates; see Other private CAs.

Deploy

  1. Create the namespace, the pull secret for your private registry, the TLS Secret and the CA Secret:

    kubectl create namespace home-cloud-control-plane
    kubectl create secret docker-registry <pull secret name> -n home-cloud-control-plane \
      --docker-server=<registry> --docker-username=<username> --docker-password=<password>
    kubectl create secret tls home-cloud-control-plane-tls -n home-cloud-control-plane \
      --cert=<chain.pem> --key=<key.pem>
    
  2. Check the values against the cluster without installing anything:

    helm install home-cloud-control-plane <chart in your registry> --version <chart version> -n home-cloud-control-plane \
      -f values.local.yaml --dry-run=server
    
  3. Install:

    helm install home-cloud-control-plane <chart in your registry> --version <chart version> -n home-cloud-control-plane \
      -f values.local.yaml --wait --timeout 30m
    

    The installation waits for the control plane's first start, which can take several minutes.

Verify the Deployment

  1. Every pod is running, and every image comes from your registry:

    kubectl get pods -n home-cloud-control-plane
    kubectl get pods -n home-cloud-control-plane -o jsonpath='{..image}' | tr ' ' '\n' | sort -u
    
  2. Sign in to the Ops UI at its hostname as the Ops UI administrator.

An ImagePullBackOff names the missing image. Either it was not mirrored, or one of the five registry values still points elsewhere.

Next Steps