Get started with the Nebari Operator in 5 minutes. This guide walks you through setting up a local development environment and deploying your first application.
- Docker
- kubectl
- make
- Kind (for local development)
Use the automated development setup to create a fully configured cluster:
cd dev
make setupThis command:
- Creates a Kind cluster (
nebari-operator-dev) with MetalLB - Installs Envoy Gateway v1.2.4
- Installs cert-manager v1.16.2 with Gateway API support
- Creates a shared Gateway (
nebari-gateway) with HTTP/HTTPS listeners - Provisions a wildcard TLS certificate for
*.nebari.local - Optionally installs Keycloak for authentication testing
Verify the environment is ready:
make statusExpected output:
✅ Cluster 'nebari-operator-dev' exists
Checking services...
...
Gateway API resources:
NAMESPACE NAME CLASS ADDRESS PROGRAMMED AGE
envoy-gateway-system nebari-gateway envoy-gateway 172.18.255.200 True 1m
From the repository root, build and deploy the operator:
# Return to root directory
cd ..
# Build the operator image
make docker-build IMG=quay.io/nebari/nebari-operator:dev
# Load image into Kind cluster
kind load docker-image quay.io/nebari/nebari-operator:dev --name nebari-operator-dev
# Install CRDs
make install
# Deploy operator to cluster
make deploy IMG=quay.io/nebari/nebari-operator:devVerify the operator is running:
kubectl get pods -n nebari-operator-system
# Expected output:
# NAME READY STATUS RESTARTS AGE
# nebari-operator-controller-manager-xxxxxxxxxx-xxxxx 2/2 Running 0 30sCreate a namespace and deploy a simple test application:
kubectl create namespace demo
kubectl label namespace demo nebari.dev/managed=true
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-app
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: hashicorp/http-echo
args:
- "-text=Hello from Nebari Operator!"
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: hello-service
namespace: demo
spec:
selector:
app: hello
ports:
- port: 80
targetPort: 5678
EOFCreate a NebariApp to expose your service:
kubectl apply -f - <<EOF
apiVersion: reconcilers.nebari.dev/v1
kind: NebariApp
metadata:
name: hello-app
namespace: demo
spec:
hostname: hello.nebari.local
service:
name: hello-service
port: 80
routing:
tls:
enabled: true
EOFCheck the NebariApp status:
kubectl get nebariapp -n demo
kubectl describe nebariapp hello-app -n demoYou should see conditions indicating success:
Ready=TrueRoutingReady=True
Verify the HTTPRoute was created:
kubectl get httproute -n demoThe dev setup automatically configures /etc/hosts entries for *.nebari.local. Test your application:
curl http://hello.nebari.localcurl -k https://hello.nebari.localExpected output:
Hello from Nebari Operator!
Note: The
-kflag skips certificate validation since we're using self-signed certificates in development.
Add authentication to your application with Keycloak:
kubectl apply -f - <<EOF
apiVersion: reconcilers.nebari.dev/v1
kind: NebariApp
metadata:
name: hello-app
namespace: demo
spec:
hostname: hello.nebari.local
service:
name: hello-service
port: 80
routing:
tls:
enabled: true
auth:
enabled: true
provider: keycloak
provisionClient: true
scopes:
- openid
- profile
- email
EOFAccess your application - you'll be redirected to Keycloak for authentication:
open https://hello.nebari.localDefault Keycloak credentials:
- Username:
admin - Password:
admin
Problem: Gateway shows ADDRESS: <none>
Solution:
cd dev
make cluster-create # Recreates cluster with MetalLBProblem: TLS not working, certificate shows Ready: False
Solution:
kubectl get certificate -n envoy-gateway-system
kubectl describe certificate nebari-gateway-cert -n envoy-gateway-system
# Force certificate renewal
kubectl delete certificate nebari-gateway-cert -n envoy-gateway-system
cd dev && make services-installProblem: NebariApp shows ServiceNotFound condition
Solution:
- Verify the service exists:
kubectl get svc hello-service -n demo - Check the port matches:
kubectl get svc hello-service -n demo -o jsonpath='{.spec.ports[0].port}'
Problem: NebariApp shows NamespaceNotOptedIn condition
Solution:
kubectl label namespace demo nebari.dev/managed=trueRemove the test application:
kubectl delete nebariapp hello-app -n demo
kubectl delete namespace demoTeardown the development environment:
cd dev
make teardown- Platform Setup - Production infrastructure setup
- Configuration Reference - Complete NebariApp CRD documentation
- Reconciler Architecture - How the operator works internally
- Authentication Guide - OIDC integration details
From the dev/ directory:
make help- Show all available commandsmake cluster-create- Create Kind cluster onlymake services-install- Install infrastructure services onlymake status- Check environment statusmake teardown- Complete cleanup
From the repository root:
make help- Show all available commandsmake build- Build manager binarymake docker-build- Build Docker imagemake install- Install CRDsmake deploy- Deploy operatormake undeploy- Remove operatormake test- Run unit testsmake test-e2e- Run end-to-end tests
See docs/makefile-reference.md for complete documentation.