summaryrefslogtreecommitdiff
path: root/f3s/forgejo/helm-chart/templates/deployment.yaml
blob: 73c5704591b611804d4e8289bf26990dc265eaac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
apiVersion: apps/v1
kind: Deployment
metadata:
  name: forgejo
  namespace: services
  labels:
    app: forgejo
spec:
  replicas: 1
  # Recreate so the old pod fully terminates before the new one starts —
  # avoids NFS-lock races on the hostPath-backed PVC during rolling updates.
  # This also matters for SQLite: exactly one process may hold the database.
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: forgejo
  template:
    metadata:
      labels:
        app: forgejo
    spec:
      securityContext:
        # The -rootless image runs entirely as the unprivileged git user (1000).
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
      initContainers:
      - name: nfs-check-data
        image: busybox:stable
        command:
        - sh
        - -c
        - |
          test -f /mnt/.nfs-sentinel || (
            echo "ERROR: NFS sentinel missing at /mnt/.nfs-sentinel"
            echo "refusing to start; node likely has NFS unmounted"
            echo "pod would otherwise bind-mount the local-XFS shadow"
            exit 1
          )
        volumeMounts:
        - name: forgejo-data
          mountPath: /mnt
          readOnly: true
      - name: nfs-check-config
        image: busybox:stable
        command:
        - sh
        - -c
        - |
          test -f /mnt/.nfs-sentinel || (
            echo "ERROR: NFS sentinel missing at /mnt/.nfs-sentinel"
            echo "refusing to start; node likely has NFS unmounted"
            echo "pod would otherwise bind-mount the local-XFS shadow"
            exit 1
          )
        volumeMounts:
        - name: forgejo-config
          mountPath: /mnt
          readOnly: true

      containers:
      - name: forgejo
        image: codeberg.org/forgejo/forgejo:16.0.1-rootless
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
          name: http
          protocol: TCP
        - containerPort: 2222
          name: ssh
          protocol: TCP
        env:
        # SQLite rather than a separate PostgreSQL pod: this is a single-writer
        # instance (replicas 1 + Recreate), and NFSv4.2 does real byte-range
        # locking, so the usual SQLite-on-NFS corruption mode does not apply.
        # Revisit if this ever needs more than one replica.
        - name: FORGEJO__database__DB_TYPE
          value: "sqlite3"
        - name: FORGEJO__database__PATH
          value: "/var/lib/gitea/data/forgejo.db"

        # Public identity. ROOT_URL must match what relayd terminates TLS for,
        # otherwise Forgejo generates clone URLs and redirects on the wrong host.
        - name: FORGEJO__server__DOMAIN
          value: "code.f3s.buetow.org"
        - name: FORGEJO__server__ROOT_URL
          value: "https://code.f3s.buetow.org/"
        - name: FORGEJO__server__HTTP_PORT
          value: "3000"

        # Built-in SSH server. SSH_LISTEN_PORT is what the container binds;
        # SSH_PORT is what Forgejo advertises in clone URLs, i.e. the NodePort
        # users actually reach. git-server already owns 30022, so this is 30222.
        - name: FORGEJO__server__START_SSH_SERVER
          value: "true"
        - name: FORGEJO__server__SSH_LISTEN_PORT
          value: "2222"
        # relayd listens on 2022 on the gateways and TCP-forwards to NodePort
        # 30222, so git+ssh works from off-LAN (see relay "forgejo_ssh4" in
        # frontends/etc/relayd.conf.tpl). Not 22: that keeps the forge clear of
        # the constant scanning on the default port. Not 2222 either -- dserver
        # already holds that on the gateways.
        #
        # SSH_PORT is what Forgejo advertises in clone URLs (2022, via relayd);
        # SSH_LISTEN_PORT above is what the container actually binds (2222).
        - name: FORGEJO__server__SSH_DOMAIN
          value: "code.f3s.buetow.org"
        - name: FORGEJO__server__SSH_PORT
          value: "2022"

        # Behind relayd -> Traefik, Forgejo's default trusts only 127.0.0.0/8,
        # so every request would be attributed to the Traefik pod IP: real client
        # IPs lost from the audit trail and per-IP rate limiting defeated. That
        # matters here because the instance is internet-facing. 10.42.0.0/16 is
        # the k3s pod CIDR; Traefik is already configured to pass the correct
        # X-Forwarded-For (see f3s/traefik-config).
        - name: FORGEJO__security__REVERSE_PROXY_TRUSTED_PROXIES
          value: "10.42.0.0/16"

        # This instance is reachable from the public internet through relayd.
        # Lock the installer (otherwise the first visitor gets the setup wizard)
        # and keep signups closed; create the admin with the CLI, see README.
        - name: FORGEJO__security__INSTALL_LOCK
          value: "true"
        - name: FORGEJO__service__DISABLE_REGISTRATION
          value: "true"

        # Catches stale NFS file handles (ESTALE) after an NFS server restart,
        # which a plain HTTP probe would not notice until a request touched disk.
        livenessProbe:
          exec:
            command: ["test", "-f", "/var/lib/gitea/.nfs-sentinel"]
          initialDelaySeconds: 60
          periodSeconds: 30
          failureThreshold: 3
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /api/healthz
            port: 3000
          initialDelaySeconds: 20
          periodSeconds: 15
          failureThreshold: 3
          timeoutSeconds: 5
        volumeMounts:
        - name: forgejo-data
          mountPath: /var/lib/gitea
        - name: forgejo-config
          mountPath: /etc/gitea
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 1Gi

      volumes:
      - name: forgejo-data
        persistentVolumeClaim:
          claimName: forgejo-data-pvc
      - name: forgejo-config
        persistentVolumeClaim:
          claimName: forgejo-config-pvc