Gitea Server with Docker

Deploying a Self-Hosted Gitea Server with Docker, Traefik & MariaDB

Self-hosting a Git service is a powerful way to gain complete control over your source code, automation workflows, and infrastructure. Gitea is a lightweight, open-source Git platform that’s easy to run in a homelab, yet feature-rich enough for production workloads.

In this post, I’ll walk through how I deployed Gitea using Docker Compose, secured it with Traefik reverse proxy, enabled SSH Git access, and connected it to a MariaDB backend.

All sensitive values, such as database passwords, are provided via environment variables, ensuring a clean, secure configuration.

Gitea

  • Complete control over your data
  • Private repositories with no vendor lock-in
  • Fast performance on local hardware
  • Integration with a wider self-hosted stack
  • Freedom to customise authentication, runners, pipelines, and storage

Gitea is a perfect choice because it’s:

  • Lightweight and efficient
  • Easy to run in Docker
  • Compatible with GitHub APIs
  • Actively maintained and community-driven

My Architecture Overview

The deployment consists of:

1. Gitea container

  • Runs the Gitea application
  • Handles repositories, UI, SSH, and API
  • Stores data in a bind-mounted ./data directory
  • Exposes SSH on port 2222

2. MariaDB database

  • Stores user accounts, repo metadata, issues, settings, and more
  • Runs in a separate Docker container using persistent storage

3. Traefik reverse proxy

  • Terminates TLS connections
  • Automatically issues certificates via Cloudflare DNS challenge
  • Routes traffic to Gitea over HTTPS

4. External overlay network (proxy)

  • Shared with other services behind Traefik
  • Keeps container communication isolated from host traffic

Docker Compose

Below is the Docker Compose configuration used to deploy the stack:

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: unless-stopped

    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=${GITEA_DB_TYPE}
      - GITEA__database__HOST=${GITEA_DB_HOST}
      - GITEA__database__NAME=${GITEA_DB_NAME}
      - GITEA__database__USER=${GITEA_DB_USER}
      - GITEA__database__PASSWD=${GITEA_DB_PASS}
      - GITEA__server__ROOT_URL=https://<your-domain>/
      - GITEA__server__DOMAIN=<your-domain>
      - GITEA__server__SSH_DOMAIN=<your-domain>

    volumes:
      - ./data:/data
    networks:
      - proxy

    ports:
      - "2222:22"       # SSH access for Git over SSH

    depends_on:
      - mariadb

    # Traefik labels
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.gitea.entrypoints=https"
      - "traefik.http.routers.gitea.rule=Host(`<your-domain>`)"
      - "traefik.http.routers.gitea.tls=true"
      - "traefik.http.routers.gitea.tls.certresolver=cloudflare"
      - "traefik.http.routers.gitea.middlewares=gitea-auth@file"
      - "traefik.http.services.gitea.loadbalancer.server.port=3000"

  mariadb:
    image: mariadb:11
    restart: unless-stopped

    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}

    volumes:
      - ./db:/var/lib/mysql
    networks:
      - proxy

networks:
  proxy:
    external: true
YAML

All sensitive values (MYSQL_PASSWORD, GITEA_DB_PASS, etc.) should be stored in your .env file or encrypted using tools like SOPS.

Notes:

  • Expose only SSH and rely on Traefik for all web traffic. Keep container ports closed to the outside world.
  • Use environment variables instead of hardcoded secrets. Even better, encrypt your .env with SOPS.
  • Back up your Gitea /data folder regularly. It contains all the repositories and the configuration.
  • Avoid SQLite for multi-user deployments. MariaDB (or PostgreSQL) is far more robust.
  • Leverage Traefik middleware (auth, security headers, rate limiting) for maximum security.

Gitea is an exceptional self-hosted Git platform, and deploying it with Docker, MariaDB, and Traefik creates a robust, secure, and resilient setup suitable for personal use, homelabs, and even small teams.

Whether you’re learning DevOps, running a homelab, or looking for an alternative to GitHub, this stack provides complete control and reliability with minimal overhead.

Back to top arrow