Hosting Gitea & Forgejo with Docker, Nginx, and Cloudflare Proxy
This guide helps beginners deploy Gitea or Forgejo Git servers using Docker containers, secure them with Nginx reverse proxy, and protect with Cloudflare.
Replace all example domains like git.yourdomain.com with your real domain or subdomain.
Step 1: Project Directory and File Structure
Connect to your VPS via SSH and create a main project directory:
Note: Add the latest Cloudflare IP ranges explicitly in REVERSE_PROXY_TRUSTED_PROXIES or TRUSTED_PROXIES environment variables to ensure accurate client IP logging and security.
Step 3: Advanced Nginx Configuration
Your Nginx config files must support important features:
Proxy headers to pass the correct client IP and protocol.
WebSocket support for real-time features.
Static file caching to improve performance.
Client body size limit to prevent abuse.
Error and access logging for troubleshooting.
Example for Gitea (nginx-gitea.conf):
The Forgejo config is analogous but proxies to http://forgejo:3000/.
Step 4: Cloudflare SSL & Firewall Integration
Use these Cloudflare settings to avoid common SSL errors:
SSL/TLS mode: set to Full (strict) to require your VPS to have a valid SSL cert.
Enable Always Use HTTPS to redirect all HTTP to HTTPS.
Upload your domain's SSL certificates with Certbot (next step) to avoid 525 SSL handshake errors.
Configure your VPS firewall (UFW) to allow inbound HTTP/HTTPS only from Cloudflare's IPs:
Automation tip: Write a script to periodically update UFW rules when Cloudflare IPs change.
Step 5: SSL Certificates with Certbot & Renewal Automation
Install Certbot and get certificates for your domain:
Certbot installs certificates in your local certs/ folder (mounted to Nginx).
Set up automatic renewal by editing the root crontab:
Add the following line to renew certs daily and reload Nginx if renewed:
Replace docker-compose-gitea.yml with your compose file if different.
Step 6: Important Application-Level Configuration for Gitea & Forgejo
Trusted Proxies
Add Cloudflare's IP ranges to trusted proxies so Gitea/Forgejo log true client IPs and prevent header spoofing.
curl https://www.cloudflare.com/ips-v4 -o cloudflare-ips-v4.txt
curl https://www.cloudflare.com/ips-v6 -o cloudflare-ips-v6.txt
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
for ip in $(cat cloudflare-ips-v4.txt); do
sudo ufw allow from $ip to any port 80,443 proto tcp
done
for ip in $(cat cloudflare-ips-v6.txt); do
sudo ufw allow from $ip to any port 80,443 proto tcp
done
sudo ufw enable
sudo ufw reload