Files
wild-directory/CLAUDE.md

6.8 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

This repository contains the Wild Cloud apps directory - a collection of Kubernetes applications packaged as Kustomize configurations. Each app is a self-contained directory with standardized manifests that can be deployed to Wild Cloud clusters using Wild Cloud CLI tools.

Repository Architecture

App Structure

Each app follows a strict structure:

  • manifest.yaml - App metadata, dependencies, default configuration, and secret requirements
  • kustomization.yaml - Kustomize configuration with standard Wild Cloud labels
  • Resource files - Kubernetes objects (deployments, services, ingresses, PVCs, jobs, etc.)

Templating System

Configuration files use gomplate templating to reference operator configuration:

  • Use {{ .cloud.domain }} for the operator's domain
  • Use {{ .apps.appname.configKey }} for app-specific configuration
  • Use {{ .operator.email }} for operator email
  • All template variables must be defined in either the app's manifest.yaml under defaultConfig or be standard Wild Cloud operator variables

Templates are compiled when users add apps to their Wild Cloud instance via the web app, CLI, or API.

Label Strategy

Wild Cloud uses a consistent labeling approach powered by Kustomize's includeSelectors: true feature:

labels:
  - includeSelectors: true
    pairs:
      app: appname           # App name (matches directory)
      managedBy: kustomize
      partOf: wild-cloud

This automatically applies labels to all resources AND their selectors. Individual resources can use simple component-specific selectors like component: web or component: worker, and Kustomize will expand them to include the standard Wild Cloud labels.

Important: Do NOT use Helm-style labels (app.kubernetes.io/name, app.kubernetes.io/instance). Use simple component labels instead.

Working with Apps

Creating/Modifying Apps

  1. Manifest fields:

    • name - Must match directory name
    • description - Brief app description
    • version - App version (follow upstream versioning)
    • icon - URL to app icon
    • requires - List of dependency apps (e.g., postgres, redis, memcached)
    • defaultConfig - Default configuration values (will be added to operator's config.yaml)
    • requiredSecrets - List of secrets in dotted path format (e.g., apps.appname.dbPassword)
  2. Kustomization requirements:

    • Must include standard Wild Cloud labels with includeSelectors: true
    • Namespace must match app name
    • List all resource files under resources:
  3. Security contexts: All pods must comply with Pod Security Standards:

    securityContext:
      runAsNonRoot: true
      runAsUser: 999  # Use appropriate non-root UID
      runAsGroup: 999
      seccompProfile:
        type: RuntimeDefault
    containers:
    - securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: [ALL]
        readOnlyRootFilesystem: false  # Set to true when possible
    

Secrets Management

Secrets use full dotted paths as keys:

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: appname-secrets
        key: apps.appname.dbPassword  # Full path, not just "dbPassword"

Database URL secrets: When apps need database URLs with embedded credentials, always use a dedicated dbUrl secret in requiredSecrets. Do NOT try to construct URLs with env var substitution in templates - Kustomize cannot process runtime environment variables.

Database Initialization Jobs

Apps requiring PostgreSQL/MySQL databases should include a db-init-job.yaml:

  • Creates the app database if it doesn't exist
  • Creates/updates the app user with proper password
  • Grants appropriate permissions
  • For PostgreSQL jobs: use runAsUser: 999 (postgres user)
  • Include any required database extensions (e.g., Immich requires vector, cube, earthdistance)

Examples: immich/db-init-job.yaml, gitea/db-init-job.yaml

External DNS Configuration

Ingress resources should include external-dns annotations:

annotations:
  external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
  external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"

This creates CNAME records pointing app subdomains to the main cluster domain.

Converting Helm Charts

Wild Cloud prefers Kustomize over Helm for transparency and Git-friendliness. To convert a Helm chart:

helm fetch --untar --untardir charts repo/chart-name
helm template --output-dir base --namespace namespace --values values.yaml release-name charts/chart-name
cd base/chart-name
kustomize create --autodetect

Then:

  1. Add manifest.yaml
  2. Replace hardcoded values with gomplate variables
  3. Update secrets to use Wild Cloud's dotted-path approach
  4. Replace Helm labels with simple component labels
  5. Add standard Wild Cloud labels to kustomization.yaml
  6. Add security contexts to all pods

Managing Wild Cloud Apps

Users can manage apps through:

  1. Web App: Navigate to the Apps page in your instance to browse, add, configure, and deploy apps

  2. CLI: Use the Wild CLI for terminal-based workflows:

    • wild app list - List all available apps
    • wild app add <app-name> - Add an app (compiles templates, updates config/secrets)
    • wild app deploy <app-name> - Deploy an app to the cluster
    • wild app list-deployed - List deployed apps
    • wild app status <app-name> - Get app status
    • wild app delete <app-name> - Delete an app
  3. API: Use the Wild Central API endpoints for automation:

    • GET /api/v1/apps/available - List all available apps
    • GET /api/v1/apps/available/{app-name} - Get app details
    • POST /api/v1/instances/{instance-name}/apps - Add an app (compiles templates, updates config/secrets)
    • POST /api/v1/instances/{instance-name}/apps/{app-name}/deploy - Deploy an app to the cluster
    • GET /api/v1/instances/{instance-name}/apps - List deployed apps
    • GET /api/v1/instances/{instance-name}/apps/{app-name}/status - Get app status

Validation

Before submitting changes:

  1. Ensure manifest.yaml has all required fields
  2. Verify kustomization.yaml includes standard Wild Cloud labels
  3. Check all templates use valid configuration paths defined in defaultConfig
  4. Confirm secrets use full dotted-path keys
  5. Verify all pods have proper security contexts
  6. Test template compilation works with sample operator config

Examples of Well-Structured Apps

  • immich - Multi-deployment app with database init, multiple services, PostgreSQL extensions
  • openproject - App with multiple dependencies (postgres, memcached), configmap-based configuration
  • gitea - Standard app with database init, PVC for storage