Installing and Configuring Gitea on CentOS Stream 9: Build a Lightweight Git Server to Replace GitLab for Small Teams with SELinux and firewalld

CentOS tutorial - IT technology blog
CentOS tutorial - IT technology blog

GitLab Is Too Heavy — Lessons from the CentOS 8 EOL Migration

My team at the time had 4 people running self-hosted GitLab on a 4GB RAM VPS. Every time someone pushed code, the server would struggle for a full minute just to finish the CI pipeline. When CentOS 8 hit EOL, I had to migrate 5 servers to Rocky Linux in a single week — here’s what I learned from that experience: I took the opportunity to swap GitLab out for Gitea entirely. That old 1GB RAM VPS ran Gitea smoothly, with response times under 2 seconds, while the whole team pushed and pulled without any issues — and there were still enough resources left to run Nginx and a few cronjobs.

If your team has fewer than 20 people and doesn’t need complex built-in CI/CD, Gitea is a far more practical choice than GitLab.

What Is Gitea and Why Is It So Lightweight?

Gitea is a self-hosted Git platform written in Go — a language known for its compact binaries and high performance. The entire Gitea installation is a single binary file, with no Ruby dependency like GitLab, no Node.js requirement, and no mandatory PostgreSQL — SQLite is perfectly sufficient for small teams.

  • Actual RAM usage: ~200–300MB
  • GitLab minimum requirement: 4GB RAM
  • Full support for: repositories, issues, pull requests, webhooks, SSH and HTTPS
  • Familiar interface that closely resembles GitHub
  • Simple backup: just copy one directory and one config file

Hands-On: Installing Gitea Step by Step on CentOS Stream 9

Step 1: Create a System User for Gitea

Never run Gitea as root. Create a dedicated user to restrict access permissions:

sudo useradd -r -m -d /home/gitea -s /bin/bash gitea

Step 2: Download the Gitea Binary

Visit the Gitea download page to get the latest version. At the time of writing, that’s 1.22.x:

wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/1.22.3/gitea-1.22.3-linux-amd64
chmod 755 /usr/local/bin/gitea

# Verify the installation
gitea --version

Step 3: Create Directories and Set Permissions

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

sudo mkdir -p /etc/gitea
sudo chown root:gitea /etc/gitea
sudo chmod 770 /etc/gitea

Step 4: Configure SELinux for Gitea

This is the part most people skip by running setenforce 0 to get things working quickly — don’t do that. CentOS Stream 9 enables SELinux by default, and Gitea needs a few specific permissions to function correctly. Proper configuration takes just 3 commands, while disabling SELinux blows wide open the entire server’s security:

# Set the SELinux context for the Gitea binary
sudo semanage fcontext -a -t bin_t "/usr/local/bin/gitea"
sudo restorecon -v /usr/local/bin/gitea

# Allow Gitea to bind to port 3000
sudo semanage port -a -t http_port_t -p tcp 3000

# If the port already exists, use -m instead of -a
# sudo semanage port -m -t http_port_t -p tcp 3000

If Gitea is still being blocked by SELinux afterward, check the AVC logs to find out exactly which permissions are missing:

sudo ausearch -m avc -ts recent | audit2allow -a

Step 5: Open Ports with firewalld

# Open port 3000 for the Gitea web interface
sudo firewall-cmd --permanent --add-port=3000/tcp

# Make sure SSH remains open (for cloning over SSH)
sudo firewall-cmd --permanent --add-service=ssh

# Apply changes
sudo firewall-cmd --reload

# Verify the result
sudo firewall-cmd --list-all

Step 6: Create a systemd Service

To have Gitea start automatically on server reboot, create a service file:

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

Paste the following content into the file:

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

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

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable gitea
sudo systemctl start gitea

# Check the service status
sudo systemctl status gitea

Step 7: Initial Setup via the Web Interface

Open a browser and navigate to http://<server-IP>:3000. Gitea will display the initial setup page (Installation Wizard). Fill in the following details:

  • Database Type: Choose SQLite3 for small teams — no additional installation required
  • Site Title: The name of your Git server, e.g., “Company Git”
  • Repository Root Path: Keep the default /home/gitea/gitea-repositories
  • Application URL: Enter the actual URL, e.g., http://git.company.com or http://192.168.1.100:3000
  • Admin Account: Create your admin account here — don’t skip this step

Click Install Gitea — Gitea will automatically generate /etc/gitea/app.ini and be ready to use immediately.

Step 8: Add Nginx as a Reverse Proxy (Recommended)

Instead of exposing port 3000 directly, use Nginx to proxy through port 80/443 — a cleaner setup that makes adding HTTPS easier later:

sudo dnf install -y nginx
sudo nano /etc/nginx/conf.d/gitea.conf
server {
    listen 80;
    server_name git.yourdomain.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;
    }
}
# SELinux: allow Nginx to connect to Gitea on localhost
sudo setsebool -P httpd_can_network_connect 1

sudo systemctl enable --now nginx

# Open ports 80/443 and close 3000 if you don't want to expose it directly
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --remove-port=3000/tcp
sudo firewall-cmd --reload

Conclusion

Gitea isn’t the choice of someone who “can’t afford GitLab” — I chose Gitea because it genuinely fits small team workflows better. Fewer dependencies, easier backup, easier restore, and significantly lower VPS costs. After that emergency CentOS 8 migration, I’ve kept Gitea running on CentOS Stream 9 ever since and haven’t had a single reason to go back to GitLab.

The most important thing when deploying on CentOS Stream 9: don’t disable SELinux — configure it correctly. The three semanage commands above are all you need — no touching setenforce 0. Disabling SELinux saves you 5 minutes of setup, but you’ll lose the most critical security layer protecting your system.

Share: