From 1b78abbdc46486284760b88e6bd66191d113cbe5 Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Tue, 30 Dec 2025 03:38:48 +0000 Subject: [PATCH] claude --- CLAUDE.md | 182 ++++-------------------------------------------------- 1 file changed, 13 insertions(+), 169 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2e7b79f..e2bd7c9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,171 +1,15 @@ -# CLAUDE.md +- @README.md +- @ADDING-APPS.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## IMPORTANT -## 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: - -```yaml -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: - ```yaml - 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: -```yaml -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](immich/db-init-job.yaml), [gitea/db-init-job.yaml](gitea/db-init-job.yaml) - -### External DNS Configuration - -Ingress resources should include external-dns annotations: -```yaml -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: - -```bash -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 ` - Add an app (compiles templates, updates config/secrets) - - `wild app deploy ` - Deploy an app to the cluster - - `wild app list-deployed` - List deployed apps - - `wild app status ` - Get app status - - `wild app delete ` - 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 +- When adding a new app to the directory, check to make sure you are adding the latest app version. +- Use traefik for ingress. +- Use postgres for database if supported. +- Keep config key naming (including nesting) consistent with other apps. +- Don't use helm +- If the app requires a specific platform (amd64, arm64, etc.), make sure it is called out in the manifest and the k8s tags are set +- when developing a new app: + - test with: + - reset to a fresh state between tests: +- secrets.yaml is not checked in and any values unrelated to your current task should be preserved