diff --git a/.gitignore b/.gitignore index d26fb67..1aa2f02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ *.secret *_secrets.env jafner-net/config/ddns/ddclient/ddclient.conf +service-key.json +.terraform/ +.terraform.lock.hcl \ No newline at end of file diff --git a/terraform/applications/main.tf b/terraform/applications/main.tf new file mode 100644 index 0000000..e69cb76 --- /dev/null +++ b/terraform/applications/main.tf @@ -0,0 +1,7 @@ +module "traefik" { + source = "./traefik" +} + +module "uptime-kuma" { + source = "./uptime-kuma" +} \ No newline at end of file diff --git a/terraform/applications/providers.tf b/terraform/applications/providers.tf new file mode 100644 index 0000000..57dd24a --- /dev/null +++ b/terraform/applications/providers.tf @@ -0,0 +1,31 @@ +terraform { + required_providers { + docker = { + source = "kreuzwerker/docker" + version = "3.0.2" + } + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 4.0" + } + } +} + +data "terraform_remote_state" "infrastructure" { + backend = "local" + config = { + path = "../infrastructure/terraform.tfstate" + } +} + +provider "docker" { + host = "ssh://root@${data.terraform_remote_state.infrastructure.outputs.birch-address}:22" + ssh_opts = ["-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"] +} + +provider "cloudflare" { + api_token = var.cloudflare_api_token +} + +variable "cloudflare_api_token" { +} \ No newline at end of file diff --git a/terraform/applications/traefik/traefik.tf b/terraform/applications/traefik/traefik.tf new file mode 100644 index 0000000..358096c --- /dev/null +++ b/terraform/applications/traefik/traefik.tf @@ -0,0 +1,50 @@ +## NOTE: Before applying, make sure to `touch /root/traefik/acme.json` +# Define the reverse proxy container +resource "docker_container" "traefik" { + image = "traefik:latest" + name = "traefik" + restart = "always" + ports { + internal = 443 + external = 443 + protocol = "tcp" + } + ports { + internal = 80 + external = 80 + protocol = "tcp" + } + volumes { + container_path = "/var/run/docker.sock" + host_path = "/var/run/docker.sock" + read_only = true + } + volumes { + container_path = "/acme.json" + host_path = "/root/traefik/acme.json" + } + upload { + source = "traefik.yaml" # source path with filename + file = "/traefik.yaml" # destination path with filename + } + networks_advanced { + name = "web" + } + connection { + host = ${data.terraform_remote_state.infrastructure.outputs.birch-address} + type = "ssh" + user = "root" + private_key = file(var.private_key) + timeout = "2m" + } + provisioner "remote-exec" { # Using a provisioner is not best practice. See: https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#provisioners-are-a-last-resort + inline = [ + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh ./get-docker.sh" + ] + } +} + +resource "docker_network" "web" { + name = "web" +} \ No newline at end of file diff --git a/terraform/applications/traefik/traefik.yaml b/terraform/applications/traefik/traefik.yaml new file mode 100644 index 0000000..dfca61d --- /dev/null +++ b/terraform/applications/traefik/traefik.yaml @@ -0,0 +1,26 @@ +entryPoints: + web: + address: :80 + http: + redirections: + entryPoint: + to: websecure + scheme: https + websecure: + address: :443 + +certificatesResolvers: + lets-encrypt: + acme: + email: jafner425@gmail.com + storage: acme.json + tlsChallenge: {} + +api: + insecure: true + dashboard: true + +providers: + docker: + watch: true + network: web diff --git a/terraform/applications/uptime-kuma/uptime-kuma.tf b/terraform/applications/uptime-kuma/uptime-kuma.tf new file mode 100644 index 0000000..b962855 --- /dev/null +++ b/terraform/applications/uptime-kuma/uptime-kuma.tf @@ -0,0 +1,35 @@ + +resource "cloudflare_record" "uptime-jafner-tools" { + zone_id = "b30ea6e5a3d8f7e9a0f64f95332635a7" + name = "uptime" + value = "${data.terraform_remote_state.imnotsurewhatthisis.outputs.synthetic-monitor-address}" + type = "A" +} + + + +# Define the application container +resource "docker_container" "uptime_kuma" { + image = "louislam/uptime-kuma:latest" + name = "uptime-kuma" + restart = "always" + volumes { + container_path = "/app/data" + volume_name = "uptime_kuma" + } + networks_advanced { + name = "web" + } + labels { + label = "traefik.http.routers.uptime-kuma.rule" + value = "Host(`uptime.jafner.tools`)" + } + labels { + label = "traefik.http.routers.uptime-kuma.tls.certresolver" + value = "lets-encrypt" + } +} + +resource "docker_volume" "uptime_kuma" { + name = "uptime_kuma" +} \ No newline at end of file diff --git a/terraform/infrastructure/digitalocean/birch.tf b/terraform/infrastructure/digitalocean/birch.tf new file mode 100644 index 0000000..e76a1f2 --- /dev/null +++ b/terraform/infrastructure/digitalocean/birch.tf @@ -0,0 +1,25 @@ +# Provision the host as a Digital Ocean droplet, configure SSH access, run docker install script +resource "digitalocean_droplet" "birch" { + image = "debian-12-x64" + name = "birch" + region = "sfo3" + size = "s-1vcpu-1gb" + ssh_keys = ["04:b4:49:d8:bc:68:73:dd:45:fd:56:1f:d3:ea:37:7a"] + connection { + host = self.ipv4_address + type = "ssh" + user = "root" + private_key = file(var.private_key) + timeout = "2m" + } + provisioner "remote-exec" { # Using a provisioner is not best practice. See: https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#provisioners-are-a-last-resort + inline = [ + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh ./get-docker.sh" + ] + } +} + +output "birch-address" { + value = digitalocean_droplet.birch.ipv4_address +} diff --git a/terraform/infrastructure/digitalocean/cedar.tf b/terraform/infrastructure/digitalocean/cedar.tf new file mode 100644 index 0000000..0ef7ae6 --- /dev/null +++ b/terraform/infrastructure/digitalocean/cedar.tf @@ -0,0 +1,25 @@ +# Provision the host as a Digital Ocean droplet, configure SSH access, run docker install script +resource "digitalocean_droplet" "cedar" { + image = "debian-12-x64" + name = "cedar" + region = "sfo3" + size = "s-1vcpu-1gb" + ssh_keys = ["04:b4:49:d8:bc:68:73:dd:45:fd:56:1f:d3:ea:37:7a"] + connection { + host = self.ipv4_address + type = "ssh" + user = "root" + private_key = file(var.private_key) + timeout = "2m" + } + provisioner "remote-exec" { # Using a provisioner is not best practice. See: https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#provisioners-are-a-last-resort + inline = [ + "curl -fsSL https://get.docker.com -o get-docker.sh", + "sudo sh ./get-docker.sh" + ] + } +} + +output "cedar-address" { + value = digitalocean_droplet.cedar.ipv4_address +} diff --git a/terraform/infrastructure/digitalocean/provider.tf b/terraform/infrastructure/digitalocean/provider.tf new file mode 100644 index 0000000..7ac4ebb --- /dev/null +++ b/terraform/infrastructure/digitalocean/provider.tf @@ -0,0 +1,22 @@ +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "~> 2.0" + } + } +} + +provider "digitalocean" { + token = var.digitalocean_token +} + +variable "digitalocean_token" { + type = string + default = "var.digitalocean_token" +} + +variable "private_key" { + type = string + default = "C:/Users/jafne/.ssh/main_id_rsa" +} diff --git a/terraform/infrastructure/google/fir.tf b/terraform/infrastructure/google/fir.tf new file mode 100644 index 0000000..f5d865c --- /dev/null +++ b/terraform/infrastructure/google/fir.tf @@ -0,0 +1,34 @@ +resource "google_compute_network" "vpc_network" { + name = "forest" +} + +resource "google_service_account" "terraform" { + account_id = "terraform-service-account" + display_name = "terraform" +} + +resource "google_compute_instance" "fir" { + name = "fir" + machine_type = "e2-micro" + zone = "us-west1-c" + + boot_disk { + initialize_params { + image = "debian-cloud/debian-12" + } + } + + // Local SSD disk + scratch_disk { + interface = "SCSI" + } + + network_interface { + network = "forest" + } + + service_account { + email = google_service_account.terraform.email + scopes = ["cloud-platform"] + } +} \ No newline at end of file diff --git a/terraform/infrastructure/google/provider.tf b/terraform/infrastructure/google/provider.tf new file mode 100644 index 0000000..2d06224 --- /dev/null +++ b/terraform/infrastructure/google/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.71.0" + } + } +} + +provider "google" { + credentials = file("./google/service-key.json") + project = "jafner-net-319520" + region = "us-west1" + zone = "us-west1-c" +} + diff --git a/terraform/infrastructure/main.tf b/terraform/infrastructure/main.tf new file mode 100644 index 0000000..fbb9b9a --- /dev/null +++ b/terraform/infrastructure/main.tf @@ -0,0 +1,7 @@ +module "digitalocean" { + source = "./digitalocean" +} + +module "google" { + source = "./google" +} \ No newline at end of file