Enabling ssh on a Gitea instance with Kubernetes

As mentioned in The Beginnings of a Homelab, I now run my own Gitea instance.

For it to become my main online git repository, pushing and pulling via ssh was a must. However, I couldn’t find any useful documentation on the topic. This post details how I set it up.

Between the Internet and my Gitea instance, there is my nginx Ingress Controller. At first, I thought I should set up ssh access through it. However, I quickly realised this wouldn’t be the best route for two main reasons. First, Ingress does not support TCP or UDP services. Second, there is no way to express exposing one path to multiple ports; that is, you’re limited to this in an Ingress:

paths:
  - path: /
    backend:
      serviceName: "gitea"
      servicePort: "gitea-http"

As for point one, I’m using the nginx Ingress Controller, and discovered that they’ve implemented a feature which I could have used. With that said though, it didn’t seem reasonable to rely on a feature not officially part of Ingress, so that went out of the window. Anyway, issue number two would have meant I’d have to serve the ssh part of Gitea at a separate domain (e.g. https://ssh.git.ssene.ca for SSH and https://git.ssene.ca for HTTP), which I really did not want to do.

The solution was pretty simple. At first, I had one service:

apiVersion: v1
kind: Service
metadata:
  name: gitea
  namespace: gitea
spec:
  ports:
    - name: gitea-http
      port: 3000
      targetPort: 3000
      protocol: TCP
  selector:
    app: gitea

with the relevant section in the deployment looking like this:

spec:
  ...
    spec:
      containers:
      - name: gitea
        image: gitea/gitea:1.12.0
        ports:
        - containerPort: 3000
          protocol: TCP
          name: gitea-http
        ...

All I did was add a new ssh-only LoadBalancer:

apiVersion: v1
kind: Service
metadata:
  name: gitea-ssh
  namespace: gitea
spec:
  ports:
    - name: gitea-ssh
      port: 22
      targetPort: 22
      protocol: TCP
  type: LoadBalancer
  selector:
    app: gitea

Checking kubectl explain service.spec.ports.port and kubectl explain service.spec.ports.targetPort, we discover that port being equal to 22 means that that port is exposed by the service, and that targetPort also being equal to 22 means that this port is the port to access on the pods targeted by the service. This requires some changes to the deployment, which can be found below:

spec:
  ...
  template:
    ...
    spec:
      containers:
      - name: gitea
        image: gitea/gitea:1.12.0
        ports:
        - containerPort: 3000
          protocol: TCP
          name: gitea-http
        - containerPort: 22
          hostIP: 127.0.0.1
          protocol: TCP
          name: gitea-ssh
        ...

A new port has been added to the list ports with a containerPort of 22. This is the port to expose on the pod’s IP address (working in tandem with targetPort). I set hostIP to localhost here because the documentation does it “to prevent it being accessible external to the host machine itself”.

And that’s it. I ran kubectl apply -f on the relevant files, and with that, Gitea became my primary online code-repository.