Homelab - Day 4 - Self-Hosting Gitea
Posted on Fri 07 March 2025 in homelab
Aims
Today’s goal was to deploy Gitea on my K3s cluster, ensuring that:
- It used persistent storage via my NAS.
- It was accessible externally through Traefik.
- It could eventually replace GitHub for my FluxCD setup.
What I Did
Storage and Permissions Woes
Running Gitea as a stateless container worked fine initially, but as soon as I introduced persistence, things got tricky. I ran into permission issues almost immediately, thanks to the interplay between Kubernetes' user permissions and my NAS file system.
- I set up a PersistentVolume (PV) backed by NFS, but the default Gitea user didn’t have the correct write permissions.
- After some trial and error (and some questionable security decisions), I got it working by setting specific user IDs and group IDs on the NAS side to align with the Gitea container.
- Long-term, I’ll need a more secure approach, likely involving init containers to set permissions properly.
Exposing Gitea with Traefik
- Since K3s includes Traefik by default, I wanted to use it to expose Gitea externally.
- Unlike Unifi, which required
IngressRouteTCP
, Gitea worked fine with a standard Ingress configuration. - I configured DNS to point
git.example.com
to my Traefik instance, and everything worked as expected. - Here’s the working setup:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea-ingress
namespace: gitea
spec:
rules:
- host: git.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea-web
port:
number: 3000
Next Steps: FluxCD Integration
Now that Gitea is running, the next challenge is configuring my FluxCD setup to pull from it rather than GitHub.
- I’ll need to generate an SSH keypair for Flux and store the public key in Gitea.
- Update my
GitRepository
resources in Flux to use the self-hosted Gitea instance. - Verify that Flux can pull manifests and reconcile changes correctly.
Lessons Learned
- Storage & Permissions: Dealing with NAS-mounted volumes on Kubernetes often introduces user/group ID mismatches. Ensuring correct ownership at the NAS level is crucial.
- Security Considerations: In my initial setup, I relaxed permissions too much just to get things running. A proper solution will involve configuring the correct UID/GID mappings in a way that doesn’t compromise security.
- Ingress Simplicity: Unlike Unifi, which required TCP passthrough for TLS termination, Gitea was happy with a simple
Ingress
resource.
Final Thoughts
With Gitea running smoothly, I’m one step closer to fully self-hosting my development workflow. Getting FluxCD working with it will be the next major milestone. Beyond that, I’ll need to consider backups, access controls, and high availability—but that’s a problem for another day!