This Terraform project deploys a self-hosted Forgejo Git hosting service on Hetzner Cloud with automatic SSL certificates via Caddy.
- Server: Ubuntu 24.04 LTS on Hetzner Cloud
- Git Hosting: Forgejo (rootless container)
- Reverse Proxy: Caddy with automatic Let's Encrypt SSL
- SSH Configuration:
- Port 2222: Admin SSH access
- Port 22: Forgejo Git SSH access
- Firewall: Configured for web traffic and SSH
- π Secure by default: Hardened SSH configuration, firewall rules
- π Automatic SSL: Let's Encrypt certificates via Caddy
- π³ Containerized: Docker Compose stack for easy management
- π Production-ready: Systemd service for automatic startup
- β‘ Fast deployment: Single
terraform applycommand
- Hetzner Cloud account and API token
- Domain name with DNS A record pointing to the server
- SSH key pair for server access
- Terraform >= 1.0 installed
git clone <your-repo>
cd forgejo-hetznerCreate a terraform.tfvars file:
# Required
hcloud_token = "your-hetzner-api-token"
public_ssh_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... your-key"
domain_name = "git.yourdomain.com"
acme_email = "your-email@example.com"
# Optional (with defaults)
server_name = "forgejo"
server_type = "cpx11"
server_location = "hel1"
admin_user = "ubuntu"terraform init
terraform plan
terraform applyAfter deployment (takes ~2-3 minutes):
- Web Interface: Visit
https://your-domain.com - Admin SSH:
ssh ubuntu@<server-ip> -p 2222 - Git SSH: Configure Git to use port 22 (default for Forgejo)
| Variable | Description | Default | Required |
|---|---|---|---|
hcloud_token |
Hetzner Cloud API token | - | β |
public_ssh_key |
SSH public key for server access | - | β |
domain_name |
Domain for Forgejo (must point to server) | droneaid.kenmac.nl |
β |
acme_email |
Email for Let's Encrypt notifications | you@example.com |
β |
server_name |
Name for the Hetzner server | forgejo |
β |
server_type |
Hetzner server type | cpx11 |
β |
server_location |
Hetzner datacenter location | hel1 |
β |
admin_user |
Admin username for server | ubuntu |
β |
Common Hetzner server types:
cpx11: 2 vCPU, 4 GB RAM, 40 GB SSD (~β¬4.15/month)cx22: 2 vCPU, 4 GB RAM, 40 GB SSD (~β¬5.83/month)cax11: 2 vCPU ARM, 4 GB RAM, 40 GB SSD (~β¬3.29/month)
Available Hetzner locations:
hel1: Helsinki, Finlandfsn1: Falkenstein, Germanynbg1: Nuremberg, Germanyash: Ashburn, Virginia, USA
| Port | Service | Description |
|---|---|---|
| 22 | Forgejo SSH | Git operations (clone, push, pull) |
| 80 | HTTP | Redirects to HTTPS |
| 443 | HTTPS | Web interface (Caddy β Forgejo) |
| 2222 | Admin SSH | Server administration |
- Visit
https://your-domain.com - Follow the initial setup wizard
- Configure your Git repositories
For Git operations over SSH:
# Clone repositories
git clone git@your-domain.com:username/repo.git
# Or configure SSH for custom port (if needed)
# Add to ~/.ssh/config:
Host your-domain.com
Port 22
User gitConnect to your server for maintenance:
ssh ubuntu@<server-ip> -p 2222
# Check service status
sudo systemctl status forgejo-stack
# View logs
sudo docker compose -f /opt/forgejo/docker-compose.yml logs -f
# Restart services
sudo systemctl restart forgejo-stack.
βββ main.tf # Main Terraform configuration
βββ variables.tf # Input variables
βββ outputs.tf # Output values
βββ cloud-init.yaml # Server initialization script
βββ terraform.tfvars # Your variable values (create this)
βββ README.md # This file
- SSH into the server:
ssh ubuntu@<server-ip> -p 2222 - Update the Docker image:
cd /opt/forgejo sudo docker compose pull sudo docker compose up -d
Important directories to backup:
/opt/forgejo/data/- Git repositories and database/opt/forgejo/conf/- Forgejo configuration/opt/caddy/data/- SSL certificates
Caddy automatically manages Let's Encrypt certificates. They renew automatically every 60 days.
- SSL Certificate Issues: Ensure your domain's A record points to the server IP
- SSH Connection Issues: Check if you're using the correct port (2222 for admin, 22 for Git)
- Firewall Issues: Verify Hetzner Cloud firewall rules are applied
# Check service status
sudo systemctl status forgejo-stack
# View container logs
sudo docker logs forgejo
sudo docker logs caddy
# Restart the entire stack
sudo systemctl restart forgejo-stack
# Check Caddy configuration
sudo docker exec caddy caddy validate --config /etc/caddy/Caddyfile- SSH password authentication is disabled
- Root login is restricted to SSH keys only
- Admin SSH runs on non-standard port (2222)
- Firewall rules restrict access to necessary ports only
- SSL certificates are managed automatically
Approximate monthly costs (EUR, as of 2024):
- Server (cpx11): β¬4.15
- Traffic: Usually free (20TB included)
- Total: ~β¬4.15/month
This project is open source. Forgejo is MIT licensed.