mirror of
https://github.com/morten-olsen/homelab-apps.git
synced 2026-02-08 01:36:28 +01:00
Compare commits
2 Commits
main
...
renovate/w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88585c56eb | ||
|
|
be53c17847 |
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash(git -C /Users/alice/Projects/private/homelab/apps log --oneline -10)",
|
|
||||||
"Bash(git -C /Users/alice/Projects/private/homelab/apps remote -v)",
|
|
||||||
"Bash(git -C /Users/alice/Projects/private/homelab/apps config --list)",
|
|
||||||
"Bash(ls:*)",
|
|
||||||
"Bash(git -C /Users/alice/Projects/private/homelab/apps log --all --oneline --decorate -15)",
|
|
||||||
"Bash(git -C /Users/alice/Projects/private/homelab/apps branch -a)",
|
|
||||||
"Bash(helm dependency:*)",
|
|
||||||
"Bash(helm lint:*)",
|
|
||||||
"Bash(helm template:*)",
|
|
||||||
"Bash(kubectl get:*)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,11 +0,0 @@
|
|||||||
# Helm chart dependencies (packaged library charts)
|
|
||||||
# These are generated by 'helm dependency update' and should not be committed
|
|
||||||
**/charts/*.tgz
|
|
||||||
charts/*.tgz
|
|
||||||
|
|
||||||
**/__pycache__/
|
|
||||||
__pycache__/
|
|
||||||
|
|
||||||
**/Chart.lock
|
|
||||||
|
|
||||||
*-local-secret.yaml
|
|
||||||
380
AGENTS.md
380
AGENTS.md
@@ -58,7 +58,6 @@ mkdir -p apps/charts/my-app/templates
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Chart.yaml
|
#### Chart.yaml
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
@@ -66,7 +65,6 @@ name: my-app
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### values.yaml
|
#### values.yaml
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
image:
|
image:
|
||||||
repository: docker.io/org/my-app
|
repository: docker.io/org/my-app
|
||||||
@@ -75,5 +73,381 @@ image:
|
|||||||
subdomain: my-app
|
subdomain: my-app
|
||||||
```
|
```
|
||||||
|
|
||||||
See ./apps/common/README.md for guide on writing charts
|
### 2. Core Templates
|
||||||
|
|
||||||
|
#### Deployment Template
|
||||||
|
Create `templates/deployment.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data
|
||||||
|
name: data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Service Template
|
||||||
|
Create `templates/service.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Persistent Volume Claim
|
||||||
|
Create `templates/pvc.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-data"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom Resource Definitions (CRDs)
|
||||||
|
|
||||||
|
This project uses several custom resources that are managed by operators in the cluster:
|
||||||
|
|
||||||
|
### 1. OIDC Client (OpenID Connect Authentication)
|
||||||
|
|
||||||
|
The `OidcClient` resource automatically provisions OAuth2/OIDC clients with your identity provider.
|
||||||
|
|
||||||
|
Create `templates/client.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /oauth/oidc/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Creates an OIDC client in your identity provider (e.g., Authentik)
|
||||||
|
- Generates a Kubernetes secret named `{{ .Release.Name }}-client` containing:
|
||||||
|
- `clientId`: The OAuth client ID
|
||||||
|
- `clientSecret`: The OAuth client secret
|
||||||
|
- `configuration`: The OIDC provider URL
|
||||||
|
|
||||||
|
**Using in deployment:**
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
- name: OAUTH_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientId
|
||||||
|
- name: OAUTH_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientSecret
|
||||||
|
- name: OPENID_PROVIDER_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. PostgreSQL Database
|
||||||
|
|
||||||
|
The `PostgresDatabase` resource automatically provisions PostgreSQL databases.
|
||||||
|
|
||||||
|
Create `templates/database.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: PostgresDatabase
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Creates a PostgreSQL database with the same name as your release
|
||||||
|
- Creates a user with appropriate permissions
|
||||||
|
- Generates a Kubernetes secret named `{{ .Release.Name }}-database` containing:
|
||||||
|
- `url`: Complete PostgreSQL connection URL
|
||||||
|
- `host`: Database hostname
|
||||||
|
- `port`: Database port
|
||||||
|
- `database`: Database name
|
||||||
|
- `username`: Database username
|
||||||
|
- `password`: Database password
|
||||||
|
|
||||||
|
**Using in deployment:**
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-database"
|
||||||
|
key: url
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Secret Generation
|
||||||
|
|
||||||
|
The `GenerateSecret` resource creates secure random secrets.
|
||||||
|
|
||||||
|
Create `templates/secret.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: GenerateSecret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-secrets"
|
||||||
|
spec:
|
||||||
|
fields:
|
||||||
|
- name: encryptionkey
|
||||||
|
encoding: hex # Options: hex, base64, alphanumeric
|
||||||
|
length: 64 # Length in bytes (before encoding)
|
||||||
|
- name: apitoken
|
||||||
|
encoding: base64
|
||||||
|
length: 32
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Generates cryptographically secure random values
|
||||||
|
- Creates a Kubernetes secret with the specified fields
|
||||||
|
- Supports different encoding formats for different use cases
|
||||||
|
|
||||||
|
**Using in deployment:**
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
- name: ENCRYPTION_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-secrets"
|
||||||
|
key: encryptionkey
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. External HTTP Service
|
||||||
|
|
||||||
|
The `ExternalHttpService` resource configures ingress routing for your application.
|
||||||
|
|
||||||
|
Create `templates/external-http-service.yaml`:
|
||||||
|
```yaml
|
||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
```
|
||||||
|
|
||||||
|
**What it does:**
|
||||||
|
- Creates ingress routes for your application
|
||||||
|
- Configures subdomain routing (e.g., `myapp.yourdomain.com`)
|
||||||
|
- Handles TLS termination automatically
|
||||||
|
- Integrates with your service mesh (if applicable)
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Naming Conventions
|
||||||
|
- Use `{{ .Release.Name }}` consistently for all resource names
|
||||||
|
- Suffix resource names appropriately: `-data`, `-secrets`, `-client`, `-database`
|
||||||
|
|
||||||
|
### 2. Container Configuration
|
||||||
|
- Always specify health checks (liveness and readiness probes)
|
||||||
|
- Use named ports (e.g., `http`, `grpc`) instead of port numbers
|
||||||
|
- Set `revisionHistoryLimit: 0` to prevent accumulation of old ReplicaSets
|
||||||
|
|
||||||
|
### 3. Environment Variables
|
||||||
|
- Never hardcode secrets in values.yaml
|
||||||
|
- Use secretKeyRef to reference generated secrets
|
||||||
|
- Group related environment variables together
|
||||||
|
|
||||||
|
### 4. Persistent Storage
|
||||||
|
- Always use PVCs for stateful data
|
||||||
|
- Consider storage requirements carefully (start with reasonable defaults)
|
||||||
|
- Mount data at standard paths for the application
|
||||||
|
|
||||||
|
### 5. OIDC Integration
|
||||||
|
- Set `ENABLE_SIGNUP: "false"` if using OIDC
|
||||||
|
- Enable OIDC signup with `ENABLE_OAUTH_SIGNUP: "true"`
|
||||||
|
- Configure email merging if needed with `OAUTH_MERGE_ACCOUNTS_BY_EMAIL`
|
||||||
|
|
||||||
|
### 6. Database Usage
|
||||||
|
- Only include database.yaml if the app needs PostgreSQL
|
||||||
|
- Applications should support DATABASE_URL environment variable
|
||||||
|
- Consider connection pooling settings for production
|
||||||
|
|
||||||
|
## Disabling Applications
|
||||||
|
|
||||||
|
To temporarily disable an application, rename its directory with `.disabled` suffix:
|
||||||
|
```bash
|
||||||
|
mv apps/charts/my-app apps/charts/my-app.disabled
|
||||||
|
```
|
||||||
|
|
||||||
|
The ArgoCD ApplicationSet will automatically exclude directories matching `*.disabled`.
|
||||||
|
|
||||||
|
## Testing Your Chart
|
||||||
|
|
||||||
|
1. **Lint your chart:**
|
||||||
|
```bash
|
||||||
|
helm lint apps/charts/my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Render templates locally:**
|
||||||
|
```bash
|
||||||
|
helm template my-app apps/charts/my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Dry run installation:**
|
||||||
|
```bash
|
||||||
|
helm install my-app apps/charts/my-app --dry-run --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment Workflow
|
||||||
|
|
||||||
|
**IMPORTANT:** There is no test environment. When creating or modifying applications:
|
||||||
|
|
||||||
|
1. **Make changes directly to the files** - The agent will write changes to the actual chart files
|
||||||
|
2. **User deploys the changes** - After changes are made, the user must deploy them to the cluster
|
||||||
|
3. **Debug with kubectl** - If issues arise after deployment, agents can use kubectl to:
|
||||||
|
- Check pod status and logs
|
||||||
|
- Inspect generated resources
|
||||||
|
- Verify secret creation
|
||||||
|
- Troubleshoot configuration issues
|
||||||
|
|
||||||
|
**Note:** Agents cannot deploy applications themselves. They can only:
|
||||||
|
- Create and modify chart files
|
||||||
|
- Use kubectl to investigate deployment issues
|
||||||
|
- Provide debugging assistance and recommendations
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Application with OIDC + Database
|
||||||
|
For apps requiring both authentication and database:
|
||||||
|
- Include `client.yaml` for OIDC
|
||||||
|
- Include `database.yaml` for PostgreSQL
|
||||||
|
- Reference both secrets in deployment
|
||||||
|
|
||||||
|
### Stateless Applications
|
||||||
|
For simple stateless apps:
|
||||||
|
- Omit `pvc.yaml`
|
||||||
|
- Remove volume mounts from deployment
|
||||||
|
- Consider using `Deployment` scaling if appropriate
|
||||||
|
|
||||||
|
### Background Services
|
||||||
|
For services without web interface:
|
||||||
|
- Omit `external-http-service.yaml`
|
||||||
|
- Omit `client.yaml` (no OIDC needed)
|
||||||
|
- Focus on service discovery within cluster
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Secret Not Found
|
||||||
|
If secrets are not being created:
|
||||||
|
1. Check that the CRD controller is running
|
||||||
|
2. Verify the `environment` value matches your setup
|
||||||
|
3. Check controller logs for provisioning errors
|
||||||
|
|
||||||
|
### OIDC Issues
|
||||||
|
1. Verify redirect URIs match exactly
|
||||||
|
2. Check that the identity provider is accessible
|
||||||
|
3. Ensure the client secret is being properly mounted
|
||||||
|
|
||||||
|
### Database Connection
|
||||||
|
1. Verify the database operator is running
|
||||||
|
2. Check network policies between namespaces
|
||||||
|
3. Ensure the database server has capacity
|
||||||
|
|
||||||
|
## Global Values
|
||||||
|
|
||||||
|
Applications can access global values through `{{ .Values.globals }}`:
|
||||||
|
- `environment`: The deployment environment (e.g., "production", "staging")
|
||||||
|
- Additional values can be added at the root chart level
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Updating Images
|
||||||
|
1. Update the tag in `values.yaml`:
|
||||||
|
```yaml
|
||||||
|
tag: v1.0.0 # Use semantic version tags only
|
||||||
|
```
|
||||||
|
2. **Note:** Do not include SHA digests in tags. Immutable digests are automatically added later by Renovate
|
||||||
|
|
||||||
|
### Renovate Integration
|
||||||
|
The project uses Renovate for automated dependency updates. Configure in `renovate.json5` to:
|
||||||
|
- Auto-update container images
|
||||||
|
- Create pull requests for updates
|
||||||
|
- Group related updates
|
||||||
|
|
||||||
|
### Backup Considerations
|
||||||
|
For applications with persistent data:
|
||||||
|
1. Consider implementing backup CronJobs
|
||||||
|
2. Use volume snapshots if available
|
||||||
|
3. Export data regularly for critical applications
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
When adding new applications:
|
||||||
|
1. Follow the existing patterns and conventions
|
||||||
|
2. Document any special requirements in the chart's README
|
||||||
|
3. Consider security implications of all configurations
|
||||||
|
4. Update this document if introducing new patterns
|
||||||
|
|
||||||
|
## Maintaining This Document
|
||||||
|
|
||||||
|
**IMPORTANT:** When making changes to the project structure, patterns, or custom resources:
|
||||||
|
- Keep this AGENTS.md file up to date with any changes
|
||||||
|
- Document new CRDs or custom resources as they are added
|
||||||
|
- Update examples if the patterns change
|
||||||
|
- Add new sections for significant new features or patterns
|
||||||
|
- Ensure all code examples remain accurate and tested
|
||||||
|
|
||||||
|
This document serves as the primary reference for creating and maintaining applications in this project. Keeping it current ensures consistency and helps onboard new contributors.
|
||||||
100
CLAUDE.md
100
CLAUDE.md
@@ -1,100 +0,0 @@
|
|||||||
# CLAUDE.md
|
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
Kubernetes Helm-based homelab application deployment system using ArgoCD for GitOps. Contains 40+ containerized applications deployed via Helm charts with a shared common library to minimize template duplication.
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Validate YAML files
|
|
||||||
yamllint .
|
|
||||||
|
|
||||||
# Helm chart operations (run from chart directory)
|
|
||||||
helm dependency build # Fetch common library dependency
|
|
||||||
helm lint . # Validate chart syntax
|
|
||||||
helm template <release> . --set globals.environment=prod --set globals.domain=example.com
|
|
||||||
|
|
||||||
# Utility scripts
|
|
||||||
./scripts/migrate_database.py <source_db> <dest_db> [--clean] # PostgreSQL migration
|
|
||||||
./scripts/sync_pvc_with_host.sh <host-path> <namespace> <pvc> # PVC sync
|
|
||||||
```
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Directory Structure
|
|
||||||
- `apps/charts/` - Individual application Helm charts (deployed to `prod` namespace)
|
|
||||||
- `apps/common/` - Shared Helm library chart with standardized templates
|
|
||||||
- `apps/root/` - ArgoCD ApplicationSet for auto-discovery
|
|
||||||
- `shared/charts/` - Shared infrastructure services (authentik, nats)
|
|
||||||
- `scripts/` - Python/Bash utility scripts for database migration and PVC sync
|
|
||||||
|
|
||||||
### Deployment Model
|
|
||||||
Three ArgoCD ApplicationSets auto-discover charts from their respective `charts/` directories. Folders suffixed with `.disabled` are excluded from deployment.
|
|
||||||
|
|
||||||
### Common Library Pattern
|
|
||||||
Most charts use the common library (`apps/common/`) which provides standardized templates. A minimal chart needs:
|
|
||||||
|
|
||||||
1. `Chart.yaml` with common library dependency:
|
|
||||||
```yaml
|
|
||||||
apiVersion: v2
|
|
||||||
version: 1.0.0
|
|
||||||
name: my-app
|
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Standardized `values.yaml` (see `apps/common/README.md` for full structure)
|
|
||||||
|
|
||||||
3. Template files that include common helpers:
|
|
||||||
```yaml
|
|
||||||
# templates/deployment.yaml
|
|
||||||
{{ include "common.deployment" . }}
|
|
||||||
```
|
|
||||||
|
|
||||||
Or use single file with `{{ include "common.all" . }}` to render all resources automatically.
|
|
||||||
|
|
||||||
### Key Templates
|
|
||||||
- `common.deployment` - Deployment with health probes, volumes, init containers
|
|
||||||
- `common.service` - Service(s) with port mapping
|
|
||||||
- `common.pvc` - Persistent volume claims
|
|
||||||
- `common.virtualService` - Istio routing (public/private gateways)
|
|
||||||
- `common.oidc` - Authentik OIDC client registration
|
|
||||||
- `common.database` - PostgreSQL database provisioning
|
|
||||||
- `common.externalSecrets` - Password generators and secret templates
|
|
||||||
|
|
||||||
### Placeholders in values.yaml
|
|
||||||
- `{release}` - Release name
|
|
||||||
- `{namespace}` - Release namespace
|
|
||||||
- `{fullname}` - Full app name
|
|
||||||
- `{subdomain}` - App subdomain (from `subdomain` value)
|
|
||||||
- `{domain}` - Global domain
|
|
||||||
- `{timezone}` - Global timezone
|
|
||||||
|
|
||||||
### Secret Naming Conventions
|
|
||||||
- OIDC credentials: `{release}-oidc-credentials` (clientId, clientSecret, issuer)
|
|
||||||
- Database connection: `{release}-connection` (url, host, port, user, password)
|
|
||||||
- Generated secrets: `{release}-secrets`
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- Chart and release names use kebab-case
|
|
||||||
- All container images pinned by SHA256 digest (Renovate manages updates)
|
|
||||||
- Storage uses `persistent` storageClassName
|
|
||||||
- Istio VirtualServices route via public/private gateways
|
|
||||||
- Deployment strategy: `Recreate` for stateful apps, `RollingUpdate` for stateless
|
|
||||||
|
|
||||||
## YAML Style
|
|
||||||
- Max line length: 120 characters
|
|
||||||
- Indentation: 2 spaces
|
|
||||||
- Truthy values: `true`, `false`, `on`, `off`
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
- `AGENTS.md` - Chart creation guidelines
|
|
||||||
- `apps/common/README.md` - Complete common library reference
|
|
||||||
- `apps/common/MIGRATION.md` - Guide for migrating charts to common library
|
|
||||||
- `apps/common/TEMPLATING.md` - Placeholder system documentation
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: vaultwarden
|
name: appsmith
|
||||||
10
apps/charts/appsmith.disabled/templates/_client.yaml
Normal file
10
apps/charts/appsmith.disabled/templates/_client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /api/auth/oidc/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
31
apps/charts/appsmith.disabled/templates/deployment.yaml
Normal file
31
apps/charts/appsmith.disabled/templates/deployment.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /appsmith-stacks
|
||||||
|
name: data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
11
apps/charts/appsmith.disabled/templates/pvc.yaml
Normal file
11
apps/charts/appsmith.disabled/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
15
apps/charts/appsmith.disabled/templates/service.yaml
Normal file
15
apps/charts/appsmith.disabled/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
apiVersion: networking.istio.io/v1
|
apiVersion: networking.istio.io/v1
|
||||||
kind: VirtualService
|
kind: VirtualService
|
||||||
metadata:
|
metadata:
|
||||||
name: "{{ .Release.Name }}-private"
|
name: "{{ .Release.Name }}"
|
||||||
namespace: "{{ .Release.Namespace }}"
|
namespace: "{{ .Release.Namespace }}"
|
||||||
spec:
|
spec:
|
||||||
gateways:
|
gateways:
|
||||||
- "{{ .Values.globals.istio.gateways.private }}"
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
- mesh
|
- mesh
|
||||||
hosts:
|
hosts:
|
||||||
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
@@ -16,4 +16,3 @@ spec:
|
|||||||
host: "{{ .Release.Name }}"
|
host: "{{ .Release.Name }}"
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
|
|
||||||
4
apps/charts/appsmith.disabled/values.yaml
Normal file
4
apps/charts/appsmith.disabled/values.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
subdomain: appsmith
|
||||||
|
image:
|
||||||
|
repository: index.docker.io/appsmith/appsmith-ce
|
||||||
|
tag: latest@sha256:0776a0a9665919800d22fc736956ec54fedd16a9a30f9d4ad3f3fc0fd8ac8694
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: audiobookshelf
|
name: audiobookshelf
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
13
apps/charts/audiobookshelf/templates/client.yaml
Normal file
13
apps/charts/audiobookshelf/templates/client.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /audiobookshelf/auth/openid/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
|
- path: /audiobookshelf/auth/openid/mobile-redirect
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -1 +1,52 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: '{{ .Release.Name }}'
|
||||||
|
image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
|
||||||
|
imagePullPolicy: '{{ .Values.image.pullPolicy }}'
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /config
|
||||||
|
name: config
|
||||||
|
- mountPath: /metadata
|
||||||
|
name: metadata
|
||||||
|
- mountPath: /audiobooks
|
||||||
|
name: audiobooks
|
||||||
|
- mountPath: /podcasts
|
||||||
|
name: podcasts
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: '{{ .Release.Name }}-config'
|
||||||
|
- name: metadata
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: '{{ .Release.Name }}-metadata'
|
||||||
|
- name: audiobooks
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: books
|
||||||
|
- name: podcasts
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: podcasts
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.dns" . }}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.oidc" . }}
|
|
||||||
@@ -1 +1,24 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-config'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-metadata'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -1,68 +1,5 @@
|
|||||||
image:
|
image:
|
||||||
repository: ghcr.io/advplyr/audiobookshelf
|
repository: ghcr.io/advplyr/audiobookshelf
|
||||||
tag: 2.32.1@sha256:a52dc5db694a5bf041ce38f285dd6c6a660a4b1b21e37ad6b6746433263b2ae5
|
tag: 2.31.0@sha256:e23adb24848d99d19cd1e251aee4e1e12ed4f5effc8ccb21754b062b6a06cf66
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
subdomain: audiobookshelf
|
subdomain: audiobookshelf
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
port: 80
|
|
||||||
healthProbe:
|
|
||||||
type: httpGet
|
|
||||||
path: /ping
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: config
|
|
||||||
mountPath: /config
|
|
||||||
persistentVolumeClaim: config # Will be prefixed with release name in template
|
|
||||||
- name: metadata
|
|
||||||
mountPath: /metadata
|
|
||||||
persistentVolumeClaim: metadata # Will be prefixed with release name in template
|
|
||||||
- name: audiobooks
|
|
||||||
mountPath: /audiobooks
|
|
||||||
persistentVolumeClaim: books
|
|
||||||
- name: podcasts
|
|
||||||
mountPath: /podcasts
|
|
||||||
persistentVolumeClaim: podcasts
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: config
|
|
||||||
size: 1Gi
|
|
||||||
storageClassName: persistent
|
|
||||||
- name: metadata
|
|
||||||
size: 5Gi
|
|
||||||
storageClassName: persistent
|
|
||||||
|
|
||||||
# DNS configuration
|
|
||||||
dns:
|
|
||||||
enabled: true
|
|
||||||
type: A
|
|
||||||
dnsClassRef:
|
|
||||||
name: private-dns
|
|
||||||
|
|
||||||
# OIDC/Authentik configuration
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
redirectUris:
|
|
||||||
- "/audiobookshelf/auth/openid/callback"
|
|
||||||
- "/audiobookshelf/auth/openid/mobile-redirect"
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
gateways:
|
|
||||||
public: true
|
|
||||||
private: true
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: shared
|
name: backup
|
||||||
48
apps/charts/backup.disabled/templates/cron-job-backup.yaml
Normal file
48
apps/charts/backup.disabled/templates/cron-job-backup.yaml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{{- $values := .Values -}}
|
||||||
|
{{- $release := .Release -}}
|
||||||
|
|
||||||
|
---
|
||||||
|
{{- range $key, $value := $values.jobs}}
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: "{{ $release.Name }}-{{ $key }}-backup"
|
||||||
|
spec:
|
||||||
|
schedule: "{{ $value.cron.backup }}"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 1
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
sidecar.istio.io/inject: "false"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ $release.Name }}-{{ $key }}-backup"
|
||||||
|
image: ghcr.io/morten-olsen/homelab-operator-backup:main
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command: ["/app/backup.sh"]
|
||||||
|
env:
|
||||||
|
- name: RESTIC_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ $values.password.name }}"
|
||||||
|
key: "{{ $values.password.key }}"
|
||||||
|
volumeMounts:
|
||||||
|
- name: source
|
||||||
|
mountPath: "/mnt/source"
|
||||||
|
- name: target
|
||||||
|
mountPath: "/mnt/backup"
|
||||||
|
subPath: "{{ $release.Name }}-{{ $key }}"
|
||||||
|
volumes:
|
||||||
|
- name: source
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ $value.source }}"
|
||||||
|
- name: target
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ $values.target }}"
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
---
|
||||||
|
{{- end }}
|
||||||
43
apps/charts/backup.disabled/templates/cron-job-cleanup.yaml
Normal file
43
apps/charts/backup.disabled/templates/cron-job-cleanup.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{{- $values := .Values -}}
|
||||||
|
{{- $release := .Release -}}
|
||||||
|
|
||||||
|
---
|
||||||
|
{{- range $key, $value := $values.jobs}}
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: "{{ $release.Name }}-{{ $key }}-cleanup"
|
||||||
|
spec:
|
||||||
|
schedule: "{{ $value.cron.cleanup }}"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 1
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
sidecar.istio.io/inject: "false"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ $release.Name }}-{{ $key }}-cleanup"
|
||||||
|
image: ghcr.io/morten-olsen/homelab-operator-backup:main
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command: ["/app/cleanup.sh"]
|
||||||
|
env:
|
||||||
|
- name: RESTIC_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ $values.password.name }}"
|
||||||
|
key: "{{ $values.password.key }}"
|
||||||
|
volumeMounts:
|
||||||
|
- name: target
|
||||||
|
mountPath: "/mnt/backup"
|
||||||
|
subPath: "{{ $release.Name }}-{{ $key }}"
|
||||||
|
volumes:
|
||||||
|
- name: target
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ $values.target }}"
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
---
|
||||||
|
{{- end }}
|
||||||
19
apps/charts/backup.disabled/values.yaml
Normal file
19
apps/charts/backup.disabled/values.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
globals:
|
||||||
|
environment: prod
|
||||||
|
timezone: Europe/Amsterdam
|
||||||
|
domain: olsen.cloud
|
||||||
|
image:
|
||||||
|
repository: garethgeorge/backrest
|
||||||
|
tag: latest@sha256:1308397161321b3c5aeca8acc6bf26eccb990df385f2532d3ce0eaa8b483dedf
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
subdomain: restic
|
||||||
|
password:
|
||||||
|
name: backup
|
||||||
|
key: password
|
||||||
|
jobs:
|
||||||
|
pictures:
|
||||||
|
cron:
|
||||||
|
backup: "0 2 * * *"
|
||||||
|
cleanup: "0 4 * * SUN"
|
||||||
|
source: pictures
|
||||||
|
target: backups
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: baikal
|
name: esphome
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
{{ include "common.database" . }}
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: PostgresDatabase
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,46 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: "{{ .Values.globals.timezone }}"
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /var/www/baikal/Specific
|
||||||
|
name: data
|
||||||
|
- mountPath: /var/www/baikal/config
|
||||||
|
name: config
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-config"
|
||||||
|
|||||||
11
apps/charts/baikal/templates/external-http-service.yaml
Normal file
11
apps/charts/baikal/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +1,24 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-data"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- "ReadWriteOnce"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "1Gi"
|
||||||
|
storageClassName: "{{ .Values.globals.environment }}"
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-config"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- "ReadWriteOnce"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "1Gi"
|
||||||
|
storageClassName: "{{ .Values.globals.environment }}"
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
|||||||
18
apps/charts/baikal/templates/virtual-service copy.yaml
Normal file
18
apps/charts/baikal/templates/virtual-service copy.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -2,49 +2,4 @@ image:
|
|||||||
repository: docker.io/ckulka/baikal
|
repository: docker.io/ckulka/baikal
|
||||||
tag: 0.10.1-nginx@sha256:434bdd162247cc6aa6f878c9b4dce6216e39e79526b980453b13812d5f8ebf4b
|
tag: 0.10.1-nginx@sha256:434bdd162247cc6aa6f878c9b4dce6216e39e79526b980453b13812d5f8ebf4b
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
subdomain: baikal
|
subdomain: baikal
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
port: 80
|
|
||||||
healthProbe:
|
|
||||||
type: tcpSocket
|
|
||||||
port: http # Use named port
|
|
||||||
|
|
||||||
# Database configuration
|
|
||||||
database:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
mountPath: /var/www/baikal/Specific
|
|
||||||
persistentVolumeClaim: data
|
|
||||||
- name: config
|
|
||||||
mountPath: /var/www/baikal/config
|
|
||||||
persistentVolumeClaim: config
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: data
|
|
||||||
size: 1Gi
|
|
||||||
- name: config
|
|
||||||
size: 1Gi
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
gateways:
|
|
||||||
public: true
|
|
||||||
private: true
|
|
||||||
|
|||||||
3
apps/charts/blinko/Chart.yaml
Normal file
3
apps/charts/blinko/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
version: 1.0.0
|
||||||
|
name: blinko
|
||||||
10
apps/charts/blinko/templates/client.yaml
Normal file
10
apps/charts/blinko/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
environment: "{{ .Values.globals.environment }}"
|
||||||
|
redirectUris:
|
||||||
|
- path: api/auth/callback/authentik
|
||||||
|
subdomain: "{{ .Values.subdomain }}"
|
||||||
|
matchingMode: strict
|
||||||
57
apps/charts/blinko/templates/deployment.yaml
Normal file
57
apps/charts/blinko/templates/deployment.yaml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 1111
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data
|
||||||
|
name: data
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: "{{ .Values.globals.timezone }}"
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: NEXTAUTH_URL
|
||||||
|
value: "https://{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- name: NEXT_PUBLIC_BASE_URL
|
||||||
|
value: "https://{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- name: NEXTAUTH_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-secrets"
|
||||||
|
key: betterauth
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-pg-connection"
|
||||||
|
key: url
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
11
apps/charts/blinko/templates/external-http-service.yaml
Normal file
11
apps/charts/blinko/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
11
apps/charts/blinko/templates/pvc.yaml
Normal file
11
apps/charts/blinko/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
9
apps/charts/blinko/templates/secret.yaml
Normal file
9
apps/charts/blinko/templates/secret.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: GenerateSecret
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-secrets'
|
||||||
|
spec:
|
||||||
|
fields:
|
||||||
|
- name: betterauth
|
||||||
|
encoding: base64
|
||||||
|
length: 64
|
||||||
15
apps/charts/blinko/templates/service.yaml
Normal file
15
apps/charts/blinko/templates/service.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 1111
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
18
apps/charts/blinko/templates/virtual-service.yaml
Normal file
18
apps/charts/blinko/templates/virtual-service.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
5
apps/charts/blinko/values.yaml
Normal file
5
apps/charts/blinko/values.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
image:
|
||||||
|
repository: blinkospace/blinko
|
||||||
|
tag: latest@sha256:04ad2a67f617e122db98425d39c2d0d901492729b3aee5a7e8c4d351009ee9e9
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
subdomain: blinko
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: bytestash
|
name: ByteStash
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
10
apps/charts/bytestash/templates/client.yaml
Normal file
10
apps/charts/bytestash/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /api/auth/oidc/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -1 +1,54 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
ports:
|
||||||
|
- containerPort: 5000
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
- name: ALLOW_NEW_ACCOUNTS
|
||||||
|
value: "true"
|
||||||
|
- name: DISABLE_INTERNAL_ACCOUNTS
|
||||||
|
value: "true"
|
||||||
|
- name: OIDC_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: OIDC_DISPLAY_NAME
|
||||||
|
value: OIDC
|
||||||
|
- name: OIDC_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientId
|
||||||
|
- name: OIDC_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientSecret
|
||||||
|
- name: OIDC_ISSUER_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: configurationIssuer
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data/snippets
|
||||||
|
name: data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
|||||||
11
apps/charts/bytestash/templates/external-http-service.yaml
Normal file
11
apps/charts/bytestash/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.oidc" . }}
|
|
||||||
@@ -1 +1,11 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 5000
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -1,74 +1,4 @@
|
|||||||
|
subdomain: bytestash
|
||||||
image:
|
image:
|
||||||
repository: ghcr.io/jordan-dalby/bytestash
|
repository: ghcr.io/jordan-dalby/bytestash
|
||||||
tag: 1.5.9@sha256:9c17b5510ca45c976fe23b0d4705ad416aa58d4bf756a70e03ef1f08cf7801fd
|
tag: 1.5.9@sha256:9c17b5510ca45c976fe23b0d4705ad416aa58d4bf756a70e03ef1f08cf7801fd
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
|
|
||||||
subdomain: bytestash
|
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 5000
|
|
||||||
protocol: TCP
|
|
||||||
healthProbe:
|
|
||||||
type: tcpSocket
|
|
||||||
port: http
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
mountPath: /data/snippets
|
|
||||||
persistentVolumeClaim: data
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: data
|
|
||||||
size: 1Gi
|
|
||||||
storageClassName: persistent
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
gateways:
|
|
||||||
public: true
|
|
||||||
private: true
|
|
||||||
|
|
||||||
# OIDC/Authentik configuration
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
redirectUris:
|
|
||||||
- "/api/auth/oidc/callback"
|
|
||||||
subjectMode: user_username
|
|
||||||
|
|
||||||
# Environment variables
|
|
||||||
env:
|
|
||||||
ALLOW_NEW_ACCOUNTS: "true"
|
|
||||||
DISABLE_INTERNAL_ACCOUNTS: "true"
|
|
||||||
OIDC_ENABLED: "true"
|
|
||||||
OIDC_DISPLAY_NAME: OIDC
|
|
||||||
OIDC_CLIENT_ID:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: clientId
|
|
||||||
OIDC_CLIENT_SECRET:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: clientSecret
|
|
||||||
OIDC_ISSUER_URL:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: issuer
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: calibre-web
|
name: calibre-web
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
10
apps/charts/calibre-web/templates/client.yaml
Normal file
10
apps/charts/calibre-web/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /api/auth/oidc/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -1 +1,44 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8083
|
||||||
|
name: http
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: "{{ .Values.globals.timezone }}"
|
||||||
|
- name: NETWORK_SHARE_MODE
|
||||||
|
value: "true"
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "1000"
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /config
|
||||||
|
name: data
|
||||||
|
- mountPath: /calibre-library
|
||||||
|
name: books
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
- name: books
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: books
|
||||||
|
|||||||
11
apps/charts/calibre-web/templates/external-http-service.yaml
Normal file
11
apps/charts/calibre-web/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +1,11 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 8083
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -2,49 +2,4 @@ image:
|
|||||||
repository: crocodilestick/calibre-web-automated
|
repository: crocodilestick/calibre-web-automated
|
||||||
tag: latest@sha256:577e846f104fd21453ef306eefb4a95dd95b3b9ddd2463a150944494284da0fd
|
tag: latest@sha256:577e846f104fd21453ef306eefb4a95dd95b3b9ddd2463a150944494284da0fd
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
subdomain: calibre-web
|
subdomain: calibre-web
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
port: 8083
|
|
||||||
healthProbe:
|
|
||||||
type: tcpSocket
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
mountPath: /config
|
|
||||||
persistentVolumeClaim: data # Will be prefixed with release name
|
|
||||||
- name: books
|
|
||||||
mountPath: /calibre-library
|
|
||||||
persistentVolumeClaim: books # External PVC, used as-is
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: data
|
|
||||||
size: 1Gi
|
|
||||||
storageClassName: persistent
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
gateways:
|
|
||||||
public: true
|
|
||||||
private: true
|
|
||||||
|
|
||||||
# Environment variables
|
|
||||||
env:
|
|
||||||
NETWORK_SHARE_MODE: "true"
|
|
||||||
PUID: "1000"
|
|
||||||
PGID: "1000"
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: coder
|
name: openwebui
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
10
apps/charts/coder/templates/client.yaml
Normal file
10
apps/charts/coder/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /api/v2/users/oidc/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -1 +1,74 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
serviceAccountName: "{{ .Release.Name }}-serviceaccount"
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 7080
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /home/coder/.config
|
||||||
|
name: data
|
||||||
|
env:
|
||||||
|
- name: CODER_HTTP_ADDRESS
|
||||||
|
value: "0.0.0.0:7080"
|
||||||
|
- name: CODER_OIDC_ALLOWED_GROUPS
|
||||||
|
value: admin
|
||||||
|
- name: CODER_OIDC_GROUP_FIELD
|
||||||
|
value: groups
|
||||||
|
- name: CODER_ACCESS_URL
|
||||||
|
value: https://coder.olsen.cloud
|
||||||
|
- name: CODER_OIDC_ICON_URL
|
||||||
|
value: https://authentik.olsen.cloud/static/dist/assets/icons/icon.png
|
||||||
|
- name: CODER_DISABLE_PASSWORD_AUTH
|
||||||
|
value: "true"
|
||||||
|
- name: CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
|
||||||
|
value: "false"
|
||||||
|
- name: CODER_OIDC_SIGN_IN_TEXT
|
||||||
|
value: "Sign in with OIDC"
|
||||||
|
- name: CODER_OIDC_SCOPES
|
||||||
|
value: openid,profile,email,offline_access
|
||||||
|
- name: CODER_OIDC_ISSUER_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: configurationIssuer
|
||||||
|
- name: CODER_OIDC_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientId
|
||||||
|
- name: CODER_OIDC_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-client"
|
||||||
|
key: clientSecret
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.oidc" . }}
|
|
||||||
@@ -1 +1,11 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
labels:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 7080
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: '{{ .Release.Name }}'
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -2,79 +2,4 @@ image:
|
|||||||
repository: ghcr.io/coder/coder
|
repository: ghcr.io/coder/coder
|
||||||
tag: v2.29.1@sha256:19b3ecd02510b4ee91ba488c61a3f40a6c164c9aeef38999c855e55fd653097c
|
tag: v2.29.1@sha256:19b3ecd02510b4ee91ba488c61a3f40a6c164c9aeef38999c855e55fd653097c
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
subdomain: coder
|
subdomain: coder
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
serviceAccountName: "{release}-serviceaccount" # Will be templated
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
port: 7080
|
|
||||||
healthProbe:
|
|
||||||
type: tcpSocket
|
|
||||||
port: http # Use named port
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# OIDC client
|
|
||||||
oidc:
|
|
||||||
enabled: true
|
|
||||||
redirectUris:
|
|
||||||
- "/api/v2/users/oidc/callback"
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
mountPath: /home/coder/.config
|
|
||||||
persistentVolumeClaim: data
|
|
||||||
storageClassName: persistent
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: data
|
|
||||||
size: 1Gi
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
allowWildcard: true
|
|
||||||
gateways:
|
|
||||||
public: false
|
|
||||||
private: true
|
|
||||||
|
|
||||||
# Environment variables
|
|
||||||
env:
|
|
||||||
CODER_HTTP_ADDRESS: "0.0.0.0:7080"
|
|
||||||
CODER_OIDC_ALLOWED_GROUPS: admin
|
|
||||||
CODER_OIDC_GROUP_FIELD: groups
|
|
||||||
CODER_ACCESS_URL:
|
|
||||||
value: "https://{subdomain}.{domain}"
|
|
||||||
CODER_WILDCARD_ACCESS_URL:
|
|
||||||
value: "*.{subdomain}.{domain}"
|
|
||||||
CODER_OIDC_ICON_URL: "https://{subdomain}.{domain}/static/dist/assets/icons/icon.png"
|
|
||||||
CODER_DISABLE_PASSWORD_AUTH: "true"
|
|
||||||
CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS: "false"
|
|
||||||
CODER_OIDC_SIGN_IN_TEXT: "Sign in with OIDC"
|
|
||||||
CODER_OIDC_SCOPES: "openid,profile,email,offline_access"
|
|
||||||
CODER_OIDC_ISSUER_URL:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: issuer
|
|
||||||
CODER_OIDC_CLIENT_ID:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: clientId
|
|
||||||
CODER_OIDC_CLIENT_SECRET:
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{release}-oidc-credentials"
|
|
||||||
key: clientSecret
|
|
||||||
|
|||||||
3
apps/charts/data/Chart.yaml
Normal file
3
apps/charts/data/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
version: 1.0.0
|
||||||
|
name: data
|
||||||
@@ -3,4 +3,4 @@ kind: PostgresDatabase
|
|||||||
metadata:
|
metadata:
|
||||||
name: '{{ .Release.Name }}'
|
name: '{{ .Release.Name }}'
|
||||||
spec:
|
spec:
|
||||||
environment: prod
|
environment: '{{ .Values.globals.environment }}'
|
||||||
1
apps/charts/data/values.yaml
Normal file
1
apps/charts/data/values.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
3
apps/charts/drip.disabled/Chart.yaml
Normal file
3
apps/charts/drip.disabled/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
version: 1.0.0
|
||||||
|
name: drip
|
||||||
80
apps/charts/drip.disabled/templates/deployment.yaml
Normal file
80
apps/charts/drip.disabled/templates/deployment.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.port }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: tcp-tunnel-min
|
||||||
|
containerPort: {{ .Values.service.tcpPortMin }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: tcp-tunnel-max
|
||||||
|
containerPort: {{ .Values.service.tcpPortMax }}
|
||||||
|
protocol: TCP
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /app/data
|
||||||
|
name: data
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: UTC
|
||||||
|
- name: AUTH_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-secrets"
|
||||||
|
key: authtoken
|
||||||
|
- name: DOMAIN
|
||||||
|
value: "{{ .Values.subdomain }}.{{ .Values.globals.environment }}"
|
||||||
|
command:
|
||||||
|
- drip-server
|
||||||
|
- --domain
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.environment }}"
|
||||||
|
- --port
|
||||||
|
- "{{ .Values.service.port }}"
|
||||||
|
- --token
|
||||||
|
- "$(AUTH_TOKEN)"
|
||||||
|
- --tcp-port-min
|
||||||
|
- "{{ .Values.service.tcpPortMin }}"
|
||||||
|
- --tcp-port-max
|
||||||
|
- "{{ .Values.service.tcpPortMax }}"
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: {{ .Values.healthcheck.test }}
|
||||||
|
initialDelaySeconds: {{ .Values.healthcheck.startPeriod | default 0 | trimSuffix "s" | int }}
|
||||||
|
periodSeconds: {{ .Values.healthcheck.interval | default 10 | trimSuffix "s" | int }}
|
||||||
|
timeoutSeconds: {{ .Values.healthcheck.timeout | default 1 | trimSuffix "s" | int }}
|
||||||
|
failureThreshold: {{ .Values.healthcheck.retries | default 3 }}
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: {{ .Values.healthcheck.test }}
|
||||||
|
initialDelaySeconds: {{ .Values.healthcheck.startPeriod | default 0 | trimSuffix "s" | int }}
|
||||||
|
periodSeconds: {{ .Values.healthcheck.interval | default 10 | trimSuffix "s" | int }}
|
||||||
|
timeoutSeconds: {{ .Values.healthcheck.timeout | default 1 | trimSuffix "s" | int }}
|
||||||
|
failureThreshold: {{ .Values.healthcheck.retries | default 3 }}
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: "{{ .Values.resources.limits.cpu }}"
|
||||||
|
memory: "{{ .Values.resources.limits.memory }}"
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: {{ .Values.service.port }}
|
||||||
11
apps/charts/drip.disabled/templates/pvc.yaml
Normal file
11
apps/charts/drip.disabled/templates/pvc.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-data"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
9
apps/charts/drip.disabled/templates/secret.yaml
Normal file
9
apps/charts/drip.disabled/templates/secret.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: GenerateSecret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}-secrets"
|
||||||
|
spec:
|
||||||
|
fields:
|
||||||
|
- name: authtoken
|
||||||
|
encoding: hex
|
||||||
|
length: 64
|
||||||
20
apps/charts/drip.disabled/templates/service.yaml
Normal file
20
apps/charts/drip.disabled/templates/service.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
- port: {{ .Values.service.tcpPortMin }}
|
||||||
|
targetPort: tcp-tunnel-min
|
||||||
|
protocol: TCP
|
||||||
|
name: tcp-tunnel-min
|
||||||
|
- port: {{ .Values.service.tcpPortMax }}
|
||||||
|
targetPort: tcp-tunnel-max
|
||||||
|
protocol: TCP
|
||||||
|
name: tcp-tunnel-max
|
||||||
|
selector:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
18
apps/charts/drip.disabled/templates/virtual-service.yaml
Normal file
18
apps/charts/drip.disabled/templates/virtual-service.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
27
apps/charts/drip.disabled/values.yaml
Normal file
27
apps/charts/drip.disabled/values.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
image:
|
||||||
|
repository: ghcr.io/gouryella/drip
|
||||||
|
tag: latest@sha256:440bcfd7eb75bf0b337d60346e44ae9e5be803e2504697ea7aa1b4f5fce568b9
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
subdomain: drip
|
||||||
|
|
||||||
|
service:
|
||||||
|
port: 443
|
||||||
|
tcpPortMin: 20000
|
||||||
|
tcpPortMax: 20100
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- wget
|
||||||
|
- --no-verbose
|
||||||
|
- --tries=1
|
||||||
|
- --spider
|
||||||
|
- http://localhost:443/health
|
||||||
|
interval: 30s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 3
|
||||||
|
startPeriod: 10s
|
||||||
3
apps/charts/environment/Chart.yaml
Normal file
3
apps/charts/environment/Chart.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
version: 1.0.0
|
||||||
|
name: environment
|
||||||
9
apps/charts/environment/templates/environment.yaml
Normal file
9
apps/charts/environment/templates/environment.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: Environment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.globals.environment }}"
|
||||||
|
spec:
|
||||||
|
domain: "{{ .Values.globals.domain }}"
|
||||||
|
networkIp: 192.168.20.180
|
||||||
|
tls:
|
||||||
|
issuer: lets-encrypt-prod
|
||||||
4
apps/charts/environment/values.yaml
Normal file
4
apps/charts/environment/values.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
globals:
|
||||||
|
environment: prod
|
||||||
|
timezone: Europe/Amsterdam
|
||||||
|
domain: olsen.cloud
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: esphome
|
name: esphome
|
||||||
dependencies:
|
|
||||||
- name: common
|
|
||||||
version: 1.0.0
|
|
||||||
repository: file://../../common
|
|
||||||
|
|||||||
@@ -1 +1,43 @@
|
|||||||
{{ include "common.deployment" . }}
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: "{{ .Release.Name }}"
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 6052
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: "{{ .Values.globals.timezone }}"
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /config
|
||||||
|
name: data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: "{{ .Release.Name }}-data"
|
||||||
|
|||||||
@@ -1 +1,11 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
{{ include "common.service" . }}
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
labels:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 6052
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
app: "{{ .Release.Name }}"
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
{{ include "common.virtualService" . }}
|
apiVersion: networking.istio.io/v1
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Release.Name }}"
|
||||||
|
namespace: "{{ .Release.Namespace }}"
|
||||||
|
spec:
|
||||||
|
gateways:
|
||||||
|
- "{{ .Values.globals.istio.gateway }}"
|
||||||
|
- mesh
|
||||||
|
hosts:
|
||||||
|
- "{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- mesh
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: "{{ .Release.Name }}"
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|||||||
@@ -1,43 +1,5 @@
|
|||||||
image:
|
image:
|
||||||
repository: ghcr.io/esphome/esphome
|
repository: ghcr.io/esphome/esphome
|
||||||
tag: 2025.12.4@sha256:a7915def0a60c76506db766b7b733760f09b47ab6a511d5052a6d38bc3f424e3
|
tag: 2025.12.1@sha256:3a81bf977aca174a74800e33baa11565a77c3f56b574206087555349c6f275bc
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
subdomain: esphome
|
subdomain: esphome
|
||||||
|
|
||||||
# Deployment configuration
|
|
||||||
deployment:
|
|
||||||
strategy: Recreate
|
|
||||||
replicas: 1
|
|
||||||
hostNetwork: true # ESPHome needs hostNetwork for device discovery
|
|
||||||
|
|
||||||
# Container configuration
|
|
||||||
container:
|
|
||||||
port: 6052
|
|
||||||
healthProbe:
|
|
||||||
type: tcpSocket
|
|
||||||
port: http # Use named port
|
|
||||||
|
|
||||||
# Service configuration
|
|
||||||
service:
|
|
||||||
port: 80
|
|
||||||
type: ClusterIP
|
|
||||||
|
|
||||||
# Volume configuration
|
|
||||||
volumes:
|
|
||||||
- name: data
|
|
||||||
mountPath: /config
|
|
||||||
persistentVolumeClaim: data
|
|
||||||
|
|
||||||
# Persistent volume claims
|
|
||||||
persistentVolumeClaims:
|
|
||||||
- name: data
|
|
||||||
size: 10Gi
|
|
||||||
storageClassName: persistent
|
|
||||||
|
|
||||||
# VirtualService configuration
|
|
||||||
virtualService:
|
|
||||||
enabled: true
|
|
||||||
gateways:
|
|
||||||
public: false
|
|
||||||
private: true
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ apiVersion: v2
|
|||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
name: forgejo
|
name: forgejo
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: common
|
- name: woodpecker
|
||||||
version: 1.0.0
|
version: 3.4.2
|
||||||
repository: file://../../common
|
repository: https://woodpecker-ci.org/
|
||||||
|
|
||||||
|
|||||||
10
apps/charts/forgejo/templates/client.yaml
Normal file
10
apps/charts/forgejo/templates/client.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: OidcClient
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
redirectUris:
|
||||||
|
- path: /user/oauth2/Authentik/callback
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
matchingMode: strict
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
{{ include "common.database" . }}
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: PostgresDatabase
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1,76 +1,106 @@
|
|||||||
{{- if .Values.actions.enabled }}
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "common.fullname" . }}
|
name: "{{ .Release.Name }}"
|
||||||
labels:
|
|
||||||
{{- include "common.labels" . | nindent 4 }}
|
|
||||||
spec:
|
spec:
|
||||||
strategy:
|
strategy:
|
||||||
type: {{ include "common.deploymentStrategy" . }}
|
type: Recreate
|
||||||
replicas: {{ .Values.deployment.replicas | default 1 }}
|
replicas: 1
|
||||||
{{- if .Values.deployment.revisionHistoryLimit }}
|
revisionHistoryLimit: 0
|
||||||
revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }}
|
|
||||||
{{- end }}
|
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "common.selectorLabels" . | nindent 6 }}
|
app: "{{ .Release.Name }}"
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
{{- include "common.selectorLabels" . | nindent 8 }}
|
app: "{{ .Release.Name }}"
|
||||||
spec:
|
spec:
|
||||||
{{- if .Values.deployment.serviceAccountName }}
|
|
||||||
serviceAccountName: {{ .Values.deployment.serviceAccountName | replace "{release}" .Release.Name | replace "{fullname}" (include "common.fullname" .) }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.deployment.hostNetwork }}
|
|
||||||
hostNetwork: {{ .Values.deployment.hostNetwork }}
|
|
||||||
{{- end }}
|
|
||||||
containers:
|
containers:
|
||||||
- name: {{ .Chart.Name }}
|
- name: "{{ .Release.Name }}"
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
|
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
|
||||||
ports:
|
ports:
|
||||||
{{ include "common.containerPorts" . | indent 12 }}
|
- name: http
|
||||||
{{- if .Values.container.healthProbe }}
|
containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
- name: ssh
|
||||||
|
containerPort: 22
|
||||||
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
{{ include "common.healthProbe" . | indent 12 }}
|
tcpSocket:
|
||||||
|
port: http
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
{{ include "common.healthProbe" . | indent 12 }}
|
tcpSocket:
|
||||||
{{- end }}
|
port: http
|
||||||
lifecycle:
|
|
||||||
postStart:
|
|
||||||
exec:
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
sleep 10
|
|
||||||
su -c "forgejo forgejo-cli actions register --keep-labels --secret ${FORGEJO_RUNNER_SHARED_SECRET}" git || true
|
|
||||||
{{- if .Values.volumes }}
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
{{ include "common.volumeMounts" . | indent 12 }}
|
- mountPath: /data
|
||||||
{{- end }}
|
name: data
|
||||||
{{- if or .Values.env .Values.globals.timezone }}
|
|
||||||
env:
|
env:
|
||||||
{{ include "common.env" . | indent 12 }}
|
- name: TZ
|
||||||
- name: FORGEJO_RUNNER_SHARED_SECRET
|
value: "{{ .Values.globals.timezone }}"
|
||||||
|
- name: USER_UID
|
||||||
|
value: "1000"
|
||||||
|
- name: USER_GID
|
||||||
|
value: "1000"
|
||||||
|
- name: FORGEJO__server__SSH_DOMAIN
|
||||||
|
value: "ssh-{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
||||||
|
- name: FORGEJO__server__SSH_PORT
|
||||||
|
value: "2206"
|
||||||
|
- name: FORGEJO__service__REQUIRE_EXTERNAL_REGISTRATION_PASSWORD
|
||||||
|
value: "true"
|
||||||
|
#- name: FORGEJO__service__ENABLE_BASIC_AUTHENTICATION
|
||||||
|
# value: 'true'
|
||||||
|
- name: FORGEJO__service__ENABLE_PASSWORD_SIGNIN_FORM
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__service__DEFAULT_KEEP_EMAIL_PRIVATE
|
||||||
|
value: "true"
|
||||||
|
- name: FORGEJO__service__DEFAULT_USER_IS_RESTRICTED
|
||||||
|
value: "true"
|
||||||
|
- name: FORGEJO__service__DEFAULT_USER_VISIBILITY
|
||||||
|
value: "private"
|
||||||
|
- name: FORGEJO__service__DEFAULT_ORG_VISIBILITY
|
||||||
|
value: "private"
|
||||||
|
- name: FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION
|
||||||
|
value: "true"
|
||||||
|
- name: FORGEJO__other__SHOW_FOOTER_POWERED_BY
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__other__SHOW_FOOTER_TEMPLATE_LOAD_TIME
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__other__SHOW_FOOTER_VERSION
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__repository__ENABLE_PUSH_CREATE_USER
|
||||||
|
value: "true"
|
||||||
|
- name: FORGEJO__repository__ENABLE_PUSH_CREATE_ORG
|
||||||
|
value: "true"
|
||||||
|
- name: FORGEJO__openid__ENABLE_OPENID_SIGNIN
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__openid__ENABLE_OPENID_SIGNUP
|
||||||
|
value: "false"
|
||||||
|
- name: FORGEJO__database__DB_TYPE
|
||||||
|
value: postgres
|
||||||
|
- name: FORGEJO__database__NAME
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Release.Name }}-runner-secrets"
|
name: "{{ .Release.Name }}-pg-connection"
|
||||||
key: shared-secret
|
key: database
|
||||||
{{- else }}
|
- name: FORGEJO__database__HOST
|
||||||
env:
|
|
||||||
- name: FORGEJO_RUNNER_SHARED_SECRET
|
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Release.Name }}-runner-secrets"
|
name: "{{ .Release.Name }}-pg-connection"
|
||||||
key: shared-secret
|
key: host
|
||||||
{{- end }}
|
- name: FORGEJO__database__DB_PORT
|
||||||
{{- if .Values.volumes }}
|
value: "5432"
|
||||||
|
- name: FORGEJO__database__USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-pg-connection"
|
||||||
|
key: user
|
||||||
|
- name: FORGEJO__database__PASSWD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Release.Name }}-pg-connection"
|
||||||
|
key: password
|
||||||
volumes:
|
volumes:
|
||||||
{{- include "common.volumes" . | nindent 8 }}
|
- name: data
|
||||||
{{- end }}
|
persistentVolumeClaim:
|
||||||
{{- else }}
|
claimName: "{{ .Release.Name }}-data"
|
||||||
{{ include "common.deployment" . }}
|
|
||||||
{{- end }}
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.dns" . }}
|
|
||||||
11
apps/charts/forgejo/templates/external-http-service.yaml
Normal file
11
apps/charts/forgejo/templates/external-http-service.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: homelab.mortenolsen.pro/v1
|
||||||
|
kind: ExternalHttpService
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}'
|
||||||
|
spec:
|
||||||
|
environment: '{{ .Values.globals.environment }}'
|
||||||
|
subdomain: '{{ .Values.subdomain }}'
|
||||||
|
destination:
|
||||||
|
host: '{{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local'
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{ include "common.oidc" . }}
|
|
||||||
@@ -1 +1,11 @@
|
|||||||
{{ include "common.pvc" . }}
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: '{{ .Release.Name }}-data'
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- 'ReadWriteOnce'
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: '1Gi'
|
||||||
|
storageClassName: '{{ .Values.globals.environment }}'
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
{{- if .Values.actions.enabled }}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-runner-config"
|
|
||||||
data:
|
|
||||||
config.yml: |
|
|
||||||
log:
|
|
||||||
level: warn
|
|
||||||
format: text
|
|
||||||
|
|
||||||
runner:
|
|
||||||
file: .runner
|
|
||||||
|
|
||||||
container:
|
|
||||||
network: host
|
|
||||||
options: -v /certs/client:/certs/client -e DOCKER_HOST=tcp://localhost:2376 -e DOCKER_TLS_VERIFY=1 -e DOCKER_CERT_PATH=/certs/client
|
|
||||||
valid_volumes:
|
|
||||||
- /certs/client
|
|
||||||
|
|
||||||
envs:
|
|
||||||
DOCKER_HOST: tcp://localhost:2376
|
|
||||||
DOCKER_TLS_VERIFY: "1"
|
|
||||||
DOCKER_CERT_PATH: /certs/client
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
{{- if .Values.actions.enabled }}
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-runner"
|
|
||||||
labels:
|
|
||||||
app: "{{ .Release.Name }}-runner"
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.actions.runner.replicas | default 1 }}
|
|
||||||
revisionHistoryLimit: 2
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: "{{ .Release.Name }}-runner"
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: "{{ .Release.Name }}-runner"
|
|
||||||
spec:
|
|
||||||
hostname: docker
|
|
||||||
initContainers:
|
|
||||||
- name: install-jq
|
|
||||||
image: curlimages/curl:latest
|
|
||||||
command:
|
|
||||||
- sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
# Download static jq binary for Linux amd64
|
|
||||||
curl -L -o /shared/jq https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64
|
|
||||||
chmod +x /shared/jq
|
|
||||||
# Verify it works
|
|
||||||
/shared/jq --version || echo "Warning: jq download may have failed"
|
|
||||||
volumeMounts:
|
|
||||||
- name: shared-tools
|
|
||||||
mountPath: /shared
|
|
||||||
containers:
|
|
||||||
- name: docker-in-docker
|
|
||||||
image: "{{ .Values.actions.runner.dind.image.repository }}:{{ .Values.actions.runner.dind.image.tag }}"
|
|
||||||
imagePullPolicy: "{{ .Values.actions.runner.dind.image.pullPolicy }}"
|
|
||||||
env:
|
|
||||||
- name: DOCKER_TLS_CERTDIR
|
|
||||||
value: /certs
|
|
||||||
- name: DOCKER_HOST
|
|
||||||
value: docker-in-docker
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
ports:
|
|
||||||
- name: docker
|
|
||||||
containerPort: 2376
|
|
||||||
protocol: TCP
|
|
||||||
volumeMounts:
|
|
||||||
- name: docker-certs
|
|
||||||
mountPath: /certs
|
|
||||||
- name: "{{ .Release.Name }}-runner"
|
|
||||||
image: "{{ .Values.actions.runner.image.repository }}:{{ .Values.actions.runner.image.tag }}"
|
|
||||||
imagePullPolicy: "{{ .Values.actions.runner.image.pullPolicy }}"
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
cd /data
|
|
||||||
# Use jq from shared volume (installed by initContainer)
|
|
||||||
export PATH="/shared:${PATH}"
|
|
||||||
export LD_LIBRARY_PATH="/shared/lib:${LD_LIBRARY_PATH}"
|
|
||||||
if ! /shared/jq --version >/dev/null 2>&1; then
|
|
||||||
echo "Error: jq is not working (checking dependencies...)"
|
|
||||||
ldd /shared/jq 2>&1 || true
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "jq is available at /shared/jq"
|
|
||||||
# Wait for shared secret to be available
|
|
||||||
while [ -z "${FORGEJO_RUNNER_SHARED_SECRET}" ]; do
|
|
||||||
echo "Waiting for shared secret..."
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
# Always ensure runner file exists and is up to date
|
|
||||||
if [ ! -f .runner ]; then
|
|
||||||
echo "Creating runner file..."
|
|
||||||
forgejo-runner create-runner-file \
|
|
||||||
--connect \
|
|
||||||
--instance "https://{{ .Values.subdomain }}.{{ .Values.globals.domain }}" \
|
|
||||||
--name "{{ .Values.actions.runner.name | default "default" }}" \
|
|
||||||
--secret "${FORGEJO_RUNNER_SHARED_SECRET}" || {
|
|
||||||
echo "Failed to create runner file, will retry..."
|
|
||||||
sleep 5
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
# Always update labels to match configuration
|
|
||||||
{{- if .Values.actions.runner.labels }}
|
|
||||||
# Verify jq is available
|
|
||||||
if ! command -v jq >/dev/null 2>&1; then
|
|
||||||
echo "Error: jq is not available"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
LABELS_JSON='[{{- range $index, $label := .Values.actions.runner.labels }}{{- if $index }},{{- end }}"{{ $label }}"{{- end }}]'
|
|
||||||
echo "Updating runner labels to match configuration..."
|
|
||||||
echo "New labels: ${LABELS_JSON}"
|
|
||||||
# Ensure .runner file exists and is readable
|
|
||||||
if [ ! -f .runner ]; then
|
|
||||||
echo "Error: .runner file does not exist"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Show current labels before update
|
|
||||||
CURRENT_LABELS_BEFORE=$(jq -r '.labels // "null"' .runner 2>/dev/null || echo "error reading file")
|
|
||||||
echo "Current labels before update: ${CURRENT_LABELS_BEFORE}"
|
|
||||||
# Update labels
|
|
||||||
if jq --argjson labels "${LABELS_JSON}" '.labels = $labels' .runner > .runner.tmp; then
|
|
||||||
mv .runner.tmp .runner
|
|
||||||
echo "Labels updated successfully"
|
|
||||||
# Verify the update
|
|
||||||
CURRENT_LABELS_AFTER=$(jq -r '.labels // "null"' .runner)
|
|
||||||
echo "Current labels after update: ${CURRENT_LABELS_AFTER}"
|
|
||||||
else
|
|
||||||
echo "Error: Failed to update labels with jq"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
{{- end }}
|
|
||||||
# Always copy config from ConfigMap to ensure it's up to date
|
|
||||||
echo "Copying config from ConfigMap..."
|
|
||||||
cp /config/config.yml config.yml || {
|
|
||||||
echo "Warning: Failed to copy config from ConfigMap, generating default..."
|
|
||||||
forgejo-runner generate-config > config.yml
|
|
||||||
}
|
|
||||||
# Wait for docker-in-docker TCP to be ready
|
|
||||||
echo "Waiting for docker-in-docker to be ready..."
|
|
||||||
while ! nc -z localhost 2376 2>/dev/null; do
|
|
||||||
echo "Docker daemon not ready, waiting..."
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
# Wait for TLS certificates to be available
|
|
||||||
while [ ! -f /certs/client/ca.pem ]; do
|
|
||||||
echo "Waiting for TLS certificates..."
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
echo "Docker daemon and certificates ready"
|
|
||||||
# Verify runner file exists before starting daemon
|
|
||||||
if [ ! -f .runner ] || [ ! -w .runner ]; then
|
|
||||||
echo "Error: .runner file is missing or not writable"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Run daemon
|
|
||||||
echo "Starting runner daemon..."
|
|
||||||
while : ; do
|
|
||||||
forgejo-runner --config config.yml daemon || {
|
|
||||||
echo "Daemon exited, restarting in 5 seconds..."
|
|
||||||
sleep 5
|
|
||||||
}
|
|
||||||
done
|
|
||||||
env:
|
|
||||||
- name: FORGEJO_INSTANCE_URL
|
|
||||||
value: "https://{{ .Values.subdomain }}.{{ .Values.globals.domain }}"
|
|
||||||
- name: FORGEJO_RUNNER_NAME
|
|
||||||
value: {{ .Values.actions.runner.name | default "default" | quote }}
|
|
||||||
- name: FORGEJO_RUNNER_SHARED_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Release.Name }}-runner-secrets"
|
|
||||||
key: shared-secret
|
|
||||||
- name: DOCKER_HOST
|
|
||||||
value: tcp://localhost:2376
|
|
||||||
- name: DOCKER_TLS_VERIFY
|
|
||||||
value: "1"
|
|
||||||
- name: DOCKER_CERT_PATH
|
|
||||||
value: /certs/client
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 1000
|
|
||||||
runAsGroup: 1000
|
|
||||||
volumeMounts:
|
|
||||||
- name: runner-data
|
|
||||||
mountPath: /data
|
|
||||||
- name: docker-certs
|
|
||||||
mountPath: /certs
|
|
||||||
- name: runner-config
|
|
||||||
mountPath: /config
|
|
||||||
readOnly: true
|
|
||||||
- name: shared-tools
|
|
||||||
mountPath: /shared
|
|
||||||
volumes:
|
|
||||||
- name: runner-data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: "{{ .Release.Name }}-runner-data"
|
|
||||||
- name: docker-certs
|
|
||||||
emptyDir: {}
|
|
||||||
- name: shared-tools
|
|
||||||
emptyDir: {}
|
|
||||||
- name: runner-config
|
|
||||||
configMap:
|
|
||||||
name: "{{ .Release.Name }}-runner-config"
|
|
||||||
{{- end }}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user