Updates documentation.
This commit is contained in:
157
CLAUDE.md
Normal file
157
CLAUDE.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 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 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:
|
||||
|
||||
```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
|
||||
|
||||
## 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 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
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user