6.0 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 requirementskustomization.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.yamlunderdefaultConfigor be standard Wild Cloud operator variables
Templates are compiled by wild-app-add when operators add apps to their Wild Cloud home directory.
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
-
Manifest fields:
name- Must match directory namedescription- Brief app descriptionversion- App version (follow upstream versioning)icon- URL to app iconrequires- List of dependency apps (e.g.,postgres,redis,memcached)defaultConfig- Default configuration values (will be added to operator'sconfig.yaml)requiredSecrets- List of secrets in dotted path format (e.g.,apps.appname.dbPassword)
-
Kustomization requirements:
- Must include standard Wild Cloud labels with
includeSelectors: true - Namespace must match app name
- List all resource files under
resources:
- Must include standard Wild Cloud labels with
-
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:
- Add
manifest.yaml - Replace hardcoded values with gomplate variables
- Update secrets to use Wild Cloud's dotted-path approach
- Replace Helm labels with simple component labels
- Add standard Wild Cloud labels to
kustomization.yaml - Add security contexts to all pods
Common Wild Cloud Commands
These commands are run by operators from their Wild Cloud home directory (not this repository):
wild-apps-list- List all available appswild-app-add <app-name>- Add an app (compiles templates, updates config/secrets)wild-app-deploy <app-name>- Deploy an app to the cluster
Validation
Before submitting changes:
- Ensure
manifest.yamlhas all required fields - Verify
kustomization.yamlincludes standard Wild Cloud labels - Check all templates use valid configuration paths defined in
defaultConfig - Confirm secrets use full dotted-path keys
- Verify all pods have proper security contexts
- 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