
If you’re a developer like me who values ownership and privacy, you’ve probably wondered if there’s a way to get the convenience of GitHub or GitLab without handing over your code to a third party. Enter Gitea - a painless, self-hosted Git service written in Go that I’ve been using for my personal projects for the past year.
Let me walk you through setting up your own Gitea instance and show you why it might be the perfect addition to your development workflow.
Why Gitea?
First, let’s talk about why you might want to run your own Git server:
- Complete control: Your code, your server, your rules.
- Privacy: Keep sensitive projects completely private.
- No limits: Create as many private repositories as you want.
- Lightweight: Gitea runs smoothly on minimal hardware (even a Raspberry Pi).
- GitHub-like experience: Familiar interface with issues, pull requests, and more.
I’ve tried several self-hosted Git solutions, but Gitea strikes the perfect balance between features and simplicity. It’s like the Goldilocks of Git servers - not too heavy, not too light, just right.
Getting Started with Gitea
Option 1: Docker Installation
The easiest way to get started with Gitea is using Docker. Here’s a simple docker-compose.yml
file to get you up and running:
version: "3"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea_password
restart: always
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
networks:
- gitea
db:
image: postgres:14
container_name: gitea-db
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea_password
- POSTGRES_DB=gitea
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- gitea
networks:
gitea:
external: false
Save this file and run:
docker-compose up -d
Your Gitea instance will be available at http://localhost:3000
.
Option 2: Kubernetes Deployment
For those running a Kubernetes cluster (like me), here’s a basic manifest to deploy Gitea:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea
labels:
app: gitea
spec:
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea
image: gitea/gitea:latest
ports:
- containerPort: 3000
- containerPort: 22
volumeMounts:
- name: data
mountPath: /data
env:
- name: USER_UID
value: "1000"
- name: USER_GID
value: "1000"
volumes:
- name: data
persistentVolumeClaim:
claimName: gitea-data
---
apiVersion: v1
kind: Service
metadata:
name: gitea
spec:
type: ClusterIP
ports:
- port: 3000
targetPort: 3000
name: web
- port: 22
targetPort: 22
name: ssh
selector:
app: gitea
Apply it with:
kubectl apply -f gitea.yaml
Initial Configuration
After installation, you’ll be greeted with Gitea’s setup page. Here are the settings I recommend:
-
Database Settings: If you followed the Docker Compose example, your database is already configured.
-
General Settings:
- Set your site title (e.g., “ArgoBox Git”)
- Disable user registration unless you’re hosting for multiple people
- Enable caching to improve performance
-
Admin Account: Create your admin user with a strong password.
My configuration looks something like this:
[server]
DOMAIN = git.laforce.it
SSH_DOMAIN = git.laforce.it
ROOT_URL = https://git.laforce.it/
DISABLE_SSH = false
SSH_PORT = 22
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true
[security]
INSTALL_LOCK = true
Integrating with Your Development Workflow
Now that Gitea is running, here’s how I integrate it into my workflow:
1. Adding Your SSH Key
First, add your SSH key to Gitea:
- Go to Settings > SSH / GPG Keys
- Click “Add Key”
- Paste your public key and give it a name
2. Creating Your First Repository
- Click the ”+” button in the top right
- Select “New Repository”
- Fill in the details and initialize with a README if desired
3. Working with Your Repository
To clone your new repository:
git clone git@your-gitea-server:username/repo-name.git
Now you can work with it just like any Git repository:
cd repo-name
echo "# My awesome project" > README.md
git add README.md
git commit -m "Update README"
git push origin main
Advanced Gitea Features
Gitea isn’t just a basic Git server - it has several powerful features that I use daily:
CI/CD with Gitea Actions
Gitea recently added support for Actions, which are compatible with GitHub Actions workflows. Here’s a simple example:
name: Go Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...
Webhooks for Integration
I use webhooks to integrate Gitea with my deployment pipeline. Here’s how to set up a simple webhook:
- Navigate to your repository
- Go to Settings > Webhooks > Add Webhook
- Select “Gitea” or “Custom” depending on your needs
- Enter the URL of your webhook receiver
- Choose which events trigger the webhook
Mirror Repositories
One of my favorite features is repository mirroring. I use this to keep a backup of important GitHub repositories:
- Create a new repository
- Go to Settings > Mirror Settings
- Enter the URL of the repository you want to mirror
- Set the sync interval
Security Considerations
When self-hosting any service, security is a top priority. Here’s how I secure my Gitea instance:
-
Reverse Proxy: I put Gitea behind Traefik with automatic SSL certificates.
-
2FA: Enable two-factor authentication for your admin account.
-
Regular Backups: I back up both the Gitea data directory and the database daily.
-
Updates: Keep Gitea updated to the latest version to get security fixes.
Here’s a sample Traefik configuration for Gitea:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: gitea
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`git.yourdomain.com`)
kind: Rule
services:
- name: gitea
port: 3000
tls:
certResolver: letsencrypt
Why I Switched from GitHub to Gitea
People often ask me why I bother with self-hosting when GitHub offers so much for free. Here are my reasons:
- Ownership: No sudden changes in terms of service affecting my workflow.
- Privacy: Some projects aren’t meant for public hosting.
- Learning: Managing my own services teaches me valuable skills.
- Integration: It fits perfectly with my other self-hosted services.
- Performance: Local Git operations are lightning-fast.
Wrapping Up
Gitea has been a fantastic addition to my self-hosted infrastructure. It’s reliable, lightweight, and provides all the features I need without the complexity of larger solutions like GitLab.
Whether you’re a privacy enthusiast, a homelab tinkerer, or just someone who wants complete control over your code, Gitea is worth considering. The setup is straightforward, and the rewards are significant.
What about you? Are you self-hosting any of your development tools? Let me know in the comments!
This post was last updated on January 18, 2024 with information about Gitea Actions and the latest configuration options.