Add new infra architecture 12

This commit is contained in:
Urtzi Alfaro
2026-01-21 16:21:24 +01:00
parent 2512de4173
commit 66dfd50fbc
20 changed files with 4082 additions and 480 deletions

View File

@@ -4,124 +4,185 @@ This directory contains the Helm values and scripts for setting up Gitea as the
## Features
- **Automatic Repository Creation**: When Gitea is installed via Helm, it automatically creates a `bakery-ia` repository owned by the admin user.
- **Pre-configured Settings**: The repository comes with issues, wiki, pull requests, and projects enabled.
- **Easy Setup Script**: A script to push your existing code to the new Gitea repository.
- **Automatic Admin User**: Admin user is created automatically from Kubernetes secret
- **Automatic Repository Creation**: The `bakery-ia` repository is created via a Kubernetes Job after Gitea starts
- **Registry Support**: Container registry enabled for storing Docker images
- **Tekton Integration**: Webhook automatically configured if Tekton is installed
## Installation
## Quick Start
### 1. Install Gitea with Helm
### Development
```bash
# Add Gitea Helm repository
# 1. Setup secrets and init job (uses default dev password)
./infrastructure/cicd/gitea/setup-admin-secret.sh
# 2. Install Gitea
helm repo add gitea https://dl.gitea.io/charts
helm repo update
helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
# Create namespace
kubectl create namespace gitea
# Install Gitea with automatic repository creation
helm install gitea gitea/gitea -n gitea \
-f infrastructure/cicd/gitea/values.yaml \
--set gitea.admin.password=your-secure-password
```
### 2. Wait for Gitea to be ready
```bash
# 3. Wait for everything to be ready
kubectl wait --for=condition=ready pod -n gitea -l app.kubernetes.io/name=gitea --timeout=300s
# 4. Check init job completed
kubectl logs -n gitea -l app.kubernetes.io/component=init --tail=50
```
### 3. Push your code to the new repository
### Production
```bash
# Set the admin password as environment variable
export GITEA_ADMIN_PASSWORD="your-secure-password"
# 1. Generate and export secure password
export GITEA_ADMIN_PASSWORD=$(openssl rand -base64 32)
# Run the setup script
./infrastructure/cicd/gitea/setup-gitea-repository.sh
# 2. Setup secrets with production flag (requires GITEA_ADMIN_PASSWORD)
./infrastructure/cicd/gitea/setup-admin-secret.sh --production
# 3. Install Gitea with production values
helm repo add gitea https://dl.gitea.io/charts
helm upgrade --install gitea gitea/gitea -n gitea \
-f infrastructure/cicd/gitea/values.yaml \
-f infrastructure/cicd/gitea/values-prod.yaml
# 4. Wait for everything to be ready
kubectl wait --for=condition=ready pod -n gitea -l app.kubernetes.io/name=gitea --timeout=300s
# 5. Install Tekton CI/CD (see tekton-helm/README.md for details)
export TEKTON_WEBHOOK_TOKEN=$(openssl rand -hex 32)
helm upgrade --install tekton-cicd infrastructure/cicd/tekton-helm \
-n tekton-pipelines \
-f infrastructure/cicd/tekton-helm/values.yaml \
-f infrastructure/cicd/tekton-helm/values-prod.yaml \
--set secrets.webhook.token=$TEKTON_WEBHOOK_TOKEN \
--set secrets.registry.password=$GITEA_ADMIN_PASSWORD \
--set secrets.git.password=$GITEA_ADMIN_PASSWORD
```
## Configuration Details
## Files
### Automatic Repository Creation
| File | Description |
|------|-------------|
| `values.yaml` | Helm values for Gitea chart |
| `values-prod.yaml` | Production Helm values |
| `setup-admin-secret.sh` | Creates secrets and applies init job |
| `gitea-init-job.yaml` | Kubernetes Job to create initial repository |
| `setup-gitea-repository.sh` | Helper to push local code to Gitea |
The `values.yaml` file includes the following configuration to automatically create the `bakery-ia` repository:
## How It Works
### 1. Admin User Initialization
The Gitea Helm chart automatically creates the admin user on first install. Credentials are read from a Kubernetes secret:
```yaml
gitea:
initialRepositories:
- name: bakery-ia
description: "Main repository for Bakery IA project - Automatically created by Helm"
private: false
auto_init: true
default_branch: main
owner: "{{ .Values.gitea.admin.username }}"
enable_issues: true
enable_wiki: true
enable_pull_requests: true
enable_projects: true
admin:
username: bakery-admin
email: admin@bakery-ia.local
existingSecret: gitea-admin-secret # Secret with username/password keys
passwordMode: keepUpdated # Sync password changes from secret
```
### Repository Features
The `setup-admin-secret.sh` script creates this secret before Helm install.
The automatically created repository includes:
- **Issues**: For tracking bugs and feature requests
- **Wiki**: For project documentation
- **Pull Requests**: For code review workflow
- **Projects**: For project management
- **Auto Initialization**: Creates an initial README.md file
### 2. Repository Initialization
Since the Gitea Helm chart doesn't support automatic repository creation, we use a Kubernetes Job (`gitea-init-job.yaml`) that:
1. Waits for Gitea to be ready
2. Creates the `bakery-ia` repository via Gitea API
3. Optionally configures a webhook for Tekton CI/CD
The Job is idempotent - it skips creation if the repository already exists.
## Detailed Installation
### Step 1: Create Secrets
```bash
# Using default password (for dev environments)
./infrastructure/cicd/gitea/setup-admin-secret.sh
# Or specify a custom password
./infrastructure/cicd/gitea/setup-admin-secret.sh "your-secure-password"
# Or use environment variable
export GITEA_ADMIN_PASSWORD="your-secure-password"
./infrastructure/cicd/gitea/setup-admin-secret.sh
```
This creates:
- `gitea-admin-secret` in `gitea` namespace - used by Gitea for admin credentials
- `gitea-registry-secret` in `bakery-ia` namespace - used for `imagePullSecrets`
- Applies `gitea-init-job.yaml` (ConfigMap + Job)
### Step 2: Install Gitea
```bash
helm repo add gitea https://dl.gitea.io/charts
helm repo update
helm install gitea gitea/gitea -n gitea \
-f infrastructure/cicd/gitea/values.yaml
```
### Step 3: Verify Installation
```bash
# Wait for Gitea pod
kubectl wait --for=condition=ready pod -n gitea -l app.kubernetes.io/name=gitea --timeout=300s
# Check init job logs
kubectl logs -n gitea job/gitea-init-repo
# Verify repository was created
curl -u bakery-admin:pvYUkGWJijqc0QfIZEXw \
https://gitea.bakery-ia.local/api/v1/repos/bakery-admin/bakery-ia
```
## CI/CD Integration
Once the repository is created and your code is pushed, you can configure your CI/CD pipelines to use this repository. The repository URL will be:
Repository URL:
```
https://gitea.bakery-ia.local/bakery-admin/bakery-ia.git
```
### Example Tekton Pipeline Configuration
```yaml
# In your Tekton PipelineRun or Task
spec:
params:
- name: git-url
value: "https://gitea.bakery-ia.local/bakery-admin/bakery-ia.git"
- name: git-revision
value: "main"
Internal cluster URL (for pipelines):
```
http://gitea-http.gitea.svc.cluster.local:3000/bakery-admin/bakery-ia.git
```
## Troubleshooting
### Repository not created
### Init Job Failed
If the repository is not automatically created:
1. Check Gitea logs: `kubectl logs -n gitea -l app.kubernetes.io/name=gitea`
2. Verify the Helm values were applied correctly
3. Manually create the repository using the setup script
```bash
# Check job status
kubectl get jobs -n gitea
### Authentication issues
# View logs
kubectl logs -n gitea job/gitea-init-repo
If you have authentication problems when pushing:
1. Verify the admin password is correct
2. Check that the Gitea service is accessible
3. Ensure your kubeconfig has access to the Gitea namespace
# Re-run the job
kubectl delete job gitea-init-repo -n gitea
kubectl apply -f infrastructure/cicd/gitea/gitea-init-job.yaml
```
## Security Notes
### Repository Not Created
- Always use a strong password for the Gitea admin user
- Consider using Kubernetes secrets for sensitive data
- The setup script uses basic authentication - for production, consider using SSH keys or tokens
1. Check if Gitea is ready: `kubectl get pods -n gitea`
2. Check init job logs: `kubectl logs -n gitea job/gitea-init-repo`
3. Manually create via API or use `setup-gitea-repository.sh`
### Authentication Issues
1. Verify secret exists: `kubectl get secret gitea-admin-secret -n gitea`
2. Check credentials: `kubectl get secret gitea-admin-secret -n gitea -o jsonpath='{.data.password}' | base64 -d`
## Upgrading
To upgrade Gitea while preserving your repositories:
```bash
helm upgrade gitea gitea/gitea -n gitea \
-f infrastructure/cicd/gitea/values.yaml \
--set gitea.admin.password=your-secure-password
-f infrastructure/cicd/gitea/values.yaml
```
The existing repositories and their contents will be preserved during upgrades.
Repositories and data are preserved during upgrades (stored in PVC).

View File

@@ -0,0 +1,176 @@
# Gitea Initialization Job
# This Job runs after Gitea is installed to create the initial repository
# It uses the same admin credentials from gitea-admin-secret
#
# Apply after Gitea is ready:
# kubectl apply -f gitea-init-job.yaml -n gitea
#
# To re-run (if needed):
# kubectl delete job gitea-init-repo -n gitea
# kubectl apply -f gitea-init-job.yaml -n gitea
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-init-script
namespace: gitea
labels:
app.kubernetes.io/name: gitea
app.kubernetes.io/component: init
data:
init-repo.sh: |
#!/bin/sh
set -e
GITEA_URL="http://gitea-http.gitea.svc.cluster.local:3000"
REPO_NAME="bakery-ia"
MAX_RETRIES=30
RETRY_INTERVAL=10
echo "=== Gitea Repository Initialization ==="
echo "Gitea URL: $GITEA_URL"
echo "Repository: $REPO_NAME"
echo "Admin User: $GITEA_ADMIN_USER"
# Wait for Gitea to be ready
echo ""
echo "Waiting for Gitea to be ready..."
RETRIES=0
until curl -sf "$GITEA_URL/api/v1/version" > /dev/null 2>&1; do
RETRIES=$((RETRIES + 1))
if [ $RETRIES -ge $MAX_RETRIES ]; then
echo "ERROR: Gitea did not become ready after $MAX_RETRIES attempts"
exit 1
fi
echo " Attempt $RETRIES/$MAX_RETRIES - Gitea not ready, waiting ${RETRY_INTERVAL}s..."
sleep $RETRY_INTERVAL
done
echo "Gitea is ready!"
# Check if repository already exists
echo ""
echo "Checking if repository '$REPO_NAME' exists..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASSWORD" \
"$GITEA_URL/api/v1/repos/$GITEA_ADMIN_USER/$REPO_NAME")
if [ "$HTTP_CODE" = "200" ]; then
echo "Repository '$REPO_NAME' already exists. Nothing to do."
exit 0
fi
# Create the repository
echo "Creating repository '$REPO_NAME'..."
RESPONSE=$(curl -s -w "\n%{http_code}" \
-u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASSWORD" \
-X POST "$GITEA_URL/api/v1/user/repos" \
-H "Content-Type: application/json" \
-d '{
"name": "'"$REPO_NAME"'",
"description": "Main repository for Bakery IA project - Automatically created",
"private": false,
"auto_init": true,
"default_branch": "main",
"readme": "Default"
}')
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP_CODE" = "201" ]; then
echo "Repository '$REPO_NAME' created successfully!"
echo ""
echo "Repository URL: $GITEA_URL/$GITEA_ADMIN_USER/$REPO_NAME"
echo "Clone URL: $GITEA_URL/$GITEA_ADMIN_USER/$REPO_NAME.git"
else
echo "ERROR: Failed to create repository (HTTP $HTTP_CODE)"
echo "Response: $BODY"
exit 1
fi
# Configure webhook for Tekton (optional - if Tekton is installed)
echo ""
echo "Checking if Tekton EventListener is available..."
TEKTON_URL="http://el-bakery-ia-listener.tekton-pipelines.svc.cluster.local:8080"
if curl -sf "$TEKTON_URL" > /dev/null 2>&1; then
echo "Tekton EventListener found. Creating webhook..."
WEBHOOK_RESPONSE=$(curl -s -w "\n%{http_code}" \
-u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASSWORD" \
-X POST "$GITEA_URL/api/v1/repos/$GITEA_ADMIN_USER/$REPO_NAME/hooks" \
-H "Content-Type: application/json" \
-d '{
"type": "gitea",
"config": {
"url": "'"$TEKTON_URL"'",
"content_type": "json"
},
"events": ["push"],
"active": true
}')
WEBHOOK_CODE=$(echo "$WEBHOOK_RESPONSE" | tail -1)
if [ "$WEBHOOK_CODE" = "201" ]; then
echo "Webhook created successfully!"
else
echo "Warning: Could not create webhook (HTTP $WEBHOOK_CODE). You may need to configure it manually."
fi
else
echo "Tekton EventListener not available. Skipping webhook creation."
fi
echo ""
echo "=== Initialization Complete ==="
---
apiVersion: batch/v1
kind: Job
metadata:
name: gitea-init-repo
namespace: gitea
labels:
app.kubernetes.io/name: gitea
app.kubernetes.io/component: init
annotations:
# Helm hook annotations (if used with Helm)
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "10"
helm.sh/hook-delete-policy: before-hook-creation
spec:
ttlSecondsAfterFinished: 300
backoffLimit: 3
template:
metadata:
labels:
app.kubernetes.io/name: gitea
app.kubernetes.io/component: init
spec:
restartPolicy: OnFailure
containers:
- name: init-repo
image: curlimages/curl:8.5.0
command: ["/bin/sh", "/scripts/init-repo.sh"]
env:
- name: GITEA_ADMIN_USER
valueFrom:
secretKeyRef:
name: gitea-admin-secret
key: username
- name: GITEA_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: gitea-admin-secret
key: password
volumeMounts:
- name: init-script
mountPath: /scripts
resources:
limits:
cpu: 100m
memory: 64Mi
requests:
cpu: 50m
memory: 32Mi
volumes:
- name: init-script
configMap:
name: gitea-init-script
defaultMode: 0755

View File

@@ -1,41 +1,86 @@
#!/bin/bash
# Setup Gitea Admin Secret
# Setup Gitea Admin Secret and Initialize Gitea
#
# This script creates TWO Kubernetes secrets:
# 1. gitea-admin-secret (gitea namespace) - Used by Gitea Helm chart for admin credentials
# 2. gitea-registry-secret (bakery-ia namespace) - Used by pods for imagePullSecrets
#
# Both secrets use the SAME credentials, ensuring consistency.
# This script:
# 1. Creates gitea-admin-secret (gitea namespace) - Used by Gitea Helm chart for admin credentials
# 2. Creates gitea-registry-secret (bakery-ia namespace) - Used by pods for imagePullSecrets
# 3. Applies the gitea-init-job.yaml to create the initial repository
#
# Usage:
# ./setup-admin-secret.sh [password]
# Development:
# ./setup-admin-secret.sh # Uses default dev password
# ./setup-admin-secret.sh [password] # Uses provided password
# ./setup-admin-secret.sh --secrets-only # Only create secrets, skip init job
#
# If password is not provided, a random one will be generated.
# Production:
# export GITEA_ADMIN_PASSWORD=$(openssl rand -base64 32)
# ./setup-admin-secret.sh --production
# ./setup-admin-secret.sh --production --secrets-only
#
# Environment variables:
# GITEA_ADMIN_PASSWORD - Password to use (required for --production)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
KUBECTL="kubectl"
GITEA_NAMESPACE="gitea"
BAKERY_NAMESPACE="bakery-ia"
REGISTRY_HOST="registry.bakery-ia.local"
ADMIN_USERNAME="bakery-admin"
# Static password for consistent dev environment setup
# This ensures the same credentials work across environment recreations
STATIC_ADMIN_PASSWORD="pvYUkGWJijqc0QfIZEXw"
# Default password for dev environment only
# For PRODUCTION: Always set GITEA_ADMIN_PASSWORD environment variable
# Generate secure password with: openssl rand -base64 32
DEV_DEFAULT_PASSWORD="pvYUkGWJijqc0QfIZEXw"
SECRETS_ONLY=false
IS_PRODUCTION=false
# Check if running in microk8s
if command -v microk8s &> /dev/null; then
KUBECTL="microk8s kubectl"
fi
# Get password from argument, environment variable, or use static default
if [ -n "$1" ]; then
ADMIN_PASSWORD="$1"
elif [ -n "$GITEA_ADMIN_PASSWORD" ]; then
ADMIN_PASSWORD="$GITEA_ADMIN_PASSWORD"
else
ADMIN_PASSWORD="$STATIC_ADMIN_PASSWORD"
echo "Using static admin password for dev environment consistency"
# Parse arguments
for arg in "$@"; do
case $arg in
--secrets-only)
SECRETS_ONLY=true
;;
--production)
IS_PRODUCTION=true
REGISTRY_HOST="registry.bakewise.ai"
;;
*)
if [ -z "$ADMIN_PASSWORD" ] && [ "$arg" != "--secrets-only" ] && [ "$arg" != "--production" ]; then
ADMIN_PASSWORD="$arg"
fi
;;
esac
done
# Get password from argument, environment variable, or use default (dev only)
if [ -z "$ADMIN_PASSWORD" ]; then
if [ -n "$GITEA_ADMIN_PASSWORD" ]; then
ADMIN_PASSWORD="$GITEA_ADMIN_PASSWORD"
echo "Using password from GITEA_ADMIN_PASSWORD environment variable"
elif [ "$IS_PRODUCTION" = true ]; then
echo "ERROR: Production deployment requires GITEA_ADMIN_PASSWORD environment variable"
echo "Generate a secure password with: openssl rand -base64 32"
echo ""
echo "Usage for production:"
echo " export GITEA_ADMIN_PASSWORD=\$(openssl rand -base64 32)"
echo " ./setup-admin-secret.sh --production"
exit 1
else
ADMIN_PASSWORD="$DEV_DEFAULT_PASSWORD"
echo "WARNING: Using default dev password. For production, set GITEA_ADMIN_PASSWORD"
fi
fi
# Validate password strength for production
if [ "$IS_PRODUCTION" = true ] && [ ${#ADMIN_PASSWORD} -lt 16 ]; then
echo "ERROR: Production password must be at least 16 characters"
exit 1
fi
# Create namespaces if they don't exist
@@ -103,9 +148,15 @@ echo "=========================================="
echo "Gitea secrets created successfully!"
echo "=========================================="
echo ""
echo "Credentials (same for both secrets):"
echo "Environment: $([ "$IS_PRODUCTION" = true ] && echo "PRODUCTION" || echo "Development")"
echo ""
echo "Credentials:"
echo " Username: $ADMIN_USERNAME"
echo " Password: $ADMIN_PASSWORD"
if [ "$IS_PRODUCTION" = true ]; then
echo " Password: (stored in secret, not displayed for security)"
else
echo " Password: $ADMIN_PASSWORD"
fi
echo ""
echo "Secrets created:"
echo " 1. gitea-admin-secret (namespace: $GITEA_NAMESPACE) - For Gitea Helm chart"
@@ -115,5 +166,44 @@ echo "Registry URLs:"
echo " External: https://$REGISTRY_HOST"
echo " Internal: $INTERNAL_REGISTRY_HOST"
echo ""
echo "Now install Gitea with:"
echo " helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml"
# Apply the init job ConfigMap and Job (but Job won't run until Gitea is installed)
if [ "$SECRETS_ONLY" = false ]; then
INIT_JOB_FILE="$SCRIPT_DIR/gitea-init-job.yaml"
if [ -f "$INIT_JOB_FILE" ]; then
echo "Applying Gitea initialization resources..."
$KUBECTL apply -f "$INIT_JOB_FILE"
echo ""
echo "Init job will create the 'bakery-ia' repository once Gitea is ready."
else
echo "Warning: gitea-init-job.yaml not found at $INIT_JOB_FILE"
fi
echo ""
fi
echo "Next steps:"
if [ "$IS_PRODUCTION" = true ]; then
echo " 1. Install Gitea for production:"
echo " helm upgrade --install gitea gitea/gitea -n gitea \\"
echo " -f infrastructure/cicd/gitea/values.yaml \\"
echo " -f infrastructure/cicd/gitea/values-prod.yaml"
echo ""
echo " 2. Install Tekton CI/CD for production:"
echo " export TEKTON_WEBHOOK_TOKEN=\$(openssl rand -hex 32)"
echo " helm upgrade --install tekton-cicd infrastructure/cicd/tekton-helm \\"
echo " -n tekton-pipelines \\"
echo " -f infrastructure/cicd/tekton-helm/values.yaml \\"
echo " -f infrastructure/cicd/tekton-helm/values-prod.yaml \\"
echo " --set secrets.webhook.token=\$TEKTON_WEBHOOK_TOKEN \\"
echo " --set secrets.registry.password=\$GITEA_ADMIN_PASSWORD \\"
echo " --set secrets.git.password=\$GITEA_ADMIN_PASSWORD"
else
echo " 1. Install Gitea (if not already installed):"
echo " helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml"
fi
echo ""
echo " $([ "$IS_PRODUCTION" = true ] && echo "3" || echo "2"). Wait for Gitea to be ready:"
echo " kubectl wait --for=condition=ready pod -n gitea -l app.kubernetes.io/name=gitea --timeout=300s"
echo ""
echo " $([ "$IS_PRODUCTION" = true ] && echo "4" || echo "3"). Check init job status:"
echo " kubectl logs -n gitea -l app.kubernetes.io/component=init --tail=50"

View File

@@ -1,9 +1,12 @@
# Gitea Helm values configuration for Bakery-IA CI/CD
# This configuration sets up Gitea with registry support and appropriate storage
#
# Prerequisites:
# 1. Run setup-admin-secret.sh to create the gitea-admin-secret
# 2. Apply the post-install job: kubectl apply -f gitea-init-job.yaml
#
# Installation:
# helm repo add gitea https://dl.gitea.io/charts
# kubectl create namespace gitea
# helm install gitea gitea/gitea -n gitea -f infrastructure/cicd/gitea/values.yaml
#
# NOTE: The namespace is determined by the -n flag during helm install, not in this file.
@@ -43,22 +46,6 @@ ingress:
hosts:
- gitea.bakery-ia.local
- registry.bakery-ia.local
# Additional ingress for container registry (same backend, different hostname)
apiIngress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "500m"
hosts:
- host: registry.bakery-ia.local
paths:
- path: /
pathType: Prefix
tls:
- secretName: bakery-dev-tls-cert
hosts:
- registry.bakery-ia.local
persistence:
enabled: true
@@ -68,39 +55,44 @@ persistence:
# For Kind: leave empty or use "standard"
storageClass: ""
# =============================================================================
# ADMIN USER CONFIGURATION
# =============================================================================
# The admin user is automatically created on first install.
# Credentials are read from the 'gitea-admin-secret' Kubernetes secret.
#
# Create the secret BEFORE installing Gitea:
# ./setup-admin-secret.sh
#
# The secret must contain:
# - username: admin username (default: bakery-admin)
# - password: admin password
# =============================================================================
gitea:
admin:
username: bakery-admin
# IMPORTANT: Override this with --set gitea.admin.password=<secure-password>
# or use existingSecret
password: ""
email: admin@bakery-ia.local
# Use existing secret for admin credentials (created by setup-admin-secret.sh)
existingSecret: gitea-admin-secret
# keepUpdated ensures password changes in secret are applied
passwordMode: keepUpdated
config:
server:
DOMAIN: gitea.bakery-ia.local
SSH_DOMAIN: gitea.bakery-ia.local
SSH_PORT: 2222
# Use HTTPS for external access; TLS termination happens at ingress
ROOT_URL: https://gitea.bakery-ia.local
HTTP_PORT: 3000
# Enable package registry
PACKAGES_ENABLED: true
# Disable built-in HTTPS since ingress handles TLS
PROTOCOL: http
repository:
ENABLE_PUSH_CREATE_USER: true
ENABLE_PUSH_CREATE_ORG: true
DEFAULT_BRANCH: main
packages:
ENABLED: true
registry:
ENABLE: true
ROOT: /var/lib/gitea-registry
STORAGE_TYPE: local
# NOTE: PORT config here is internal - registry is accessed via HTTP port on /v2/ path
# Additional registry configuration for proper external access
docker:
ENABLE: true
REGISTRY_SSL_REDIRECT: false # SSL termination happens at ingress
webhook:
ALLOWED_HOST_LIST: "*"
# Allow internal cluster URLs for Tekton EventListener
@@ -109,21 +101,6 @@ gitea:
DISABLE_REGISTRATION: false
REQUIRE_SIGNIN_VIEW: false
# Initial repositories to create automatically after Gitea installation
# These will be created with the admin user as owner
initialRepositories:
- name: bakery-ia
description: "Main repository for Bakery IA project - Automatically created by Helm"
private: false
auto_init: true
default_branch: main
owner: "{{ .Values.gitea.admin.username }}"
# Enable issues, wiki, and other features
enable_issues: true
enable_wiki: true
enable_pull_requests: true
enable_projects: true
# Use embedded SQLite for simpler local development
# For production, enable postgresql
postgresql:

View File

@@ -18,10 +18,30 @@ kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/
Then install the chart:
### Development Installation
```bash
helm repo add tekton-pipelines https://tekton.dev/charts
helm repo update
helm install tekton-cicd infrastructure/helm/tekton --namespace tekton-pipelines --create-namespace
helm install tekton-cicd infrastructure/cicd/tekton-helm \
--namespace tekton-pipelines \
--create-namespace
```
### Production Installation
**Important**: Never use default secrets in production. Always provide secure credentials.
```bash
# Generate secure webhook token
export TEKTON_WEBHOOK_TOKEN=$(openssl rand -hex 32)
# Use the same password as Gitea admin (from GITEA_ADMIN_PASSWORD)
helm upgrade --install tekton-cicd infrastructure/cicd/tekton-helm \
-n tekton-pipelines \
-f infrastructure/cicd/tekton-helm/values.yaml \
-f infrastructure/cicd/tekton-helm/values-prod.yaml \
--set secrets.webhook.token=$TEKTON_WEBHOOK_TOKEN \
--set secrets.registry.password=$GITEA_ADMIN_PASSWORD \
--set secrets.git.password=$GITEA_ADMIN_PASSWORD
```
## Configuration

View File

@@ -65,7 +65,8 @@ spec:
git config --global user.name "bakery-ia-ci"
# Clone the main repository (not a separate gitops repo)
REPO_URL="https://${GIT_USERNAME}:${GIT_PASSWORD}@gitea.bakery-ia.local/bakery-admin/bakery-ia.git"
# Use internal cluster DNS which works in all environments
REPO_URL="https://${GIT_USERNAME}:${GIT_PASSWORD}@gitea-http.gitea.svc.cluster.local:3000/bakery-admin/bakery-ia.git"
git clone "$REPO_URL" /tmp/gitops
cd /tmp/gitops

View File

@@ -0,0 +1,81 @@
# Production values for tekton-cicd Helm chart
# This file overrides values.yaml for production deployment
#
# Installation:
# helm upgrade --install tekton-cicd infrastructure/cicd/tekton-helm \
# -n tekton-pipelines \
# -f infrastructure/cicd/tekton-helm/values.yaml \
# -f infrastructure/cicd/tekton-helm/values-prod.yaml \
# --set secrets.webhook.token=$TEKTON_WEBHOOK_TOKEN \
# --set secrets.registry.password=$GITEA_ADMIN_PASSWORD \
# --set secrets.git.password=$GITEA_ADMIN_PASSWORD
#
# Required environment variables:
# TEKTON_WEBHOOK_TOKEN - Secure webhook token (generate with: openssl rand -hex 32)
# GITEA_ADMIN_PASSWORD - Gitea admin password (must match gitea-admin-secret)
# Global settings for production
global:
# Git configuration
git:
userEmail: "ci@bakewise.ai"
# Pipeline configuration for production
pipeline:
# Build configuration
build:
verbosity: "warn" # Less verbose in production
# Test configuration
test:
skipTests: "false"
skipLint: "false"
# Workspace configuration - ensure storage class exists in production cluster
workspace:
size: "10Gi"
storageClass: "standard" # Adjust to your production storage class
# Tekton controller settings - increased resources for production
controller:
replicas: 2
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 200m
memory: 256Mi
# Tekton webhook settings - increased resources for production
webhook:
replicas: 2
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
# Secrets configuration
# IMPORTANT: These MUST be overridden via --set flags during deployment
# DO NOT commit actual secrets to this file
secrets:
# Webhook secret for validating incoming webhooks
# Override with: --set secrets.webhook.token=$TEKTON_WEBHOOK_TOKEN
webhook:
token: "" # MUST be set via --set flag
# Registry credentials for pushing images
# Override with: --set secrets.registry.password=$GITEA_ADMIN_PASSWORD
registry:
username: "bakery-admin"
password: "" # MUST be set via --set flag
registryUrl: "gitea-http.gitea.svc.cluster.local:3000"
# Git credentials for GitOps updates
# Override with: --set secrets.git.password=$GITEA_ADMIN_PASSWORD
git:
username: "bakery-admin"
password: "" # MUST be set via --set flag

View File

@@ -3,33 +3,61 @@
# This secret stores Mailgun credentials for outbound email relay.
# Mailu uses Mailgun as an external SMTP relay to send all outbound emails.
#
# ============================================================================
# HOW TO CONFIGURE:
# ============================================================================
#
# 1. Go to https://www.mailgun.com and create an account
# 2. Add and verify your domain (e.g., bakery-ia.dev or bakewise.ai)
# 3. Go to Domain Settings > SMTP credentials
#
# 2. Add and verify your domain:
# - For dev: bakery-ia.dev
# - For prod: bakewise.ai
#
# 3. Go to Domain Settings > SMTP credentials in Mailgun dashboard
#
# 4. Note your SMTP credentials:
# - SMTP hostname: smtp.mailgun.org
# - Port: 587 (TLS)
# - Username: usually postmaster@yourdomain.com
# - Password: your Mailgun SMTP password (NOT API key)
# 5. Base64 encode your password:
# - Port: 587 (TLS/STARTTLS)
# - Username: typically postmaster@yourdomain.com
# - Password: your Mailgun SMTP password (NOT the API key)
#
# 5. Base64 encode your credentials:
# echo -n 'postmaster@bakewise.ai' | base64
# echo -n 'your-mailgun-smtp-password' | base64
# 6. Replace MAILGUN_SMTP_PASSWORD_BASE64 below with the encoded value
#
# 6. Replace the placeholder values below with your encoded credentials
#
# 7. Apply this secret:
# kubectl apply -f mailgun-credentials-secret.yaml -n bakery-ia
#
# ============================================================================
# IMPORTANT NOTES:
# - Use the SMTP password from Mailgun, not the API key
# - The username is typically postmaster@yourdomain.com
# - For sandbox domains, Mailgun requires authorized recipients
# - Production domains need DNS verification (SPF, DKIM, MX records)
# ============================================================================
#
# - Use the SMTP password from Mailgun, NOT the API key
# - The username format is: postmaster@yourdomain.com
# - For sandbox domains, Mailgun requires adding authorized recipients
# - Production domains need DNS verification (SPF, DKIM records)
#
# ============================================================================
# DNS RECORDS REQUIRED FOR MAILGUN:
# You will need to add these DNS records for your domain:
# - SPF: TXT record for email authentication
# - DKIM: TXT records for email signing (Mailgun provides these)
# - MX: If you want to receive emails via Mailgun (optional for relay-only)
# ============================================================================
#
# Add these DNS records to your domain for proper email delivery:
#
# 1. SPF Record (TXT):
# Name: @
# Value: v=spf1 include:mailgun.org ~all
#
# 2. DKIM Records (TXT):
# Mailgun will provide two DKIM keys to add as TXT records
# (check your Mailgun domain settings for exact values)
#
# 3. MX Records (optional, only if receiving via Mailgun):
# Priority 10: mxa.mailgun.org
# Priority 10: mxb.mailgun.org
#
# ============================================================================
---
apiVersion: v1
kind: Secret
@@ -39,39 +67,28 @@ metadata:
labels:
app: mailu
component: external-relay
annotations:
description: "Mailgun SMTP credentials for Mailu external relay"
type: Opaque
data:
# Base64 encoded Mailgun SMTP password
# To encode: echo -n 'your-password' | base64
# To decode: echo 'encoded-value' | base64 -d
RELAY_PASSWORD: MAILGUN_SMTP_PASSWORD_BASE64
---
# Development environment secret (separate for different Mailgun domain)
apiVersion: v1
kind: Secret
metadata:
name: mailu-mailgun-credentials-dev
namespace: bakery-ia
labels:
app: mailu
component: external-relay
environment: dev
type: Opaque
data:
# Mailgun credentials for bakery-ia.dev domain
RELAY_PASSWORD: MAILGUN_DEV_SMTP_PASSWORD_BASE64
---
# Production environment secret
apiVersion: v1
kind: Secret
metadata:
name: mailu-mailgun-credentials-prod
namespace: bakery-ia
labels:
app: mailu
component: external-relay
environment: prod
type: Opaque
data:
# Mailgun credentials for bakewise.ai domain
RELAY_PASSWORD: MAILGUN_PROD_SMTP_PASSWORD_BASE64
stringData:
# ============================================================================
# REPLACE THESE VALUES WITH YOUR MAILGUN CREDENTIALS
# ============================================================================
#
# Option 1: Use stringData (plain text - Kubernetes will encode automatically)
# This is easier for initial setup but shows credentials in the file
#
RELAY_USERNAME: "postmaster@sandboxc1bff891532b4f0c83056a68ae080b4c.mailgun.org"
RELAY_PASSWORD: "2e47104abadad8eb820d00042ea6d5eb-77c6c375-89c7ea55"
#
# ============================================================================
# ALTERNATIVE: Use pre-encoded values (more secure for version control)
# ============================================================================
# Comment out stringData above and uncomment data below:
#
# data:
# # Base64 encoded values
# # echo -n 'postmaster@bakewise.ai' | base64
# RELAY_USERNAME: cG9zdG1hc3RlckBiYWtld2lzZS5haQ==
# # echo -n 'your-password' | base64
# RELAY_PASSWORD: WU9VUl9NQUlMR1VOX1NNVFBfUEFTU1dPUkQ=

View File

@@ -0,0 +1,34 @@
# Mailu Admin Credentials Secret
# This secret stores the initial admin account password for Mailu
#
# The password is used by the Helm chart's initialAccount feature to create
# the admin user automatically during deployment.
#
# IMPORTANT: Replace the base64-encoded password before applying!
#
# To generate a secure password and encode it:
# PASSWORD=$(openssl rand -base64 16 | tr -d '/+=' | head -c 16)
# echo -n "$PASSWORD" | base64
#
# To apply this secret:
# kubectl apply -f mailu-admin-credentials-secret.yaml -n bakery-ia
#
# After deployment, you can log in to the Mailu admin panel at:
# https://mail.<domain>/admin
# Username: admin@<domain>
# Password: <the password you set>
#
apiVersion: v1
kind: Secret
metadata:
name: mailu-admin-credentials
namespace: bakery-ia
labels:
app.kubernetes.io/name: mailu
app.kubernetes.io/component: admin
type: Opaque
data:
# Base64-encoded password
# Example: "changeme123" = Y2hhbmdlbWUxMjM=
# IMPORTANT: Replace with your own secure password!
password: "Y2hhbmdlbWUxMjM="

View File

@@ -36,17 +36,29 @@ domain: "bakery-ia.dev"
hostnames:
- "mail.bakery-ia.dev"
# Initial admin account for dev environment
# Password is stored in mailu-admin-credentials secret
initialAccount:
enabled: true
username: "admin"
domain: "bakery-ia.dev"
existingSecret: "mailu-admin-credentials"
existingSecretPasswordKey: "password"
mode: "ifmissing"
# External relay configuration for dev (Mailgun)
# All outbound emails will be relayed through Mailgun SMTP
# To configure:
# 1. Register at mailgun.com and verify your domain (bakery-ia.dev)
# 2. Get your SMTP credentials from Mailgun dashboard
# 3. Update the secret in configs/mailgun-credentials-secret.yaml
# 4. Apply the secret: kubectl apply -f configs/mailgun-credentials-secret.yaml
# 4. Apply the secret: kubectl apply -f configs/mailgun-credentials-secret.yaml -n bakery-ia
externalRelay:
host: "[smtp.mailgun.org]:587"
username: "postmaster@bakery-ia.dev" # Your Mailgun SMTP username (usually postmaster@yourdomain)
password: "" # Will be loaded from secret - see configs/mailgun-credentials-secret.yaml
# Credentials loaded from Kubernetes secret
secretName: "mailu-mailgun-credentials"
usernameKey: "RELAY_USERNAME"
passwordKey: "RELAY_PASSWORD"
# Environment-specific configurations
persistence:
@@ -92,6 +104,13 @@ resources:
limits:
cpu: "200m"
memory: "128Mi"
webmail:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
clamav:
requests:
cpu: "100m"

View File

@@ -21,17 +21,29 @@ domain: "bakewise.ai"
hostnames:
- "mail.bakewise.ai"
# Initial admin account for production environment
# Password is stored in mailu-admin-credentials secret
initialAccount:
enabled: true
username: "admin"
domain: "bakewise.ai"
existingSecret: "mailu-admin-credentials"
existingSecretPasswordKey: "password"
mode: "ifmissing"
# External relay configuration for production (Mailgun)
# All outbound emails will be relayed through Mailgun SMTP
# To configure:
# 1. Register at mailgun.com and verify your domain (bakewise.ai)
# 2. Get your SMTP credentials from Mailgun dashboard
# 3. Update the secret in configs/mailgun-credentials-secret.yaml
# 4. Apply the secret: kubectl apply -f configs/mailgun-credentials-secret.yaml
# 4. Apply the secret: kubectl apply -f configs/mailgun-credentials-secret.yaml -n bakery-ia
externalRelay:
host: "[smtp.mailgun.org]:587"
username: "postmaster@bakewise.ai" # Your Mailgun SMTP username
password: "" # Will be loaded from secret - see configs/mailgun-credentials-secret.yaml
# Credentials loaded from Kubernetes secret
secretName: "mailu-mailgun-credentials"
usernameKey: "RELAY_USERNAME"
passwordKey: "RELAY_PASSWORD"
# Environment-specific configurations
persistence:

View File

@@ -7,8 +7,8 @@
# 1. Unbound DNS deployment (for DNSSEC validation)
# 2. CoreDNS configuration (forward to Unbound)
# 3. TLS certificate secret creation
# 4. Mailu Helm deployment
# 5. Admin user creation
# 4. Admin credentials secret creation
# 5. Mailu Helm deployment (admin user created automatically via initialAccount)
#
# Usage:
# ./deploy-mailu-prod.sh [--domain DOMAIN] [--admin-password PASSWORD]
@@ -174,9 +174,35 @@ else
fi
# =============================================================================
# Step 4: Deploy Mailu via Helm
# Step 4: Create Admin Credentials Secret
# =============================================================================
print_step "Step 4: Deploying Mailu via Helm..."
print_step "Step 4: Creating admin credentials secret..."
if kubectl get secret mailu-admin-credentials -n "$NAMESPACE" &>/dev/null; then
print_success "Admin credentials secret already exists"
# Retrieve existing password for summary output
if [ -z "$ADMIN_PASSWORD" ]; then
ADMIN_PASSWORD=$(kubectl get secret mailu-admin-credentials -n "$NAMESPACE" -o jsonpath='{.data.password}' | base64 -d)
fi
else
if [ -z "$ADMIN_PASSWORD" ]; then
# Generate a random password
ADMIN_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=' | head -c 16)
echo -e "${YELLOW}Generated admin password: $ADMIN_PASSWORD${NC}"
echo -e "${YELLOW}Please save this password securely!${NC}"
fi
kubectl create secret generic mailu-admin-credentials \
--from-literal=password="$ADMIN_PASSWORD" \
-n "$NAMESPACE"
print_success "Admin credentials secret created"
fi
# =============================================================================
# Step 5: Deploy Mailu via Helm
# =============================================================================
print_step "Step 5: Deploying Mailu via Helm..."
# Add Mailu Helm repository
helm repo add mailu https://mailu.github.io/helm-charts 2>/dev/null || true
@@ -189,12 +215,12 @@ helm upgrade --install mailu mailu/mailu \
-f "$MAILU_HELM_DIR/prod/values.yaml" \
--timeout 10m
print_success "Mailu Helm release deployed"
print_success "Mailu Helm release deployed (admin user will be created automatically)"
# =============================================================================
# Step 5: Wait for Pods to be Ready
# Step 6: Wait for Pods to be Ready
# =============================================================================
print_step "Step 5: Waiting for Mailu pods to be ready..."
print_step "Step 6: Waiting for Mailu pods to be ready..."
echo "This may take 5-10 minutes (ClamAV takes time to initialize)..."
@@ -212,24 +238,7 @@ echo ""
echo "Mailu Pod Status:"
kubectl get pods -n "$NAMESPACE" | grep mailu
# =============================================================================
# Step 6: Create Admin User
# =============================================================================
print_step "Step 6: Creating admin user..."
if [ -z "$ADMIN_PASSWORD" ]; then
# Generate a random password
ADMIN_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=' | head -c 16)
echo -e "${YELLOW}Generated admin password: $ADMIN_PASSWORD${NC}"
echo -e "${YELLOW}Please save this password securely!${NC}"
fi
kubectl exec -n "$NAMESPACE" deployment/mailu-admin -- \
flask mailu admin admin "$DOMAIN" "$ADMIN_PASSWORD" 2>/dev/null || {
print_warning "Admin user may already exist or failed to create"
}
print_success "Admin user configured"
print_success "Admin user created automatically via Helm initialAccount"
# =============================================================================
# Summary

View File

@@ -25,6 +25,18 @@ timezone: "Etc/UTC"
# Postmaster configuration
postmaster: "admin"
# Initial admin account configuration
# This creates an admin user as part of the Helm deployment
# Credentials can be provided directly or via Kubernetes secret
initialAccount:
enabled: true
username: "admin"
domain: "" # Set in environment-specific values (dev/prod)
password: "" # Leave empty to use existingSecret
existingSecret: "mailu-admin-credentials"
existingSecretPasswordKey: "password"
mode: "ifmissing" # Only create if account doesn't exist
# TLS configuration
tls:
flavor: "notls" # Disable TLS for development
@@ -40,16 +52,18 @@ limits:
# External relay configuration (Mailgun)
# Mailu will relay all outbound emails through Mailgun SMTP
# Credentials should be provided via Kubernetes secret or environment-specific values
# Credentials are loaded from Kubernetes secret for security
externalRelay:
host: "[smtp.mailgun.org]:587"
username: "" # Set in environment-specific values or via secret
password: "" # Set in environment-specific values or via secret
# Use existing secret for credentials (recommended for security)
secretName: "mailu-mailgun-credentials"
usernameKey: "RELAY_USERNAME"
passwordKey: "RELAY_PASSWORD"
# Webmail configuration
webmail:
enabled: true
flavor: "roundcube"
type: "roundcube"
# Antivirus and antispam configuration
antivirus: