Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Ignore terraform files
.terraform
*.tfvars
*tfstate*

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
45 changes: 45 additions & 0 deletions infrastructure/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 72 additions & 0 deletions infrastructure/compose-app/cloud-init.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#cloud-config

# Upgrade on first boot
package_update: true
package_upgrade: true

# Add baseline packages
packages:
- git

write_files:
# Setup the reconciliation data (systemd)
- path: /etc/systemd/system/reconcile.service
permissions: '0644'
content: |
[Unit]
Description=Run reconciliation script

[Service]
Type=oneshot
ExecStart=/usr/local/bin/reconcile.sh

- path: /etc/systemd/system/reconcile.timer
permissions: '0644'
content: |
[Unit]
Description=Timer for reconciliation script

[Timer]
OnBootSec=${boot_delay}
OnUnitActiveSec=${reconciliation_intervall}
Persistent=true

[Install]
WantedBy=timers.target

- path: /usr/local/bin/reconcile.sh
permissions: '0755'
content: |
${indented_reconciliation_script}

runcmd:
# Add Docker's official GPG key
- install -m 0755 -d /etc/apt/keyrings
- curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- chmod a+r /etc/apt/keyrings/docker.gpg

# Add Docker's official repository
- |
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" \
> /etc/apt/sources.list.d/docker.list

# Update package index and install Docker components
- apt-get update
# - apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Ensure docker is running
- systemctl enable docker
- systemctl start docker

# Create GitOps repo dir
- mkdir -p /srv/gitops

# Setup the reconciliation service
- chmod +x /usr/local/bin/reconcile.sh
- systemctl daemon-reload
- systemctl enable reconcile.timer
- systemctl start reconcile.timer
12 changes: 12 additions & 0 deletions infrastructure/compose-app/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
output "info" {
description = "Compose application description"
value = hcloud_server.server
}

output "cloud_init" {
value = local.cloud_init
}

output "reconciliation_script" {
value = local.reconciliation_script
}
16 changes: 16 additions & 0 deletions infrastructure/compose-app/reconciliation-script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
set -e

REPO_DIR="/srv/gitops/repo"
COMPOSE_FILE="$REPO_DIR/${compose_path}"

if [ ! -d "$REPO_DIR/.git" ]; then
echo "[INFO] Initial clone of repo..."
git clone --branch "${branch}" "${git_remote}" "$REPO_DIR"
else
echo "[INFO] Updating existing repo..."
git -C "$REPO_DIR" pull
fi

docker compose --file "$COMPOSE_FILE" pull
docker compose --file "$COMPOSE_FILE" up --detach --remove-orphans
31 changes: 31 additions & 0 deletions infrastructure/compose-app/server.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
locals {
reconciliation_script = templatefile("${path.module}/reconciliation-script.sh", {
git_remote = var.source_repository
branch = var.branch
compose_path = var.compose_path
})

cloud_init = templatefile("${path.module}/cloud-init.yaml", {
boot_delay = "2min"
reconciliation_intervall = var.reconciliation_interval
indented_reconciliation_script = indent(6, local.reconciliation_script)
})
}

resource "hcloud_server" "server" {
name = "compose-app"

server_type = var.server_type
datacenter = var.datacenter

labels = {
app = "compose-app"
interval = var.reconciliation_interval
}

image = "debian-12"

user_data = local.cloud_init

ssh_keys = var.ssh_key != null ? [var.ssh_key.id] : [] # HCL ternary syntax
}
34 changes: 34 additions & 0 deletions infrastructure/compose-app/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
variable "server_type" {
description = "The architecture and size of the server. See Hetzner server type lists for valid values."
type = string
}

variable "datacenter" {
description = "The datacenter to use. See Hetzners location for valid values."
type = string
}

variable "source_repository" {
description = "Git repository to use as source for application."
type = string
}

variable "branch" {
description = "The branch to target."
type = string
}

variable "compose_path" {
description = "Path to the compose file."
type = string
}

variable "reconciliation_interval" {
description = "Interval between reconciliation attempts."
type = string
}

variable "ssh_key" {
description = "Optional SSH key reference on Hetzner. You need to upload this yourself."
default = null
}
8 changes: 8 additions & 0 deletions infrastructure/compose-app/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "1.50.0"
}
}
}
35 changes: 35 additions & 0 deletions infrastructure/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
variable "debug_key" {
description = "Public SSH key for debugging. Optional."
type = string
default = null
}

resource "hcloud_ssh_key" "debug_key" {
name = "compose-app-ssh-key"
# Associated Id stored in /secrets/debug_key
public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAaB/mzskgoQF0xcRY79l9FbIzVwK7Vqgowaxk5klJf8"
}

module "gitops_lite" {
source = "./compose-app"

# Hardware configuration
server_type = "cpx31" # Hetzner Machine type -> arch=x86, cores=4vCPU, ram=8GB, hdd=160GB
datacenter = "hel1-dc2" # Helsinki

# Application configuration
source_repository = "https://github.com/jaurund/learning-project-for-RESTAPI-OAuth-SQL-Container.git"
branch = "main"
compose_path = "docker-compose.yaml"
reconciliation_interval = "1min"

# DEVELOPMENT ONLY
ssh_key = hcloud_ssh_key.debug_key
}

output "compose_app" {
value = {
ipv4_address = module.gitops_lite.info.ipv4_address
ipv6_address = module.gitops_lite.info.ipv6_address
}
}
18 changes: 18 additions & 0 deletions infrastructure/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "1.50.0"
}
}
}

provider "hcloud" {
token = var.hetzner_token
}

variable "hetzner_token" {
description = "Hetzner API token"
type = string
sensitive = true
}