Automate the creation and deployment of ugly websites, so you don’t need to ask your cousin.
Demo project for Codemotion Milan 2025 Speech: "The operator's mindset: customize Kubernetes for your applications"
Kubernetes is super extensible, letting you bend it to your will (or at least to your app’s needs) by extending its APIs with Custom Resource Definitions (CRDs) and custom controllers.
The Ugly Website Operator is a tongue-in-cheek example showing how to make Kubernetes do something truly important: automate the build and deployment of gloriously ugly static websites. Because why settle for beautiful, when you can have blinking marquees, and eye-searing backgrounds? 🤩💥
This project is here to help developers and platform engineers learn:
- 📦 How to define and use Kubernetes CRDs.
- 🤖 How to build and deploy a custom operator.
- ⚙️How to automate application-specific workflows on Kubernetes.
- 😱 How to make your friends and colleagues groan at your design choices.
- 🎛️ CRD: Defines a custom resource for
Websiteso you can declaratively configure each ugly website (no design skills required). - 🚀 Operator: Watches for
Websiteresources and automates the creation and deployment of your masterpiece. - ✅ Webhook: Validates the applied
Websiteresources (so your ugly sites are at least valid ugly).
To proceed with this guide, you’ll need the following on your local machine:
To install the operator, you’ll need a Kubernetes cluster.
- ☁️ Spin up a Kubernetes cluster in no time with Aruba Cloud’s managed service. Pass by the Aruba Stand at Codemotion Milan 2025 (September 14–15) to get some free credits!
- 💻 Or spin up a local cluster with Kind
Ugly Website Operator requires cert-manager for automatic TLS certificate provisioning.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yamlWait for cert-manager pods to be ready:
kubectl -n cert-manager get podsIf you don’t have one, you might want to install an ingress controller to expose the (ugly) websites created with this operator.
For example, you can install the HAProxy ingress controller:
-
Add the HAProxy Technologies Helm repository:
helm repo add haproxytech https://haproxytech.github.io/helm-charts
-
Update your list of Helm charts:
helm repo update
-
Install the latest version of the ingress controller:
helm install haproxy-kubernetes-ingress haproxytech/kubernetes-ingress \ --create-namespace \ --namespace haproxy-controller
- Clone this repository:
git clone https://github.com/ArubaKube/ugly-websites-operator.git- Install the Helm chart on your cluster:
helm install website-operator ./ugly-websites-operator/dist/chart \
--create-namespace \
--namespace website-operatorCreate a YAML file (e.g., my-ugly-website.yaml):
apiVersion: webapp.arubakube.cloud/v1
kind: Website
metadata:
name: website-sample
spec:
features:
hurtingEyesBg: true
jokes: false
marquee: true
morningGifs: true
ingress:
enabled: true
host: my-website.local
path: /
replicas: 1
textContent: Welcome to my ugly website!
title: My Ugly WebsiteApply it:
kubectl apply -f my-ugly-website.yamlThe operator will provision the website and configure an ingress exposing the website under my-website.local. Add it to your /etc/hosts file and brace yourself for the design. 🕶️
No ingress? No problem! Use port-forwarding to see your creation:
kubectl port-forward services/website-sample 8080:80Now open http://localhost:8080 from your browser and enjoy the horror. 👀
dist/chart/- Helm chart for deploying the operator and CRDsconfig/- Kubernetes manifests and CRD definitionscmd/- Operator entrypointpkg/- Operator logic and controllers
Contributions are very welcome-help us make the websites even uglier! Add new features, new themes, or just more ways to make designers cry. 🎨😭
To contribute:
- Fork the repository
- Create your feature branch (
git checkout -b feature/my-feature) - Commit your changes (
git commit -am 'Add new feature') - Push to the branch (
git push origin feature/my-feature) - Open a pull request
You can change the Website resource by editing the struct definitions under api/v1/website_types.go. Once you make changes, regenerate the manifests by running:
make manifestsYou can run the test suite with:
make test