Wednesday, 2021 April 07

Over the years I've gone through a few different methods of storing my git repositories. A few years back I settled on the 'bronze' tier on Gitlab. For the most part I was a satisfied customer. However, back in January I was notified that they were discontinuing the bronze tier. Not only did this in general annoy me, the sheer quantity of buzzwords in the email made it clear that the marketing department was running Gitlab. I resolved to move off of it.

First I looked at SourceHut. I liked the idea of it, but I had a hard time working up the enthusiasm to do anything further after I signed up.

Coincidentally, there was a a thread on Hacker News about Kallithea, a self-hosted Github alternative. This got me thinking about whether or not I should self-host, and eventually I decided that was probably my best bet long-term. I looked at the options and settled on Gogs, mostly because it looked good and because it had built-in support for issue tracking.

It was actually pretty straightforward to get it set up on my Kubernetes cluster. First, I created a manifest.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gogs-data
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: do-block-storage
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
  name: gogs-http-service
spec:
  type: ClusterIP
  selector:
    stage: prod
    component: gogs
  ports:
  - port: 80
    targetPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: gogs-ssh-service
spec:
  type: NodePort
  selector:
    stage: prod
    component: gogs
  ports:
  - protocol: TCP
    nodePort: 32022
    port: 32022
    targetPort: 22
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: gogs-ingress-route
spec:
  entryPoints:
  - websecure
  tls:
    certResolver: letsencrypt
  routes:
  - match: Host(`gogs.brutallogic.net`)
    kind: Rule
    middlewares:
    - name: basic-auth
    services:
    - name: gogs-http-service
      port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gogs-deployment
  labels:
    stage: prod
    component: gogs
  annotations:
    flux.weave.works/automated: 'true'
spec:
  replicas: 1
  selector:
    matchLabels:
      stage: prod
      component: gogs
  template:
    metadata:
      labels:
        stage: prod
        component: gogs
    spec:
      containers:
      - resources:
        name: gogs
        image: gogs/gogs:0.12
        ports:
        - name: gogs-http-port
          containerPort: 3000
        - name: gogs-ssh-port
          containerPort: 22
        volumeMounts:
        - mountPath: /data
          name: gogs-volume
      volumes:
      - name: gogs-volume
        persistentVolumeClaim:
          claimName: gogs-data

This will be automatically applied by flux. DigitalOcean automatically creates persistent volumes when needed, so I didn't need to do anything on the storage side. I did, however, need to punch open a new port in the DigitalOcean load balancer that sits in front of Traefik. This is all managed by Terraform.

...
resource "digitalocean_loadbalancer" "loadbalancer" {
...
  forwarding_rule {
    entry_port     = 22
    entry_protocol = "tcp"

    target_port     = 32022
    target_protocol = "tcp"
  }
...

At this point Gogs was up and running and I could log in via the web interface. I then added a new SSH key and was able to successfully add it as a remote and push code to it.

This is a great start on replacing Gitlab. The next two major pieces of functionality will be to replace the pipeline functionality, and to make sure that I'm backing up all of the data. I will cover both of those in future blog posts. I may also look into exporting my issues in Gitlab and importing them into Gogs, but honestly I'm not sure there's much value in that.

Tuesday, 2021 April 06 Saturday, 2021 June 05