Files
wild-cloud-dev/ai/wildcloud-v.PoC/apps-system.md
2025-10-11 18:08:04 +00:00

595 lines
18 KiB
Markdown

# Wild Cloud Apps System
The Wild Cloud apps system provides a streamlined way to deploy and manage applications on your Kubernetes cluster. It uses Kustomize for configuration management and follows a standardized structure for consistent deployment patterns.
## App Structure and Components
### Directory Structure
Each subdirectory represents a Wild Cloud app. Each app directory contains:
**Required Files:**
- `manifest.yaml` - App metadata and configuration
- `kustomization.yaml` - Kustomize configuration with Wild Cloud labels
**Standard Configuration Files (one or more YAML files containing Kubernetes resource definitions):**
```
apps/myapp/
├── manifest.yaml # Required: App metadata and configuration
├── kustomization.yaml # Required: Kustomize configuration with Wild Cloud labels
├── namespace.yaml # Kubernetes namespace definition
├── deployment.yaml # Application deployment
├── service.yaml # Kubernetes service definition
├── ingress.yaml # HTTPS ingress with external DNS
├── pvc.yaml # Persistent volume claims (if needed)
├── db-init-job.yaml # Database initialization (if needed)
└── configmap.yaml # Configuration data (if needed)
```
### App Manifest (`manifest.yaml`)
The required `manifest.yaml` file contains metadata about the app. Here's an example `manifest.yaml` file:
```yaml
name: myapp
description: A brief description of the application and its purpose.
version: 1.0.0
icon: https://example.com/icon.png
requires:
- name: postgres
defaultConfig:
image: myapp/server:1.0.0
domain: myapp.{{ .cloud.domain }}
timezone: UTC
storage: 10Gi
dbHostname: postgres.postgres.svc.cluster.local
dbUsername: myapp
requiredSecrets:
- apps.myapp.dbPassword
- apps.postgres.password
```
**Manifest Fields**:
- `name` - The name of the app, used for identification (must match directory name)
- `description` - A brief description of the app
- `version` - The version of the app (should generally follow the versioning scheme of the app itself)
- `icon` - A URL to an icon representing the app
- `requires` - A list of other apps that this app depends on (each entry should be the name of another app)
- `defaultConfig` - A set of default configuration values for the app (when an app is added using `wild-app-add`, these values will be added to the Wild Cloud `config.yaml` file)
- `requiredSecrets` - A list of secrets that must be set in the Wild Cloud `secrets.yaml` file for the app to function properly (these secrets are typically sensitive information like database passwords or API keys; keys with random values will be generated automatically when the app is added)
### Kustomization Configuration
Wild Cloud apps use standard Kustomize with required Wild Cloud labels:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: myapp
labels:
- includeSelectors: true
pairs:
app: myapp
managedBy: kustomize
partOf: wild-cloud
resources:
- namespace.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- pvc.yaml
- db-init-job.yaml
```
**Kustomization Requirements**:
- Every Wild Cloud kustomization should include the Wild Cloud labels in its `kustomization.yaml` file (this allows Wild Cloud to identify and manage the app correctly)
- The `app` label and `namespace` should match the app's name/directory
- **includeSelectors: true** - Automatically applies labels to all resources AND their selectors
#### Standard Wild Cloud Labels
Wild Cloud uses a consistent labeling strategy across all apps:
```yaml
labels:
- includeSelectors: true
pairs:
app: myapp # The app name (matches directory)
managedBy: kustomize # Managed by Kustomize
partOf: wild-cloud # Part of Wild Cloud ecosystem
```
The `includeSelectors: true` setting automatically applies these labels to all resources AND their selectors, which means:
1. **Resource labels** - All resources get the standard Wild Cloud labels
2. **Selector labels** - All selectors automatically include these labels for robust selection
This allows individual resources to use simple, component-specific selectors:
```yaml
selector:
matchLabels:
component: web
```
Which Kustomize automatically expands to:
```yaml
selector:
matchLabels:
app: myapp
component: web
managedBy: kustomize
partOf: wild-cloud
```
### Template System
Wild Cloud apps are actually **templates** that get compiled with your specific configuration when you run `wild-app-add`. This allows for:
- **Dynamic Configuration** - Reference user settings via `{{ .apps.appname.key }}`
- **Gomplate Processing** - Full template capabilities including conditionals and loops
- **Secret Integration** - Automatic secret generation and referencing
- **Domain Management** - Automatic subdomain assignment based on your domain
**Template Variable Examples**:
```yaml
# Configuration references
image: "{{ .apps.myapp.image }}"
domain: "{{ .apps.myapp.domain }}"
namespace: "{{ .apps.myapp.namespace }}"
# Cloud-wide settings
timezone: "{{ .cloud.timezone }}"
domain_suffix: "{{ .cloud.domain }}"
# Conditional logic
{{- if .apps.myapp.enableSSL }}
- name: ENABLE_SSL
value: "true"
{{- end }}
```
## App Lifecycle Management
### 1. Discovery Phase
**Command**: `wild-apps-list`
Lists all available applications with metadata:
```bash
wild-apps-list --verbose # Detailed view with descriptions
wild-apps-list --json # JSON output for automation
```
Shows:
- App name and description
- Version and dependencies
- Installation status
- Required configuration
### 2. Configuration Phase
**Command**: `wild-app-add <app-name>`
Processes app templates and prepares for deployment:
**What it does**:
1. Reads app manifest directly from Wild Cloud repository
2. Merges default configuration with existing `config.yaml`
3. Generates required secrets automatically
4. Compiles templates with gomplate using your configuration
5. Creates ready-to-deploy Kustomize files in `apps/<app-name>/`
**Generated Files**:
- Compiled Kubernetes manifests (no more template variables)
- Standard Kustomize configuration
- App-specific configuration merged into your `config.yaml`
- Required secrets added to your `secrets.yaml`
### 3. Deployment Phase
**Command**: `wild-app-deploy <app-name>`
Deploys the app to your Kubernetes cluster:
**Deployment Process**:
1. Creates namespace if it doesn't exist
2. Handles app dependencies (deploys required apps first)
3. Creates secrets from your `secrets.yaml`
4. Applies Kustomize configuration to cluster
5. Copies TLS certificates to app namespace
6. Validates deployment success
**Options**:
- `--force` - Overwrite existing resources
- `--dry-run` - Preview changes without applying
### 4. Operations Phase
**Monitoring**: `wild-app-doctor <app-name>`
- Runs app-specific diagnostic tests
- Checks pod status, resource usage, connectivity
- Options: `--keep`, `--follow`, `--timeout`
**Updates**: Re-run `wild-app-add` then `wild-app-deploy`
- Use `--force` flag to overwrite existing configuration
- Updates configuration changes
- Handles image updates
- Preserves persistent data
**Removal**: `wild-app-delete <app-name>`
- Deletes namespace and all resources
- Removes local configuration files
- Options: `--force` for no confirmation
## Configuration System
### Configuration Storage
**Global Configuration** (`config.yaml`):
```yaml
cloud:
domain: example.com
timezone: America/New_York
apps:
myapp:
domain: app.example.com
image: myapp:1.0.0
storage: 20Gi
timezone: UTC
```
**Secrets Management** (`secrets.yaml`):
```yaml
apps:
myapp:
dbPassword: "randomly-generated-password"
adminPassword: "user-set-password"
postgres:
password: "randomly-generated-password"
```
### Secret Generation
When you run `wild-app-add`, required secrets are automatically generated:
- **Random Generation**: 32-character base64 strings for passwords/keys
- **User Prompts**: For secrets that need specific values
- **Preservation**: Existing secrets are never overwritten
- **Permissions**: `secrets.yaml` has 600 permissions (owner-only)
### Configuration Commands
```bash
# Read app configuration
wild-config apps.myapp.domain
# Set app configuration
wild-config-set apps.myapp.storage "50Gi"
# Read app secrets
wild-secret apps.myapp.dbPassword
# Set app secrets
wild-secret-set apps.myapp.adminPassword "my-secure-password"
```
## Networking and DNS
### External DNS Integration
Wild Cloud apps automatically manage DNS records through ingress annotations:
```yaml
metadata:
annotations:
external-dns.alpha.kubernetes.io/target: {{ .cloud.domain }}
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
```
**How it works**:
1. App ingress created with external-dns annotations
2. ExternalDNS controller detects new ingress
3. Creates CNAME record: `app.yourdomain.com``yourdomain.com`
4. DNS resolves to MetalLB load balancer IP
5. Traefik routes traffic to appropriate service
### HTTPS Certificate Management
Automatic TLS certificates via cert-manager:
```yaml
metadata:
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
tls:
- hosts:
- {{ .apps.myapp.domain }}
secretName: myapp-tls
```
**Certificate Lifecycle**:
1. Ingress created with TLS configuration
2. cert-manager detects certificate requirement
3. Let's Encrypt challenge initiated automatically
4. Certificate issued and stored in Kubernetes secret
5. Traefik uses certificate for TLS termination
6. Automatic renewal before expiration
## Database Integration
### Database Initialization Jobs
Apps that require databases use initialization jobs to set up the database before the main application starts:
```yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myapp-db-init
spec:
template:
spec:
containers:
- name: db-init
image: postgres:15
command:
- /bin/bash
- -c
- |
PGPASSWORD=$ROOT_PASSWORD psql -h $DB_HOST -U postgres -c "
CREATE DATABASE IF NOT EXISTS $DB_NAME;
CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
"
env:
- name: DB_HOST
value: {{ .apps.myapp.dbHostname }}
- name: ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: myapp-secrets
key: apps.postgres.password
restartPolicy: OnFailure
```
**Database URL Secrets**: For apps requiring database URLs with embedded credentials, always use dedicated secrets:
```yaml
# In manifest.yaml
requiredSecrets:
- apps.myapp.dbUrl
# Generated secret (by wild-app-add)
apps:
myapp:
dbUrl: "postgresql://myapp:password123@postgres.postgres.svc.cluster.local/myapp"
```
### Supported Databases
Wild Cloud apps commonly integrate with:
- **PostgreSQL** - Via `postgres` app dependency
- **MySQL** - Via `mysql` app dependency
- **Redis** - Via `redis` app dependency
- **SQLite** - For apps with embedded database needs
## Storage Management
### Persistent Volume Claims
Apps requiring persistent storage define PVCs:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: {{ .apps.myapp.storage }}
```
**Storage Integration**:
- **Longhorn Storage Class** - Distributed, replicated storage
- **Dynamic Provisioning** - Automatic volume creation
- **Backup Support** - Via `wild-app-backup` command
- **Expansion** - Update storage size in configuration
### Backup and Restore
**Application Backup**: `wild-app-backup <app-name>`
- Discovers databases and PVCs automatically
- Creates restic snapshots with deduplication
- Supports PostgreSQL and MySQL database backups
- Streams PVC data for efficient storage
**Application Restore**: `wild-app-restore <app-name> <snapshot-id>`
- Restores from restic snapshots
- Options: `--db-only`, `--pvc-only`, `--skip-globals`
- Creates safety snapshots before destructive operations
## Security Considerations
### Pod Security Standards
All Wild Cloud apps comply with Pod Security Standards:
```yaml
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
seccompProfile:
type: RuntimeDefault
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false # Set to true when possible
```
### Secret Management
- **Kubernetes Secrets** - All sensitive data stored as Kubernetes secrets
- **Secret References** - Apps reference secrets via `secretKeyRef`, never inline
- **Full Dotted Paths** - Always use complete secret paths (e.g., `apps.myapp.dbPassword`)
- **No Plaintext** - Secrets never stored in manifests or config files
### Network Policies
Apps can define network policies for traffic isolation:
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: myapp-network-policy
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- from:
- namespaceSelector:
matchLabels:
name: traefik
```
## Available Applications
Wild Cloud includes apps for common self-hosted services:
### Content Management
- **Ghost** - Publishing platform for blogs and websites
- **Discourse** - Community discussion platform
### Development & Project Management Tools
- **Gitea** - Self-hosted Git service with web interface
- **OpenProject** - Open-source project management software
- **Docker Registry** - Private container image registry
### Media & File Management
- **Immich** - Self-hosted photo and video backup solution
### Communication
- **Keila** - Newsletter and email marketing platform
- **Listmonk** - Newsletter and mailing list manager
### Databases
- **PostgreSQL** - Relational database service
- **MySQL** - Relational database service
- **Redis** - In-memory data structure store
- **Memcached** - Distributed memory caching system
### AI/ML
- **vLLM** - Fast LLM inference server with OpenAI-compatible API
### Examples & Templates
- **example-admin** - Example admin interface application
- **example-app** - Template application for development reference
## Creating Custom Apps
### App Development Process
1. **Create Directory**: `apps/myapp/`
2. **Write Manifest**: Define metadata and configuration
3. **Create Resources**: Kubernetes manifests with templates
4. **Test Locally**: Use `wild-app-add` and `wild-app-deploy`
5. **Validate**: Ensure all resources deploy correctly
### Best Practices
**Manifest Design**:
- Include comprehensive `defaultConfig` for all configurable values
- List all `requiredSecrets` the app needs
- Specify dependencies in `requires` field
- Use semantic versioning
**Template Usage**:
- Reference configuration via `{{ .apps.myapp.key }}`
- Use conditionals for optional features
- Include proper gomplate syntax for lists and objects
- Test template compilation
**Resource Configuration**:
- Always include Wild Cloud standard labels
- Use appropriate security contexts
- Define resource requests and limits
- Include health checks and probes
**Storage and Networking**:
- Use Longhorn storage class for persistence
- Include external-dns annotations for automatic DNS
- Configure TLS certificates via cert-manager annotations
- Follow database initialization patterns for data apps
### Converting from Helm Charts
Wild Cloud provides tooling to convert Helm charts to Wild Cloud apps:
```bash
# Convert Helm chart to Kustomize base
helm fetch --untar --untardir charts stable/mysql
helm template --output-dir base --namespace mysql mysql charts/mysql
cd base/mysql
kustomize create --autodetect
# Then customize for Wild Cloud:
# 1. Add manifest.yaml
# 2. Replace hardcoded values with templates
# 3. Update labels to Wild Cloud standard
# 4. Configure secrets properly
```
## Troubleshooting Applications
### Common Issues
**App Won't Start**:
- Check pod logs: `kubectl logs -n <app-namespace> deployment/<app-name>`
- Verify secrets exist: `kubectl get secrets -n <app-namespace>`
- Check resource constraints: `kubectl describe pod -n <app-namespace>`
**Database Connection Issues**:
- Verify database is running: `kubectl get pods -n <db-namespace>`
- Check database initialization job: `kubectl logs job/<app>-db-init -n <app-namespace>`
- Validate database credentials in secrets
**DNS/Certificate Issues**:
- Check ingress status: `kubectl get ingress -n <app-namespace>`
- Verify certificate creation: `kubectl get certificates -n <app-namespace>`
- Check external-dns logs: `kubectl logs -n external-dns deployment/external-dns`
**Storage Issues**:
- Check PVC status: `kubectl get pvc -n <app-namespace>`
- Verify Longhorn cluster health: Access Longhorn UI
- Check storage class availability: `kubectl get storageclass`
### Diagnostic Tools
```bash
# App-specific diagnostics
wild-app-doctor <app-name>
# Resource inspection
kubectl get all -n <app-namespace>
kubectl describe deployment/<app-name> -n <app-namespace>
# Log analysis
kubectl logs -f deployment/<app-name> -n <app-namespace>
kubectl logs job/<app>-db-init -n <app-namespace>
# Configuration verification
wild-config apps.<app-name>
wild-secret apps.<app-name>
```
The Wild Cloud apps system provides a powerful, consistent way to deploy and manage self-hosted applications with enterprise-grade features like automatic HTTPS, DNS management, backup/restore, and integrated security.