diff --git a/.argocdignore b/.argocdignore
new file mode 100644
index 0000000..8738c73
--- /dev/null
+++ b/.argocdignore
@@ -0,0 +1,22 @@
+# ArgoCD ignore patterns
+# Exclude template files from ArgoCD deployment
+
+# Secret templates (deployed separately by scripts)
+templates/
+**/secret.yaml
+
+# Documentation and scripts
+docs/
+scripts/
+*.md
+README*
+
+# Development files
+.env*
+.git*
+.vscode/
+.idea/
+
+# CI/CD files
+.gitea/
+.github/
\ No newline at end of file
diff --git a/VorgabenUI/settings.py b/VorgabenUI/settings.py
index f24d35b..e35a33a 100644
--- a/VorgabenUI/settings.py
+++ b/VorgabenUI/settings.py
@@ -21,7 +21,17 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '429ti9tugj9gΓΌLLO))(G&G94KF452R3Fieaek$&6s#zlao-ca!#)_@j6*u+8s&bvfil^qyo%&-sov$ysi'
+SECRET_KEY = os.environ.get('VORGABENUI_SECRET')
+if not SECRET_KEY:
+ # Use DEBUG environment variable or assume debug mode for local development
+ debug_mode = os.environ.get('DEBUG', 'True').lower() in ('true', '1', 'yes', 'on')
+ if debug_mode:
+ # Fixed fallback key for local development only
+ SECRET_KEY = 'dev-fallback-key-for-local-debugging-only-not-for-production-use-12345'
+ import logging
+ logging.warning("π¨ Using fallback SECRET_KEY for local development. This should NEVER happen in production!")
+ else:
+ raise ValueError("VORGABENUI_SECRET environment variable is required")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
diff --git a/argocd/deployment.yaml b/argocd/deployment.yaml
index 2a26804..2fd3041 100644
--- a/argocd/deployment.yaml
+++ b/argocd/deployment.yaml
@@ -25,8 +25,14 @@ spec:
mountPath: /data
containers:
- name: web
- image: git.baumann.gr/adebaumann/vui:0.975
+ image: git.baumann.gr/adebaumann/vui:0.976
imagePullPolicy: Always
+ env:
+ - name: VORGABENUI_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: vorgabenui-secrets
+ key: vorgabenui_secret
ports:
- containerPort: 8000
volumeMounts:
diff --git a/argocd/secret.yaml b/argocd/secret.yaml
new file mode 100644
index 0000000..05c1856
--- /dev/null
+++ b/argocd/secret.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: vorgabenui-secrets
+ namespace: vorgabenui
+ annotations:
+ # Prevent ArgoCD from managing this secret - it's deployed by script
+ argocd.argoproj.io/ignore: "true"
+type: Opaque
+data:
+ # Base64 encoded SECRET_KEY - populated by deployment script
+ # This is a TEMPLATE FILE - not deployed by ArgoCD
+ vorgabenui_secret: ""
\ No newline at end of file
diff --git a/docs/kubernetes-secrets.md b/docs/kubernetes-secrets.md
new file mode 100644
index 0000000..2a24e13
--- /dev/null
+++ b/docs/kubernetes-secrets.md
@@ -0,0 +1,242 @@
+# Kubernetes Secret Management for VorgabenUI Django
+
+This document describes how to manage Django's SECRET_KEY using Kubernetes secrets with the `VORGABENUI_SECRET` environment variable.
+
+## Overview
+
+The Django SECRET_KEY has been moved from hardcoded configuration to a Kubernetes secret for improved security. This change ensures that:
+
+1. The SECRET_KEY is not stored in version control
+2. Different environments can use different keys
+3. Key rotation is easier to manage
+4. Follows Kubernetes security best practices
+5. Includes fallback for local development
+
+## Files Changed
+
+### VorgabenUI/settings.py
+- Replaced hardcoded `SECRET_KEY` with `VORGABENUI_SECRET` environment variable lookup
+- Added fallback secret key for local development (only works when DEBUG=True)
+- Added warning when fallback key is used
+
+### Files Created/Updated
+- `templates/secret.yaml` - Secret template (excluded from ArgoCD deployment)
+- `argocd/secret.yaml` - ArgoCD-specific secret template with ignore annotation
+- `argocd/deployment.yaml` - Updated with environment variable configuration
+- `scripts/deploy-argocd-secret.sh` - ArgoCD-specific script to deploy secrets
+- `.argocdignore` - ArgoCD ignore patterns for templates and scripts
+- `k8s/django-secret.yaml` - Updated for consistency (vorgabenui namespace)
+- `k8s/django-deployment-example.yaml` - Updated example deployment
+- `scripts/deploy-django-secret.sh` - Updated with new defaults
+
+## Usage
+
+### 1. Deploy the Secret (ArgoCD Production)
+
+For the ArgoCD production deployment, use the dedicated script:
+
+```bash
+# Deploy secret to vorgabenui namespace
+./scripts/deploy-argocd-secret.sh
+
+# Verify existing secret
+./scripts/deploy-argocd-secret.sh --verify-only
+
+# Dry run to see what would happen
+./scripts/deploy-argocd-secret.sh --dry-run
+
+# Get help
+./scripts/deploy-argocd-secret.sh --help
+```
+
+### 2. Deploy Secret for Other Environments
+
+For development or other environments, use the general script:
+
+```bash
+# Deploy to vorgabenui namespace (default)
+./scripts/deploy-django-secret.sh
+
+# Deploy to specific namespace
+./scripts/deploy-django-secret.sh -n development
+
+# Get help
+./scripts/deploy-django-secret.sh --help
+```
+
+### 3. Environment Variable Configuration
+
+The ArgoCD deployment (`argocd/deployment.yaml`) is already configured with:
+
+```yaml
+env:
+- name: VORGABENUI_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: vorgabenui-secrets
+ key: vorgabenui_secret
+```
+
+For other deployments, see `k8s/django-deployment-example.yaml` for a complete example.
+
+### 4. Verify the Deployment
+
+Check that the secret was created:
+
+```bash
+kubectl get secrets vorgabenui-secrets -n vorgabenui
+kubectl describe secret vorgabenui-secrets -n vorgabenui
+```
+
+Check that Django pods can access the secret:
+
+```bash
+kubectl exec -n vorgabenui deployment/django -- printenv VORGABENUI_SECRET
+```
+
+## Development Environment
+
+### Local Development with Fallback
+
+The application now includes a fallback secret key for local development. When running locally:
+
+1. **Automatic fallback**: If `VORGABENUI_SECRET` is not set and `DEBUG=True`, a fallback key is used automatically
+2. **Warning message**: The application will log a warning when using the fallback key
+3. **Production safety**: Fallback only works when `DEBUG=True` or `DEBUG` env var is set
+
+### Manual Environment Variable
+
+You can still set the environment variable manually:
+
+```bash
+# Option 1: Export the variable
+export VORGABENUI_SECRET="your-development-key-here"
+python manage.py runserver
+
+# Option 2: Use a .env file (recommended)
+echo "VORGABENUI_SECRET=your-development-key-here" > .env
+# Then load it in your settings or use python-dotenv
+```
+
+### Development vs Production
+
+- **Local Development**: Fallback key works automatically when `DEBUG=True`
+- **Production**: Must have `VORGABENUI_SECRET` environment variable set, no fallback
+
+## ArgoCD Integration and Exclusions
+
+### Preventing ArgoCD from Deploying Secret Templates
+
+This setup includes multiple approaches to prevent ArgoCD from trying to deploy the secret template:
+
+#### 1. Template Directory (`templates/`)
+- Secret template moved to `templates/` directory
+- ArgoCD deployment script automatically uses this location
+- Excluded via `.argocdignore` file
+
+#### 2. ArgoCD Ignore Annotation
+- `argocd/secret.yaml` has `argocd.argoproj.io/ignore: "true"` annotation
+- Provides fallback if templates directory approach fails
+
+#### 3. `.argocdignore` File
+- Global exclusion patterns for templates, scripts, and documentation
+- Prevents ArgoCD from syncing non-deployment files
+
+### ArgoCD Sync Behavior
+- ArgoCD will sync only the actual deployment files (`deployment.yaml`, `ingress.yaml`, etc.)
+- Secret templates are excluded and must be deployed manually using the deployment script
+- This ensures secrets are created outside of GitOps workflow for security
+
+## Security Considerations
+
+1. **Never commit the actual SECRET_KEY** - Only templates and scripts are in version control
+2. **Use different keys per environment** - Production, staging, and development should all have unique keys
+3. **Rotate keys regularly** - Run the deployment script periodically to generate new keys
+4. **Limit access** - Use Kubernetes RBAC to control who can access secrets
+5. **ArgoCD exclusion** - Secret templates are excluded from ArgoCD to prevent empty/template secrets from being deployed
+
+## Troubleshooting
+
+### Django fails to start with "VORGABENUI_SECRET environment variable is required"
+
+This means the environment variable is not set in your pod and DEBUG=False. Check:
+
+1. The secret exists: `kubectl get secret vorgabenui-secrets -n vorgabenui`
+2. The deployment references the secret correctly
+3. The pod has the environment variable: `kubectl exec -n vorgabenui -- env | grep VORGABENUI_SECRET`
+4. For local development, ensure `DEBUG=True` to use the fallback key
+
+### Secret deployment fails
+
+Check that:
+
+1. You have kubectl access to the cluster
+2. You have permission to create secrets in the `vorgabenui` namespace
+3. Python3 is available for key generation
+4. The ArgoCD secret template exists: `argocd/secret.yaml`
+
+### Key rotation
+
+To rotate the SECRET_KEY:
+
+1. **For ArgoCD production**: Run `./scripts/deploy-argocd-secret.sh` again
+2. **For other environments**: Run `./scripts/deploy-django-secret.sh` again
+3. Restart your Django pods to pick up the new key:
+ ```bash
+ # For ArgoCD production
+ kubectl rollout restart deployment/django -n vorgabenui
+
+ # For other environments
+ kubectl rollout restart deployment/your-django-deployment -n your-namespace
+ ```
+
+## Script Options
+
+### ArgoCD Production Script (`deploy-argocd-secret.sh`)
+
+This script is specifically for ArgoCD production deployment:
+
+- `--verify-only` - Only verify existing secret, don't create new one
+- `--dry-run` - Show what would be done without making changes
+- `-h, --help` - Show help message
+
+Configuration is hardcoded for ArgoCD:
+- Namespace: `vorgabenui`
+- Secret name: `vorgabenui-secrets`
+- Secret key: `vorgabenui_secret`
+- Template location: `templates/secret.yaml` (excluded from ArgoCD)
+
+### General Script (`deploy-django-secret.sh`)
+
+For development and other environments:
+
+- `-n, --namespace NAMESPACE` - Target Kubernetes namespace (default: vorgabenui)
+- `-s, --secret-name NAME` - Secret name (default: vorgabenui-secrets)
+- `-k, --key-name NAME` - Secret key name (default: vorgabenui_secret)
+- `-h, --help` - Show help message
+
+Environment variables:
+- `NAMESPACE` - Override default namespace
+
+## Migration from Hardcoded Key
+
+### Migration from Old Setup
+
+If you're migrating from the previous `DJANGO_SECRET_KEY` setup:
+
+1. **Deploy the new secret** using `./scripts/deploy-argocd-secret.sh`
+2. **Update any existing deployments** to use `VORGABENUI_SECRET` instead of `DJANGO_SECRET_KEY`
+3. **Test locally** - the fallback key should work automatically in DEBUG mode
+4. **Deploy the updated application** - ArgoCD deployment is already configured
+
+### Migration from Hardcoded Key
+
+If you're migrating from a completely hardcoded key:
+
+1. **Backup your current key** (in case you need to rollback)
+2. **Deploy the secret first** using the deployment script
+3. **Apply the updated ArgoCD deployment** (already done in this setup)
+4. **Test thoroughly** - local development should work with fallback
+5. **Deploy the updated settings.py** after confirming the secret works
+
+The ArgoCD deployment (`argocd/deployment.yaml`) now includes the environment variable configuration, so Django will automatically pick up the secret after deployment.
\ No newline at end of file
diff --git a/k8s/django-deployment-example.yaml b/k8s/django-deployment-example.yaml
new file mode 100644
index 0000000..fe5d436
--- /dev/null
+++ b/k8s/django-deployment-example.yaml
@@ -0,0 +1,52 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: vgui-cicd-django
+ namespace: vorgabenui
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: vgui-cicd-django
+ template:
+ metadata:
+ labels:
+ app: vgui-cicd-django
+ spec:
+ containers:
+ - name: django
+ image: your-django-image:latest
+ ports:
+ - containerPort: 8000
+ env:
+ # Django SECRET_KEY from Kubernetes secret
+ - name: VORGABENUI_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: vorgabenui-secrets
+ key: vorgabenui_secret
+ # Other environment variables can be added here
+ - name: DEBUG
+ value: "False"
+ # Add database configuration, etc.
+ resources:
+ requests:
+ memory: "256Mi"
+ cpu: "250m"
+ limits:
+ memory: "512Mi"
+ cpu: "500m"
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: vgui-cicd-django-service
+ namespace: vorgabenui
+spec:
+ selector:
+ app: vgui-cicd-django
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 8000
+ type: ClusterIP
\ No newline at end of file
diff --git a/k8s/django-secret.yaml b/k8s/django-secret.yaml
new file mode 100644
index 0000000..922df47
--- /dev/null
+++ b/k8s/django-secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: vorgabenui-secrets
+ namespace: vorgabenui
+type: Opaque
+data:
+ # Base64 encoded SECRET_KEY - will be populated by deployment script
+ vorgabenui_secret: ""
\ No newline at end of file
diff --git a/pages/templates/base.html b/pages/templates/base.html
index 087c085..81e4f1e 100644
--- a/pages/templates/base.html
+++ b/pages/templates/base.html
@@ -219,7 +219,7 @@
-
Version {{ version|default:"0.973" }}
+
Version {{ version|default:"0.976" }}
diff --git a/scripts/deploy-argocd-secret.sh b/scripts/deploy-argocd-secret.sh
new file mode 100755
index 0000000..c712e1f
--- /dev/null
+++ b/scripts/deploy-argocd-secret.sh
@@ -0,0 +1,311 @@
+#!/bin/bash
+
+# deploy-argocd-secret.sh
+# ArgoCD-specific script to generate and deploy Django SECRET_KEY to vorgabenui namespace
+
+set -euo pipefail
+
+# ArgoCD-specific configuration (hardcoded for consistency)
+NAMESPACE="vorgabenui"
+SECRET_NAME="vorgabenui-secrets"
+SECRET_KEY_NAME="vorgabenui_secret"
+SCRIPT_DIR="$(dirname "$0")"
+ARGOCD_DIR="$SCRIPT_DIR/../argocd"
+TEMPLATES_DIR="$SCRIPT_DIR/../templates"
+SECRET_TEMPLATE="$TEMPLATES_DIR/secret.yaml"
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# Logging functions
+log_info() {
+ echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+log_warn() {
+ echo -e "${YELLOW}[WARN]${NC} $1"
+}
+
+log_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+log_step() {
+ echo -e "${BLUE}[STEP]${NC} $1"
+}
+
+# Function to generate a secure Django SECRET_KEY
+generate_secret_key() {
+ # Generate a 50-character secret key using Python (same as Django's default)
+ python3 -c "
+import secrets
+import string
+
+# Django-style secret key generation
+chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)'
+print(''.join(secrets.choice(chars) for _ in range(50)))
+"
+}
+
+# Function to check if kubectl is available
+check_kubectl() {
+ if ! command -v kubectl &> /dev/null; then
+ log_error "kubectl is not installed or not in PATH"
+ exit 1
+ fi
+}
+
+# Function to check if Python3 is available
+check_python() {
+ if ! command -v python3 &> /dev/null; then
+ log_error "python3 is not installed or not in PATH"
+ exit 1
+ fi
+}
+
+# Function to check if secret template exists
+check_template() {
+ if [ ! -f "$SECRET_TEMPLATE" ]; then
+ # Fallback to argocd directory if templates directory doesn't exist
+ FALLBACK_TEMPLATE="$ARGOCD_DIR/secret.yaml"
+ if [ -f "$FALLBACK_TEMPLATE" ]; then
+ SECRET_TEMPLATE="$FALLBACK_TEMPLATE"
+ log_warn "Using fallback template: $SECRET_TEMPLATE"
+ else
+ log_error "Secret template not found at either:"
+ log_error " Primary: $TEMPLATES_DIR/secret.yaml"
+ log_error " Fallback: $FALLBACK_TEMPLATE"
+ exit 1
+ fi
+ fi
+}
+
+# Function to create the secret
+create_secret() {
+ local secret_key="$1"
+
+ log_step "Creating Kubernetes secret '$SECRET_NAME' in namespace '$NAMESPACE'..."
+
+ # Create the secret directly with kubectl (this will create or update)
+ kubectl create secret generic "$SECRET_NAME" \
+ --from-literal="$SECRET_KEY_NAME=$secret_key" \
+ --namespace="$NAMESPACE" \
+ --dry-run=client -o yaml | kubectl apply -f -
+
+ if [ $? -eq 0 ]; then
+ log_info "Successfully created/updated secret '$SECRET_NAME'"
+ return 0
+ else
+ log_error "Failed to create/update secret '$SECRET_NAME'"
+ return 1
+ fi
+}
+
+# Function to verify the secret
+verify_secret() {
+ log_step "Verifying secret deployment..."
+
+ if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" &> /dev/null; then
+ log_info "β
Secret '$SECRET_NAME' exists in namespace '$NAMESPACE'"
+
+ # Show secret metadata (without revealing the actual key)
+ echo ""
+ log_info "Secret details:"
+ kubectl describe secret "$SECRET_NAME" --namespace="$NAMESPACE" | grep -E "^(Name|Namespace|Type|Data)"
+
+ # Verify the key exists in the secret
+ if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" -o jsonpath="{.data.$SECRET_KEY_NAME}" &> /dev/null; then
+ log_info "β
Secret key '$SECRET_KEY_NAME' is present in the secret"
+ return 0
+ else
+ log_error "β Secret key '$SECRET_KEY_NAME' not found in secret"
+ return 1
+ fi
+ else
+ log_error "β Secret '$SECRET_NAME' not found in namespace '$NAMESPACE'"
+ return 1
+ fi
+}
+
+# Function to test secret in pod (if deployment exists)
+test_secret_in_pod() {
+ log_step "Testing secret accessibility in Django deployment..."
+
+ # Check if Django deployment exists
+ if kubectl get deployment django --namespace="$NAMESPACE" &> /dev/null; then
+ log_info "Django deployment found, testing secret access..."
+
+ # Try to get the secret value from a pod (this will fail if env var not configured)
+ local pod_name
+ pod_name=$(kubectl get pods -l app=django --namespace="$NAMESPACE" -o jsonpath="{.items[0].metadata.name}" 2>/dev/null)
+
+ if [ -n "$pod_name" ] && [ "$pod_name" != "" ]; then
+ log_info "Testing secret in pod: $pod_name"
+ if kubectl exec "$pod_name" --namespace="$NAMESPACE" -- printenv VORGABENUI_SECRET &> /dev/null; then
+ log_info "β
VORGABENUI_SECRET environment variable is accessible in pod"
+ else
+ log_warn "β οΈ VORGABENUI_SECRET environment variable not found in pod"
+ log_warn " This is expected if the deployment hasn't been updated yet"
+ fi
+ else
+ log_warn "β οΈ No running Django pods found"
+ fi
+ else
+ log_info "Django deployment not found - secret will be available when deployment is updated"
+ fi
+}
+
+# Function to show usage
+show_usage() {
+ echo "ArgoCD Secret Deployment Script for VorgabenUI"
+ echo ""
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "This script deploys Django SECRET_KEY to the vorgabenui namespace for ArgoCD."
+ echo ""
+ echo "Options:"
+ echo " -h, --help Show this help message"
+ echo " --verify-only Only verify existing secret, don't create new one"
+ echo " --dry-run Show what would be done without making changes"
+ echo ""
+ echo "Configuration (hardcoded for ArgoCD):"
+ echo " Namespace: $NAMESPACE"
+ echo " Secret Name: $SECRET_NAME"
+ echo " Secret Key: $SECRET_KEY_NAME"
+ echo " Template: $SECRET_TEMPLATE"
+ echo ""
+ echo "Examples:"
+ echo " $0 # Generate and deploy new secret"
+ echo " $0 --verify-only # Verify existing secret"
+ echo " $0 --dry-run # Preview changes"
+ echo ""
+ echo "After running this script, update argocd/deployment.yaml to reference the secret."
+}
+
+# Parse command line arguments
+VERIFY_ONLY=false
+DRY_RUN=false
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --verify-only)
+ VERIFY_ONLY=true
+ shift
+ ;;
+ --dry-run)
+ DRY_RUN=true
+ shift
+ ;;
+ -h|--help)
+ show_usage
+ exit 0
+ ;;
+ *)
+ log_error "Unknown option: $1"
+ show_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Main execution
+main() {
+ echo ""
+ log_info "π ArgoCD Django SECRET_KEY Deployment Script"
+ log_info "============================================="
+ echo ""
+ log_info "Target Configuration:"
+ log_info " Namespace: $NAMESPACE"
+ log_info " Secret Name: $SECRET_NAME"
+ log_info " Secret Key Name: $SECRET_KEY_NAME"
+ echo ""
+
+ # Perform checks
+ log_step "Performing pre-flight checks..."
+ check_kubectl
+ check_python
+ check_template
+ log_info "β
All pre-flight checks passed"
+ echo ""
+
+ # Verify-only mode
+ if [ "$VERIFY_ONLY" = true ]; then
+ log_info "π Verify-only mode - checking existing secret"
+ verify_secret
+ test_secret_in_pod
+ exit $?
+ fi
+
+ # Generate new secret key
+ log_step "Generating new Django SECRET_KEY..."
+ SECRET_KEY=$(generate_secret_key)
+
+ if [ -z "$SECRET_KEY" ]; then
+ log_error "Failed to generate secret key"
+ exit 1
+ fi
+
+ log_info "β
Generated secret key (first 10 chars): ${SECRET_KEY:0:10}..."
+ echo ""
+
+ # Dry-run mode
+ if [ "$DRY_RUN" = true ]; then
+ log_info "π Dry-run mode - showing what would be done:"
+ echo ""
+ log_info "Would create secret with the following command:"
+ echo " kubectl create secret generic $SECRET_NAME \\"
+ echo " --from-literal=$SECRET_KEY_NAME='[GENERATED_KEY]' \\"
+ echo " --namespace=$NAMESPACE \\"
+ echo " --dry-run=client -o yaml | kubectl apply -f -"
+ echo ""
+ log_info "Secret key would be: ${SECRET_KEY:0:10}...${SECRET_KEY: -5}"
+ echo ""
+ log_info "Run without --dry-run to execute the deployment"
+ exit 0
+ fi
+
+ # Create namespace if it doesn't exist
+ if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
+ log_warn "Namespace '$NAMESPACE' does not exist, creating..."
+ kubectl create namespace "$NAMESPACE"
+ log_info "β
Created namespace '$NAMESPACE'"
+ fi
+
+ # Create the secret
+ if create_secret "$SECRET_KEY"; then
+ echo ""
+ # Verify deployment
+ verify_secret
+ echo ""
+ test_secret_in_pod
+ echo ""
+
+ log_info "π Secret deployment completed successfully!"
+ echo ""
+ log_info "π Next steps:"
+ log_info "1. Update argocd/deployment.yaml to include environment variable:"
+ echo ""
+ echo " env:"
+ echo " - name: VORGABENUI_SECRET"
+ echo " valueFrom:"
+ echo " secretKeyRef:"
+ echo " name: $SECRET_NAME"
+ echo " key: $SECRET_KEY_NAME"
+ echo ""
+ log_info "2. Apply the updated deployment:"
+ echo " kubectl apply -f argocd/deployment.yaml"
+ echo ""
+ log_info "3. Verify Django pods restart and pick up the new secret"
+ echo ""
+ else
+ log_error "Secret deployment failed"
+ exit 1
+ fi
+}
+
+# Run main function
+main
\ No newline at end of file
diff --git a/scripts/deploy-django-secret.sh b/scripts/deploy-django-secret.sh
new file mode 100755
index 0000000..5a0c695
--- /dev/null
+++ b/scripts/deploy-django-secret.sh
@@ -0,0 +1,201 @@
+#!/bin/bash
+
+# deploy-django-secret.sh
+# Script to generate a secure Django SECRET_KEY and deploy it to Kubernetes
+
+set -euo pipefail
+
+# Configuration
+NAMESPACE="${NAMESPACE:-vorgabenui}"
+SECRET_NAME="vorgabenui-secrets"
+SECRET_KEY_NAME="vorgabenui_secret"
+K8S_DIR="$(dirname "$0")/../k8s"
+SECRET_YAML="$K8S_DIR/django-secret.yaml"
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+# Logging functions
+log_info() {
+ echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+log_warn() {
+ echo -e "${YELLOW}[WARN]${NC} $1"
+}
+
+log_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+# Function to generate a secure Django SECRET_KEY
+generate_secret_key() {
+ # Generate a 50-character secret key using Python (same as Django's default)
+ python3 -c "
+import secrets
+import string
+
+# Django-style secret key generation
+chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)'
+print(''.join(secrets.choice(chars) for _ in range(50)))
+"
+}
+
+# Function to check if kubectl is available
+check_kubectl() {
+ if ! command -v kubectl &> /dev/null; then
+ log_error "kubectl is not installed or not in PATH"
+ exit 1
+ fi
+}
+
+# Function to check if Python3 is available
+check_python() {
+ if ! command -v python3 &> /dev/null; then
+ log_error "python3 is not installed or not in PATH"
+ exit 1
+ fi
+}
+
+# Function to create the secret
+create_secret() {
+ local secret_key="$1"
+ local encoded_key
+
+ # Base64 encode the secret key
+ encoded_key=$(echo -n "$secret_key" | base64 -w 0)
+
+ log_info "Creating Kubernetes secret '$SECRET_NAME' in namespace '$NAMESPACE'..."
+
+ # Create the secret directly with kubectl
+ kubectl create secret generic "$SECRET_NAME" \
+ --from-literal="$SECRET_KEY_NAME=$secret_key" \
+ --namespace="$NAMESPACE" \
+ --dry-run=client -o yaml | kubectl apply -f -
+
+ if [ $? -eq 0 ]; then
+ log_info "Successfully created/updated secret '$SECRET_NAME'"
+ else
+ log_error "Failed to create/update secret '$SECRET_NAME'"
+ exit 1
+ fi
+}
+
+# Function to verify the secret
+verify_secret() {
+ log_info "Verifying secret deployment..."
+
+ if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" &> /dev/null; then
+ log_info "Secret '$SECRET_NAME' exists in namespace '$NAMESPACE'"
+
+ # Show secret (without revealing the actual key)
+ kubectl describe secret "$SECRET_NAME" --namespace="$NAMESPACE"
+ return 0
+ else
+ log_error "Secret '$SECRET_NAME' not found in namespace '$NAMESPACE'"
+ return 1
+ fi
+}
+
+# Function to show usage
+show_usage() {
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " -n, --namespace NAMESPACE Kubernetes namespace (default: vorgabenui)"
+ echo " -s, --secret-name NAME Secret name (default: django-secrets)"
+ echo " -k, --key-name NAME Secret key name (default: django-secret-key)"
+ echo " -h, --help Show this help message"
+ echo ""
+ echo "Environment variables:"
+ echo " NAMESPACE Override default namespace"
+ echo ""
+ echo "Examples:"
+ echo " $0 # Deploy to vorgabenui namespace"
+ echo " $0 -n production # Deploy to production namespace"
+ echo " NAMESPACE=staging $0 # Deploy to staging namespace"
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -n|--namespace)
+ NAMESPACE="$2"
+ shift 2
+ ;;
+ -s|--secret-name)
+ SECRET_NAME="$2"
+ shift 2
+ ;;
+ -k|--key-name)
+ SECRET_KEY_NAME="$2"
+ shift 2
+ ;;
+ -h|--help)
+ show_usage
+ exit 0
+ ;;
+ *)
+ log_error "Unknown option: $1"
+ show_usage
+ exit 1
+ ;;
+ esac
+done
+
+# Main execution
+main() {
+ log_info "Django SECRET_KEY Deployment Script"
+ log_info "==================================="
+ log_info "Namespace: $NAMESPACE"
+ log_info "Secret Name: $SECRET_NAME"
+ log_info "Secret Key Name: $SECRET_KEY_NAME"
+ echo ""
+
+ # Perform checks
+ check_kubectl
+ check_python
+
+ # Generate new secret key
+ log_info "Generating new Django SECRET_KEY..."
+ SECRET_KEY=$(generate_secret_key)
+
+ if [ -z "$SECRET_KEY" ]; then
+ log_error "Failed to generate secret key"
+ exit 1
+ fi
+
+ log_info "Generated secret key (first 10 chars): ${SECRET_KEY:0:10}..."
+
+ # Create namespace if it doesn't exist
+ if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
+ log_warn "Namespace '$NAMESPACE' does not exist, creating..."
+ kubectl create namespace "$NAMESPACE"
+ fi
+
+ # Create the secret
+ create_secret "$SECRET_KEY"
+
+ # Verify deployment
+ verify_secret
+
+ echo ""
+ log_info "Deployment completed successfully!"
+ log_info "To use this secret in your Django deployment, add the following to your pod spec:"
+ echo ""
+ echo " env:"
+ echo " - name: VORGABENUI_SECRET"
+ echo " valueFrom:"
+ echo " secretKeyRef:"
+ echo " name: $SECRET_NAME"
+ echo " key: $SECRET_KEY_NAME"
+ echo ""
+ log_warn "The old secret key in settings.py has been replaced with environment variable lookup."
+ log_warn "Make sure your Django deployment uses the environment variable before deploying."
+}
+
+# Run main function
+main
\ No newline at end of file
diff --git a/templates/secret.yaml b/templates/secret.yaml
new file mode 100644
index 0000000..42d4e40
--- /dev/null
+++ b/templates/secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: vorgabenui-secrets
+ namespace: vorgabenui
+type: Opaque
+data:
+ # Base64 encoded SECRET_KEY - populated by deployment script
+ # This is a TEMPLATE FILE in templates/ directory - not deployed by ArgoCD
+ vorgabenui_secret: ""
\ No newline at end of file