Add Template to deploy forgejo.
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.
This commit is contained in:
parent
a9f546f92a
commit
822e42dbb8
48 changed files with 6846 additions and 2 deletions
12
terraform/scaleway/compute/terraform.tfvars.example
Normal file
12
terraform/scaleway/compute/terraform.tfvars.example
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Scaleway Forgejo Instance Configuration
|
||||
# Copy this file to terraform.tfvars and update with your values:
|
||||
# cp terraform.tfvars.example terraform.tfvars
|
||||
|
||||
# Instance type (DEV1-M = 4GB RAM, DEV1-L = 8GB RAM)
|
||||
instance_type = "DEV1-M"
|
||||
|
||||
# Your SSH public key (contents of your ~/.ssh/id_ed25519.pub or similar)
|
||||
# ssh_public_key = "ssh-ed25519 AAAA... your-email@example.com"
|
||||
|
||||
# Your domain name for Forgejo
|
||||
# domain_name = "git.example.com"
|
||||
224
terraform/scaleway/compute/terragrunt.hcl
Normal file
224
terraform/scaleway/compute/terragrunt.hcl
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
# 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
|
||||
# Scaleway Compute Instance for Forgejo
|
||||
|
||||
variable "project_name" {
|
||||
description = "Project name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Environment name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "Scaleway region"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
description = "Scaleway zone"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "common_tags" {
|
||||
description = "Common tags for all resources"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
description = "Instance type for Forgejo server"
|
||||
type = string
|
||||
default = "DEV1-M" # 4GB RAM, 2 vCPUs, 40GB SSD
|
||||
}
|
||||
|
||||
variable "ssh_public_key" {
|
||||
description = "SSH public key for server access"
|
||||
type = string
|
||||
default = "" # Will use SSH agent keys if not provided
|
||||
}
|
||||
|
||||
variable "domain_name" {
|
||||
description = "Domain name for Forgejo (e.g., git.example.com)"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
# Data sources
|
||||
data "scaleway_instance_image" "ubuntu" {
|
||||
architecture = "x86_64"
|
||||
name = "Ubuntu 24.04 Noble Numbat"
|
||||
latest = true
|
||||
}
|
||||
|
||||
# Security Group
|
||||
resource "scaleway_instance_security_group" "forgejo" {
|
||||
name = "$${var.project_name}-$${var.environment}-sg"
|
||||
inbound_default_policy = "drop"
|
||||
outbound_default_policy = "accept"
|
||||
|
||||
inbound_rule {
|
||||
action = "accept"
|
||||
port = "22"
|
||||
protocol = "TCP"
|
||||
ip_range = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
inbound_rule {
|
||||
action = "accept"
|
||||
port = "80"
|
||||
protocol = "TCP"
|
||||
ip_range = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
inbound_rule {
|
||||
action = "accept"
|
||||
port = "443"
|
||||
protocol = "TCP"
|
||||
ip_range = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
# SSH alternative port (optional, configured via Ansible)
|
||||
inbound_rule {
|
||||
action = "accept"
|
||||
port = "2222"
|
||||
protocol = "TCP"
|
||||
ip_range = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
tags = [for k, v in var.common_tags : "$${k}:$${v}"]
|
||||
}
|
||||
|
||||
# SSH Key (using IAM SSH key for Scaleway provider v2.x)
|
||||
resource "scaleway_iam_ssh_key" "forgejo" {
|
||||
count = var.ssh_public_key != "" ? 1 : 0
|
||||
name = "$${var.project_name}-$${var.environment}-key"
|
||||
public_key = var.ssh_public_key
|
||||
}
|
||||
|
||||
# Block Volume for data persistence (create before instance)
|
||||
resource "scaleway_block_volume" "forgejo_data" {
|
||||
name = "$${var.project_name}-$${var.environment}-data"
|
||||
size_in_gb = 50
|
||||
iops = 5000
|
||||
|
||||
tags = [for k, v in var.common_tags : "$${k}:$${v}"]
|
||||
}
|
||||
|
||||
# Reserved IP (create before instance for stability)
|
||||
resource "scaleway_instance_ip" "forgejo" {}
|
||||
|
||||
# Compute Instance
|
||||
resource "scaleway_instance_server" "forgejo" {
|
||||
name = "$${var.project_name}-$${var.environment}"
|
||||
type = var.instance_type
|
||||
image = data.scaleway_instance_image.ubuntu.id
|
||||
security_group_id = scaleway_instance_security_group.forgejo.id
|
||||
ip_id = scaleway_instance_ip.forgejo.id
|
||||
|
||||
tags = [for k, v in var.common_tags : "$${k}:$${v}"]
|
||||
|
||||
# Ensure SSH key is registered before instance is created
|
||||
depends_on = [scaleway_iam_ssh_key.forgejo]
|
||||
|
||||
# Cloud-init for initial setup (user_data is a map in v2.x)
|
||||
user_data = {
|
||||
cloud-init = <<-CLOUDINIT
|
||||
#cloud-config
|
||||
package_update: true
|
||||
package_upgrade: true
|
||||
packages:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
- python3
|
||||
- python3-pip
|
||||
|
||||
write_files:
|
||||
- path: /etc/sysctl.d/99-forgejo.conf
|
||||
content: |
|
||||
# Forgejo optimizations
|
||||
net.core.somaxconn = 1024
|
||||
net.ipv4.tcp_max_syn_backlog = 2048
|
||||
vm.swappiness = 10
|
||||
|
||||
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
|
||||
CLOUDINIT
|
||||
}
|
||||
}
|
||||
|
||||
# Attach block volume to instance
|
||||
resource "scaleway_block_snapshot" "forgejo_data" {
|
||||
count = 0 # Only create if you need snapshots
|
||||
name = "$${var.project_name}-$${var.environment}-snapshot"
|
||||
volume_id = scaleway_block_volume.forgejo_data.id
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "server_id" {
|
||||
description = "Forgejo server ID"
|
||||
value = scaleway_instance_server.forgejo.id
|
||||
}
|
||||
|
||||
output "server_ip" {
|
||||
description = "Forgejo server public IP"
|
||||
value = scaleway_instance_ip.forgejo.address
|
||||
}
|
||||
|
||||
output "server_private_ip" {
|
||||
description = "Forgejo server private IP"
|
||||
value = length(scaleway_instance_server.forgejo.private_ips) > 0 ? scaleway_instance_server.forgejo.private_ips[0].address : null
|
||||
}
|
||||
|
||||
output "security_group_id" {
|
||||
description = "Security group ID"
|
||||
value = scaleway_instance_security_group.forgejo.id
|
||||
}
|
||||
|
||||
output "volume_id" {
|
||||
description = "Data volume ID"
|
||||
value = scaleway_block_volume.forgejo_data.id
|
||||
}
|
||||
|
||||
output "ssh_command" {
|
||||
description = "SSH command to connect to server"
|
||||
value = "ssh root@$${scaleway_instance_ip.forgejo.address}"
|
||||
}
|
||||
|
||||
output "dns_record" {
|
||||
description = "DNS A record to create"
|
||||
value = var.domain_name != "" ? "$${var.domain_name} IN A $${scaleway_instance_ip.forgejo.address}" : "No domain configured"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Dependencies
|
||||
dependency "storage" {
|
||||
config_path = "../storage"
|
||||
skip_outputs = true
|
||||
mock_outputs = {
|
||||
bucket_name = "forgejo-storage"
|
||||
}
|
||||
}
|
||||
70
terraform/scaleway/root.hcl
Normal file
70
terraform/scaleway/root.hcl
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Scaleway Root Configuration
|
||||
# This file contains common configuration for all Scaleway resources
|
||||
|
||||
locals {
|
||||
# Project configuration
|
||||
project_name = "forgejo"
|
||||
environment = "production"
|
||||
|
||||
# Scaleway configuration
|
||||
region = "fr-par"
|
||||
zone = "fr-par-1"
|
||||
|
||||
# Tags for resource organization
|
||||
common_tags = {
|
||||
Project = "forgejo"
|
||||
Environment = "production"
|
||||
ManagedBy = "terragrunt"
|
||||
}
|
||||
}
|
||||
|
||||
# Generate provider configuration
|
||||
generate "provider" {
|
||||
path = "provider.tf"
|
||||
if_exists = "overwrite_terragrunt"
|
||||
contents = <<EOF
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
||||
required_providers {
|
||||
scaleway = {
|
||||
source = "scaleway/scaleway"
|
||||
version = "~> 2.31"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "scaleway" {
|
||||
region = "${local.region}"
|
||||
zone = "${local.zone}"
|
||||
|
||||
# Credentials should be set via environment variables:
|
||||
# SCW_ACCESS_KEY
|
||||
# SCW_SECRET_KEY
|
||||
# SCW_DEFAULT_PROJECT_ID
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Remote state configuration (adjust for your backend)
|
||||
remote_state {
|
||||
backend = "local"
|
||||
|
||||
config = {
|
||||
path = "${get_parent_terragrunt_dir()}/terraform.tfstate"
|
||||
}
|
||||
|
||||
generate = {
|
||||
path = "backend.tf"
|
||||
if_exists = "overwrite_terragrunt"
|
||||
}
|
||||
}
|
||||
|
||||
# Input values available to all child configurations
|
||||
inputs = {
|
||||
project_name = local.project_name
|
||||
environment = local.environment
|
||||
region = local.region
|
||||
zone = local.zone
|
||||
common_tags = local.common_tags
|
||||
}
|
||||
154
terraform/scaleway/storage/terragrunt.hcl
Normal file
154
terraform/scaleway/storage/terragrunt.hcl
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
# Include root configuration
|
||||
include "root" {
|
||||
path = find_in_parent_folders("root.hcl")
|
||||
}
|
||||
|
||||
# Terragrunt configuration
|
||||
terraform {
|
||||
source = "."
|
||||
}
|
||||
|
||||
# Generate the storage Terraform configuration
|
||||
generate "main" {
|
||||
path = "main.tf"
|
||||
if_exists = "overwrite"
|
||||
contents = <<EOF
|
||||
# Scaleway Object Storage for Forgejo
|
||||
|
||||
variable "project_name" {
|
||||
description = "Project name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Environment name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "Scaleway region"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "common_tags" {
|
||||
description = "Common tags for all resources"
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
# Object Storage Bucket for Git LFS and Artifacts
|
||||
resource "scaleway_object_bucket" "forgejo_lfs" {
|
||||
name = "$${var.project_name}-$${var.environment}-lfs"
|
||||
region = var.region
|
||||
|
||||
tags = var.common_tags
|
||||
|
||||
# Enable versioning for data protection
|
||||
versioning {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
# Lifecycle rules to manage storage costs
|
||||
lifecycle_rule {
|
||||
id = "delete-old-versions"
|
||||
enabled = true
|
||||
|
||||
expiration {
|
||||
days = 90
|
||||
}
|
||||
|
||||
noncurrent_version_expiration {
|
||||
days = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Object Storage Bucket for Backups
|
||||
resource "scaleway_object_bucket" "forgejo_backups" {
|
||||
name = "$${var.project_name}-$${var.environment}-backups"
|
||||
region = var.region
|
||||
|
||||
tags = var.common_tags
|
||||
|
||||
versioning {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
# Keep backups for 30 days
|
||||
lifecycle_rule {
|
||||
id = "expire-old-backups"
|
||||
enabled = true
|
||||
|
||||
expiration {
|
||||
days = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Access Key for application usage
|
||||
resource "scaleway_iam_application" "forgejo" {
|
||||
name = "$${var.project_name}-$${var.environment}"
|
||||
description = "Application credentials for Forgejo object storage"
|
||||
|
||||
tags = [for k, v in var.common_tags : "$${k}=$${v}"]
|
||||
}
|
||||
|
||||
resource "scaleway_iam_api_key" "forgejo" {
|
||||
application_id = scaleway_iam_application.forgejo.id
|
||||
description = "API key for Forgejo object storage access"
|
||||
}
|
||||
|
||||
# Policy for bucket access
|
||||
resource "scaleway_iam_policy" "forgejo_storage" {
|
||||
name = "$${var.project_name}-$${var.environment}-storage-policy"
|
||||
description = "Policy for Forgejo storage buckets"
|
||||
application_id = scaleway_iam_application.forgejo.id
|
||||
|
||||
rule {
|
||||
project_ids = [data.scaleway_account_project.main.id]
|
||||
permission_set_names = ["ObjectStorageFullAccess"]
|
||||
}
|
||||
}
|
||||
|
||||
data "scaleway_account_project" "main" {
|
||||
name = var.project_name
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "lfs_bucket_name" {
|
||||
description = "LFS bucket name"
|
||||
value = scaleway_object_bucket.forgejo_lfs.name
|
||||
}
|
||||
|
||||
output "lfs_bucket_endpoint" {
|
||||
description = "LFS bucket endpoint"
|
||||
value = scaleway_object_bucket.forgejo_lfs.endpoint
|
||||
}
|
||||
|
||||
output "backup_bucket_name" {
|
||||
description = "Backup bucket name"
|
||||
value = scaleway_object_bucket.forgejo_backups.name
|
||||
}
|
||||
|
||||
output "backup_bucket_endpoint" {
|
||||
description = "Backup bucket endpoint"
|
||||
value = scaleway_object_bucket.forgejo_backups.endpoint
|
||||
}
|
||||
|
||||
output "access_key" {
|
||||
description = "Access key for object storage"
|
||||
value = scaleway_iam_api_key.forgejo.access_key
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "secret_key" {
|
||||
description = "Secret key for object storage"
|
||||
value = scaleway_iam_api_key.forgejo.secret_key
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "s3_region" {
|
||||
description = "S3-compatible region"
|
||||
value = var.region
|
||||
}
|
||||
EOF
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue