Running Gitea on Kubernetes

Gitea is an open source, self hosted git repository with a powerful web UI. In the following short tutorial I will explain (and remember myself) how to setup Gitea on self managed Kubernetes cluster. If you do not yet have a Kubernetes cluster take a look to the Imixs-Cloud project.

The Deployment

Gitea comes with a official docker image. Gitea supports a Helm Chart but personally I am not a fried of Helm so I use the native deployment strategy with yaml files. For the deployment I use 3 yaml files to separate the setup configuration – which is a good practice:

  • 010-deployment.yaml
  • 020-volumes.yaml
  • 030-network.yaml

010-deployment.yaml

The deployment.yaml file is quite easy:

###################################################
# Namespace Gitea
###################################################
apiVersion: v1
kind: Namespace
metadata:
  name: gitea-repo

###############################
# Deplyoment Gitea
###############################
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitea
  namespace: gitea-repo
  labels:
    app: gitea
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gitea
  template:
    metadata:
      labels:
        app: gitea
    spec:
      containers:
      - name: gitea
        image: gitea/gitea:1.13.2
        ports:
        - containerPort: 3000
          name: gitea
        - containerPort: 22
          name: git-ssh
        volumeMounts:
        - mountPath: /data
          name: git-data
      volumes:
      - name: git-data
        persistentVolumeClaim:
          claimName: git-pvc

Gitea exposes the ports 3000 for HTTP and the SSH port 20.

020-volumes.yaml

As you can see I use a persistent volume with the name ‘git-data’ to map the /data folder of Gitea to a Kubernetes volume. If you don’t have yet a distributed storage solution in your Kubernetes cluster take again a look into the section ‘Storage’ of the Imixs-Cloud project.

The yaml file looks like this:

---
###################################################
# Persistence Volume Claim
###################################################
kind: PersistentVolume
apiVersion: v1
metadata:
  name: git-pv
  namespace: gitea-repo
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  claimRef:
    namespace: gitea-repo
    name: git-pvc
  csi:
    driver: driver.longhorn.io
    fsType: ext4
    volumeHandle: git-data
  storageClassName: longhorn-durable


---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: git-pvc
  namespace: gitea-repo
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-durable
  resources:
    requests:
      storage: 5Gi
  volumeName: "git-pv"

Here I define a persistence volume of 5Gi with a durable storage class. Please edit the volume configuration according to your Kubernetes environment. I will not discuss volumes in this tutorial.

030-network.yaml

Finally we need a network configuration consisting of the services to be exposes and a ingress configuration:

###############################
# Service
###############################
---
kind: Service
apiVersion: v1
metadata:
  name: gitea-service
  namespace: gitea-repo
spec:
  selector:
    app: gitea
  ports:
  - name: gitea-http
    port: 3000
  - name: gitea-ssh
    port: 22


---
###################################################
# Ingress
###################################################
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: git-tls
  namespace: gitea-repo
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - gitea.foo.com
    secretName: tls-gitea
  rules:
  - host: gitea.foo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gitea-service
            port:
              number: 3000

Here I expose the port 3000 (http) as an ingress. I use the kubernetes nginx controller and Let’s Encrypt for the ingress. Again you can find description how to use NGINX and Let’s Encrypt in the section ‘NGNIX of the Imixs-Cloud project.

Replace the ‘gita.foo.com’ dns name with your own public internet host name.

Run it…

Now all configuration is ready and we can start the deployment using kubectl:

kubectl apply -f ./your-gitea-config/

Now you should be able to can access your gitea repo from your web browser!

Customizing

Gitea offers many ways to customize the UI and functionality. Most of the configuration can be done in the property file /data/gitea/conf/app.ini . You can find a complete list of properties and options in the Gitea Cheat Sheet . To change the app.ini file first do a ssh into your gitea pod. From inside the pod you can use the vi editor to edit the file. First make a backup:

$ cp /data/gitea/conf/app.ini /data/gitea/conf/app.backup
$ vi /data/gitea/conf/app.ini

After you have changed and saved the file you need to restart the POD.

SSH

Finally I will explain how to enable SSH for the git repo. This step in optional.

I assume that you use the NGINX Ingress Controller. In its default setup the controller listens to the port 80, 443 and 8443. But not to ssh port 22.

Background: an Ingress is specifically for virtual-hosting using the header of the incoming request to know which backend to use. There is no such mechanism in SSH. However, the NGINX Ingress controller supports TCP and UDP services as long as you can assign a dedicated port for them (which we can do in our case). Via a ConfigMap we can configure which port on the ingress controller to map to the port on the Gitea service. Than we can expose the port to the internet. Find details here.

To avoid using port 22 I change the configuration of the Gitea SSH port to 2222.

In the following patch configuration I tell the NGINX Ingress Controller to listen on port 2222 :

spec:
  template:
    spec:
      containers:
      - name: controller
        # defind cusotm tcp/udp configmap
        args:
        - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-configmap-giteassh

        ports:
         - name: ssh
           containerPort: 2222
           protocol: TCP

This patch also apples the configmap ‘tcp-configmap-giteassh’. The config map looks like this:

apiVersion: v1
kind: ConfigMap
metadata:
  name: tcp-configmap-giteassh
  namespace: gitea-repo
data:
  2222: "gitea-repo/gitea-service:2222"

See also the discussion here.

My Personal Conclusion

Finally I come to the conclusion that running gitea on Kubernetes did not really work with the NGINX Ingress Controller. You need to do different tweaks in the controller. Because I use git also for my kubernetes configuration I run Gitea on a separate virtual cloud server outside of my cluster to make these things independent from each other.

Read my tutorial Running Gitea on a Virtual Cloud Server to see how you can setup Gitea in a few minutes on a internet cloud server using Docker.

One Reply to “Running Gitea on Kubernetes”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.