Replicating Gitea Docker SSH Passthrough on K3s
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.
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:
$(kubectl get po -n gitea -l app=gitea -o name --no-headers=true)
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 but when I moved Gitea to k3s I couldn’t find any guides on how to achieve the same thing.
I installed Gitea using the official 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:
#!/bin/sh
/usr/local/bin/kubectl exec -i -n gitea gitea-0 -c gitea -- env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" /bin/sh "$@"
Your namespace might be different.
Then run as root (or sudo):
chmod +x /usr/local/bin/gitea-shell
usermod -s /usr/local/bin/gitea-shell git
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:
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
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.
ssh git@<your gitea url>
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 , but Gitea does not provide shell access. If this is unexpected, please log in with password and setup Gitea under another user. Connection to closed.
Now you can create a repo and you should be able to clone and push via SSH.