blob: d85c6051737a6357e2621dcd7a467246854ae4ce [file] [log] [blame]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: git
namespace: mulk
labels:
name: git
k8s-app: git
spec:
replicas: 1
selector:
matchLabels:
k8s-app: git
name: git
template:
metadata:
labels:
name: git
k8s-app: git
spec:
containers:
- name: cgit
# Serves cgit at / (lighttpd rewrites /<repo>/... to cgit.cgi?url=...).
# The image's own sshd listens on :22 and is unused; gitolite is on :2222.
image: docker.io/woahbase/alpine-cgit:1.3_20260805
imagePullPolicy: IfNotPresent
env:
# Formatters for the about pages and syntax highlighting.
- name: S6_NEEDED_PACKAGES
value: "groff python3 py3-docutils py3-markdown py3-pygments"
# /home/git is gitolite's volume (owned by gitolite's uid 106), so
# cgit must not chown it: CGIT_SKIP_PERMFIX skips cgit's permfix,
# and an empty S6_USER skips the base image's usermod/chown of the
# user's home (scripts fall back to user "git").
- name: CGIT_SKIP_PERMFIX
value: "true"
- name: S6_USER
value: ""
resources:
limits:
cpu: 2000m
memory: 100Mi
requests:
cpu: 10m
memory: 50Mi
ports:
- containerPort: 80
name: cgit-http
protocol: TCP
volumeMounts:
- name: data
mountPath: /home/git
- name: config
mountPath: /etc/cgitrc
subPath: cgitrc
readOnly: true
- name: gitolite
image: docker.io/elsdoerfer/gitolite:v3.6.15-ubuntu-26.04-20260824.3
imagePullPolicy: IfNotPresent
env: []
#tty: true
#stdin: true
#command:
# - /bin/cat
resources:
limits:
cpu: 2000m
memory: 100Mi
requests:
cpu: 10m
memory: 50Mi
ports:
- containerPort: 2222
name: gitolite-ssh
protocol: TCP
volumeMounts:
- name: data
mountPath: /home/git/repositories
subPath: repositories
#- name: data
# mountPath: /home/git/projects.list
# subPath: projects.list
- name: data
mountPath: /home/git/.gitolite
subPath: .gitolite
- name: data
mountPath: /home/git/.gitolite.rc
subPath: .gitolite.rc
- name: data
mountPath: /home/git/.ssh
subPath: .ssh
- name: ssh
mountPath: /etc/ssh
volumes:
- name: data
persistentVolumeClaim:
claimName: git-data
- name: ssh
persistentVolumeClaim:
claimName: git-ssh
- name: config
configMap:
name: git-config
---
apiVersion: v1
kind: Service
metadata:
name: git-cgit
namespace: mulk
labels:
k8s-app: git
name: git-cgit
spec:
selector:
k8s-app: git
type: ClusterIP
ports:
- name: http
port: 80
targetPort: cgit-http
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: git-gitolite
namespace: mulk
labels:
k8s-app: git
name: git-gitolite
spec:
selector:
k8s-app: git
type: NodePort
ports:
- name: ssh
port: 22
targetPort: gitolite-ssh
protocol: TCP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: git-data
namespace: mulk
labels:
name: git-data
k8s-app: git
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Gi
storageClassName: local-path
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: git-ssh
namespace: mulk
labels:
name: git-ssh
k8s-app: git
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
storageClassName: local-path
---
# TLS certificate for the cgit IngressRoute below. It used to be created
# by cert-manager's ingress-shim from an nginx Ingress, which has been
# removed; the HTTP-01 solver still goes through Traefik's nginx-class
# compat provider (see the letsencrypt-prod ClusterIssuer).
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: git-cgit-cgi-tls
namespace: mulk
spec:
secretName: git-cgit-cgi-tls
dnsNames:
- git.benkard.de
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
---
# Traefik route for cgit. Traefik's ingress-nginx provider does not
# support nginx snippet annotations, and it has no global per-host rate
# limit, so cgit gets a native IngressRoute instead.
#
# A crawler botnet with thousands of rotating IPs and browser user agents
# hammers cgit; cap it at 5 r/s in total (not per client). A single router
# keeps the limit in one bucket (each router gets its own limiter).
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: git-cgit-ratelimit
namespace: mulk
spec:
rateLimit:
average: 5
period: 1s
burst: 20
sourceCriterion:
requestHost: true
---
# Same as the rewrite-target of the Ingress above: strip a ".git" suffix
# from the repository name and route everything to cgit.cgi.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: git-cgit-rewrite
namespace: mulk
spec:
replacePathRegex:
regex: "^/(?:(.*)[.]git(/.*)?|(.*))$"
replacement: "/${1}${2}${3}"
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: git-cgit-https-redirect
namespace: mulk
spec:
redirectScheme:
scheme: https
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: git-cgit-cgi
namespace: mulk
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`git.benkard.de`)
middlewares:
- name: git-cgit-ratelimit
- name: git-cgit-rewrite
services:
- name: git-cgit
port: 80
tls:
secretName: git-cgit-cgi-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: git-cgit-cgi-http
namespace: mulk
spec:
entryPoints:
- web
routes:
- kind: Rule
match: Host(`git.benkard.de`)
middlewares:
- name: git-cgit-https-redirect
services:
- name: git-cgit
port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: git-cgit-assets
namespace: mulk
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /cgit/$1
spec:
rules:
- host: static.git.benkard.de
http:
paths:
- backend:
service:
name: git-cgit
port:
number: 80
path: /(.*)
pathType: ImplementationSpecific
tls:
- hosts:
- static.git.benkard.de
secretName: git-cgit-assets-tls
---
apiVersion: v1
kind: ConfigMap
metadata:
name: git-config
namespace: mulk
data:
cgitrc: |-
css=https://static.git.benkard.de/cgit.css
logo=https://static.git.benkard.de/cgit.png
remove-suffix=1
enable-commit-graph=1
enable-index-links=1
enable-log-filecount=1
enable-log-linecount=1
enable-git-config=1
case-sensitive-sort=0
virtual-root=https://git.benkard.de/
#cache-size=10000
#cache-root=/var/cache/cgit
# needs Pygments
#source-filter=/usr/lib/cgit/filters/syntax-highlighting.py
about-filter=/usr/lib/cgit/filters/about-formatting.sh
clone-url=https://git.benkard.de/$CGIT_REPO_URL
readme=:README.md
readme=:README.markdown
readme=:README.html
readme=:README.txt
readme=:README
project-list=/home/git/projects.list
scan-path=/home/git/repositories/
#
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: git-github-replication
namespace: mulk
labels: &labels
k8s-app: git
spec:
schedule: "*/120 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
ttlSecondsAfterFinished: 3600
template:
metadata:
name: git-github-replication
labels: *labels
spec:
restartPolicy: OnFailure
volumes:
- name: github-secrets
secret:
secretName: github-secrets
defaultMode: 0444
- name: data
persistentVolumeClaim:
claimName: git-data
- name: etc
emptyDir: {}
initContainers:
- name: init
image: docker.io/library/buildpack-deps:scm
securityContext:
runAsUser: 100
runAsGroup: 101
command:
- bash
- -c
- |
echo git:x:106:107:Git:/home/git:/bin/sh >/etc/passwd
volumeMounts:
- name: etc
mountPath: /etc
containers:
- name: main
image: docker.io/library/buildpack-deps:scm
securityContext:
runAsUser: 106
runAsGroup: 107
command:
- bash
- -c
- |
for x in \
kartipalist
do
if ! test -e "/git/repositories/kellertomaten/$x.git"; then
printf "SKIP %s / %s\n" kellertomaten "$x"
continue
fi
cd "/git/repositories/kellertomaten/$x.git"
for branch in master main
do
printf "COPY %s / %s / %s\n" kellertomaten "$x" "$branch"
git fetch "ssh://git@gitlab.benkard.de:32222/kellertomaten/${x}.git" "$branch:$branch" && \
( git push "ssh://mulk@gerrit.benkard.de:29418/${x}.git" "$branch"; \
git push "git@github.com:kellertomaten/${x}.git" "$branch" )
done
done
for x in \
.github \
aendggner \
aquifer \
benki \
cellspp \
cl-json-template \
cl-mulkutils \
cl-protocols \
cljssss-g \
demos \
dose \
fibers \
hellonet \
hello-world-ng \
instadump \
jgvariant \
json-template-r6rs \
json-template-racket \
json-template-typed-racket \
kubeia \
logikorr \
mulkbav \
mulkcms \
mulkcms2 \
mulkjournal \
mulklib \
mulkontainers \
mulkrypt-for-racket \
mulkyid \
objective-cl \
quarkus-googlecloud-jsonlogging \
renovate-config \
rust-samples \
rust-tutorial \
sb-eval2 \
toilet
do
if ! test -e "/git/repositories/mulk/$x.git"; then
printf "SKIP %s / %s\n" mulk "$x"
continue
fi
cd "/git/repositories/mulk/$x.git"
for branch in master main
do
printf "COPY %s / %s / %s\n" mulk "$x" "$branch"
git fetch "https://gitlab.benkard.de/mulk/${x}.git" "$branch:$branch" && \
( git push "ssh://mulk@gerrit.benkard.de:29418/${x}.git" "$branch"; \
git push "git@github.com:benkard/${x}.git" "$branch" )
done
done
true
env:
- name: HOME
value: /home/git
resources:
limits:
memory: 100Mi
requests:
cpu: 20m
memory: 100Mi
volumeMounts:
- name: github-secrets
mountPath: /home/git/.ssh
readOnly: true
- name: data
mountPath: /git
- name: etc
subPath: passwd
mountPath: /etc/passwd