01Why Self-Host a Git Server?
02Docker Compose Setup with PostgreSQL
1services: 2 gitea: 3 image: gitea/gitea:1.234 environment: 5 - USER_UID=10006 - USER_GID=10007 - GITEA__database__DB_TYPE=postgres8 - GITEA__database__HOST=db:54329 - GITEA__database__NAME=gitea10 - GITEA__database__USER=gitea11 - GITEA__database__PASSWD=${DB_PASSWORD}12 - GITEA__server__ROOT_URL=https://git.example.com/13 - GITEA__server__SSH_DOMAIN=git.example.com14 - GITEA__server__SSH_PORT=222215 - GITEA__service__DISABLE_REGISTRATION=true16 volumes: 17 - gitea-data:/data18 - /etc/timezone:/etc/timezone:ro19 - /etc/localtime:/etc/localtime:ro20 ports: 21 - "3000:3000"22 - "2222:22"23 depends_on: 24 db: 25 condition: service_healthy26 restart: unless-stopped2728 db: 29 image: postgres:16-alpine30 environment: 31 - POSTGRES_USER=gitea32 - POSTGRES_PASSWORD=${DB_PASSWORD}33 - POSTGRES_DB=gitea34 volumes: 35 - postgres-data:/var/lib/postgresql/data36 healthcheck: 37 test: ["CMD", "pg_isready", "-U", "gitea"]38 interval: 10s39 timeout: 5s40 retries: 541 restart: unless-stopped4243volumes: 44 gitea-data: 45 postgres-data: For solo use or very small teams (2-3 people), SQLite works fine and simplifies the setup — just remove the db service and set DB_TYPE to sqlite3. I ran SQLite for my first year with zero issues. Switch to PostgreSQL when you notice search or concurrent push operations slowing down.
03Essential Configuration
1# Database2DB_PASSWORD=use-a-strong-random-password-here34# Generate with: openssl rand -hex 325GITEA__security__SECRET_KEY=your-secret-key-here6GITEA__security__INTERNAL_TOKEN=your-internal-token-here78# Email notifications (optional)9GITEA__mailer__ENABLED=true10GITEA__mailer__PROTOCOL=smtps11GITEA__mailer__SMTP_ADDR=smtp.example.com12GITEA__mailer__SMTP_PORT=46513GITEA__mailer__USER=gitea@example.com14GITEA__mailer__PASSWD=email-password15GITEA__mailer__FROM=gitea@example.com04Built-In CI/CD with Gitea Actions
1# .gitea/workflows/ci.yml — works like GitHub Actions2name: CI3on: 4 push: 5 branches: [main]6 pull_request: 7 branches: [main]89jobs: 10 test: 11 runs-on: ubuntu-latest12 steps: 13 - uses: actions/checkout@v414 - uses: actions/setup-node@v415 with: 16 node-version: '22'17 - run: npm ci18 - run: npm test19 - run: npm run buildThe Gitea Actions runner consumes significant resources during builds. On a resource-constrained server, set concurrency limits (labels and capacity settings in the runner config) to prevent builds from overwhelming your system. I limit mine to 2 concurrent jobs on a 4-core VPS.