# How to Set Up a Personal Git Server with Gitea: A Complete Self-Hosting Guide

> Learn how to set up a personal Git server with Gitea. This guide covers Docker deployment, web configuration, and optional HTTPS setup for secure code hosting.

- Repository: [Michael Royal/Self-Hosting-Guide](https://github.com/mikeroyal/Self-Hosting-Guide)
- Tags: how-to-guide
- Published: 2026-06-17

---

**To set up a personal Git server with Gitea, deploy the official `gitea/gitea` Docker image with persistent volumes for data and SQLite, complete the initial configuration via the web installer, and optionally add a reverse proxy like Caddy for HTTPS.**

Gitea is a lightweight, self-hosted Git service written in Go and released under the MIT license. As a community-maintained fork of Gogs, it provides a fully-featured web UI for managing repositories, users, teams, pull requests, and issues. According to the `mikeroyal/Self-Hosting-Guide` repository, Gitea is distributed as a single binary or Docker image, storing all data on the host file system, making it ideal for personal or small-team Git servers.

## Architecture Overview

A typical Gitea deployment consists of several components working together:

- **Gitea binary or Docker image**: Handles HTTP API, web UI, authentication, and Git operations. The official image is `gitea/gitea:latest`.
- **Persistent storage**: Host-mounted directories (e.g., `/var/lib/gitea`) that hold repositories, database files, and configuration.
- **Database**: Built-in SQLite for personal use, or external MySQL/PostgreSQL for larger setups.
- **Reverse proxy (optional)**: Provides TLS termination and URL rewriting using Caddy, Nginx, or Traefik.
- **SSH daemon**: Integrated into Gitea via the `gitea ssh` sub-command or external OpenSSH for `git@host:repo.git` cloning.

## Prerequisites

Before deploying Gitea, ensure your system meets these requirements:

- **Operating system**: Any modern Linux distribution (Ubuntu 22.04 LTS, Debian 12, etc.)
- **Docker Engine**: Version 20.10 or newer
- **Docker Compose**: v2 plugin installed
- **Network access**: Ports 80/443 for HTTP/HTTPS and optionally port 22 for SSH
- **Disk space**: At least 2 GB for the container plus additional space for repositories
- **Permissions**: Root or sudo access to install Docker if not already present

## Step-by-Step Deployment with Docker Compose

The simplest production-ready approach uses a Docker Compose stack with SQLite persistence.

### Prepare the Directory Structure

Create the host directories that will store Gitea data and database files:

```bash
mkdir -p $HOME/gitea/data $HOME/gitea/db/sqlite
chmod -R 755 $HOME/gitea

```

The resulting layout should look like this:

```text
$HOME/gitea/
├── docker-compose.yml
├── data/
│   └── gitea/
│       ├── custom/
│       ├── data/
│       ├── logs/
│       └── repositories/
└── db/
    └── sqlite/

```

### Create the Docker Compose Configuration

Create a [`docker-compose.yml`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/docker-compose.yml) file in `$HOME/gitea/` with the following content:

```yaml
version: "3.8"

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: unless-stopped
    environment:
      - USER_UID=1000
      - USER_GID=1000
    ports:
      - "3000:3000"
      - "2222:22"
    volumes:
      - ./data/gitea:/var/lib/gitea

```

Key configuration points:

- **Ports**: `3000` exposes the web UI, while `2222` maps to the internal SSH server on port `22`.
- **Volumes**: The `./data/gitea:/var/lib/gitea` mount ensures all data persists across container restarts.
- **Environment**: `USER_UID` and `USER_GID` should match your host user to maintain consistent file ownership.

### Launch the Gitea Container

Navigate to your Gitea directory and start the stack:

```bash
cd $HOME/gitea
docker compose up -d

```

Docker will pull the `gitea/gitea` image (approximately 180 MB) and launch the container.

### Complete the Web-Based Installation

Open your browser and navigate to `http://<YOUR_HOST_IP>:3000`. On the first-time setup page, configure the following fields:

- **Database Type**: Select `SQLite3` (pre-selected by default)
- **Path**: `/var/lib/gitea/data/gitea.db`
- **Application URL**: `http://<YOUR_HOST_IP>:3000/`
- **Server Domain**: Your host IP or DNS name
- **SSH Port**: `2222` (the host-exposed port)
- **Repository Root Path**: `/var/lib/gitea/data/git/repositories`
- **Disable Registration**: **Enabled** (recommended for personal servers)

Click **Install Gitea** to create the SQLite database, write the configuration to your mounted volume, and initialize the web UI.

## Optional: Secure Your Server with HTTPS Using Caddy

For production use, add a reverse proxy to handle TLS termination automatically.

### Add the Caddy Service

Extend your [`docker-compose.yml`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/docker-compose.yml) to include Caddy:

```yaml
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

```

### Configure the Caddyfile

Create `./caddy/Caddyfile` with the following configuration:

```text
yourdomain.example.com {
    reverse_proxy gitea:3000
    tls you@example.com
}

```

Replace `yourdomain.example.com` with your actual DNS name. After adding the service, restart the stack:

```bash
docker compose up -d

```

Caddy automatically provisions Let's Encrypt certificates, allowing you to access Gitea securely at `https://yourdomain.example.com`.

## Using Your Personal Git Server

Once deployed, you can immediately start hosting code.

### Creating Your First Repository

1. Log in with the admin account created during installation.
2. Click **New Repository**, provide a name (e.g., `my-project`), and select **Public** or **Private**.
3. Click **Create Repository** to initialize the repository.

### Clone via HTTPS

Use the standard Git clone command with your server address:

```bash
git clone http://<HOST_OR_DOMAIN>/username/my-project.git

```

### Clone via SSH

First, add your public SSH key under **Settings → SSH / GPG Keys** in the Gitea web interface. Then clone using:

```bash
git clone ssh://git@<HOST_OR_DOMAIN>:2222/username/my-project.git

```

If you configured the default port 22 on the host, omit the `:2222` port specification.

## Maintenance and Backup

Regular maintenance ensures your Git server remains secure and reliable:

- **Backup the entire Gitea data directory**:
  ```bash
  docker exec gitea tar czf - /var/lib/gitea | gzip > gitea-backup-$(date +%F).tgz
  ```

- **Upgrade Gitea to the latest version**:
  ```bash
  docker compose pull gitea && docker compose up -d gitea
  ```

- **Check container logs**:
  ```bash
  docker logs -f gitea
  ```

- **Clean up unused Docker resources**:
  ```bash
  docker system prune -f
  ```

## Source Files and References

This guide references the following files from the `mikeroyal/Self-Hosting-Guide` repository:

- [`README.md`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/README.md) (lines 346-364): Lists Gitea as a community-managed self-hosted Git service.
- [`README.md`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/README.md) (line 466): Provides the official Gitea URL reference.
- `Getting Started with Self-Hosting.dockerfile`: Demonstrates the Docker-based environment setup used throughout the guide.
- [`CONTRIBUTING.md`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/CONTRIBUTING.md): Documents how community members can contribute to or update this documentation.

## Summary

- **Gitea** provides a lightweight, single-binary solution for self-hosted Git repositories, ideal for personal use.
- **Docker Compose** with SQLite offers the simplest deployment path, requiring only a persistent volume and port mapping.
- **Data persistence** is achieved through host-mounted volumes at `/var/lib/gitea`, making backups and migrations straightforward file operations.
- **Security enhancements** like HTTPS via Caddy reverse proxy are recommended for production deployments.
- **SSH access** on a custom port (e.g., `2222`) allows secure Git operations without interfering with the host's SSH daemon.

## Frequently Asked Questions

### What is the difference between Gitea and Gogs?

Gitea is a community-maintained fork of Gogs that was created to ensure open governance and continued development. While Gogs development slowed, Gitea has expanded to include features like built-in package management, GitHub Actions support via act runners, and a more active maintenance cycle. Both are lightweight Go-based Git servers, but Gitea offers more frequent updates and a larger feature set for self-hosting.

### Can I use MySQL or PostgreSQL instead of SQLite?

Yes, Gitea supports MySQL, PostgreSQL, and MSSQL as alternatives to SQLite. For a personal server with low traffic, SQLite is sufficient and requires no additional containers. For larger teams or heavy usage, uncomment the `db` service in the Docker Compose configuration and set the database type to MySQL or PostgreSQL during the initial setup. External databases provide better concurrency and backup options for production environments.

### How do I migrate my existing repositories to Gitea?

Gitea provides a built-in migration feature accessible from the web UI. Click the **+** menu and select **New Migration**, then choose your source (GitHub, GitLab, or another Gitea instance). Enter the repository URL and credentials if needed. Alternatively, you can manually push existing repositories by adding your Gitea instance as a remote and using `git push --mirror` to transfer all branches and tags.

### Why should I disable user registration on a personal server?

Disabling registration prevents unauthorized users from creating accounts on your private Git server. In the initial setup wizard, enable the **Disable Registration** option to ensure only the administrator can create accounts. This is a critical security measure for personal servers exposed to the internet, as it prevents unauthorized access and resource consumption by public users.