Gitea Docker Setup: Host Your Own Lightweight GitHub Alternative
Learn how to deploy Gitea using Docker Compose. A complete guide to hosting your own fast, lightweight, and fully customized GitHub/GitLab alternative.
Prerequisites
Before starting, ensure your VPS meets the following minimum requirements: * A Linux VPS (Ubuntu 22.04 LTS or Debian 12 recommended). * A user account with sudo privileges. * Docker Engine and Docker Compose V2 installed. * A domain name pointing to your VPS IP address (e.g., git.example.com).
Directory and Permission Setup
Gitea executes inside Docker as a non-root user (default UID 1000, GID 1000). To avoid volume mounting and file permission mismatch issues on the host, create a dedicated directory structure and verify local ownership:
# Create the root project directory
sudo mkdir -p /opt/gitea
# Create directories for Gitea data and PostgreSQL
sudo mkdir -p /opt/gitea/data /opt/gitea/postgres
# Change ownership to UID 1000 to match Gitea container defaults
sudo chown -R 1000:1000 /opt/gitea/data
sudo chown -R 999:999 /opt/gitea/postgres
The Docker Compose Configuration
Create /opt/gitea/docker-compose.yml with the following service definitions. This configuration sets up Gitea alongside a PostgreSQL database, isolates them on a private Docker bridge network, and sets limit restraints on PostgreSQL.
version: '3.8'
networks:
gitea_net:
driver: bridge
services:
db:
image: postgres:15-alpine
container_name: gitea_db
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=secure_postgres_password_here
- POSTGRES_DB=gitea
networks:
- gitea_net
volumes:
- ./postgres:/var/lib/postgresql/data
shm_size: '256mb'
deploy:
resources:
limits:
memory: 1gb
web:
image: gitea/gitea:1.21.11
container_name: gitea_web
restart: always
depends_on:
- db
networks:
- gitea_net
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:2222:22"
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=secure_postgres_password_here
Key Configuration Directives:
- Port Binding: The ports
3000(HTTP) and22(SSH) are bound strictly to127.0.0.1. This blocks direct external access, forcing all web traffic through a reverse proxy and securing the raw HTTP server. - User mapping:
USER_UID=1000andUSER_GID=1000ensure files written to the volume map back to user1000on the host, preventing root-owned lockouts.
Configuring SSH Passthrough
While mapping port 2222 to the host allows SSH Git operations, it requires remote users to configure custom SSH URLs (e.g., git clone ssh://git@domain:2222/user/repo.git). To enable standard git@domain:user/repo.git links, configure SSH container passthrough on the host.
Step 1: Create the git User on the Host
Create a dedicated git user on your VPS host system matching the container's UID/GID:
sudo groupadd -g 1000 git
sudo useradd -u 1000 -g git -m -s /bin/bash git
Step 2: Set Up Authorized Keys Forwarding
Create a wrapper script on the host to forward incoming SSH commands directly into the Gitea Docker container.
Create /usr/local/bin/gitea-shell on the host:
sudo tee /usr/local/bin/gitea-shell << 'EOF'
#!/bin/sh
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
EOF
sudo chmod +x /usr/local/bin/gitea-shell
Next, link Gitea's internal public keys list to the host git user's keys. Add the following symbolic link so keys updated inside Gitea's web UI are instantly recognized by the host:
sudo mkdir -p /home/git/.ssh
sudo ln -s /opt/gitea/data/git/.ssh/authorized_keys /home/git/.ssh/authorized_keys
sudo chown -R git:git /home/git/.ssh
Reverse Proxy Configuration
You must use a reverse proxy to terminate TLS certificates and route traffic to the container. Below are configuration templates for both Nginx and Caddy.
Option A: Nginx with Let's Encrypt
Install Nginx and certbot:
sudo apt update && sudo apt install nginx certbot python3-certbot-nginx -y
Create /etc/nginx/sites-available/gitea with the following configuration:
server {
listen 80;
server_name git.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable the configuration and fetch a Let's Encrypt certificate:
sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d git.example.com
Option B: Caddy (Automatic HTTPS)
If you prefer a simpler alternative with automated certificate rotation, use a Caddyfile:
git.example.com {
reverse_proxy 127.0.0.1:3000
}
Initial Deployment and Post-Installation
Start the stack using Docker Compose:
cd /opt/gitea
docker compose up -d
Navigate to https://git.example.com in your browser. Gitea will display its initial setup wizard. Set the following options under Gitea Settings:
- Database Type: PostgreSQL
- Host:
db:5432 - Database Name:
gitea - Database Username:
gitea - Database Password:
<your_postgres_password> - Server Domain:
git.example.com - SSH Port:
22(Ensure this reflects the host port since passthrough is set up) - Gitea HTTP Port:
3000 - Gitea Base URL:
https://git.example.com/
Create your administrator account on the setup page, and click Install Gitea.
Backup Strategy
Gitea provides a built-in dump utility to back up the database, repositories, and configurations cleanly. Run the following command to generate a backup archive:
docker exec -u 1000 -it gitea_web gitea dump -c /data/gitea/conf/app.ini
This generates a .zip archive containing: * SQL database dump. * Server configuration (app.ini). * Git repositories. * User uploads and SSH keys.
You can automate this with a cron job to push back up files offsite (e.g., to an S3-compatible storage or another VPS).