Gitea helm

Cover Image for Gitea helm
Tomas
Tomas

Gitea is lightweight version control system based on git. It has many similarities to GitLab and GitHub, to see the full comparison check out Gitea docs. This article covers Kubernetes based Gitea installation using helm chart. K3s Kubernetes cluster is setup on libvirt vm and is hosting docker registry.

Downloading docker images

There are 3 docker images required for Gitea helm chart. Pull dependent images locally:

$ sudo docker pull gitea/gitea:1.11.5
$ sudo docker pull postgres:11
$ sudo docker pull memcached:1.5.19-alpine

Once images is on the local system, tag it with registry prefix:

$ sudo docker tag gitea/gitea:1.11.5 docker-registry.apps.local/gitea/gitea:1.11.
$ sudo docker tag postgres:11 docker-registry.apps.local/postgres:11
$ sudo docker tag memcached:1.5.19-alpine docker-registry.apps.local/memcached:1.5.19-alpine

Push images to local registry:

$ sudo docker push docker-registry.apps.local/gitea/gitea:1.11.5
$ sudo docker push docker-registry.apps.local/postgres:11
$ sudo docker push docker-registry.apps.local/memcached:1.5.19-alpine

Instaling Gitea using helm chart

At the time of writing there's no official Gitea helm chart, however keyporttech provides helm chart on GitHub. Use helm repo add command to add keyporttech repo:

$ helm repo add keyporttech https://keyporttech.github.io/helm-charts/
"keyporttech" has been added to your repositories       

After helm repo is added, create chart values file in /tmp/chart_values.yaml which will override default chart values.

# docker images location, referencing local docker registry
images:
  gitea: "docker-registry.apps.local/gitea/gitea:1.11.5"
  postgres: "docker-registry.apps.local/postgres:11"
  memcached: "docker-registry.apps.local/memcached:1.5.19-alpine"

# enable ingress and tls cert
ingress:
  enabled: true
  protocol: https
  useSSL: true
  ingress_annotations:
    kubernetes.io/ingress.class: traefik
  tls:
    - secretName: wildcard-tls

# define http and ssh services on git.apps.local
service:
  http:
    serviceType: ClusterIP
    port: 3000
    externalHost: git.apps.local
    # unset externalPort and httpAPIPort  
    externalPort:
    httpAPIPort:
  ssh:
    serviceType: NodePort
    port: 22
    externalHost: git.apps.local
    nodePort: 30022
    # expose ssh on port 30022
    externalPort: 30022

# enable and setup data persistence
persistence:
  enabled: true
  giteaSize: 1Gi
  postgresSize: 500Mi
  accessMode: ReadWriteOnce
  storageClass: local-path
  # To keep pvc after chart is uninstalled set annotations
  annotations:
    "helm.sh/resource-policy": keep  

# set postgress password
inPodPostgres:
  postgresPassword: "test"

# set Gitea password
config:
  secretKey: "test"

Install Gitea to Kubernetes apps-local namespace using chart values from /tmp/chart_values.yaml:

$ helm install Gitea keyporttech/gitea \
--namespace apps-local \
--values /tmp/chart_values.yaml

After installation completes, Gitea will be served on https://git.apps.local, test connection using curl. Expect any path to redirect to /install:

$ curl -I https://git.apps.local/login
HTTP/2 302
content-type: text/html; charset=utf-8
date: Sun, 02 Aug 2020 13:24:05 GMT
location: /install
set-cookie: lang=en-US; Path=/; Max-Age=2147483647 
set-cookie: i_like_gitea=15ca8b4d478ad4cf; Path=/; HttpOnly
set-cookie: _csrf=r3gSLu9cs4ESUBhzZRxETFm8pWM6MTU5NjM3NDY0NTIzMTAzNzA2NA; Path=/; Expires=Mon, 03 Aug 2020 13:24:05 GMT; HttpOnly
vary: Accept-Encoding 
x-frame-options: SAMEORIGIN

Navigate to Gitea url https://git.apps.local/login using the browser and create the admin user:

screenshot

When Gitea is configured, add ssh key and create a project.

Gitea helm upgrade

When presistance.annotations['helm.sh/resource-policy'] section is set to "keep", Kubernetes storage claims are not removed when chart is deleted. Thus existing storage can be reused when upgrading or installing the chart again. Access token setup earlier will be used to verify Gitea data integrity after deletion and installation.

Delete Gitea in apps-local namespace.

$ helm delete gitea -n apps-local 

Verify Gitea storage has not been deleted.

$ kubectl get pvc gitea-gitea gitea-postgres -n apps-local

Setup chart values file in /tmp/chart_values.yaml with existing storage.

images:
  gitea: "docker-registry.apps.local/gitea/gitea:1.11.5"
  postgres: "docker-registry.apps.local/postgres:11"
  memcached: "docker-registry.apps.local/memcached:1.5.19-alpine"

ingress:
  enabled: true
  protocol: https
  useSSL: true
  ingress_annotations:
    kubernetes.io/ingress.class: traefik
  tls:
    - secretName: wildcard-tls

service:
  http:
    serviceType: ClusterIP
    port: 3000
    externalHost: git.apps.local
    externalPort:
    httpAPIPort:
  ssh:
    serviceType: NodePort
    port: 22
    externalHost: git.apps.local
    nodePort: 30022
    externalPort: 30022

persistence:
  enabled: true
  # use existing storage claims
  existingGiteaClaim: gitea-gitea
  existingPostgresClaim: gitea-postgres

inPodPostgres:
  postgresPassword: "test"

config:
  secretKey: "test"
  # since existing storage is used, disable Gitea installer
  disableInstaller: true

Install Gitea to apps-local namespace using chart values from /tmp/chart_values.yaml.

$ helm install gitea keyporttech/gitea \
--namespace apps-local \
--values /tmp/chart_values.yaml

After installation is complete, test connection to Gitea api using token value that was setup earlier.

$ TOKEN=c4ecf3f183404bcbdaa5e776d5f8751adffa4b70
$ curl -X GET "https://git.apps.local/api/v1/user?access_token=${TOKEN}" -H  "accept: application/json" | jq
{
"id": 1,
"login": "tomas", 
"full_name": "",
"email": "tomas@apps.local",
"avatar_url": "https://git.apps.local/user/avatar/tomas/-1",
"language": "", 
"is_admin": true, 
"last_login": "1970-01-01T00:00:00Z", 
"created": "2020-08-18T00:48:39Z",
"username": "tomas"
}

Navigate to Gitea url https://git.apps.local using the browser:

screenshot

Clone project that was created after Gitea installation:

$ git clone ssh://git@git.apps.local:30022/tomas/ansible.git  
Cloning into 'ansible'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (5/5), done.

back