Install
Install Harthelm with Helm: minimal values, first sign-in and the health check.
This is the generic install: a bundled database, an Ingress controller and cert-manager. The tracks for on-premises, EKS, AKS and GKE say which pieces of each platform to use; the steps here stay the same.
Before you start
- The cluster meets the requirements and you are cluster admin.
helm,kubectlandopensslon your machine, andhartfor the last step.- The licence file you received with Harthelm, or a trial licence; see Licence.
- Replace these names everywhere below:
| Name | Stands for |
|---|---|
console.example.com | the console host |
example.net | the workspace domain; it must be a different registrable domain from the console's |
public | your IngressClass |
letsencrypt-dns | a cert-manager ClusterIssuer that can solve DNS-01 for both names |
letsencrypt-http | an issuer for your users' custom domains, for example HTTP-01 |
https://id.example.com/ | your OIDC issuer |
10.0.0.0/16 | the addresses of your ingress controller's pods |
<your registry>, <version> | where you got the chart, and the release, for example 1.0.2 |
Install the operators
Install cert-manager and the CloudNativePG operator with their own charts. Put the operator into cnpg-system, which
networkPolicy.cnpgNamespaceSelector expects.
Point DNS at the ingress
Create records for console.example.com and *.example.net that resolve to your Ingress controller's load balancer.
DNS and TLS has the details.
Create the sign-in client
At your OIDC provider, create a confidential client with:
- redirect URI
https://console.example.com/auth/oidc/callback; - the scopes
openid profile email groups; - a group, for example
harthelm-admins, for the people who administer Harthelm.
Then store its id and secret:
kubectl create namespace harthelm-system
kubectl label namespace harthelm-system pod-security.kubernetes.io/enforce=restricted
kubectl -n harthelm-system create secret generic harthelm-oidc \
--from-literal=clientID=<client id> --from-literal=clientSecret=<client secret>Provider notes are in Sign-in.
Create the master key
The master key encrypts every stored token and secret: a restored database is useless without it. Core generates one on first start unless you bring your own; create it yourself so it is in your secret store from the start:
kubectl -n harthelm-system create secret generic harthelm-master-key \
--from-literal=active=k1 --from-literal=key.k1="$(openssl rand -base64 32)"With masterKey.existingSecret set, core refuses to generate another one. Keep a copy outside the cluster.
Store the licence
Every installation needs a licence; without one it starts restricted and refuses new teams and workspaces. Put the file into a Secret:
kubectl -n harthelm-system create secret generic harthelm-license --from-file=license=company.licenseThe values below name it. The preflight checks it with the keys of the release you install. You can also install the
licence later in the console or with hart; Licence has the three ways. A licence that
names an installation needs its id first: see Order of a fresh install.
Write the values
platform:
host: console.example.com
workspaceDomain: example.net
# The ingress controller's pods, so limits and audit rows see the real client address.
trustedProxies: [10.0.0.0/16]
routing:
edge: ingress
ingress:
className: public
tls:
certManager:
enabled: true
issuerRef: {name: letsencrypt-dns, kind: ClusterIssuer, group: cert-manager.io}
oidc:
issuer: https://id.example.com/
displayName: Example ID # the button says "Sign in with Example ID"
adminGroup: harthelm-admins # members are cluster admins of Harthelm
existingSecret: harthelm-oidc
masterKey:
existingSecret: harthelm-master-key
license:
existingSecret: harthelm-license
storage:
class: "" # the default StorageClass
mode: auto
customDomains:
cnameTarget: edge.example.net # resolves to your ingress; users CNAME their domains to it
issuer: {name: letsencrypt-http, kind: ClusterIssuer, group: cert-manager.io}
backup:
enabled: true
workspaces:
enabled: trueEvery key is in the chart values reference. The schema is strict: an unknown key or a missing required value fails the render.
Render, then install
helm template harthelm oci://<your registry>/charts/harthelm --version <version> \
-n harthelm-system -f my-values.yaml > /dev/null
helm install harthelm oci://<your registry>/charts/harthelm --version <version> \
-n harthelm-system -f my-values.yamlThe preflight Job runs first and fails the install with a list of what is missing: an operator, a Secret, a StorageClass, an issuer, a licence this release accepts. Read it with:
kubectl -n harthelm-system logs job/harthelm-preflightThen the database comes up, core migrates it (it has up to 5 minutes at the first start) and the routers start.
Prove the network policies
helm test harthelm -n harthelm-systemA probe checks that the NetworkPolicies are enforced, port ranges included. It fails when they are not. Run it again after every CNI change.
Sign in
Open https://console.example.com and click Sign in with Example ID as a member of harthelm-admins.
Every installation starts with the organization Default and its team Default (tenancy.defaultOrg,
tenancy.defaultTeam). From here, Team administration shows how to create
organizations and teams and invite people.
Check the installation
Sign in with hart as a cluster admin and run the doctor:
hart login --api https://console.example.com
hart admin doctor --capabilitiesEvery check should pass, the last one, license, included; Troubleshooting explains
each one. The console shows what the cluster offers under Platform → Capabilities and, since 1.5.0,
runs the checks themselves under Platform → Doctor
(The Doctor page).
From Harthelm 1.2 on, hart smoke then walks the path a user takes, end to end: it creates a scratch workspace in a
team, writes a small app into it, sets an env var, runs Sync, prepare and Run, waits until the app answers on the
workspace's dev URL, and deletes the workspace again (purged with a team admin's key):
hart smoke --team 1It passes in well under a minute, needs nothing from the internet, and a member with the Developer role may run it
too. A failure names the step that failed; --keep leaves the workspace for a look and -o json prints every step.
Then create a first workspace as a test user with the Quickstart.
Order of a fresh install
A licence bound to an installation names the installation's id, and core creates that id at its first start. A fresh installation therefore runs restricted from its first minute (there is no grace period for it), and a restricted installation refuses the first sign-in of a person it has not seen. The order that works:
-
Install without the licence Secret. Leave
license.existingSecretout of the values: with it set, the preflight refuses a missing Secret and stops the install. The database and core start and the console answers; the doctor'slicensecheck fails with the sentence that says why and names the installation id. That is expected. -
Read the installation id. Since 1.5, core logs it at
INFOon every start while no licence is in force:Terminal kubectl -n harthelm-system logs deploy/harthelm-core -c core | grep "no licence installed" # no licence installed; installation id 0b9e4c6a-3f1d-4a8e-9c2b-7d5e1f0a6b3c; see docs/license.mdThe chart's notes print the same command while
license.existingSecretis not set: afterhelm installandhelm upgrade, and again withhelm status harthelm(Argo CD does not show chart notes).hart admin licenseshows the id asInstallation:to a signed-in cluster admin, which on a fresh install is the break-glass administrator (below). Send the id with your order: asaasorinternallicence names it. A licence that names no installation needs no id and can go in with the first sync. -
Install the licence. Create the Secret
harthelm-license(Store the licence) and setlicense.existingSecret: harthelm-license; that is the second sync (helm upgrade, or the Argo CD sync of the values commit), and core reads the Secret within a minute without a restart. Or sign in with the break-glass account and runhart admin license install -f company.license, or paste the file in the console. -
Sign in through OIDC, as in Sign in.
Break-glass is the bootstrap path. The licence never refuses the break-glass administrator. With
auth.breakGlass enabled at the first sync, a restricted
installation can be signed in to at once: no id is needed to get in, and the licence can be installed through hart
or the console without a second sync. Keep the account afterwards as the way in when the OIDC provider is down. Without
it nobody can sign in before the licence is installed, not even an admin who has never signed in before. See
Licence.
Optional values
| Topic | Values | Page |
|---|---|---|
| Workspaces from Git | git.providers | Git providers |
| Invitation mails | mail | |
| Workspace and service sizes | plans | Workspaces |
| The default team quota | teams.quota | Team administration |
| Where pods run | scheduling | Workspaces |
| Emergency access | auth.breakGlass | Sign-in |