Gitfed
bastien-mrq/gitfed / deploy / k8s / deployment.yaml
# Two containers, one pod, one shared PVC:
#   - server: owns the bbolt store exclusively and the admin Unix socket
#     (/data/admin.sock). git+ssh only, no ordinary auth beyond keys/certs.
#   - web:    the web UI (public repo browsing + password-authenticated
#     self-service + admin section). Real login now exists, so unlike the
#     earlier admin-only iteration of this deployment, it's meant to be
#     reachable from the internet — see service.yaml/ingress.yaml.
#
# web talks to server over the admin socket (internal/opsconnect), never by
# opening the bbolt file itself — that file's exclusive lock means only one
# process may ever hold it, which is why it waits for the socket to appear
# rather than racing server for the store at pod startup.
#
# There is no account until you create one: after this Deployment comes up,
# bootstrap your first (admin) account with
#   kubectl -n gitfed exec -it deployment/gitfed -c server -- \
#     gitfed-tui -config /etc/gitfed/gitfed.json
# (Add user → fill in username/key/password, answer "y" to Admin.)
#
# replicas MUST stay at 1: bbolt, the admin socket, and the SSH hostPort are
# all single-instance by construction. strategy=Recreate so a rollout tears
# down the old pod (and its hostPort/PVC claim) before starting the new one,
# rather than briefly running two.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitfed
  namespace: gitfed
  labels:
    app: gitfed
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: gitfed
  template:
    metadata:
      labels:
        app: gitfed
    spec:
      securityContext:
        fsGroup: 1000
      containers:
        - name: server
          image: gitfed:1.2.11
          imagePullPolicy: Never
          command: ["/usr/local/bin/gitfed-server", "-config", "/etc/gitfed/gitfed.json"]
          ports:
            - name: ssh
              containerPort: 2222
              hostPort: 2222
            - name: wellknown
              containerPort: 8443
          volumeMounts:
            - name: data
              mountPath: /data
            - name: config
              mountPath: /etc/gitfed
              readOnly: true
            - name: tmp
              mountPath: /tmp
            - name: home
              mountPath: /home/gitfed
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: [ALL]
            seccompProfile:
              type: RuntimeDefault
          resources:
            requests: {cpu: 20m, memory: 32Mi}
            limits: {cpu: 300m, memory: 256Mi}
          readinessProbe:
            tcpSocket: {port: ssh}
            initialDelaySeconds: 2
          livenessProbe:
            tcpSocket: {port: ssh}
            initialDelaySeconds: 5
            periodSeconds: 20

        - name: web
          image: gitfed:1.2.11
          imagePullPolicy: Never
          command:
            - sh
            - -c
            - |
              until [ -S /data/admin.sock ]; do sleep 1; done
              exec /usr/local/bin/gitfed-web -config /etc/gitfed/gitfed.json
          ports:
            - name: web
              containerPort: 8088
          volumeMounts:
            - name: data
              mountPath: /data
            - name: config
              mountPath: /etc/gitfed
              readOnly: true
            - name: web-tmp
              mountPath: /tmp
            - name: web-home
              mountPath: /home/gitfed
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: [ALL]
            seccompProfile:
              type: RuntimeDefault
          resources:
            requests: {cpu: 10m, memory: 32Mi}
            limits: {cpu: 200m, memory: 128Mi}
          readinessProbe:
            httpGet: {path: /, port: web}
            initialDelaySeconds: 3

      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: gitfed-data
        - name: config
          configMap:
            name: gitfed-config
        # Writable scratch for the read-only root filesystem: git and the
        # runtime need a writable /tmp and $HOME even though the rootfs is
        # locked down. Per-container so the two never share scratch state.
        - name: tmp
          emptyDir: {}
        - name: home
          emptyDir: {}
        - name: web-tmp
          emptyDir: {}
        - name: web-home
          emptyDir: {}