namesny-com/content/blog/gitea.md

82 lines
3.7 KiB
Markdown

---
title: "Replicating Gitea Docker SSH Passthrough on K8s"
date: "2023-02-12"
---
If you are selfhosting Gitea on a single node Kubernetes cluster and want to enable git through SSH while keeping SSH connection to the cluster, this guide is for you.
<!--more-->
**Update**
As of Gitea Helm Chart v9.0.0, Gitea is not a StatefulSet but a Deployment instead. In order to make this work you have to replace pod pod name `gitea-0` with:
{{< highlight bash >}}
$(kubectl get po -n gitea -l app=gitea -o name --no-headers=true)
{{< / highlight >}}
Command substitution does not work in `AuthorizedKeysCommand` so I suggest creating a separate script along the lines of `/usr/local/bin/gitea-shell`
## Background
I am currently in the process of migrating my selfhosted applications from docker-compose to Kubernetes. One of my most used selfhosted app is Gitea. I use it to host my projects, dotfiles and config files where I don't expect any contributions or I simply want to keep it more private. In my docker-compose setup I used SSH Container Passthrough from [Gitea docs](https://docs.gitea.io/en-us/install-with-docker/#SSH-container-passthrough) but when I moved Gitea to k8s I couldn't find any guides on how to achieve the same thing.
I installed Gitea using the official [Helm Chart](https://gitea.com/gitea/helm-chart/). The documentation says this about enabling SSH:
> If you're using ingress and want to use SSH, keep in mind, that ingress is not able to forward SSH Ports. You will need a LoadBalancer like metallb and a setting in your SSH service annotations.
However using this method will route all incoming SSH connections to the Gitea container, essentialy disabling SSH connection to the host. Therefore we need a way to pass SSH connections to user `git` to our Gite container running on Kubernetes and at the same time allow SSH connections to host for some other user(s)
## Kubernetes Setup
Create user git on your host and deploy Gitea to Kubernetes (e.g. using Helm). You don't need to expose port 22 using a service.
First we are going to create a new login shell for user git. Create file `/usr/local/bin/gitea-shell` with content:
{{< highlight bash >}}
#!/bin/sh
/usr/local/bin/kubectl exec -i -n gitea gitea-0 -c gitea -- env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" /bin/sh "$@"
{{< / highlight >}}
Your namespace might be different.
Then run as root (or sudo):
{{< highlight bash >}}
chmod +x /usr/local/bin/gitea-shell
usermod -s /usr/local/bin/gitea-shell git
{{< / highlight >}}
Now everytime the user git logs in (i.e. using git via SSH) `/usr/local/bin/gitea-shell` gets executed which means our original SSH command will be executed in the gitea container.
Finally we need to make sure that the SSH keys we add through Gitea interface allow us to 'login' as git user.
Edit `/etc/SSH/SSHd_config` and add the following:
{{< highlight yaml>}}
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/local/bin/kubectl exec -i -n gitea gitea-0 -c gitea -- /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
{{< / highlight >}}
If you are using `AllowUsers` directive don't forget to add user git
## Testing
Open Gitea in web browser and add you SSH key. Then try to SSH into the Gitea container.
{{< highlight bash >}}
ssh git@<your gitea url>
{{< / highlight >}}
You should get a message like this:
> PTY allocation request failed on channel 0
> Hi there, test! You've successfully authenticated with the key named <your ssh key>, but Gitea does not provide shell access.
> If this is unexpected, please log in with password and setup Gitea under another user.
> Connection to <your gitea url> closed.
Now you can create a repo and you should be able to clone and push via SSH.