bolt Valebyte VPS from $4/mo — NVMe, 60s deploy.

Get a VPS arrow_forward
eco Beginner Tutorial/How-to

Install Gitea on VPS: Lightweight

calendar_month Jul 21, 2026 schedule 23 min read visibility 42 views
info

Need a server for this guide? We offer dedicated servers and VPS in 50+ countries with instant setup.

Need a server for this guide?

Deploy a VPS or dedicated server in minutes.

Installing Gitea on a VPS: Lightweight self-hosted Git server with Docker and SSL

TL;DR

In this guide, we will set up Gitea — a lightweight and powerful self-hosted Git server — on your VPS, using Docker and automatic SSL certificate acquisition via Caddy. You will get a fully functional platform for managing repositories, accessible via a domain name with HTTPS, ready for team development or personal projects.

  • Set up a modern VPS based on Ubuntu 24.04 LTS with basic security.
  • Install Docker and Docker Compose for easy application management.
  • Deploy Gitea in a Docker container, using persistent volumes for data.
  • Configure Caddy as a reverse proxy for Gitea, automatically providing HTTPS with Let's Encrypt.
  • Prepare a backup system to protect your data.
  • Gain control over your own Git infrastructure, completely independent of third-party services.

What We Are Setting Up and Why

In the modern development world, Git has become the de facto standard for version control. However, relying on third-party services like GitHub, GitLab.com, or Bitbucket is not always optimal. Many teams and individual developers need their own, fully controlled Git server. Gitea solves precisely this problem.

Gitea is a lightweight, open-source, and self-hosted Git service written in Go. It provides full functionality similar to GitHub or GitLab, but consumes significantly fewer resources, making it an ideal choice for deployment on a VPS or even a mini-computer like a Raspberry Pi. You will get an intuitive web interface for managing repositories, users, teams, pull requests, issue tracking, and much more.

What the Reader Will Get in the End

After completing this guide, you will have a fully configured and operational Gitea Git server, accessible via your domain name with a secure HTTPS connection. You will be able to create public and private repositories, invite colleagues for collaboration, manage access, and use all familiar Git operations via the web interface or command line. Your infrastructure will be entirely under your control, ensuring confidentiality and independence.

What Alternatives Exist and Why Self-Hosted on a VPS

There are several main approaches to hosting Git repositories:

  • Cloud-managed services (GitHub, GitLab.com, Bitbucket): This is the simplest option in terms of maintenance. You simply register and start working. However, you depend on the provider's policy and infrastructure, may encounter limitations of free plans, and also face data privacy concerns as data is stored on third-party servers.
  • Self-hosted GitLab Community Edition (CE): GitLab CE is a powerful solution offering not only Git hosting but also a complete DevOps cycle: CI/CD, container registry, monitoring, and much more. However, GitLab CE requires significantly more resources (minimum 4 GB RAM for comfortable operation), making it less suitable for small VPS and teams.
  • Self-hosted Gitea: Gitea occupies a niche between simple cloud services and resource-intensive GitLab. It offers rich Git hosting functionality with minimal resource consumption. This is an ideal choice if you need a full-fledged Git server without unnecessary features and without large infrastructure costs. Deployment on a VPS gives you full control over your data, the ability to customize, and integrate with your own ecosystem. Additionally, Docker significantly simplifies Gitea deployment and management, isolating it from the main system and making it portable.

Choosing Gitea on a VPS allows combining the advantages of self-hosting (control, privacy) with efficient resource utilization and ease of deployment thanks to Docker.

What VPS Configuration is Needed for This Task

Installing Gitea on a VPS with Docker and Caddy generally does not require extremely powerful resources. Gitea is optimized to run on modest hardware, but the presence of Docker and Caddy adds a small overhead. It's important to consider how many users will actively work with Gitea and how many repositories are planned to be hosted.

Minimum Requirements

  • CPU: 1 vCore (e.g., Intel Xeon E3/E5 or AMD EPYC). This will be sufficient for small teams of up to 5-10 people.
  • RAM: 2 GB. This will be enough for the operating system, Docker daemon, Gitea, and Caddy containers. If very active use or other services are planned on the same VPS, it's better to consider 4 GB.
  • Disk: 40-60 GB SSD. SSD is critical for Git operation performance. 40 GB will be enough for the OS, Docker images, and several dozen repositories. If repositories will be very large or numerous, consider 80-100 GB.
  • Network: 100 Mbps. For most scenarios, this is more than sufficient. Channel stability and low latency are more important.

Specific VPS Plan for the Task (current as of 2026)

For comfortable operation of Gitea with Docker and Caddy for a team of up to 10-20 developers and dozens of repositories, the following VPS configuration is recommended:

  • CPU: 2 vCore (e.g., Intel Xeon E5-2690v4 or AMD EPYC 7002 series).
  • RAM: 4 GB DDR4.
  • Disk: 80 GB NVMe SSD. NVMe will provide maximum disk operation speed, which is important for Git.
  • Network: 1 Gbps port with unlimited or high volume traffic.

Such a VPS configuration will provide excellent performance and future headroom. For example, you can get a VPS with the specified characteristics.

When a Dedicated Server is Needed, Not a VPS

A dedicated server should be considered if:

  • Very large team: More than 50-100 active users.
  • Extremely large repositories: Repositories with gigabytes of binary files (LFS).
  • Critical performance requirements: High load on Git operations 24/7.
  • Strict security/isolation requirements: Complete isolation from "neighbors" on the hypervisor.
  • Many other services are planned: In addition to Gitea, CI/CD agents, databases, web servers for other projects, etc., will run on the server.

For most Gitea tasks, especially for startups, small teams, and personal projects, a VPS will be an optimal and cost-effective solution.

Location: What It Affects

The choice of VPS location matters for:

  • Latency: The closer the server is to your team and main users, the lower the latency will be when performing Git operations and working with the web interface. This is especially critical for developers located far from the server.
  • Legal Compliance: In some cases, especially for companies, there may be requirements for data storage in a specific jurisdiction.
  • Availability: Choose a location with reliable network infrastructure and good communication channels.

It is optimal to choose a data center located geographically close to most of your users.

Server Preparation

Before proceeding with Gitea installation, you need to perform basic configuration of your VPS. We will use Ubuntu Server 24.04 LTS, as it is a current and stable version of the operating system as of 2026.

Minimum Configuration After Provisioning

After gaining access to your VPS (usually via SSH as the root user), first update the system and create a new user with sudo privileges.


# Update package list and upgrade them to the latest versions
sudo apt update && sudo apt upgrade -y

# Create a new user (replace 'your_user' with the desired name)
sudo adduser ваш_пользователь

# Add the user to the sudo group to get administrative privileges
sudo usermod -aG sudo ваш_пользователь

Exit the root session and log in as the new user:


exit
# Then log in again with your_user
ssh ваш_пользователь@ваш_ip_сервера

SSH Key Setup (Recommended)

For increased security, it is recommended to use SSH keys instead of passwords. Generate a key on your local machine (if you don't have one already):


# On your local machine
ssh-keygen -t ed25519 -C "ваш[email protected]"

Copy the public key to the server:


# On your local machine
ssh-copy-id ваш_пользователь@ваш_ip_сервера

After this, disable password login for SSH (file /etc/ssh/sshd_config):


# On the server
sudo nano /etc/ssh/sshd_config

Find and change the following lines:


# /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PermitRootLogin no

Restart the SSH server:


sudo systemctl restart sshd

Install Fail2Ban

Fail2Ban protects your server from brute-force attacks by blocking IP addresses from which numerous failed login attempts occur.


# Install Fail2Ban
sudo apt install fail2ban -y

# Copy the default config for customization
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Open the file for editing (optional, for finer tuning)
sudo nano /etc/fail2ban/jail.local

Default settings are usually sufficient, but you can change bantime, findtime, and maxretry. Make sure the [sshd] section is enabled.


# Example jail.local content (make sure enabled = true)
[DEFAULT]
bantime  = 1d
findtime = 10m
maxretry = 5

[sshd]
enabled = true
mode   = aggressive
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

# Restart Fail2Ban to apply changes
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban

Firewall Configuration (UFW)

Uncomplicated Firewall (UFW) is an easy-to-use interface for iptables. We will configure it to allow only the necessary ports.


# Install UFW
sudo apt install ufw -y

# Allow SSH (default port 22)
sudo ufw allow ssh

# Allow HTTP (port 80) and HTTPS (port 443) for the web server (Caddy)
sudo ufw allow http
sudo ufw allow https

# Enable UFW
sudo ufw enable

Confirm enabling by pressing y. You can check the firewall status with the command sudo ufw status verbose.

Now your server is ready for Docker and Gitea installation.

Software Installation — Step-by-Step

We will use Docker and Docker Compose to deploy Gitea. This ensures application isolation, simplifies dependency management, and facilitates updates.

1. Install Docker Engine

To install Docker Engine on Ubuntu 24.04 LTS (Noble Numbat), follow the official recommendations, current as of 2026.


# Remove old Docker versions if they exist
for pkg in docker.io docker-doc docker-compose docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin; do sudo apt remove $pkg; done

# Update package list
sudo apt update

# Install necessary packages to work with repositories
sudo apt install ca-certificates curl gnupg -y

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Add Docker repository to APT sources
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Update package list after adding Docker repository
sudo apt update

# Install Docker Engine, Docker CLI, containerd, and Docker Compose plugin
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Verify Docker installation:


# Check Docker version
docker --version

# Check Docker service status
sudo systemctl status docker

# Run 'hello-world' test container
sudo docker run hello-world

Add your user to the docker group to avoid using sudo for every Docker command:


# Add user to docker group
sudo usermod -aG docker ваш_пользователь

# Apply group changes (log out and log back in or reboot the system)
newgrp docker

2. Create Directory Structure for Gitea

We will create directories to store Gitea data and Docker Compose configuration. This will ensure data persistence and a clean structure.


# Create root directory for Gitea project
mkdir -p ~/gitea

# Navigate to the created directory
cd ~/gitea

# Create directory for persistent Gitea data
mkdir -p ./data

3. Create docker-compose.yml file for Gitea and Caddy

This file will define the Gitea and Caddy services, their dependencies, volumes, and network settings. We will use SQLite as the database for simplicity, which is ideal for small installations. For larger projects, consider PostgreSQL or MySQL.

Create the file docker-compose.yml in the ~/gitea directory:


# Create docker-compose.yml file
nano docker-compose.yml

Paste the following content, replacing your.domain.com with your actual domain:


# docker-compose.yml
version: "3.8"

services:
  gitea:
    image: gitea/gitea:1.22.0 # Current version as of 2026, check https://dl.gitea.io/gitea/
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__DATABASE__DB_TYPE=sqlite3 # Using SQLite for simplicity
      - GITEA__DATABASE__PATH=/data/gitea.db # Path to SQLite database file
      - GITEA__SERVER__DOMAIN=your.domain.com # Your domain
      - GITEA__SERVER__SSH_DOMAIN=your.domain.com # Domain for SSH access
      - GITEA__SERVER__HTTP_PORT=3000 # Internal Gitea port
      - GITEA__SERVER__APP_DATA_PATH=/data # Path for Gitea data inside the container
      - GITEA__SERVER__ROOT_URL=https://your.domain.com/ # Base URL for Gitea
      - GITEA__SECURITY__INSTALL_LOCK=true # Lock installation page after initial setup
      - GITEA__SERVICE__DISABLE_REGISTRATION=false # Allow new user registration (true for a private server)
      - GITEA__SERVICE__REQUIRE_SIGNIN_VIEW=false # Require sign-in to view repositories (true for a private server)
      - GITEA__SESSION__PROVIDER=db # Using database for sessions
      - GITEA__CACHE__ADAPTER=redis # Recommended for performance
      - GITEA__CACHE__HOST=redis:6379 # Redis host
      - GITEA__QUEUE__TYPE=redis # Task queue via Redis
      - GITEA__QUEUE__CONN_STR=redis://redis:6379/0 # Redis connection string
    restart: always
    volumes:
      - ./data:/data # Mapping local data directory to container
      - /etc/timezone:/etc/timezone:ro # Timezone synchronization
      - /etc/localtime:/etc/localtime:ro # Local time synchronization
    ports:
      - "3000:3000" # Internal Gitea HTTP port (for Caddy)
      - "2222:22" # Gitea SSH port (mapping to 2222 to avoid conflict with host)
    networks:
      - gitea-network

  caddy:
    image: caddy:2.7.5 # Current Caddy version as of 2026
    container_name: caddy
    restart: always
    ports:
      - "80:80" # HTTP for Let's Encrypt challenge and redirection
      - "443:443" # HTTPS
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile # Caddy configuration file
      - ./caddy_data:/data # Caddy storage for certificates and state
    environment:
      - GITEA_DOMAIN=your.domain.com # Pass domain to Caddyfile via variable
    networks:
      - gitea-network
    depends_on:
      - gitea # Caddy depends on Gitea

  redis:
    image: redis:7.2-alpine # Lightweight Redis version
    container_name: redis
    restart: always
    volumes:
      - ./redis_data:/data # Redis data storage
    networks:
      - gitea-network
    command: redis-server --appendonly yes # Enable data persistence

networks:
  gitea-network:
    driver: bridge

Important: Replace your.domain.com with your actual domain. Ensure that an A-record is created for your domain (e.g., gitea.example.com) pointing to your VPS's IP address.

Note on versions: Versions gitea/gitea:1.22.0, caddy:2.7.5, and redis:7.2-alpine are listed as current for 2026. Always check official Docker Hub repositories for the latest and most stable versions.

4. Create Caddyfile for Caddy

Caddy automatically manages SSL certificates via Let's Encrypt. Create the Caddyfile in the same ~/gitea directory:


# Create Caddyfile
nano Caddyfile

Paste the following content:


# Caddyfile
{env.GITEA_DOMAIN} {
    # Automatic HTTPS
    tls {
        # Use Let's Encrypt
        acme_challenge http
    }

    # Reverse proxy for Gitea
    reverse_proxy gitea:3000 {
        # Proxy headers required by Gitea
        header_up Host {host}
        header_up X-Real-IP {remote_ip}
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-For {remote_ip}
    }

    # Settings for large files (Git LFS)
    # Gitea handles LFS itself, but Caddy must pass large requests
    # If you have very large LFS files, increasing body_size might be necessary
    # (Caddy handles up to 10MB by default)
    # For Gitea, this is usually not required, as it receives data itself
}

The {env.GITEA_DOMAIN} variable will be automatically replaced with the value from docker-compose.yml.

5. Start Gitea and Caddy with Docker Compose

After creating both files, you are ready to start Gitea.


# Navigate to the directory containing the files
cd ~/gitea

# Start all services in the background
docker compose up -d

This command will download the necessary Docker images (Gitea, Caddy, Redis), create the containers, and start them. The first run may take some time while the images are downloaded.

You can check the status of the running containers with the command:


# Check container status
docker compose ps

You should see that all containers (gitea, caddy, redis) are in running status.

At this stage, the installation of the main components is complete. Now let's move on to the final configuration.

Configuration

After successfully launching the Gitea and Caddy containers, you need to perform the initial Gitea setup via the web interface and ensure that all parameters meet your requirements.

1. Initial Gitea Setup via Web Interface

Open your domain (e.g., https://your.domain.com) in a web browser. You should see the Gitea initial setup page.

On this page, check and, if necessary, modify the following parameters:

  • Database Settings:
    • Database Type: SQLite3 (should be selected by default).
    • Database File Path: /data/gitea.db (should be set from environment variables).
  • General Application Settings:
    • Domain: your.domain.com (set from environment variables).
    • Base URL: https://your.domain.com/ (set from environment variables).
    • Gitea Root Path: /data (set from environment variables).
    • SSH Server Port: 2222 (set from environment variables).
    • Gitea Log Path: /data/log.
  • Administrator Settings:

    Create the first administrative user. Enter a username, password, and email address. This will be the main account for managing Gitea.

  • Mail Server (SMTP) Settings: If you want Gitea to send notifications (e.g., for registration, password reset, mentions), configure the SMTP server.
    
    # Example SMTP settings for Gitea (in the web interface)
    [mailer]
    ENABLED = true
    HOST = smtp.yourprovider.com:587
    FROM = [email protected]
    USER = [email protected]
    PASSWD = ваш_пароль_smtp
    PROTOCOL = smtps # or smtp+tls
    

After checking all parameters, click the "Install Gitea" button. If successful, you will be redirected to the login page.

2. Configuration File app.ini

Most Gitea settings can be changed via the administrator web interface, but some parameters are stored in the app.ini file inside the container. This file is located at /data/gitea/conf/app.ini. Since we mounted ./data to /data, you can access it on the host:


# Access app.ini on the host
nano ~/gitea/data/gitea/conf/app.ini

After the initial installation, Gitea will automatically populate this file. Here are some important sections you might want to check or modify:


# app.ini (example of important sections)
[server]
DOMAIN = your.domain.com
SSH_DOMAIN = your.domain.com
HTTP_PORT = 3000
ROOT_URL = https://your.domain.com/
DISABLE_SSH = false
SSH_PORT = 2222 # Internal Gitea port for SSH
LFS_START_SERVER = true
LFS_HTTP_HOST = https://your.domain.com/ # URL for Git LFS

[database]
DB_TYPE = sqlite3
PATH = /data/gitea.db

[repository]
ROOT = /data/git/repositories # Path for storing repositories
DEFAULT_BRANCH = main # Default branch for new repositories

[service]
REGISTER_EMAIL_ACTIVE = false # Is email activation required for registration
DISABLE_REGISTRATION = false # Allow registration (true for private server)
REQUIRE_SIGNIN_VIEW = false # Require sign-in to view repositories (true for private server)
NO_REPLY_ADDRESS = [email protected] # Address for "no-reply" commits

[session]
PROVIDER = db

[cache]
ADAPTER = redis
HOST = redis:6379

[queue]
TYPE = redis
CONN_STR = redis://redis:6379/0

[security]
INSTALL_LOCK = true # Important: should be true after installation
SECRET_KEY = ваш_сгенерированный_ключ # Automatically generated

If you manually make changes to app.ini, remember to restart the Gitea container:


# Restart Gitea container
docker compose restart gitea

3. TLS/HTTPS via Caddy

Caddy automatically obtained and configured SSL certificates for your domain. This is confirmed by the fact that you were able to access Gitea via HTTPS. Caddy will automatically renew certificates before they expire.

You can check the status of Caddy certificates:


# View Caddy logs to check certificate status
docker compose logs caddy | grep -i "certificate"

You should see entries about obtaining and/or renewing Let's Encrypt certificates.

4. Health Check

Ensure that Gitea is fully functional:

  • HTTPS Access: Open https://your.domain.com in your browser. Ensure the connection is secure (green padlock).
  • Login and Repository Creation: Log in as the created administrator, create a new repository.
  • HTTPS Cloning: Try cloning a repository via HTTPS from your local machine:
    
    git clone https://your.domain.com/ваш_пользователь/ваш_репозиторий.git
    

    You will be prompted to enter your Gitea username and password.

  • SSH Access: Gitea uses port 2222 for SSH. To configure SSH access, you need to add your Gitea user's public SSH key via the web interface (Profile Settings -> SSH/GPG Keys). Then you can clone a repository via SSH:
    
    git clone ssh://[email protected]:2222/ваш_пользователь/ваш_репозиторий.git
    

    Important: Ensure that port 2222 is open in your VPS firewall. If you are using UFW:

    
    sudo ufw allow 2222/tcp
    sudo ufw reload
    
  • Healthcheck: Check the status of your containers:
    
    docker compose ps
    

    All should be running and healthy.

Congratulations! Your Gitea server is fully configured and ready for use.

Backups and Maintenance

Having a working Git server is only half the battle. It is crucial to have a reliable backup strategy and maintenance plan to ensure the long-term stability and security of your data.

What to Back Up

For Gitea, three main components need to be backed up:

  1. Gitea Database: In our case, this is the file gitea.db. It contains all information about users, repositories, issues, pull requests, comments, etc.
  2. Git Repository Files: The Git repositories themselves, including LFS objects. They are stored in /data/git/repositories.
  3. Configuration File app.ini: Contains all Gitea settings. Located at /data/gitea/conf/app.ini.
  4. Gitea SSH Keys: If Gitea generates its own SSH keys for internal operations or SSH access, they are also located in /data/gitea/.ssh.
  5. Caddy Data: Let's Encrypt certificates and other Caddy configuration are stored in ./caddy_data. While they can be restored automatically, backing them up will speed up recovery.

All these data are located in the ~/gitea/data and ~/gitea/caddy_data directories on your host.

Simple Auto-Backup Script

Let's create a simple script that will create an archive with the necessary data. For SQLite, simply copying the database file is sufficient, but Gitea also provides the gitea dump utility, which creates a complete dump of all data in a single archive.

Create the file backup_gitea.sh in your home directory:


# Create backup script
nano ~/backup_gitea.sh

Insert the following content:


#!/bin/bash

# Settings
BACKUP_DIR="/var/backups/gitea"
GITEA_DIR="/home/ваш_пользователь/gitea" # Path to the directory containing docker-compose.yml
DATE=$(date +%Y%m%d%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/gitea_backup_${DATE}.zip"

# Create backup directory if it doesn't exist
mkdir -p ${BACKUP_DIR}

echo "--- Starting Gitea backup (${DATE}) ---"

# 1. Dump Gitea using the built-in utility (inside the container)
# This will create a zip archive in /tmp inside the Gitea container
echo "Creating Gitea dump..."
docker exec gitea gitea dump -c /data/gitea/conf/app.ini

# 2. Copying the created dump from the container to the host
echo "Copying dump to host..."
DUMP_CONTAINER_PATH=$(docker exec gitea find /tmp -name "gitea-dump-*.zip" -print -quit)
if [ -z "$DUMP_CONTAINER_PATH" ]; then
    echo "Error: Gitea dump not found in container."
    exit 1
fi
docker cp gitea:${DUMP_CONTAINER_PATH} ${BACKUP_FILE}

# 3. Deleting the dump from the container
echo "Deleting temporary dump from container..."
docker exec gitea rm ${DUMP_CONTAINER_PATH}

# 4. Copying Caddy data (certificates)
echo "Copying Caddy data..."
tar -czf ${BACKUP_DIR}/caddy_data_backup_${DATE}.tar.gz -C ${GITEA_DIR}/caddy_data .

echo "Backup completed: ${BACKUP_FILE} and ${BACKUP_DIR}/caddy_data_backup_${DATE}.tar.gz"

# Clean up old backups (e.g., keep last 7 days)
echo "Cleaning up old backups..."
find ${BACKUP_DIR} -type f -name "gitea_backup_*.zip" -mtime +7 -delete
find ${BACKUP_DIR} -type f -name "caddy_data_backup_*.tar.gz" -mtime +7 -delete

echo "--- Gitea backup completed ---"

Make the script executable:


chmod +x ~/backup_gitea.sh

Now you can add this script to cron for daily or weekly execution:


# Open crontab for editing
crontab -e

Add the following line for a daily backup at 03:00 AM:


# Daily Gitea backup at 03:00
0 3 * * * /home/ваш_пользователь/backup_gitea.sh >> /var/log/gitea_backup.log 2>&1

Where to Store Backups

Storing backups on the same server as the main service is extremely risky. If the VPS fails or is compromised, you will lose both your data and your backups. It is recommended to use external storage:

  • S3-compatible Storage: Cloud storage services such as Amazon S3, DigitalOcean Spaces, Backblaze B2. This is an economical and reliable option. You can use utilities like s3cmd, rclone, or restic for automatic backup synchronization.
  • Separate VPS: A small, inexpensive VPS located in a different data center can serve as backup storage, where you will copy archives via SCP/RSYNC.
  • Local Storage: For very small projects, you can temporarily store backups locally and manually download them to your machine.

For automatic upload to S3, you can integrate rclone into your script:


# Example of adding rclone to the backup_gitea.sh script
# ... (after backup creation)
echo "Sending backup to S3..."
/usr/bin/rclone copy ${BACKUP_FILE} my-s3-remote:gitea-backups/
/usr/bin/rclone copy ${BACKUP_DIR}/caddy_data_backup_${DATE}.tar.gz my-s3-remote:gitea-backups/caddy-data/

# ... (cleaning up old backups on S3, if configured in rclone or via S3 policies)

Don't forget to configure rclone with your S3 credentials using the rclone config command.

Updates: rolling vs maintenance window

Regular updates are critical for security and new features.

  • Operating System Updates: Regularly run sudo apt update && sudo apt upgrade -y. This can be done monthly or when important security patches are released.
  • Docker Image Updates (Gitea, Caddy, Redis):

    For Docker containers, it is recommended to use a "maintenance window" strategy rather than a "rolling update" strategy, as changes can be significant.

    1. Before updating, create a fresh backup.
    2. Stop Gitea services: docker compose down
    3. Pull new images: docker compose pull
    4. Start services: docker compose up -d

    Always check the Gitea changelog for breaking changes before updating to a new major version. For example, if you are updating from 1.21.x to 1.22.x, ensure there are no special database migration instructions.

  • Docker Engine Updates: Also require caution. It is usually sufficient to update Docker Engine every few months, or when necessary to address vulnerabilities. After updating Docker Engine, a server reboot will be required for all containers to start correctly.

Always test updates on a test server, if possible, before applying them to a production environment.

Troubleshooting + FAQ

Even with the most careful setup, problems can arise. Here is a list of common questions and issues you might encounter when deploying Gitea with Docker and Caddy.

What is the minimum suitable VPS configuration?

For a basic Gitea installation (without Docker) for a small number of users (1-5), 1 vCore CPU, 1 GB RAM, and 20-30 GB SSD might suffice. However, if you are using Docker and Caddy, and plan for up to 10-15 users, a minimum of 2 vCore CPU, 2 GB RAM, and 40 GB SSD is recommended. This will ensure stable operation and sufficient resource headroom for the operating system, Docker daemon, and all containers.

What to choose — VPS or dedicated for this task?

For most Gitea usage scenarios (personal projects, teams up to 50 people, moderate number of repositories), a VPS is the optimal choice. It offers sufficient performance, flexibility, and is significantly lower in cost than a dedicated server. A dedicated server should only be considered in cases of very high load (hundreds of users, thousands of repositories), strict isolation requirements, or when needing to run many other resource-intensive services on the same machine.

Gitea does not start or the container constantly restarts. What to do?

First, check the Gitea container logs: docker compose logs gitea. Common reasons:

  • Port conflict: Ensure that port 3000 (Gitea's internal port) is not occupied by another process inside the container or on the host (although in our configuration, it is not directly exposed externally).
  • Database issues: If Gitea cannot connect to Redis or the SQLite file is corrupted. Check Gitea logs for errors related to database or cache.
  • Incorrect file permissions: Ensure that the Docker user inside the container (UID/GID 1000) has write permissions to the ./data directory. You can check permissions on the host: ls -la ~/gitea/data.
  • Incorrect app.ini: Syntax errors or incorrect values in the Gitea configuration file.

Caddy is not obtaining an SSL certificate or not redirecting traffic.

Check Caddy logs: docker compose logs caddy. Possible reasons:

  • DNS issues: Ensure that your domain's A-record (e.g., your.domain.com) correctly points to your VPS's IP address. You can check this with dig your.domain.com.
  • Firewall blocking ports 80/443: Ensure that UFW (or another firewall) allows incoming connections on ports 80 and 443. Check sudo ufw status.
  • Another process occupies ports 80/443 on the host: Ensure that no other web server (Apache, Nginx) or another Caddy instance is running on the host and using these ports.
  • Incorrect Caddyfile: Syntax errors or incorrect proxy settings.
  • Let's Encrypt limits: If you have repeatedly tried to obtain a certificate for the same domain in a short period, you might have hit a Let's Encrypt rate limit. Wait a few hours.

SSH access to Gitea repositories is not working.

Check the following:

  • Port 2222 open in firewall: sudo ufw status should show permission for port 2222.
  • SSH key added to Gitea: Ensure that your public SSH key has been added to your Gitea profile settings via the web interface.
  • Correct clone command: Use git clone ssh://[email protected]:2222/your_user/your_repository.git. Pay attention to git@ and port :2222.
  • Gitea SSH server running: Check Gitea logs for SSH-related errors.

Gitea does not start after updating Docker images.

This might be due to changes in the new version of Gitea or Docker. Always check official changelogs. If Gitea requires a database migration, it usually runs automatically on the first startup. If not, check the logs. It might be necessary to revert to a previous image version (e.g., gitea/gitea:1.21.10 instead of gitea/gitea:1.22.0) and review migration instructions.

How to update Gitea?

To update Gitea (and other containers), follow these steps in the ~/gitea directory:


# 1. Create a backup! This is critically important.
# 2. Stop current containers
docker compose down
# 3. Update Docker images to the latest versions specified in docker-compose.yml
#    If you want to update to a newer version, change the image tag in docker-compose.yml
docker compose pull
# 4. Start updated containers
docker compose up -d

After starting, check the logs and the web interface.

How to change Gitea settings after initial installation?

Most settings can be changed via the web interface by logging in as an administrator: "Admin Panel" -> "Site Configuration". Some specific settings may require manual editing of the ~/gitea/data/gitea/conf/app.ini file, followed by restarting the Gitea container (docker compose restart gitea).

Conclusion and Next Steps

You have successfully set up and deployed your own Gitea Git server on your VPS, using Docker and Caddy for automatic SSL certificate acquisition. You now have a fully controlled and secure platform for managing your repositories, ensuring privacy and independence from third-party services. This self-hosted Git server is a powerful tool for individual developers, teams, and startups, providing functionality similar to large Git providers with significantly fewer resource costs.

Next Steps

After the basic Gitea setup, you might consider the following steps to extend its functionality and integrate it into your workflow:

  1. CI/CD Integration: Set up Gitea integration with Continuous Integration/Continuous Delivery (CI/CD) systems such as Drone CI, Jenkins, GitLab CI (using Gitea as the code source), or custom scripts. This will allow you to automatically test and deploy your code with each commit.
  2. Monitoring and Logging: Implement monitoring systems (e.g., Prometheus + Grafana) to track the status of your VPS and Gitea/Caddy/Redis containers. Set up centralized logging (e.g., ELK Stack or Loki + Promtail) for convenient analysis of all service logs.
  3. Scaling and Optimization: If your team grows or the number of repositories increases, consider migrating from SQLite to PostgreSQL or MySQL for the Gitea database, as well as optimizing VPS resources. For very large installations, you might consider dedicating Gitea, the database, and cache to separate servers.
  4. Additional Gitea Features: Explore Gitea's rich functionality, such as the built-in wiki, time tracking, labels, projects, package manager (Gitea Packages), and integrations with external services via webhooks.

Was this guide helpful?

Your feedback helps us improve our guides.

Share this post:

Send this guide to someone who may find it useful.

Telegram VKVK WhatsApp Facebook LinkedIn XX

Gitea installation on VPS: lightweight self-hosted Git server with Docker and SSL
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.