Alex Ellis
Alex shows you how to access Gita from within a private Kubernetes cluster, from anywhere.
Blaise Pabon, a long-time community member told me he was struggling to set up a Gitea instance in his homelab. He wanted it to show off his portfolio and knowledge of Kubernetes whilst interviewing for his next role. I took some time out to look into this for him and write it up so anyone can follow along.
We’re using inlets to get remote access to Gitea’s HTTPS and SSH ports, but you could find other ways to do this if you wish. Check out my post on When your ISP won’t give you a static IP and the inlets FAQ for some of the differences.
GitHub is a great place to host your code, but it’s not the only place. There are many other Git hosting providers, and you can even host your own Git server. In this post, I’ll show you how to host your own Git server using Gitea, and how to expose it to the world.
Why would you want to do that?
As an ardent user of GitHub myself for personal projects, Open Source and commercial software, I’m probably not the target market here, but I have run my own Git server in the past with plain SSH and also with GitLab. There’s something satisfying about having your own code server, of being able to invite your friends, show off your work, and to customise it however you see fit.
Gitea (“A painless self-hosted Git service.”) is an Open Source fork of the Gogs project, and has a built-in UI that looks very similar to GitHub’s. It has integration points for CI, webhooks, bots, and Role Based Access Control (RBAC).
There are two main ways to access it as a user:
Since the web UI requires HTTPS, the easiest way to expose Gitea to the world is to use an Ingress Controller, leaning on cert-manager to acquire, manage and renew a free TLS certificate from Let’s Encrypt.
Initially, I struggled to find the right configuration for Gitea but got there in the end and want to share that with you, so you can get up and running quickly.
I’m using arkade to install charts and CLIs, however you can use Helm or kubectl directly, if you prefer. Just navigate to the homepage of each tool and follow the instructions to install them.
Before we get started:
arkade get kubectl helm
First, set up an Ingress Controller and cert-manager.
arkade install nginx-ingress
arkade install cert-manager
If you’re using K3s, you may have Traefik pre-installed. You can use Traefik, or delete it and install nginx-ingress instead.
(Optional step to remove Traefik):
kubectl delete svc/traefik -n kube-system
kubectl delete deploy/traefik -n kube-system
Create an issuer for cert-manager to use to obtain certificates from Let’s Encrypt:
export DOMAIN="gitea.example.com"
export EMAIL="webmaster@$DOMAIN"
cat > issuer-prod.yaml <<EOF
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-prod
namespace: gitea
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: $EMAIL
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- selector: {}
http01:
ingress:
class: nginx
EOF
kubectl apply -f issuer-prod.yaml
Just remember to replace “nginx” with “traefik” if you’re using K3s, and didn’t switch to ingress-nginx.
Create an initial password for an admin user. We’ll be exposing this on the Internet, so OpenSSL can be used to generate a password:
$(openssl rand -base64 32) > admin.txt
kubectl create secret generic gitea-admin-secret \
-n gitea \
--from-literal username=git \
--from-file password=./admin.txt
Gitea can be installed using a Helm chart, you can find out more about it here: Gitea helm chart
You need to customise this before pasting it in.
Set the DOMAIN and EMAIL variables accordingly, then run the command:
export DOMAIN=gitea.example.com
export EMAIL=webmaster@$DOMAIN
cat <<EOF > values.yaml
ingress:
enabled: true
annotations:
cert-manager.io/issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
hosts:
- host: $DOMAIN
paths:
- path: /
pathType: Prefix
tls:
- secretName: gitea-tls
hosts:
- $DOMAIN
service:
http:
type: ClusterIP
port: 3000
clusterIP: None
ssh:
type: LoadBalancer
port: 2222
clusterIP: None
gitea:
admin:
existingSecret: gitea-admin-secret
email: $EMAIL
config:
server:
SSH_DOMAIN: gitea-ssh.example.com
service:
DISABLE_REGISTRATION: true
SHOW_REGISTRATION_BUTTON: false
EOF
I’ve turned off anonymous registration, to prevent any unwanted users from signing up and uploading spurious content to our server.
helm repo add gitea-charts https://dl.gitea.io/charts/
helm repo update
kubectl create namespace gitea
helm upgrade --install gitea \
gitea-charts/gitea \
--namespace gitea \
-f ./values.yaml
The inlets-operator will look for any LoadBalancer services in your Kubernetes cluster and create a tunnel server for each of them. The Gitea chart needs one LoadBalancer IP for the HTTP UI and another for SSH.
Install the inlets-operator using this guide: Docs: inlets-operator installation
Find the IP of the Ingress Controller in the default namespace, or kube-system for traefik.
kubectl get tunnels -o wide
NAME SERVICE TUNNEL HOSTSTATUS HOSTIP HOSTID
ingress-nginx-controller-tunnel ingress-nginx-controller active 134.209.22.40 337809678
Find the IP of of the SSH service in the gitea namespace.
kubectl get tunnels -o wide -n gitea
NAME SERVICE TUNNEL HOSTSTATUS HOSTIP HOSTID
gitea-ssh-tunnel gitea-ssh active 159.65.28.33 337809677
Once you find the public IP address created by the inlets-operator, you’ll need to create a DNS A record in your DNS control panel.
I.e. gitea.example.com
should point to the IP address of the LoadBalancer service for ingress-nginx or traefik.
Create a separate DNS A record for the SSH service, i.e. ssh.gitea.example.com
should point to the IP address of the LoadBalancer service for the SSH service.
If you’re using DigitalOcean to manage your DNS records, you can create the entries like this:
doctl compute domain create \
--ip-address 134.209.22.40 \
gitea.example.com
doctl compute domain create \
--ip-address 159.65.28.33 \
gitea-ssh.example.com
Log in as an administrator by visiting https://gitea.example.com/admin.
Then, you can log out and log in as a regular user.
The username is git and the password was saved in the “admin.txt” file in an earlier step.
Create the first user
You should now be able to access the Gitea UI at https://gitea.example.com
Note that the URL for cloning via SSH is configured in the Helm chart and is different from the URLs for the UI.
git clone ssh://git@gitea-ssh.o6s.io:2222/alex/web-scraper.git
Here you can see the domain configured and showing up in clone URLs:
The SSH URL is configured in the Gitea config
If you see 503 Service Temporarily Unavailable
or a bad TLS record, then the chances are that you didn’t edit the domain in one of the commands, or tried to use an invalid configuration setting.
Gitea uses initialisation and migration scripts, I found that when changing settings, I had to delete the PersistentVolumes and Helm chart before configuration would reload.
This is how I found out what was failing:
kubectl logs pod/gitea-0 -n gitea -c configure-gitea
Learn how to troubleshoot Kubernetes with my guide: How to Troubleshoot Applications on Kubernetes
There are many different configuration options for Gitea, you may want to explore how you can configure it through the documentation.
What other ideas do you have? Feel free to reach out to me on Twitter: @alexellisuk
Related articles:
Subscribe for updates and new content from OpenFaaS Ltd.
By providing your email, you agree to receive marketing emails.