How to Set Up a Git Server with Gitea on RHEL 7

Gitea is a lightweight, self-hosted Git service written in Go. It provides a GitHub-style web interface for repository management, issue tracking, pull requests, webhooks, and user management — all from a single binary that consumes a fraction of the resources required by GitLab or Bitbucket. On Red Hat Enterprise Linux 7, Gitea is an excellent choice for teams that need a private Git server without the operational overhead of a full DevOps platform. This guide covers creating a dedicated system user, downloading and installing the Gitea binary, configuring the app.ini file, creating a systemd service, setting up an Nginx reverse proxy, and migrating existing repositories from GitHub.

Prerequisites

  • RHEL 7 server with at least 1 CPU core and 512 MB RAM (1 GB recommended)
  • Root or sudo access
  • Nginx installed and running (or ready to install)
  • A supported database: SQLite3 (default, zero-config), MySQL/MariaDB, or PostgreSQL
  • Port 3000 free on the host, or a different port of your choice
  • A domain name or IP address for the Gitea web interface

Step 1: Create the git System User and Directory Structure

Gitea should run under a dedicated, non-privileged system account. Create the git user with a home directory where repositories will be stored, and set up the required directories:

sudo useradd 
    --system 
    --shell /bin/bash 
    --comment "Gitea git user" 
    --create-home 
    --home-dir /home/git 
    git

Create the directories Gitea needs for its data, configuration, log files, and custom templates:

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

The /etc/gitea directory needs write permission during initial setup so the web installer can write app.ini. After setup is complete, you will tighten these permissions.

Step 2: Download the Gitea Binary

Gitea is distributed as a pre-compiled binary for Linux on the GitHub releases page. Download the latest stable release for the linux-amd64 architecture. Check https://dl.gitea.io/gitea/ for the current stable version and replace 1.21.11 with the latest:

GITEA_VERSION="1.21.11"

sudo wget -O /usr/local/bin/gitea 
    "https://dl.gitea.io/gitea/${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64"

Download and verify the SHA256 checksum:

sudo wget -O /tmp/gitea.sha256 
    "https://dl.gitea.io/gitea/${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64.sha256"

# Verify checksum (cd to /usr/local/bin first)
cd /usr/local/bin
sha256sum -c /tmp/gitea.sha256

Successful output: gitea: OK

Make the binary executable:

sudo chmod +x /usr/local/bin/gitea

Confirm it runs:

gitea --version

Step 3: Configure the Database (SQLite for Small Deployments)

For installations with fewer than 20 concurrent users, SQLite3 is the simplest choice — it requires no separate database server. SQLite is built into the Gitea binary. Ensure the sqlite shared library is present:

sudo yum install -y sqlite

For MySQL/MariaDB (recommended for larger teams), install MariaDB and create the database:

sudo yum install -y mariadb-server mariadb
sudo systemctl enable mariadb
sudo systemctl start mariadb
sudo mysql_secure_installation

sudo mysql -u root -p <<'EOF'
CREATE DATABASE gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'gitea'@'localhost' IDENTIFIED BY 'strong-password-here';
GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'localhost';
FLUSH PRIVILEGES;
EOF

Step 4: Create the Gitea systemd Service

Create a systemd unit file so Gitea starts automatically on boot and can be managed with systemctl:

sudo tee /etc/systemd/system/gitea.service <<'EOF'
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mariadb.service

[Service]
RestartSec=2s
Type=simple
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

# Limit number of open files
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

If you are not using MariaDB, remove the After=mariadb.service line. Reload systemd and enable the service (do not start it yet — the web installer must run first):

sudo systemctl daemon-reload
sudo systemctl enable gitea

Step 5: Configure app.ini

Gitea’s configuration file is /etc/gitea/app.ini. You can either let the web installer generate it or write it manually for automation. Here is a production-ready template for a SQLite installation:

sudo tee /etc/gitea/app.ini <<'EOF'
APP_NAME = My Gitea Instance
RUN_USER = git
RUN_MODE = prod

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

[repository]
ROOT = /var/lib/gitea/data/gitea-repositories

[server]
DOMAIN           = git.example.com
HTTP_PORT        = 3000
ROOT_URL         = https://git.example.com/
DISABLE_SSH      = false
SSH_PORT         = 22
SSH_LISTEN_PORT  = 2222
LFS_START_SERVER = true
LFS_JWT_SECRET   = generate-a-random-64-char-string-here

[mailer]
ENABLED = false

[service]
REGISTER_EMAIL_CONFIRM            = false
ENABLE_NOTIFY_MAIL                = false
DISABLE_REGISTRATION              = false
ALLOW_ONLY_EXTERNAL_REGISTRATION  = false
ENABLE_CAPTCHA                    = false
REQUIRE_SIGNIN_VIEW               = false
DEFAULT_KEEP_EMAIL_PRIVATE        = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING       = true
NO_REPLY_ADDRESS                  = [email protected]

[picture]
AVATAR_UPLOAD_PATH = /var/lib/gitea/data/avatars

[attachment]
PATH = /var/lib/gitea/data/attachments

[log]
MODE      = file
LEVEL     = Info
ROOT_PATH = /var/lib/gitea/log

[security]
INSTALL_LOCK   = true
SECRET_KEY     = generate-a-random-64-char-string-here
INTERNAL_TOKEN = generate-a-different-random-token-here
EOF

Generate random secrets with:

openssl rand -hex 32

Set ownership and restrict permissions on the config file once written:

sudo chown root:git /etc/gitea/app.ini
sudo chmod 640 /etc/gitea/app.ini

Step 6: Open the Firewall and Start Gitea

Allow traffic on port 3000 (Gitea web) and port 2222 (Git over SSH, if using a non-standard port):

sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

Start the Gitea service:

sudo systemctl start gitea
sudo systemctl status gitea

Check the log to confirm a clean start:

sudo journalctl -u gitea -f

You should see lines like Listen: http://0.0.0.0:3000. Gitea is now reachable at http://<server-ip>:3000.

Step 7: Configure Nginx as a Reverse Proxy

Install Nginx from EPEL and configure a virtual host for Gitea:

sudo yum install -y epel-release
sudo yum install -y nginx
sudo tee /etc/nginx/conf.d/gitea.conf <<'EOF'
server {
    listen 80;
    server_name git.example.com;

    # Uncomment to redirect HTTP to HTTPS:
    # return 301 https://$host$request_uri;

    access_log /var/log/nginx/gitea.access.log;
    error_log  /var/log/nginx/gitea.error.log;

    client_max_body_size 512m;

    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;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade    $http_upgrade;
        proxy_set_header   Connection $http_connection;
    }
}
EOF

Test and enable Nginx:

sudo nginx -t
sudo systemctl enable nginx
sudo systemctl start nginx

Allow HTTP through the firewall:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Step 8: Complete the Initial Admin Setup

If INSTALL_LOCK = false in app.ini (the default when no app.ini exists), navigate to http://git.example.com in a browser. The first-run installer presents a form to configure the database, site title, and admin credentials. Fill in the fields and click Install Gitea.

If you pre-wrote app.ini with INSTALL_LOCK = true, create the admin user directly from the command line:

sudo -u git gitea admin user create 
    --username admin 
    --password 'SecurePassword123!' 
    --email [email protected] 
    --admin 
    --config /etc/gitea/app.ini

Log in to the web interface and verify the admin account works.

Step 9: Upload SSH Keys and Create a Repository

Navigate to your Gitea user profile, click Settings > SSH / GPG Keys > Add Key, and paste your public key:

cat ~/.ssh/id_ed25519.pub

Create a new repository in the web interface under + > New Repository, or clone the empty repository immediately:

git clone [email protected]:admin/my-project.git
cd my-project
echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit"
git push origin main

If using the non-standard SSH port 2222, configure your SSH client in ~/.ssh/config:

Host git.example.com
    Hostname git.example.com
    User     git
    Port     2222
    IdentityFile ~/.ssh/id_ed25519

Step 10: Migrate Repositories from GitHub

Gitea has a built-in migration feature that imports repositories, issues, pull requests, milestones, and labels from GitHub, GitLab, Bitbucket, and other Gitea instances. To migrate from GitHub:

  1. In Gitea, click + > New Migration > GitHub
  2. Enter your GitHub personal access token (needs repo scope) in the API Token field
  3. Enter the repository owner and name
  4. Select which items to migrate: Issues, Labels, Milestones, Pull Requests, Releases, Wiki
  5. Click Migrate Repository

For bulk migration using the Gitea CLI on the server:

sudo -u git gitea admin repo-sync-push-mirror 
    --config /etc/gitea/app.ini

Or use the Gitea API to automate migration of multiple repositories:

curl -X POST 
  -H "Content-Type: application/json" 
  -H "Authorization: token YOUR_GITEA_TOKEN" 
  -d '{
    "clone_addr": "https://github.com/myorg/myrepo",
    "auth_token": "YOUR_GITHUB_TOKEN",
    "uid": 1,
    "repo_name": "myrepo",
    "mirror": false,
    "private": true,
    "issues": true,
    "pull_requests": true,
    "releases": true,
    "labels": true,
    "milestones": true
  }' 
  https://git.example.com/api/v1/repos/migrate

Step 11: Tighten Security and Configure Backups

After initial setup is complete, lock down the installation directory permissions:

sudo chmod 750 /etc/gitea
sudo chmod 640 /etc/gitea/app.ini

Set up a nightly backup with a simple cron job that archives the data directory and database:

sudo tee /etc/cron.d/gitea-backup <<'EOF'
0 2 * * * git /usr/local/bin/gitea dump 
    --config /etc/gitea/app.ini 
    --file /var/backups/gitea/gitea-dump-$(date +%Y%m%d).zip 
    --skip-log 2>&1 | logger -t gitea-backup
EOF

sudo mkdir -p /var/backups/gitea
sudo chown git:git /var/backups/gitea

Conclusion

Gitea is now running on your RHEL 7 server, secured behind Nginx, managed by systemd, and ready to host Git repositories for your team. You have created a dedicated system user, configured the application through app.ini, set up SSH key authentication, and established a path for migrating existing GitHub repositories. Gitea’s minimal resource footprint makes it an excellent fit for resource-constrained environments or air-gapped networks where a full-featured platform would be prohibitive. From here, consider integrating Gitea with your CI/CD system — Gitea supports webhooks and has native integrations with Drone CI, Woodpecker CI, and Jenkins.