--- title: "Self-Hosting Git with Gitea: Your Own GitHub Alternative" description: A comprehensive guide to setting up Gitea - a lightweight, self-hosted Git service that gives you full control over your code repositories. pubDate: 2025-04-19 updatedDate: 2025-04-18 category: Services tags: - gitea - git - self-hosted - devops - kubernetes heroImage: /blog/images/posts/prometheusk8.png --- 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: ```yaml 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: ```bash 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: ```yaml 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: ```bash kubectl apply -f gitea.yaml ``` ## Initial Configuration After installation, you'll be greeted with Gitea's setup page. Here are the settings I recommend: 1. **Database Settings**: If you followed the Docker Compose example, your database is already configured. 2. **General Settings**: - Set your site title (e.g., "LaForceIT Git") - Disable user registration unless you're hosting for multiple people - Enable caching to improve performance 3. **Admin Account**: Create your admin user with a strong password. My configuration looks something like this: ```ini [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: 1. Go to Settings > SSH / GPG Keys 2. Click "Add Key" 3. Paste your public key and give it a name ### 2. Creating Your First Repository 1. Click the "+" button in the top right 2. Select "New Repository" 3. Fill in the details and initialize with a README if desired ### 3. Working with Your Repository To clone your new repository: ```bash git clone git@your-gitea-server:username/repo-name.git ``` Now you can work with it just like any Git repository: ```bash 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: ```yaml 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: 1. Navigate to your repository 2. Go to Settings > Webhooks > Add Webhook 3. Select "Gitea" or "Custom" depending on your needs 4. Enter the URL of your webhook receiver 5. 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: 1. Create a new repository 2. Go to Settings > Mirror Settings 3. Enter the URL of the repository you want to mirror 4. Set the sync interval ## Security Considerations When self-hosting any service, security is a top priority. Here's how I secure my Gitea instance: 1. **Reverse Proxy**: I put Gitea behind Traefik with automatic SSL certificates. 2. **2FA**: Enable two-factor authentication for your admin account. 3. **Regular Backups**: I back up both the Gitea data directory and the database daily. 4. **Updates**: Keep Gitea updated to the latest version to get security fixes. Here's a sample Traefik configuration for Gitea: ```yaml 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: 1. **Ownership**: No sudden changes in terms of service affecting my workflow. 2. **Privacy**: Some projects aren't meant for public hosting. 3. **Learning**: Managing my own services teaches me valuable skills. 4. **Integration**: It fits perfectly with my other self-hosted services. 5. **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._