-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from ivov/provision-with-terraform
ci: Provision infrastructure with Terraform
- Loading branch information
Showing
16 changed files
with
407 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
.DS_Store | ||
bin/* | ||
!**/.gitkeep | ||
!**/.gitkeep | ||
*.tfstate | ||
*.tfstate.* | ||
.terraform/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Provisioning | ||
|
||
This guide explains how to provision the requisite infrastructure for `n8n-shortlink`: | ||
|
||
- **Server**: CAX11 on Hetzner Cloud. ARM64 with 2 vCPU, 4 GiB RAM, 40 GiB disk, running Ubuntu 22.04, located at `nbg1-dc3` (Nuremberg) data center. Ingress rules configured at network level for TCP ports 22 (SSH with source IP restriction), 80 (HTTP), and 443 (HTTPS) | ||
- **Backup**: AWS S3 bucket for backup storage with 10-day retention policy. Dedicated IAM user with programmatic access via access key pair, constrained by least-privilege policy granting bucket-specific read (`GetObject`, `ListBucket`) and write (`PutObject`) permissions. | ||
|
||
## Setup | ||
|
||
1. Install Terraform: | ||
|
||
```sh | ||
brew install terraform | ||
terraform --version # >= 1.9.8 | ||
``` | ||
|
||
2. Create an SSH key pair: | ||
|
||
```sh | ||
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_shortlink_via_terraform | ||
``` | ||
|
||
3. Sign up for [Hetzner Cloud](https://www.hetzner.com/cloud/), create a project `n8n-shortlink`, and create an API token for the project. | ||
|
||
4. Sign up for [HCP Terraform](https://www.hashicorp.com/products/terraform), create an organization `ivov` and a workspace `n8n-shortlink`. In workspace settings, set execution mode to `local`, so that apply occurs locally and HCP Terraform is used only to store state. Set these workspace variables: | ||
|
||
- `ssh_public_key`: Content of `~/.ssh/id_ed25519_shortlink_via_terraform.pub` from step 2. Mark as sensitive. | ||
- `hcloud_token`: API token from step 3. Mark as sensitive. | ||
- `allowed_ssh_ips`: `["your-ip-address"]`, i.e. string array in CIDR notation. Mark as sensitive and _as HCL-type variable_. | ||
|
||
5. Sign up for [AWS](https://aws.amazon.com/console/), create an IAM policy `n8n-shortlink-terraform-automation-policy`, create an IAM user `n8n-shortlink-terraform-automation-user` (disallow AWS Management Console access) attaching the policy to this user, generate access keys for this user (select "Third-party service") and store them in HCP Terraform: | ||
|
||
- `tf_automation_aws_access_key_id`: Access key ID for `terraform-automation` IAM user. Mark as sensitive. | ||
- `tf_automation_aws_secret_access_key`. Secret access key for `terraform-automation` IAM user. Mark as sensitive. | ||
|
||
```jsonc | ||
// n8n-shortlink-terraform-automation-policy | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Action": "iam:*", | ||
"Resource": "arn:aws:iam::*:user/n8n-shortlink-terraform-backup-user", | ||
}, | ||
{ | ||
"Effect": "Allow", | ||
"Action": "s3:*", | ||
"Resource": [ | ||
"arn:aws:s3:::n8n-shortlink-terraform-backup-bucket", | ||
"arn:aws:s3:::n8n-shortlink-terraform-backup-bucket/*", | ||
], | ||
}, | ||
], | ||
} | ||
``` | ||
|
||
## Provision | ||
|
||
1. Log in to HCP Terraform: | ||
|
||
```sh | ||
terraform login | ||
``` | ||
|
||
2. Initialize Terraform: | ||
|
||
```sh | ||
cd infra/provision | ||
terraform init | ||
``` | ||
|
||
3. Plan and apply: | ||
|
||
```sh | ||
terraform plan | ||
terraform apply | ||
``` | ||
|
||
4. Note down IP address and retrieve credentials from state: | ||
|
||
```sh | ||
Outputs: | ||
backup_credentials = (sensitive value) | ||
server_ip = "87.148.121.19" | ||
|
||
terraform output -json backup_credentials | ||
``` |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module "server" { | ||
source = "./modules/server" | ||
project_name = var.project_name | ||
server_type = "cax11" | ||
location = "nbg1" | ||
hcloud_token = var.hcloud_token | ||
allowed_ssh_ips = var.allowed_ssh_ips | ||
ssh_public_key = var.ssh_public_key | ||
} | ||
|
||
module "backup" { | ||
source = "./modules/backup" | ||
project_name = var.project_name | ||
bucket_name = "${var.project_name}-backup-bucket" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
resource "aws_s3_bucket" "backup" { | ||
bucket = var.bucket_name | ||
} | ||
|
||
resource "aws_s3_bucket_lifecycle_configuration" "backup" { | ||
bucket = aws_s3_bucket.backup.id | ||
|
||
rule { | ||
id = "cleanup" | ||
status = "Enabled" | ||
|
||
filter { | ||
prefix = "${var.project_name}-backup/" | ||
} | ||
|
||
expiration { | ||
days = 10 | ||
} | ||
} | ||
} | ||
|
||
resource "aws_iam_user" "backup" { | ||
name = "${var.project_name}-backup-user" | ||
} | ||
|
||
resource "aws_iam_access_key" "backup" { | ||
user = aws_iam_user.backup.name | ||
} | ||
|
||
resource "aws_iam_user_policy" "backup" { | ||
name = "${var.project_name}-backup-policy" | ||
user = aws_iam_user.backup.name | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Effect = "Allow" | ||
Action = [ | ||
"s3:PutObject", | ||
"s3:GetObject", | ||
"s3:ListBucket" | ||
] | ||
Resource = [ | ||
aws_s3_bucket.backup.arn, | ||
"${aws_s3_bucket.backup.arn}/*" | ||
] | ||
} | ||
] | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
output "backup_user_access_key" { | ||
description = "AWS access key for backup user" | ||
value = aws_iam_access_key.backup.id | ||
} | ||
|
||
output "backup_user_secret_key" { | ||
description = "AWS secret key for backup user" | ||
value = aws_iam_access_key.backup.secret | ||
sensitive = true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
variable "project_name" { | ||
description = "Project name for resource naming" | ||
type = string | ||
} | ||
|
||
variable "bucket_name" { | ||
description = "Name of the S3 bucket for backups" | ||
type = string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
resource "hcloud_ssh_key" "main" { | ||
name = "${var.project_name}-key" | ||
public_key = var.ssh_public_key | ||
} | ||
|
||
resource "hcloud_firewall" "main" { | ||
name = "${var.project_name}-fw" | ||
|
||
rule { | ||
direction = "in" | ||
protocol = "tcp" | ||
port = "22" | ||
source_ips = var.allowed_ssh_ips | ||
} | ||
|
||
rule { | ||
direction = "in" | ||
protocol = "tcp" | ||
port = "80" | ||
source_ips = [ | ||
"0.0.0.0/0" | ||
] | ||
} | ||
|
||
rule { | ||
direction = "in" | ||
protocol = "tcp" | ||
port = "443" | ||
source_ips = [ | ||
"0.0.0.0/0" | ||
] | ||
} | ||
} | ||
|
||
resource "hcloud_server" "main" { | ||
name = var.project_name | ||
server_type = var.server_type | ||
image = "ubuntu-22.04" | ||
location = var.location | ||
ssh_keys = [hcloud_ssh_key.main.id] | ||
|
||
firewall_ids = [hcloud_firewall.main.id] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
output "server_ip" { | ||
description = "Public IP of the server" | ||
value = hcloud_server.main.ipv4_address | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
terraform { | ||
required_providers { | ||
hcloud = { | ||
source = "hetznercloud/hcloud" | ||
version = "~> 1.45.0" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
variable "project_name" { | ||
description = "Project name for resource naming" | ||
type = string | ||
} | ||
|
||
variable "hcloud_token" { | ||
description = "Hetzner Cloud API Token" | ||
type = string | ||
sensitive = true | ||
} | ||
|
||
variable "server_type" { | ||
description = "Hetzner server type" | ||
type = string | ||
} | ||
|
||
variable "location" { | ||
description = "Hetzner datacenter location" | ||
type = string | ||
} | ||
|
||
variable "ssh_public_key" { | ||
description = "SSH public key content" | ||
type = string | ||
} | ||
|
||
variable "allowed_ssh_ips" { | ||
description = "List of CIDR IP addresses allowed to connect via SSH" | ||
type = list(string) | ||
sensitive = true # prevent IPs from showing in logs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
output "server_ip" { | ||
description = "Public IP of the Hetzner server" | ||
value = module.server.server_ip | ||
} | ||
|
||
output "backup_credentials" { | ||
description = "AWS credentials for backup user" | ||
value = { | ||
access_key = module.backup.backup_user_access_key | ||
secret_key = module.backup.backup_user_secret_key | ||
} | ||
sensitive = true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
provider "hcloud" { | ||
token = var.hcloud_token | ||
} | ||
|
||
provider "aws" { | ||
region = var.aws_region | ||
access_key = var.tf_automation_aws_access_key_id | ||
secret_key = var.tf_automation_aws_secret_access_key | ||
} |
Oops, something went wrong.