Skip to content

Commit 4965de6

Browse files
authored
Merge pull request #1 from cloudijs/test-iac
Test IAC GH Actions
2 parents f456fe6 + 28c7e32 commit 4965de6

15 files changed

Lines changed: 431 additions & 36 deletions

File tree

.github/workflows/apply.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Apply Terraform plan
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: read
10+
pull-requests: write
11+
12+
jobs:
13+
apply:
14+
runs-on: ubuntu-latest
15+
name: Apply Terraform plan
16+
env:
17+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
TF_VAR_hcloud_token: ${{ secrets.TF_HCLOUD_TOKEN }}
19+
STATE_BUCKET_NAME: ${{ secrets.TF_STATE_BUCKET_NAME }}
20+
STATE_BUCKET_KEY: ${{ secrets.TF_STATE_BUCKET_KEY }}
21+
AWS_ACCESS_KEY_ID: ${{ secrets.TF_STATE_ACCESS_KEY }}
22+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TF_STATE_SECRET_KEY }}
23+
AWS_CA_BUNDLE: ""
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Setup Homebrew
29+
run: |
30+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
31+
echo >> ~/.bashrc
32+
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"' >> ~/.bashrc
33+
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"
34+
env:
35+
NONINTERACTIVE: 1
36+
37+
- name: Install Packer
38+
run: |
39+
sudo apt update
40+
sudo apt install packer
41+
packer
42+
locate packer
43+
44+
- name: Install Talosctl
45+
run: /home/linuxbrew/.linuxbrew/bin/brew install siderolabs/tap/talosctl
46+
47+
- name: Terraform apply
48+
uses: dflook/terraform-apply@v2
49+
with:
50+
path: infra
51+
backend_config: bucket=${{ env.STATE_BUCKET_NAME }} key=${{ env.STATE_BUCKET_KEY }}

.github/workflows/lint.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Lint Terraform plan
2+
3+
on:
4+
push:
5+
branches-ignore:
6+
- main
7+
8+
jobs:
9+
validate:
10+
runs-on: ubuntu-latest
11+
name: Validate Terraform
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Terraform validate
17+
uses: dflook/terraform-validate@v2
18+
with:
19+
path: infra
20+
21+
fmt-check:
22+
runs-on: ubuntu-latest
23+
name: Terraform formatting
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Terraform fmt
29+
uses: dflook/terraform-fmt-check@v2
30+
with:
31+
path: infra

.github/workflows/plan.yaml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Create Terraform plan
2+
3+
on: [pull_request]
4+
5+
permissions:
6+
contents: read
7+
pull-requests: write
8+
9+
jobs:
10+
plan:
11+
runs-on: ubuntu-latest
12+
name: Create a Terraform plan
13+
env:
14+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
15+
TF_VAR_hcloud_token: ${{ secrets.TF_HCLOUD_TOKEN }}
16+
STATE_BUCKET_NAME: ${{ secrets.TF_STATE_BUCKET_NAME }}
17+
STATE_BUCKET_KEY: ${{ secrets.TF_STATE_BUCKET_KEY }}
18+
AWS_ACCESS_KEY_ID: ${{ secrets.TF_STATE_ACCESS_KEY }}
19+
AWS_SECRET_ACCESS_KEY: ${{ secrets.TF_STATE_SECRET_KEY }}
20+
AWS_CA_BUNDLE: ""
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
# - name: Setup Homebrew
26+
# run: |
27+
# /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
28+
# echo >> ~/.bashrc
29+
# echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"' >> ~/.bashrc
30+
# eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"
31+
# env:
32+
# NONINTERACTIVE: 1
33+
34+
# - name: Install Packer
35+
# run: |
36+
# sudo wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
37+
# sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
38+
# sudo apt update
39+
# sudo apt install packer
40+
41+
# - name: Install Talosctl
42+
# run: curl -sL https://talos.dev/install | sh
43+
44+
- name: Terraform plan
45+
uses: dflook/terraform-plan@v2
46+
with:
47+
path: infra
48+
backend_config: bucket=${{ env.STATE_BUCKET_NAME }} key=${{ env.STATE_BUCKET_KEY }}
49+
env:
50+
TERRAFORM_PRE_RUN: |
51+
# Install prerequisites
52+
apt update
53+
apt install -y lsb-release
54+
55+
# Install latest Packer
56+
wget -O - https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
57+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list
58+
apt install -y packer
59+
60+
# Install latest Talosctl
61+
curl -sL https://talos.dev/install | sh

.gitignore

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ terraform.tfvars
77
*.auto.tfvars
88

99
# secrets
10-
kubeconfig
11-
talosconfig
10+
.kubeconfig
11+
.kubeconfig.bak
12+
.talosconfig
13+
.talosconfig.bak
14+
.env
15+
.environment

README.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,42 @@
22

33
# Cloudijs Platform
44

5-
Hosting platform based on Kubernetes. This repository contain the IAC used to setup this platform on [Hetzner](https://www.hetzner.com). The platform relies heavily on the amazing [terraform-hcloud-kubernetes](https://github.com/hcloud-k8s/terraform-hcloud-kubernetes) Terraform module.
5+
Hosting platform based on Kubernetes. This repository contain the Terraform code used to setup this platform on [Hetzner](https://www.hetzner.com). The platform relies heavily on the amazing [terraform-hcloud-kubernetes](https://github.com/hcloud-k8s/terraform-hcloud-kubernetes) Tofu/Terraform module.
6+
7+
## Pre-requisites
8+
9+
* [Hetzner Account](https://www.hetzner.com)
10+
* [OpenTofu](https://opentofu.org/docs/intro/install/)
11+
* [Taskfile](https://taskfile.dev/docs/installation)
612

713
## Deployment
814

9-
To deploy the platform you will need a Hetzer account and create a [token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token/). Then run Terraform or Tofu after setting the token variable:
10-
```bash
11-
export TF_VAR_hcloud_token="<your-token>"
12-
tofu plan
13-
tofy apply
15+
To deploy the platform you will need a Hetzner account, create an S3 bucket and create an [API token](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token/). Make sure to gather the values for the S3 bucket configuration. These can be specified as environment variables or in an `.env` file:
16+
```sh
17+
export HCLOUD_TOKEN="<your-token>"
18+
19+
export STATE_BUCKET_NAME="<your-object-storage-bucket-name>"
20+
export STATE_BUCKET_KEY="<your-object-storage-bucket-key>"
21+
22+
export STATE_BUCKET_ACCESS_KEY="<your-s3-credentials-access-key>"
23+
export STATE_BUCKET_SECRET_KEY="<your-s3-credentials-secret-key>"
24+
```
25+
```
26+
# .env
27+
28+
HCLOUD_TOKEN="<your-token>"
29+
30+
STATE_BUCKET_NAME="<your-object-storage-bucket-name>"
31+
STATE_BUCKET_KEY="<your-object-storage-bucket-key>"
32+
33+
STATE_BUCKET_ACCESS_KEY="<your-s3-credentials-access-key>"
34+
STATE_BUCKET_SECRET_KEY="<your-s3-credentials-secret-key>"
35+
```
36+
Run Tofu after setting the required variables to setup the platform:
37+
```sh
38+
task create
1439
```
40+
Other available tasks like destroying the environment can be found using the `task` command.
1541

1642
## Sources
1743

@@ -20,7 +46,8 @@ tofy apply
2046
* https://registry.terraform.io/providers/hetznercloud/hcloud/latest
2147
* https://docs.hetzner.cloud/changelog#2025-04-23-talos-linux-v195-iso-now-available
2248
* https://github.com/hetznercloud/hcloud-cloud-controller-manager/tree/main
49+
* https://github.com/dflook/terraform-github-actions
2350

2451
## License
2552

26-
[MIT license](LICENSE)
53+
[MIT license](LICENSE)

Taskfile.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
version: "3"
3+
4+
dotenv:
5+
- .env
6+
- ../.env
7+
8+
tasks:
9+
default:
10+
desc: List available tasks
11+
cmds:
12+
- task --list-all
13+
14+
create:
15+
desc: Create all resources
16+
dir: infra/
17+
cmds:
18+
- tofu init -backend-config="bucket=${STATE_BUCKET_NAME}" -backend-config="key=${STATE_BUCKET_KEY}" -upgrade
19+
- tofu apply -auto-approve
20+
env:
21+
AWS_ACCESS_KEY_ID:
22+
sh: echo "${STATE_BUCKET_ACCESS_KEY}"
23+
AWS_SECRET_ACCESS_KEY:
24+
sh: echo "${STATE_BUCKET_SECRET_KEY}"
25+
TF_VAR_hcloud_token:
26+
sh: echo "${HCLOUD_TOKEN}"
27+
28+
delete:
29+
desc: Destroy all resources
30+
dir: infra/
31+
cmds:
32+
- cmd: tofu state rm 'module.kubernetes.talos_machine_configuration_apply.worker'
33+
ignore_error: true
34+
- cmd: tofu state rm 'module.kubernetes.talos_machine_configuration_apply.control_plane'
35+
ignore_error: true
36+
- cmd: tofu state rm 'module.kubernetes.talos_machine_secrets.this'
37+
ignore_error: true
38+
- cmd: tofu destroy -auto-approve
39+
- cmd: rm -rf terraform terraform.lock.hcl ../.kubeconfig ../.kubeconfig.bak ../.talosconfig ../.talosconfig.bak
40+
env:
41+
AWS_ACCESS_KEY_ID:
42+
sh: echo "${STATE_BUCKET_ACCESS_KEY}"
43+
AWS_SECRET_ACCESS_KEY:
44+
sh: echo "${STATE_BUCKET_SECRET_KEY}"
45+
TF_VAR_hcloud_token:
46+
sh: echo "${HCLOUD_TOKEN}"
47+
48+
validate:
49+
desc: Run syntax and linting checks
50+
cmds:
51+
- cmd: tflint --chdir infra/
52+
53+
recreate:
54+
desc: Recreate all resources
55+
cmds:
56+
- task: delete
57+
- task: create

infra/backend.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
terraform {
2+
backend "s3" {
3+
region = "us-east-1" # Required but not used by Hetzner
4+
endpoints = { s3 = "https://fsn1.your-objectstorage.com" } # Falkenstein region
5+
use_path_style = true
6+
skip_credentials_validation = true
7+
skip_region_validation = true
8+
skip_requesting_account_id = true
9+
skip_metadata_api_check = true
10+
}
11+
}

infra/main.tf

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module "kubernetes" {
2+
source = "hcloud-k8s/kubernetes/hcloud"
3+
version = "3.26.1"
4+
5+
# General configuration
6+
cluster_name = "platform"
7+
hcloud_token = var.hcloud_token
8+
9+
cluster_delete_protection = false
10+
11+
# Export configs for talosctl and kubectl
12+
cluster_kubeconfig_path = var.kubernetes_config_path
13+
cluster_talosconfig_path = var.talos_config_path
14+
15+
# Firewall configuration
16+
firewall_use_current_ipv4 = true
17+
18+
# Enable Cilium Gateway API and Cert Manager
19+
cert_manager_enabled = true
20+
cilium_gateway_api_enabled = true
21+
22+
control_plane_nodepools = [
23+
{ name = "control", type = "cx23", location = "fsn1", count = 1 }
24+
]
25+
worker_nodepools = [
26+
{ name = "worker", type = "cx33", location = "fsn1", count = 2 }
27+
]
28+
}
29+
30+
# Setup Cloudijs System
31+
module "cloudijs-system" {
32+
depends_on = [module.kubernetes]
33+
source = "./modules/cloudijs-system"
34+
35+
namespace = var.system_namespace
36+
repository_url = var.repository_url
37+
repository_ref = var.repository_ref
38+
repository_path = var.repository_path
39+
}

infra/manifests/issuer.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: cert-manager.io/v1
2+
kind: ClusterIssuer
3+
metadata:
4+
name: http-issuer
5+
spec:
6+
acme:
7+
server: https://acme-v02.api.letsencrypt.org/directory
8+
privateKeySecretRef:
9+
name: http-issuer-account-key
10+
solvers:
11+
- http01:
12+
ingress:
13+
ingressClassName: nginx
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Create namespace for Cloudijs system deployments
2+
resource "kubernetes_namespace_v1" "platform_system" {
3+
metadata {
4+
name = var.namespace
5+
}
6+
}
7+
8+
# Deploy and configure Flux Operator
9+
resource "helm_release" "flux_operator" {
10+
depends_on = [kubernetes_namespace_v1.platform_system]
11+
12+
name = "flux-operator"
13+
namespace = var.namespace
14+
repository = "oci://ghcr.io/controlplaneio-fluxcd/charts"
15+
chart = "flux-operator"
16+
}
17+
18+
resource "helm_release" "flux_instance" {
19+
depends_on = [helm_release.flux_operator]
20+
21+
name = "flux"
22+
namespace = var.namespace
23+
repository = "oci://ghcr.io/controlplaneio-fluxcd/charts"
24+
chart = "flux-instance"
25+
26+
set = [
27+
{
28+
name = "instance.sync.kind"
29+
value = "GitRepository"
30+
},
31+
{
32+
name = "instance.sync.url"
33+
value = var.repository_url
34+
},
35+
{
36+
name = "instance.sync.ref"
37+
value = var.repository_ref
38+
},
39+
{
40+
name = "instance.sync.path"
41+
value = var.repository_path
42+
}
43+
]
44+
}

0 commit comments

Comments
 (0)