summaryrefslogtreecommitdiff
path: root/f3s/git-server/README.md
blob: 28050b84bc65f962c79ac139fc23ce2df0f7cc80 (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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# Self-Hosted Git Server with SSH and CGit Web UI

A self-hosted git repository solution for the f3s k3s cluster, replacing external Codeberg dependency.

## Components

- **SSH Git Server**: Alpine-based container with OpenSSH and git for repository access
- **CGit Web UI**: Browse repositories at `http://cgit.f3s.buetow.org`
- **Single Pod Design**: Both containers share storage via ReadWriteMany PVC
- **Persistent SSH Host Keys**: Keys are stored in NFS and persist across pod restarts

## Architecture

```
┌────────────────────────────────────────┐
│     Pod: git-server (cicd namespace)   │
├────────────────────────────────────────┤
│ Container 1: SSH Git Server            │
│  - Port 22 (SSH)                       │
│  - User: git (UID 1000)                │
│                                        │
│ Container 2: cgit + nginx              │
│  - Port 8080 (HTTP)                    │
│  - User: www-data (UID 33)             │
│                                        │
│ Shared Volume: /repos (5Gi, NFS)       │
└────────────────────────────────────────┘
```

## Network Access

- **Internal (ArgoCD)**: `git-server.cicd.svc.cluster.local:22`
- **External SSH**: NodePort 30022 on any cluster node
- **Web UI**: `http://cgit.f3s.buetow.org`

## Initial Setup

### 1. Build and Push Docker Image

```bash
cd docker-image
just f3s
```

### 2. Setup Storage on Cluster Nodes

```bash
ssh root@r0
mkdir -p /data/nfs/k3svolumes/git-server/repos
chown -R 1000:33 /data/nfs/k3svolumes/git-server
chmod -R 0755 /data/nfs/k3svolumes/git-server
```

### 3. Initialize Repository

Clone the existing Codeberg repository as a bare repo:

```bash
ssh root@r0
cd /data/nfs/k3svolumes/git-server/repos
git clone --bare https://codeberg.org/snonux/conf.git conf.git
chown -R 1000:33 conf.git
chmod -R 0755 conf.git
```

### 4. Create SSH Key Secrets

**IMPORTANT**: Secrets must be created manually in Kubernetes, NOT stored in git.

#### For ArgoCD Access

Generate SSH key pair:

```bash
ssh-keygen -t ed25519 -C "argocd@f3s.cluster" -f /tmp/argocd-git-key -N ""
```

Create authorized_keys secret for git-server:

```bash
# Save public key to file
cat /tmp/argocd-git-key.pub > /tmp/authorized_keys

# Create secret in Kubernetes
kubectl create secret generic git-server-authorized-keys \
  --from-file=authorized_keys=/tmp/authorized_keys \
  -n cicd
```

Create private key secret for ArgoCD (needed later):

```bash
kubectl create secret generic argocd-git-ssh-key \
  --from-file=sshPrivateKey=/tmp/argocd-git-key \
  -n cicd
```

#### For User Push Access

To add additional SSH keys for users to push:

```bash
# Get current authorized_keys
kubectl get secret git-server-authorized-keys -n cicd -o jsonpath='{.data.authorized_keys}' | base64 -d > /tmp/authorized_keys

# Add your SSH public key
echo "ssh-ed25519 AAAAC3Nza... user@host" >> /tmp/authorized_keys

# Update secret
kubectl create secret generic git-server-authorized-keys \
  --from-file=authorized_keys=/tmp/authorized_keys \
  -n cicd \
  --dry-run=client -o yaml | kubectl apply -f -

# Restart git-server to pick up new keys
kubectl rollout restart deployment/git-server -n cicd
```

### 5. Deploy via ArgoCD

```bash
kubectl apply -f /home/paul/git/conf/f3s/argocd-apps/cicd/git-server.yaml
```

Or commit and push the ArgoCD Application manifest to let ArgoCD sync automatically.

### 6. Verify Deployment

```bash
# Check pod status
kubectl get pods -n cicd -l app=git-server

# Check logs
kubectl logs -n cicd -l app=git-server -c git-server --tail=50
kubectl logs -n cicd -l app=git-server -c cgit --tail=50

# Test cgit web UI
curl -I http://cgit.f3s.buetow.org
```

## Repository URLs

### For ArgoCD (Internal)

```
ssh://git@git-server.cicd.svc.cluster.local/repos/conf.git
```

### For Users (External)

```bash
# Via NodePort (direct)
git clone ssh://git@r0:30022/repos/conf.git

# Via SSH config alias
# Add to ~/.ssh/config:
Host f3s-git
  HostName r0.f3s.buetow.org
  Port 30022
  User git
  IdentityFile ~/.ssh/id_f3s_git

# Then clone with:
git clone f3s-git:/repos/conf.git
```

## Managing Repositories

### Add New Repository

```bash
ssh root@r0
cd /data/nfs/k3svolumes/git-server/repos
git init --bare newrepo.git
chown -R 1000:33 newrepo.git
chmod -R 0755 newrepo.git
```

The new repository will automatically appear in cgit (scan-path feature).

### Remove Repository

```bash
ssh root@r0
rm -rf /data/nfs/k3svolumes/git-server/repos/oldrepo.git
```

## Troubleshooting

### Git Push Fails with Permission Denied

1. Check if your SSH key is in authorized_keys:
   ```bash
   kubectl get secret git-server-authorized-keys -n cicd -o jsonpath='{.data.authorized_keys}' | base64 -d
   ```

2. Verify git-server pod is running:
   ```bash
   kubectl get pods -n cicd -l app=git-server
   ```

3. Check SSH logs:
   ```bash
   kubectl logs -n cicd -l app=git-server -c git-server -f
   ```

### CGit Shows No Repositories

1. Check if repos exist in storage:
   ```bash
   ssh root@r0 ls -la /data/nfs/k3svolumes/git-server/repos/
   ```

2. Check cgit container logs:
   ```bash
   kubectl logs -n cicd -l app=git-server -c cgit
   ```

3. Verify cgit configuration:
   ```bash
   kubectl get configmap cgit-config -n cicd -o yaml
   ```

### ArgoCD Can't Clone Repository

1. Verify ArgoCD SSH key secret exists:
   ```bash
   kubectl get secret argocd-git-ssh-key -n cicd
   ```

2. Check if ArgoCD public key is in authorized_keys:
   ```bash
   kubectl get secret git-server-authorized-keys -n cicd -o jsonpath='{.data.authorized_keys}' | base64 -d
   ```

3. Test SSH connection from ArgoCD repo-server:
   ```bash
   kubectl exec -n cicd deploy/argocd-repo-server -- \
     ssh -T git@git-server.cicd.svc.cluster.local
   ```

## Backup and Recovery

Backups are handled by ZFS snapshots at the storage layer (`/data/nfs/k3svolumes/git-server`).

To recover:
1. Restore ZFS snapshot
2. Redeploy git-server application via ArgoCD

## Security Notes

- SSH keys are restricted to git-shell only (no shell access)
- git-server container runs as non-root user (UID 1001)
- cgit container has read-only access to repositories
- All container capabilities dropped for enhanced security
- Secrets managed via Kubernetes Secrets, never committed to git
- SSH host keys stored in NFS but copied to local emptyDir at startup (OpenSSH security requirement)

## Monitoring

View logs:

```bash
# SSH server logs
kubectl logs -n cicd -l app=git-server -c git-server -f

# CGit web server logs
kubectl logs -n cicd -l app=git-server -c cgit -f
```

Check resource usage:

```bash
kubectl top pod -n cicd -l app=git-server
```