How to Self-Host a Git Server With Gitea (September 2026)?

Self-hosting your own Git server gives you complete control over your code, ensures privacy for sensitive projects, and eliminates dependency on cloud services. Gitea is a lightweight, open-source Git service that provides a familiar GitHub-like interface while using a fraction of the resources. In this guide, I’ll walk you through how to self-host a Git server with Gitea and configure SSH access step by step.

We’ll cover everything from installation to troubleshooting the most common SSH issues that trip people up. By the end, you’ll have a fully functional Git server ready for personal or team use.

Why Choose Gitea Over GitLab or GitHub?

Gitea is the lightest self-hosted Git option available. A basic Gitea installation runs comfortably on a server with just 512MB RAM, while GitLab typically needs at least 4GB. For individual developers or small teams, this efficiency makes a real difference in hosting costs.

Key advantages of Gitea:

  • Single binary written in Go (easy to deploy and update)

  • Familiar GitHub-like interface (minimal learning curve)

  • Active community with frequent releases

  • MIT licensed (fully open source)

  • Works with SQLite, PostgreSQL, or MySQL

Gitea handles repositories, issues, pull requests, and even has built-in CI/CD through Gitea Actions. It’s ideal when you want self-hosting without the overhead of GitLab or the privacy concerns of cloud-hosted services.

Prerequisites for Self-Hosting Gitea

Before starting, make sure you have:

  • Server: Any Linux distribution (Ubuntu, Debian, RHEL, or Alpine work well)

  • Minimum specs: 1 CPU core, 512MB RAM, 10GB storage for personal use

  • Domain name: Optional but recommended for SSL certificates

  • SSH access: Root or sudo privileges on your server

  • Open ports: 80, 443 for web access; port 22 or custom port for SSH

You can deploy Gitea using three methods: a standalone binary, Docker, or Docker Compose. I’ll cover the binary method as the primary approach and include Docker Compose as an alternative.

Step 1: Install Gitea on Your Server

Let’s start with the binary installation method, which is the most straightforward approach for most users.

Option A: Binary Installation (Recommended)

First, create a dedicated system user for Gitea. This is crucial for security and proper SSH operation:

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git

Download the latest Gitea binary for your architecture:

wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/1.22.0/gitea-1.22.0-linux-amd64
chmod +x /usr/local/bin/gitea

Create the required directory structure:

mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea
chmod -R 750 /var/lib/gitea
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

Option B: Docker Compose Installation

If you prefer containerized deployment, create a docker-compose.yml file:

version: "3"

services:
  gitea:
    image: gitea/gitea:1.22.0
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2222:22"
    depends_on:
      - db

  db:
    image: postgres:15
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=gitea
      - POSTGRES_DB=gitea
    networks:
      - gitea
    volumes:
      - ./postgres:/var/lib/postgresql/data

networks:
  gitea:

Start the containers:

docker-compose up -d

Note that Docker deployment maps Gitea’s SSH port to 2222 to avoid conflicts with your server’s system SSH on port 22.

Step 2: Set Up the Database

Gitea supports SQLite, PostgreSQL, and MySQL. Your choice depends on your expected usage.

SQLite (Simplest Option)

SQLite works perfectly for personal use or small teams. No setup is required—Gitea creates the database file automatically during initial configuration. It’s ideal when you have fewer than 10 concurrent users.

PostgreSQL (Production Recommended)

For production deployments, PostgreSQL offers better performance and concurrent access. Install it:

sudo apt install postgresql postgresql-contrib
sudo -u postgres psql

Create the Gitea database and user:

CREATE USER gitea WITH PASSWORD 'your_secure_password';
CREATE DATABASE gitea OWNER gitea;
GRANT ALL PRIVILEGES ON DATABASE gitea TO gitea;
q

MySQL Alternative

If your infrastructure already uses MySQL, it works well with Gitea. Create the database:

sudo mysql
CREATE DATABASE gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL ON gitea.* TO 'gitea'@'localhost' IDENTIFIED BY 'your_secure_password';
FLUSH PRIVILEGES;

Step 3: Create a Systemd Service

Running Gitea as a systemd service ensures it starts automatically and restarts on failure. Create the service file:

sudo nano /etc/systemd/system/gitea.service

Add this configuration:

[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=postgresql.service

[Service]
RestartSec=2s
Type=notify
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable gitea
sudo systemctl start gitea
sudo systemctl status gitea

Step 4: Configure Reverse Proxy with Nginx

Running Gitea behind a reverse proxy lets you use a proper domain name and SSL certificates. Install Nginx:

sudo apt install nginx

Create a server block configuration:

sudo nano /etc/nginx/sites-available/gitea

Add this configuration (replace git.yourdomain.com with your actual domain):

server {
    listen 80;
    server_name git.yourdomain.com;

    location / {
        proxy_pass http://localhost: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 site and test:

sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl reload nginx

SSL with Let’s Encrypt

Install Certbot and obtain an SSL certificate:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d git.yourdomain.com

Certbot automatically configures HTTPS and sets up automatic renewal. Test the renewal process:

sudo certbot renew --dry-run

Step 5: Complete Initial Web Configuration

Visit your Gitea instance in a browser (http://your-server-ip:3000 or https://git.yourdomain.com). The first launch shows a configuration wizard.

Key settings to configure:

  • Database Type: Select SQLite, PostgreSQL, or MySQL based on your setup

  • Domain: Enter your domain name or server IP

  • SSH Port: Use 22 for system SSH or 2222 for Gitea’s built-in SSH

  • HTTP Port: 3000 (default, works behind reverse proxy)

  • Base URL: https://git.yourdomain.com/

Create an administrator account with a strong password. After clicking “Install Gitea,” you’ll see the main dashboard ready for use.

How to Configure SSH Access for Gitea

SSH access is where most users encounter issues. Understanding the two options prevents common problems.

Option 1: Built-in SSH Server (Recommended for Docker)

Gitea includes its own SSH server. When configured on a custom port (like 2222), it doesn’t conflict with your system SSH. This approach is cleaner for Docker deployments.

Edit the Gitea configuration file:

sudo nano /etc/gitea/app.ini

Add these SSH settings:

[server]
SSH_DOMAIN       = git.yourdomain.com
DOMAIN           = git.yourdomain.com
HTTP_PORT        = 3000
ROOT_URL         = https://git.yourdomain.com/
DISABLE_SSH      = false
SSH_PORT         = 2222
START_SSH_SERVER = true

Restart Gitea:

sudo systemctl restart gitea

Option 2: System SSH Daemon (For Binary Installation)

With this approach, Gitea writes to your system’s authorized_keys file. The git user must exist, and Gitea manages keys through its web interface.

Configure app.ini for system SSH:

[server]
SSH_DOMAIN       = git.yourdomain.com
DOMAIN           = git.yourdomain.com
SSH_PORT         = 22
SSH_LISTEN_PORT  = 22
START_SSH_SERVER = false

Generate and Add Your SSH Key

On your local machine, generate an SSH key pair:

ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/gitea_key

Display the public key:

cat ~/.ssh/gitea_key.pub

Copy the output and add it in Gitea:

  1. Go to Settings → SSH / GPG Keys

  2. Click “Add Key”

  3. Paste your public key and save

Configure SSH Client for Custom Port

If you’re using Gitea’s built-in SSH on port 2222, configure your SSH client to use this port automatically. Edit your local SSH config:

nano ~/.ssh/config

Add a Host entry:

Host git.yourdomain.com
    HostName git.yourdomain.com
    Port 2222
    User git
    IdentityFile ~/.ssh/gitea_key

Now you can clone repositories using the standard format:

git clone [email protected]:username/repository.git

Step 7: Configure Firewall and Security

Proper firewall configuration protects your server while allowing necessary access.

Using UFW (Ubuntu/Debian)

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw allow 2222/tcp
sudo ufw enable

Using Firewalld (RHEL/CentOS)

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=22/tcp
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

SELinux Configuration for RHEL

If you’re running RHEL with SELinux enabled, allow Gitea to bind to its ports:

sudo setsebool -P httpd_can_network_connect 1
sudo semanage port -a -t http_port_t -p tcp 3000

Disable Password Authentication

For better security, disable password-based SSH login. Edit the SSH daemon configuration:

sudo nano /etc/ssh/sshd_config

Set these options:

PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no

Restart SSH:

sudo systemctl restart sshd

Gitea vs GitLab vs Forgejo vs Gogs Comparison

Choosing the right self-hosted Git platform depends on your needs. Here’s how they compare:

  • Gitea: Lightest option (512MB RAM), single binary, active community, MIT license. Best for personal use and small teams.

  • GitLab: Most feature-complete (CI/CD, registry, monitoring), but requires 4GB+ RAM. Best for enterprises needing full DevOps tooling.

  • Forgejo: Community fork of Gitea focusing on open governance. Similar resource usage to Gitea. Best if you want community-controlled development.

  • Gogs: Original lightweight Git service (predecessor to Gitea). Less actively maintained. Good for ultra-light deployments.

For most users in 2026, Gitea or Forgejo provides the best balance of features and resource efficiency.

Troubleshooting Common SSH Issues

SSH problems are the most common issues users face with Gitea. Here are the solutions to frequent errors.

Permission Denied (publickey)

This error means SSH can’t authenticate with your key. Check these common causes:

  1. Wrong key file: Verify you’re using the correct identity file with ssh -i ~/.ssh/gitea_key [email protected]

  2. Key not added to Gitea: Confirm your public key appears in Settings → SSH Keys

  3. Port mismatch: If Gitea SSH runs on 2222, specify it: ssh -p 2222 [email protected]

  4. Wrong user: Always use git as the SSH user, not your Gitea username

Gitea Asks for Password Despite SSH Key

This typically happens when you have multiple SSH keys and SSH tries them all. The server rejects attempts after too many failures.

Fix it by specifying exactly which key to use:

git config --global core.sshCommand "ssh -i ~/.ssh/gitea_key -o IdentitiesOnly=yes"

Or add this to your SSH config:

Host git.yourdomain.com
    IdentityFile ~/.ssh/gitea_key
    IdentitiesOnly yes

Too Many Authentication Attempts

When your SSH agent holds many keys, the server may reject your connection after 6 attempts. The fix is to limit which keys SSH offers:

ssh-add ~/.ssh/gitea_key
ssh -o IdentitiesOnly=yes [email protected]

Connection Refused on Custom Port

If you configured Gitea SSH on port 2222 but connections fail:

  1. Verify Gitea is listening: sudo netstat -tulpn | grep 2222

  2. Check firewall allows the port

  3. Confirm START_SSH_SERVER = true in app.ini

Docker SSH Networking Issues

For Docker deployments, SSH requires proper port mapping. Your docker-compose.yml must expose the SSH port:

ports:
  - "2222:22"

Then clone using the mapped port:

git clone ssh://[email protected]:2222/username/repository.git

Testing Your SSH Connection

Always test SSH before cloning:

ssh -T [email protected] -p 2222

A successful connection shows: “Hi there, username! You’ve successfully authenticated.”

Frequently Asked Questions

How do I self-host a git server with Gitea and configure SSH access?

Install Gitea as a binary or via Docker Compose, set up a database (SQLite for simplicity or PostgreSQL for production), configure a reverse proxy with Nginx, obtain SSL certificates with Let’s Encrypt, generate SSH keys, add your public key through the Gitea web UI, and configure your SSH client to connect. The entire process takes about 30-60 minutes for a basic setup.

What is Gitea and how does it compare to GitLab?

Gitea is a lightweight, open-source self-hosted Git service written in Go. It provides a GitHub-like interface with minimal resource requirements (512MB RAM vs GitLab’s 4GB+). GitLab offers more features like built-in CI/CD, container registry, and monitoring, but requires significantly more server resources. Gitea is ideal for individuals and small teams, while GitLab suits enterprises needing full DevOps tooling.

How do I set up SSH keys for Gitea?

Generate an SSH key pair locally using ssh-keygen -t ed25519 -C ‘[email protected]’, copy the public key contents, log into Gitea’s web UI, go to Settings → SSH/GPG Keys, click ‘Add Key’, paste your public key, and save. Then configure your SSH client in ~/.ssh/config with the correct host, port, and identity file.

Why does Gitea ask for a password when my SSH key is correct?

This usually happens when your SSH client tries multiple keys and the server rejects your connection after too many authentication attempts. Fix it by adding IdentitiesOnly=yes to your SSH config, or use git config u002du002dglobal core.sshCommand ‘ssh -i ~/.ssh/your_key -o IdentitiesOnly=yes’ to specify exactly which key to use.

How do I fix SSH Permission denied (publickey) on Gitea?

Check that your public key is added to your Gitea account, verify you’re using the correct key file with -i flag, confirm the SSH port (22 for system SSH, 2222 for Gitea’s built-in SSH), ensure you’re using ‘git’ as the SSH user (not your username), and verify the key file permissions (600 for private key, 644 for public key).

How do I separate the Gitea and system SSH servers?

Set START_SSH_SERVER = true and SSH_PORT = 2222 in your app.ini configuration file. This makes Gitea run its own SSH server on port 2222 while your system SSH remains on port 22. Configure your SSH client to use port 2222 in ~/.ssh/config, or use git config u002du002dglobal core.sshCommand ‘ssh -p 2222’.

Can Gitea run on Docker?

Yes, Gitea runs excellently on Docker and Docker Compose. The official gitea/gitea image is available on Docker Hub. Docker deployment is often preferred because it simplifies dependency management. Use docker-compose.yml to orchestrate Gitea with your database, and map port 2222 to 22 for SSH access to avoid conflicts with system SSH.

How do I configure Gitea on RHEL?

On RHEL/CentOS systems, use dnf to install dependencies, configure PostgreSQL or MariaDB, create the gitea user, and pay special attention to SELinux. Run setsebool -P httpd_can_network_connect 1 to allow reverse proxy connections, and use firewall-cmd to open ports 80, 443, and your SSH port. The binary installation method works best on RHEL.

Conclusion

You now know how to self-host a Git server with Gitea and configure SSH access properly. We covered binary and Docker Compose installation, database setup, reverse proxy configuration, SSH key management, and troubleshooting the most common issues users face.

Your self-hosted Git server gives you complete control over your code without relying on external services. For next steps, consider setting up automated backups of your repositories and database, or explore Gitea Actions for CI/CD workflows directly within your instance.

Leave a Comment