Files
homelab-starter/docs/adding-an-app.md
2026-02-14 10:46:57 -05:00

4.1 KiB

Adding an App: Step-by-Step

This guide walks through adding a new app to your cluster, using a simple whoami test service as an example. By the end, you'll have a working app accessible at https://whoami.example.com.

Overview

Adding an app requires touching 4 places:

  1. Namespacebootstrap/ns/apps.yaml
  2. App manifestsapps/whoami/install/
  3. Flux Kustomizationbootstrap/kustomization/apps/whoami/
  4. IngressRouteinfrastructure/routes/whoami.yaml

Step 1: Create the namespace

Edit bootstrap/ns/apps.yaml and add:

---
apiVersion: v1
kind: Namespace
metadata:
  name: whoami

Step 2: Create the app manifests

Create apps/whoami/install/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: whoami
resources:
  - deployment.yaml

Create apps/whoami/install/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: whoami
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami:latest
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: whoami
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: whoami

Step 3: Create the Flux Kustomization

Create bootstrap/kustomization/apps/whoami/whoami-install.yaml:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: install-whoami--app
  namespace: flux-system
spec:
  interval: 5m
  timeout: 4m
  dependsOn:
    - name: install-traefik--infra
  path: ./apps/whoami/install
  prune: true
  wait: true
  sourceRef:
    kind: GitRepository
    name: flux-system

Step 4: Create the IngressRoute

Create infrastructure/routes/whoami.yaml:

apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
  namespace: whoami
spec:
  redirectScheme:
    scheme: https
    permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-ingress-http
  namespace: whoami
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`whoami.example.com`)
      kind: Rule
      middlewares:
        - name: redirect-https
      services:
        - name: whoami
          namespace: whoami
          port: 80
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-ingress
  namespace: whoami
  annotations:
    cert-manager.io/issuer: "cert-issuer"
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`whoami.example.com`)
      kind: Rule
      services:
        - name: whoami
          namespace: whoami
          port: 80
  tls:
    secretName: whoami-tls
    domains:
      - main: whoami.example.com
        sans:
          - whoami.example.com

Step 5: Commit and push

git add -A
git commit -m "Add whoami app"
git push

Flux will automatically detect the change and deploy your app. Watch it happen:

# Watch Flux pick up the change
flux get kustomizations --watch

# Verify the pod is running
kubectl get pods -n whoami

# Test it
curl https://whoami.example.com

Using a Helm Chart Instead

If your app has a Helm chart, the pattern is slightly different:

  1. Add a HelmRepository in bootstrap/repositories/ pointing to the chart source
  2. In your app's install directory, use a HelmRelease instead of raw manifests:
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: my-app-release
  namespace: my-app
spec:
  chart:
    spec:
      chart: my-app
      version: 1.0.0
      sourceRef:
        kind: HelmRepository
        name: my-app-repo
        namespace: flux-system
  interval: 15m
  releaseName: my-app
  valuesFrom:
    - kind: ConfigMap
      name: my-app-chart-overrides
      valuesKey: values.yaml
  1. Create a ConfigMap with your chart value overrides (same pattern as Traefik/MetalLB)
  2. Everything else (namespace, Flux Kustomization, IngressRoute) stays the same