This template allows deploying a forgejo en either Scaleway or Hetzner (untested) without much knowledge about them. It DOES require knowledge about Terragrunt and ansible. A wizard of sorts is provided but it will not guarantee success without some knowledge about the underlying technology.
304 lines
6.4 KiB
HCL
304 lines
6.4 KiB
HCL
# Include root configuration
|
|
include "root" {
|
|
path = find_in_parent_folders("root.hcl")
|
|
}
|
|
|
|
# Terragrunt configuration
|
|
terraform {
|
|
source = "."
|
|
}
|
|
|
|
# Generate the main Terraform configuration
|
|
generate "main" {
|
|
path = "main.tf"
|
|
if_exists = "overwrite"
|
|
contents = <<EOF
|
|
# Hetzner Cloud Infrastructure for Forgejo
|
|
|
|
variable "project_name" {
|
|
description = "Project name"
|
|
type = string
|
|
}
|
|
|
|
variable "environment" {
|
|
description = "Environment name"
|
|
type = string
|
|
}
|
|
|
|
variable "location" {
|
|
description = "Hetzner location"
|
|
type = string
|
|
}
|
|
|
|
variable "common_labels" {
|
|
description = "Common labels for all resources"
|
|
type = map(string)
|
|
}
|
|
|
|
variable "server_type" {
|
|
description = "Server type for Forgejo"
|
|
type = string
|
|
default = "cpx21" # 4 vCPU, 8GB RAM, 80GB SSD
|
|
}
|
|
|
|
variable "ssh_keys" {
|
|
description = "List of SSH key IDs or names to add to server"
|
|
type = list(string)
|
|
default = []
|
|
}
|
|
|
|
variable "domain_name" {
|
|
description = "Domain name for Forgejo"
|
|
type = string
|
|
default = ""
|
|
}
|
|
|
|
# Data sources
|
|
data "hcloud_ssh_keys" "all" {
|
|
count = length(var.ssh_keys) > 0 ? 0 : 1
|
|
}
|
|
|
|
# Network for private communication
|
|
resource "hcloud_network" "forgejo" {
|
|
name = "$${var.project_name}-$${var.environment}-network"
|
|
ip_range = "10.0.0.0/16"
|
|
labels = var.common_labels
|
|
}
|
|
|
|
resource "hcloud_network_subnet" "forgejo" {
|
|
network_id = hcloud_network.forgejo.id
|
|
type = "cloud"
|
|
network_zone = "eu-central"
|
|
ip_range = "10.0.1.0/24"
|
|
}
|
|
|
|
# Firewall
|
|
resource "hcloud_firewall" "forgejo" {
|
|
name = "$${var.project_name}-$${var.environment}-firewall"
|
|
labels = var.common_labels
|
|
|
|
rule {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = "22"
|
|
source_ips = [
|
|
"0.0.0.0/0",
|
|
"::/0"
|
|
]
|
|
description = "SSH access"
|
|
}
|
|
|
|
rule {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = "80"
|
|
source_ips = [
|
|
"0.0.0.0/0",
|
|
"::/0"
|
|
]
|
|
description = "HTTP"
|
|
}
|
|
|
|
rule {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = "443"
|
|
source_ips = [
|
|
"0.0.0.0/0",
|
|
"::/0"
|
|
]
|
|
description = "HTTPS"
|
|
}
|
|
|
|
rule {
|
|
direction = "in"
|
|
protocol = "tcp"
|
|
port = "2222"
|
|
source_ips = [
|
|
"0.0.0.0/0",
|
|
"::/0"
|
|
]
|
|
description = "SSH alternative port"
|
|
}
|
|
|
|
rule {
|
|
direction = "in"
|
|
protocol = "icmp"
|
|
source_ips = [
|
|
"0.0.0.0/0",
|
|
"::/0"
|
|
]
|
|
description = "ICMP (ping)"
|
|
}
|
|
}
|
|
|
|
# Placement Group for better availability
|
|
resource "hcloud_placement_group" "forgejo" {
|
|
name = "$${var.project_name}-$${var.environment}"
|
|
type = "spread"
|
|
labels = var.common_labels
|
|
}
|
|
|
|
# Cloud-init configuration
|
|
data "cloudinit_config" "forgejo" {
|
|
gzip = false
|
|
base64_encode = false
|
|
|
|
part {
|
|
content_type = "text/cloud-config"
|
|
content = yamlencode({
|
|
package_update = true
|
|
package_upgrade = true
|
|
|
|
packages = [
|
|
"apt-transport-https",
|
|
"ca-certificates",
|
|
"curl",
|
|
"gnupg",
|
|
"lsb-release",
|
|
"python3",
|
|
"python3-pip",
|
|
"ufw"
|
|
]
|
|
|
|
write_files = [
|
|
{
|
|
path = "/etc/sysctl.d/99-forgejo.conf"
|
|
content = <<-SYSCTL
|
|
# Forgejo optimizations
|
|
net.core.somaxconn = 1024
|
|
net.ipv4.tcp_max_syn_backlog = 2048
|
|
net.ipv4.ip_forward = 1
|
|
vm.swappiness = 10
|
|
fs.file-max = 65535
|
|
SYSCTL
|
|
}
|
|
]
|
|
|
|
runcmd = [
|
|
"sysctl -p /etc/sysctl.d/99-forgejo.conf",
|
|
"systemctl enable ssh",
|
|
"ufw --force enable",
|
|
"ufw allow 22/tcp",
|
|
"ufw allow 80/tcp",
|
|
"ufw allow 443/tcp",
|
|
"ufw allow 2222/tcp"
|
|
]
|
|
})
|
|
}
|
|
}
|
|
|
|
# Server
|
|
resource "hcloud_server" "forgejo" {
|
|
name = "$${var.project_name}-$${var.environment}"
|
|
server_type = var.server_type
|
|
image = "ubuntu-24.04"
|
|
location = var.location
|
|
ssh_keys = length(var.ssh_keys) > 0 ? var.ssh_keys : data.hcloud_ssh_keys.all[0].ssh_keys[*].id
|
|
placement_group_id = hcloud_placement_group.forgejo.id
|
|
user_data = data.cloudinit_config.forgejo.rendered
|
|
|
|
labels = var.common_labels
|
|
|
|
public_net {
|
|
ipv4_enabled = true
|
|
ipv6_enabled = true
|
|
}
|
|
|
|
firewall_ids = [hcloud_firewall.forgejo.id]
|
|
|
|
# Attach to private network
|
|
network {
|
|
network_id = hcloud_network.forgejo.id
|
|
ip = "10.0.1.5"
|
|
}
|
|
|
|
depends_on = [hcloud_network_subnet.forgejo]
|
|
}
|
|
|
|
# Volume for data persistence
|
|
resource "hcloud_volume" "forgejo_data" {
|
|
name = "$${var.project_name}-$${var.environment}-data"
|
|
size = 50
|
|
location = var.location
|
|
format = "ext4"
|
|
labels = var.common_labels
|
|
}
|
|
|
|
resource "hcloud_volume_attachment" "forgejo_data" {
|
|
volume_id = hcloud_volume.forgejo_data.id
|
|
server_id = hcloud_server.forgejo.id
|
|
automount = false # We'll mount via Ansible for better control
|
|
}
|
|
|
|
# Outputs
|
|
output "server_id" {
|
|
description = "Server ID"
|
|
value = hcloud_server.forgejo.id
|
|
}
|
|
|
|
output "server_name" {
|
|
description = "Server name"
|
|
value = hcloud_server.forgejo.name
|
|
}
|
|
|
|
output "server_ipv4" {
|
|
description = "Server IPv4 address"
|
|
value = hcloud_server.forgejo.ipv4_address
|
|
}
|
|
|
|
output "server_ipv6" {
|
|
description = "Server IPv6 address"
|
|
value = hcloud_server.forgejo.ipv6_address
|
|
}
|
|
|
|
output "server_private_ip" {
|
|
description = "Server private IP"
|
|
value = hcloud_server.forgejo.network[0].ip
|
|
}
|
|
|
|
output "volume_id" {
|
|
description = "Data volume ID"
|
|
value = hcloud_volume.forgejo_data.id
|
|
}
|
|
|
|
output "volume_device" {
|
|
description = "Volume device path"
|
|
value = "/dev/disk/by-id/scsi-0HC_Volume_$${hcloud_volume.forgejo_data.id}"
|
|
}
|
|
|
|
output "network_id" {
|
|
description = "Network ID"
|
|
value = hcloud_network.forgejo.id
|
|
}
|
|
|
|
output "ssh_command" {
|
|
description = "SSH command to connect"
|
|
value = "ssh root@$${hcloud_server.forgejo.ipv4_address}"
|
|
}
|
|
|
|
output "dns_records" {
|
|
description = "DNS records to create"
|
|
value = var.domain_name != "" ? {
|
|
ipv4 = "$${var.domain_name} IN A $${hcloud_server.forgejo.ipv4_address}"
|
|
ipv6 = "$${var.domain_name} IN AAAA $${hcloud_server.forgejo.ipv6_address}"
|
|
} : {}
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# Generate cloudinit provider
|
|
generate "cloudinit_provider" {
|
|
path = "cloudinit.tf"
|
|
if_exists = "overwrite"
|
|
contents = <<EOF
|
|
terraform {
|
|
required_providers {
|
|
cloudinit = {
|
|
source = "hashicorp/cloudinit"
|
|
version = "~> 2.3"
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
}
|