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
SQLite3for 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.comorhttp://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.
