Skip to main content

Try Holos Locally

This guide walks through the process of building and managing a software development platform with Holos. The k3d platform built in this guide is a slimmed down version of the larger, more holistic, Holos reference platform.

Holos is different from existing tools in a few important ways.

  1. Holos provides a unified configuration model purpose built to improve on unmodified Helm charts, Kustomize bases, or anything else that produces structured configuration data.
  2. Holos all but eliminates the need to template yaml, a common source of frustration and errors in production.
  3. Holos platforms are composable and have breadth. The toolchain and techniques scale down to one machine and up to multiple clusters across multiple regions.
  4. The unified configuration model is well suited to a Zero Trust security model. Platform wide policy configuration is easier to manage with Holos.

This guide assumes commands are run locally. Capitalized terms have specific definitions described in the Glossary.

What you'll need

You'll need the following tools installed to complete this guide.

  1. holos - to build the platform.
  2. helm - to render Holos components that wrap upstream Helm charts.
  3. k3d - to provide a k8s api server.
  4. OrbStack or Docker - to use k3d.
  5. kubectl - to interact with the k8s api server.
  6. mkcert - to make trusted TLS certificates.
  7. jq - to fiddle with JSON output.
note

Registering an account is recommended to try out proper authentication and authorization in Holos, but you can complete this guide without signing up.

Goal

By the end of this guide you'll have built the foundation of a software development platform. The foundation provides Zero Trust security by holistically integrating off-the-shelf open source software.

  1. Istio is configured to authenticate and authorize requests using an OIDC ID-Token issued by ZITADEL before requests reach backend services.
  2. The platform provides single sign-on and role based access control for all services running on the platform.

This guide strives to keep things neat and tidy. All of the resources are located in one k3d cluster and one local Git repository. If you want to clean up at any point, do so with:

k3d cluster delete workload
rm -rf holos-k3d

Sign In or Out

Holos provides integrated authentication and authorization which we'll use in this guide to protect a service. We recommend registering an account to see this in action. Registration also enables you to explore the customizable web form that simplifies complex configuration.

If you opt-out, the platform will be configured to use a fake identity in place of real id tokens.

holos register user

Create the Platform

A server-side platform resource in Holos stores the web form used to simplify platform wide configuration.

First, initialize an empty Git repository:

mkdir holos-k3d
cd holos-k3d
git init

Use holos to make the rpc call to create the server-side platform resource.

holos create platform --name k3d --display-name "Try Holos Locally"

Generate the Platform

Generate the platform code in the repository root.

holos generate platform k3d

Commit the generated platform config to the repository.

git add .
git commit -m "holos generate platform k3d - $(holos --version)"

Push the Platform Form

Each Holos platform has a Platform Form used to submit top level, platform-wide configuration values. The purpose of the form is to validate configuration values and simplify complicated configurations and integrations.

Push the Platform Form to publish it. Browse to the printed URL to view the form.

holos push platform form .

The Platform Form is defined locally in forms/platform/platform-form.cue.

On the web it looks like: Platform Form Default Values

Update the Platform Model

Holos needs initial, top level configuration values to render the platform. The Platform Model is the term we use for these values. In this section you will configure role based access control by way of updating the Platform Model.

In the k3d platform you're building now, role based access control is implemented by asserting against the oidc id token subject. Update the form with the sub claim value from your id token. This will ensure only you have access to platform services.

Copy and paste the sub value into your Platform Form's Subject field.

holos login --print-claims --log-level=error | jq -r .sub

After pasting the sub value, click Submit on the form.

Pull the Platform Model

The Platform Model needs to be pulled into the local Git repository after the form has been submitted. Next, we'll run holos render which operates exclusively on local files.

Holos stores the Platform Model in the platform.config.json file. Holos provides this file as input to CUE when rendering the platform. This file is intended to be added to version control.

Pull the updated Platform Model into the local repository.

holos pull platform model .
git add platform.config.json
git commit -m "Add platform model"

Render the Platform

Holos has everything necessary to render the platform once the platform.config.json file and the code from holos generate are in the current directory.

Rendering a platform is the process of iterating over each platform component and rendering it into plain yaml. Holos does not apply the resulting manifests. Other tools like kubectl, ArgoCD, or Flux are responsible for applying the manifests.

holos render platform ./platform

The render command writes the manifest files to the deploy/ directory. Commit the files so they can be applied via GitOps later.

git add deploy
git commit -m "holos render platform ./platform"
Don't blink, this is where Holos builds the platform

It usually takes no more than a few seconds.

Rendering the holos reference platform currently results in about 500K lines of yaml. In contrast, roughly 80K lines are produced by this slimmed down k3d platform.

We mention this because the scale doesn't matter as much as it does with other tools. Manage millions of lines of configuration with Holos the same way this guide manages thousands. This is made possible by the unique way CUE unifies all configuration into one single model.

Configure DNS

Configure your machine to resolve *.holos.localhost to your loopback interface. This is necessary for requests to reach the workload cluster.

Cache sudo credentials.

Admin access is necessary to setup a local dnsmasq instance and configure macOS's DNS resolver.

sudo -v

Resolve *.holos.localhost DNS queries to 127.0.0.1.

bash ./scripts/local-dns

Create the Cluster

The Workload Cluster is where your applications and services will be deployed. In production this is usually an EKS, GKE, or AKS cluster.

tip

Holos supports all compliant Kubernetes clusters. Holos was developed and tested on GKE, EKS, Talos, k3s, and Kubeadm clusters.

Use this command when exploring Holos.

k3d cluster create workload \
--port "443:443@loadbalancer" \
--k3s-arg "--disable=traefik@server:0"

Traefik is disabled because Istio provides the same functionality.

Apply the Platform Components

Use kubectl to apply each platform component. In production, it's common to fully automate this process with ArgoCD, but we use kubectl to the same effect.

Local CA

Holos platforms use cert manager to issue tls certificates. The browser and tools we're using need to trust these certificates to work together.

Admin access is necessary for mkcert to manage the certificate into your trust stores.

sudo -v

Manage the local CA and copy the CA key to the workload cluster so that cert manager can manage trusted certificates.

bash ./scripts/local-ca
warning

Take care to run the local-ca script each time you create the workload cluster so that Certificates are issued correctly.

Service Mesh

The platform service mesh provides an ingress gateway and connectivity useful for observability, reliability, and security.

Namespaces

With Holos, components are automatically added to the namespaces component, useful for centrally managed policies.

kubectl apply --server-side=true -f ./deploy/clusters/workload/components/namespaces

Custom Resource Definitions

kubectl apply --server-side=true -f ./deploy/clusters/workload/components/gateway-api
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istio-base

Cert Manager

Apply the cert-manager controller.

kubectl apply --server-side=true -f ./deploy/clusters/workload/components/cert-manager

Apply the ClusterIssuer which issues Certificate resources using the local certificate authority.

kubectl -n cert-manager wait pod -l app.kubernetes.io/component=webhook --for=condition=Ready
kubectl apply --server-side=true -f deploy/clusters/workload/components/local-ca
kubectl apply --server-side=true -f deploy/clusters/workload/components/certificates
kubectl -n istio-gateways wait certificate httpbin.holos.localhost --for=condition=Ready
warning

The certificate will time out before becoming ready if the local-ca script was not run after the cluster was created.

Istio

Istio implements the Service Mesh.

kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istio-cni
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istiod
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/gateway

Verify the Gateway is programmed and the listeners have been accepted:

kubectl -n istio-gateways wait gateway default --for=condition=Accepted

httpbin

httpbin is a simple backend service useful for end-to-end testing.

kubectl apply --server-side=true -f deploy/clusters/workload/components/httpbin-backend
kubectl apply --server-side=true -f deploy/clusters/workload/components/httpbin-routes
kubectl -n holos-system wait pod -l app.kubernetes.io/instance=httpbin --for=condition=Ready
info

Browse to https://httpbin.holos.localhost/ to verify end to end connectivity. You should see the httpbin index page.

Authenticating Proxy

The auth proxy is responsible for authenticating browser requests, handling the oidc authentication flow, and providing a signed id token to the rest of the services in the mesh.

The auth proxy stores session information in an encrypted cookie. Generate a random cookie encryption Secret and apply.

LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom \
| head -c 32 \
| kubectl create secret generic "authproxy" \
--from-file=cookiesecret=/dev/stdin \
--dry-run=client -o yaml \
| kubectl apply -n istio-gateways -f-

Deployment

The auth proxy Deployment receives requests from web browsers and responds with an authentication decision.

kubectl apply --server-side=true -f deploy/clusters/workload/components/authproxy
kubectl apply --server-side=true -f deploy/clusters/workload/components/authroutes
info

Verify authentication is working by browsing to https://httpbin.holos.localhost/holos/authproxy.

We want a simple Authenticated response.

tip

You may need to refresh the page a few times while the platform configures itself.

Istio will respond with no healthy upstream until the pod becomes ready. Wait for the pod to become ready with:

kubectl -n holos-system wait pod -l app.kubernetes.io/instance=httpbin --for=condition=Ready

Once authenticated, visit https://httpbin.holos.localhost/holos/authproxy/userinfo which returns a subset of claims from your id token.

warning

If you get Unauthorized instead of a json response body, make sure you authenticated first.

{
"user": "275552236589843464",
"email": "demo@holos.run",
"preferredUsername": "demo"
}

Authorization Policy

Configure authorization policies using attributes of the authenticated request. Authorization policies route web requests through the auth proxy and then validate all requests against the x-oidc-id-token header.

kubectl apply --server-side=true -f deploy/clusters/workload/components/authpolicy

Istio make take a few seconds to program the Gateway with the AuthorizationPolicy resources.

Try out Zero Trust

A basic Zero Trust security model is now in place. The platform authenticates and authorizes requests before they reach the backend service.

Browser

The platform has been configured to authorize requests with a x-oidc-id-token header.

  1. Verify authentication is working by browsing to https://httpbin.holos.localhost/dump/request.
    • Refresh the page a few times.
    • The httpbin backend pods should echo back the x-oidc-id-token header injected by the auth proxy.
  2. Note the x-oidc-id-token header is not sent by your browser but is received by the backend service.
    • This design reduces the risk of exposing id tokens in the browser.
    • Browser request size remains constant as more claims are added to id tokens.
    • Reliability improves because id tokens often overflow request header buffers when they pass through middle boxes across the internet.

Command Line

Verify unauthenticated requests are blocked by default outside the browser.

curl -I https://httpbin.holos.localhost/dump/request

You should receive a HTTP/2 302 response that redirects to location: https://login.holos.run to start the oauth login flow.

Next, verify authenticated requests are allowed.

The platform is configured to authenticate the id token present in the x-oidc-id-token header.

💡 It also works with grpcurl.

curl -H x-oidc-id-token:$(holos token) https://httpbin.holos.localhost/dump/request

You should receive a response showing the request headers the backend received.

tip

Note how the platform secures both web browser and command line api access to the backend httpbin service. httpbin itself has no authentication or authorization functionality.

Summary

Thank you for taking the time to try out Holos. In this guide, you built the foundation of a software development platform that:

  1. Provides a unified configuration model with CUE that
    • Supports unmodified Helm Charts, Kustomize Kustomizations, plain YAML.
    • Provides a web form to pass top level parameters.
  2. Reduces errors by eliminating the need to template unstructured text.
  3. Is composable and scales down to a local machine.
  4. Provides an way to safely configure broad authentication and authorization policy.

Next Steps

Dive deeper with the following resources that build on the foundation you have now.

  1. Explore the Rendering Process in Holos.
  2. Dive deeper into the Platform Manifests rendered in this guide.
  3. Deploy ArgoCD onto the foundation you built.
  4. Deploy Backstage as a portal to the integrated platform components.

Clean-Up

If you'd like to clean up the resources you created in this guide, remove them with:

k3d cluster delete workload
rm -rf holos-k3d