InstallCluster
TLS Certificate
NOTE

If you are currently installing the single-node Cluster as shown in the quick installation guide (read more here), it is easier and more recommended to stick to the post-installation guide there as shown here.

The Cluster requires a main TLS certificate, issued by a public certificate authority such as Let's Encrypt, to serve the Cluster's public Services (read more about public BeyondCorp Services here) and anonymous Services (read more here) over the internet. Such Services include the Cluster's own Services such as the API Server and the AuthServer. Therefore, you should issue and set the Cluster TLS certificate as soon as you install the Cluster to begin using octelium and octeliumctl commands, and log in via the web portal of the AuthServer.

NOTE

The Cluster installs an initial self-signed TLS certificate during the Cluster installation. You can use the octelium and octeliumctl commands before setting your real Cluster certificate, issued by a real CA such as Let's Encrypt, by setting OCTELIUM_INSECURE_TLS or OCTELIUM_DEV environment variables to true before using the octelium or octeliumctl commands.

Regardless of the certificate authority you use or the method you use to issue the TLS certificate, you will need to provide the issued certificate to the Cluster through a Kubernetes TLS secret with the name cert-cluster in the Kubernetes namespace octelium as shown in detail here.

Cluster Domain Certificate

The Cluster certificate needs to include the following domains in the SAN list:

  1. The Cluster domain <DOMAIN>.
  2. The wildcard domain *.<DOMAIN>.
  3. The wildcard domains *.local.<DOMAIN> and *.default.local.<DOMAIN>.

Issuing the Certificate

There is no one canonical way to issue your Cluster certificate by a certificate authority. You can use Let's Encrypt via Certbot, for example, to issue a certificate for your Cluster domain for free.

Certbot

Here is an example of issuing the certificate using the certbot CLI tool via a DNS challenge:

sudo certbot certonly --email <YOUR_EMAIL> --agree-tos --cert-name <DOMAIN> -d "<DOMAIN>,*.<DOMAIN>,*.local.<DOMAIN>" --manual --preferred-challenges dns
# Your certificate is stored by default in /etc/letsencrypt/live/<DOMAIN>/

cert-manager

In a production environment, it is recommended to automate the process of issuing and rotating the Cluster certificate. You can also use a Kubernetes-based open source solution such as cert-manager. The following example shows the ClusterIssuer and Certificate cert-manager resources needed for a certificate that uses Let's Encrypt and Cloudflare.

The ClusterIssuer should look as follows:

1
apiVersion: cert-manager.io/v1
2
kind: ClusterIssuer
3
metadata:
4
name: letsencrypt-cloudflare
5
spec:
6
acme:
7
server: https://acme-v02.api.letsencrypt.org/directory
8
email: contact-acme@<DOMAIN>.com
9
privateKeySecretRef:
10
name: letsencrypt-cloudflare-account
11
solvers:
12
- dns01:
13
cloudflare:
14
email: cloudflare-account@<DOMAIN>
15
apiTokenSecretRef:
16
name: cloudflare-api-token-secret
17
key: api-key
18
selector: {}

The Certificate should look like this:

1
apiVersion: cert-manager.io/v1
2
kind: Certificate
3
metadata:
4
name: octelium-cluster
5
namespace: octelium
6
spec:
7
secretName: cert-cluster
8
issuerRef:
9
name: letsencrypt-cloudflare
10
kind: ClusterIssuer
11
commonName: <DOMAIN>
12
dnsNames:
13
- <DOMAIN>
14
- '*.<DOMAIN>'
15
- '*.local.<DOMAIN>'

Manually Setting the Certificate

Once you issue the certificate, you can manually provide it to the Cluster by creating a Kubernetes secret with the name cert-cluster in the namespace octelium. You can use the kubectl create secret tls command as follows:

kubectl create secret tls cert-cluster -n octelium --key </PATH/TO/PRIVATE_KEY.PEM> --cert </PATH/TO/CERT_CHAIN.PEM>

Alternatively, you can use the octops cert command to provide the same functionality as the kubectl create/update secret tls command above as follows:

octops cert <DOMAIN> --key </PATH/TO/PRIVATE_KEY.PEM> --cert </PATH/TO/CERT_CHAIN.PEM> --kubeconfig </PATH/TO/KUBECONFIG>

The Cluster watches for that specific Kubernetes secret and once it is created or updated, it is synchronized into an Octelium Secret resource.

Namespace Certificates

As shown above, the Cluster TLS certificate only serves for direct subdomains of the Cluster domain. This makes it only useful for Services belonging to the default Namespace (read more about Namespaces here). If you want to enable public/BeyondCorp access (i.e. via isPublic) or/and just TLS over the client-based access (i.e. isTLS field), you will have to issue a TLS certificate that uses the wildcard domains *.<NAMESPACE>.local.<DOMAIN> and *.<NAMESPACE>.<DOMAIN>. You can set/rotate a Namespace certificate via the octops cert command via --namespace field. For example, if the Namespace is production, then the octops cert command is used as follows:

octops cert <DOMAIN> --key </PATH/TO/PRIVATE_KEY.PEM> --cert </PATH/TO/CERT_CHAIN.PEM> --kubeconfig </PATH/TO/KUBECONFIG> --namespace production

You can also directly use Kubernetes commands (e.g. kubectl create secret) or via the SDKs. The name of the Kubernetes secret needs to be cert-ns-<NAMESPACE>. For example, if the Namespace is production, then the kubectl create secret command is used as follows:

kubectl create secret tls cert-ns-production -n octelium --key </PATH/TO/PRIVATE_KEY.PEM> --cert </PATH/TO/CERT_CHAIN.PEM>
© 2025 octelium.comOctelium Labs, LLCAll rights reserved
Octelium and Octelium logo are trademarks of Octelium Labs, LLC.
WireGuard is a registered trademark of Jason A. Donenfeld