Added initial infrastructure defintions

This commit is contained in:
Dennis Nemec
2026-01-30 15:59:15 +01:00
parent b37b93484d
commit c201ccbb4e
12 changed files with 423 additions and 1 deletions

View File

@ -1,2 +1,25 @@
# infrastructure
# Softvisor GmbH Infrastruktur
# Installation von Kubernetes
# Installation von Gitea
Um Gitea zu installieren, muss folgendes installiert sein:
- helm
- microk8s
Der Windows-Server muss im gleichen Tailscale-Netzwerk sein, in dem der AuthKey generiert wurde.
## Values
Es müssen in der Datei ```gitea/values.yaml``` folgende Attribute gesetzt sein:
1. tailscale.authKey
2. gitea.gitea.ldap.bindPassword
Die betroffenen Zeilen sind in der Datei markiert.
## Befehl
Im Ordner ```infrastructure``` ausführen:
```
helm upgrade gitea gitea --install \
-n gitea \
```

103
backup/gitea-backup.yaml Normal file
View File

@ -0,0 +1,103 @@
# gitea-backup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-backup-script
namespace: gitea
data:
backup.sh: |
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup/gitea"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="gitea_${DATE}.zip"
RETENTION_DAYS=30
echo "[$(date)] Starting Gitea backup..."
# Create backup directory (may fail if permissions issue, that's ok)
mkdir -p ${BACKUP_DIR} 2>/dev/null || true
# Change to temp directory for dump
cd /tmp
# Run Gitea dump
if gitea dump -c /data/gitea/conf/app.ini --type zip; then
echo "[$(date)] ✓ Gitea dump successful"
# Find the created dump file
DUMP_FILE=$(ls -t gitea-dump-*.zip 2>/dev/null | head -1)
if [ -n "$DUMP_FILE" ] && [ -f "$DUMP_FILE" ]; then
# Move to backup directory with our naming convention
mv "$DUMP_FILE" ${BACKUP_DIR}/${BACKUP_FILE}
SIZE=$(du -h ${BACKUP_DIR}/${BACKUP_FILE} | cut -f1)
echo "[$(date)] Backup size: ${SIZE}"
else
echo "[$(date)] ✗ ERROR: Dump file not found!"
exit 1
fi
else
echo "[$(date)] ✗ Gitea dump failed!"
exit 1
fi
# Cleanup old backups
echo "[$(date)] Cleaning up backups older than ${RETENTION_DAYS} days..."
find ${BACKUP_DIR} -name "gitea_*.zip" -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
# List recent backups
echo "[$(date)] Recent backups:"
ls -lh ${BACKUP_DIR} 2>/dev/null | tail -5 || echo "Could not list backups"
echo "[$(date)] Gitea backup completed successfully"
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: gitea-backup
namespace: gitea
spec:
schedule: "0 3 * * *"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
securityContext:
runAsUser: 1000 # Run as git user
runAsGroup: 1000 # Run as git group
fsGroup: 1000 # Set filesystem group
containers:
- name: gitea-backup
image: gitea/gitea:1.24 # Match your version
command: ["/bin/bash", "/scripts/backup.sh"]
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
volumeMounts:
- name: backup-script
mountPath: /scripts
- name: gitea-data
mountPath: /data
- name: backup-storage
mountPath: /backup
- name: tmp
mountPath: /tmp
volumes:
- name: backup-script
configMap:
name: gitea-backup-script
defaultMode: 0755
- name: gitea-data
persistentVolumeClaim:
claimName: gitea-shared-storage # Adjust to your PVC name
- name: backup-storage
hostPath:
path: /mnt/backup/k8s-backups # Fixed path
type: DirectoryOrCreate
- name: tmp
emptyDir: {}
restartPolicy: OnFailure

View File

@ -0,0 +1,92 @@
# postgres-backup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-backup-script
namespace: gitea
data:
backup.sh: |
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup/postgres"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="postgres_${DATE}.sql.gz"
RETENTION_DAYS=30
echo "[$(date)] Starting PostgreSQL backup..."
# Create backup directory
mkdir -p ${BACKUP_DIR}
# Perform backup
if pg_dump -h ${POSTGRES_HOST} -U ${POSTGRES_USER} ${POSTGRES_DB} | gzip > ${BACKUP_DIR}/${BACKUP_FILE}; then
echo "[$(date)] ✓ Backup successful: ${BACKUP_FILE}"
# Verify backup file exists and is not empty
if [ -s ${BACKUP_DIR}/${BACKUP_FILE} ]; then
SIZE=$(du -h ${BACKUP_DIR}/${BACKUP_FILE} | cut -f1)
echo "[$(date)] Backup size: ${SIZE}"
else
echo "[$(date)] ✗ ERROR: Backup file is empty!"
exit 1
fi
else
echo "[$(date)] ✗ Backup failed!"
exit 1
fi
# Cleanup old backups
echo "[$(date)] Cleaning up backups older than ${RETENTION_DAYS} days..."
find ${BACKUP_DIR} -name "postgres_*.sql.gz" -mtime +${RETENTION_DAYS} -delete
# List recent backups
echo "[$(date)] Recent backups:"
ls -lh ${BACKUP_DIR} | tail -5
echo "[$(date)] Backup completed successfully"
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: postgres-backup
namespace: gitea
spec:
schedule: "0 2 * * *" # Daily at 2 AM
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
containers:
- name: postgres-backup
image: postgres:17 # Match your PostgreSQL version
command: ["/bin/bash", "/scripts/backup.sh"]
env:
- name: POSTGRES_HOST
value: "gitea-postgresql" # Adjust to your service name
- name: POSTGRES_USER
value: "gitea"
- name: POSTGRES_DB
value: "gitea"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: gitea-postgresql # Adjust to your secret name
key: password
volumeMounts:
- name: backup-script
mountPath: /scripts
- name: backup-storage
mountPath: /backup
volumes:
- name: backup-script
configMap:
name: postgres-backup-script
defaultMode: 0755
- name: backup-storage
hostPath:
path: /mnt/backup/k8s-backups
type: DirectoryOrCreate
restartPolicy: OnFailure

23
gitea/.helmignore Normal file
View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

6
gitea/Chart.lock Normal file
View File

@ -0,0 +1,6 @@
dependencies:
- name: gitea
repository: https://dl.gitea.io/charts/
version: 12.1.1
digest: sha256:b405ec6017f5958c8222d326e69e15f7be65f42988767b63d9b5648f4bfd60a8
generated: "2025-06-28T16:26:16.845530159+02:00"

29
gitea/Chart.yaml Normal file
View File

@ -0,0 +1,29 @@
apiVersion: v2
name: gitea
description: Infrastructure configuration for Softvisor GmbH
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
dependencies:
- name: gitea
version: 12.1.1
repository: https://dl.gitea.io/charts/

Binary file not shown.

View File

View File

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "gitea.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "gitea.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "gitea.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "gitea.labels" -}}
helm.sh/chart: {{ include "gitea.chart" . }}
{{ include "gitea.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "gitea.selectorLabels" -}}
app.kubernetes.io/name: {{ include "gitea.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "gitea.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "gitea.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: gitea-admin-secret
type: Opaque
stringData:
username: softvisor
password: "#softvisor!2024?"
email: "git@softvisor.de"

View File

@ -0,0 +1,16 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: lets-encrypt
spec:
acme:
email: {{ .Values.global.domain.mail }}
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource that will be used to store the account's private key.
name: lets-encrypt-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: public

59
gitea/values.yaml Normal file
View File

@ -0,0 +1,59 @@
global:
domain:
git: &domain git.dev.softvisor.de
mail: &mail admin@softvisor.de
gitea:
valkey-cluster:
enabled: false
valkey:
enabled: true
postgresql:
enabled: true
postgresql-ha:
enabled: false
persistence:
enabled: true
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: public
cert-manager.io/cluster-issuer: lets-encrypt
tls:
- secretName: lets-encrypt-private-key
hosts:
- *domain
hosts:
- host: *domain
paths:
- path: /
pathType: Prefix
service:
http:
type: ClusterIP
port: 3000
ssh:
type: LoadBalancer
port: 22
clusterIP: None
annotations:
metallb.universe.tf/allow-shared-ip: test
gitea:
admin:
email: *mail
existingSecret: gitea-admin-secret
config:
database:
DB_TYPE: postgres
indexer:
ISSUE_INDEXER_TYPE: bleve
REPO_INDEXER_ENABLED: true
server:
SSH_DOMAIN: *domain
service:
DISABLE_REGISTRATION: true
SHOW_REGISTRATION_BUTTON: false