Add healthchecksio provider and refactor ip-for-host collection

This commit is contained in:
Tobias Reisinger 2024-10-06 17:08:25 +02:00
parent ed51a86935
commit 6fdfd338a1
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
14 changed files with 147 additions and 49 deletions

View file

@ -136,6 +136,24 @@ provider "registry.opentofu.org/hetznercloud/hcloud" {
]
}
provider "registry.opentofu.org/kristofferahl/healthchecksio" {
version = "1.6.3"
constraints = "~> 1.6.0"
hashes = [
"h1:UG8BANZc208Tjw/Byraf+1W7waDCusGmolAxeiGZ9eQ=",
"zh:12cd30c19472bcecbd81f9fb6555f055d8a665477a1b2aadd20a9d43b95df0cf",
"zh:174bbe2e2f49132fb4fb9c2b5abaa5743ba49c29f970daae32b7774c8eb259fd",
"zh:214c06082f93bbd11919f73e5bdded8f916c990a2c2c46103c827e070120a6ea",
"zh:21db5fa48fc61cd88e72d34414063e15d99677d871bdb4d231800c8f7daf6bc1",
"zh:39b8d77b8849b3bdd0167ecd465d1980dd42bc1f3cbb9136c9cf8281d36d446a",
"zh:5b81782d766a41272767b6804520eb8d07e82986f5d90818b3f000b26e4efdf2",
"zh:8c045b836f4e6d86518f12c4b113db43715bad412f7f3cde7afbcc87a21bbfe1",
"zh:9c3c6cedd21298d78c93c8a76d8a144a519664bd9def34c5b4a830f2aeeabe6d",
"zh:9f1e6a1aba1d21b90c6bf4520c4b5b5d2fce20bd988852a6429acbc6365fa151",
"zh:a5d15ed31ac4bc194bc7a32e96e902d7b322ab032c1637c67b16dbee968d1fae",
]
}
provider "registry.opentofu.org/ovh/ovh" {
version = "0.48.0"
constraints = "~> 0.48.0"

View file

@ -22,12 +22,17 @@ PWD := $(shell pwd)
| yq -y '{opentofu: with_entries(.value |= .value)}' \
> ./inventory/group_vars/all/opentofu.yaml
outputs: ./dns/hosts.json ./dns/services.json ./inventory/group_vars/all/opentofu.yaml
output: ./dns/hosts.json ./dns/services.json ./inventory/group_vars/all/opentofu.yaml
./types-dnscontrol.d.ts:
dnscontrol write-types
tofu:
tofu apply
echo "\n=====\n"
$(MAKE) output
dns: ./types-dnscontrol.d.ts ./dns/hosts.json ./dns/services.json
dnscontrol push

View file

@ -8,38 +8,28 @@ all:
local-dev:
ansible_connection: local
node001:
ansible_host: node001.vpn.serguzim.net
ansible_port: "{{ vault_node001.ansible_port }}"
ansible_user: "{{ vault_node001.ansible_user }}"
interactive_user: "{{ vault_node001.interactive_user }}"
host_vpn:
domain: node001.vpn.serguzim.net
ip: 100.64.0.1
host_backup:
hc_uid: "{{ vault_node001.backup.hc_uid }}"
uptime_kuma_token: "{{ vault_node001.backup.uptime_kuma_token }}"
node002:
ansible_host: node002.vpn.serguzim.net
ansible_host: "{{ opentofu.hosts.node002.fqdn_vpn }}"
ansible_port: "{{ vault_node002.ansible_port }}"
ansible_user: "{{ vault_node002.ansible_user }}"
interactive_user: "{{ vault_node002.interactive_user }}"
host_vpn:
domain: node002.vpn.serguzim.net
ip: 100.64.0.2
domain: "{{ opentofu.hosts.node002.fqdn_vpn }}"
ip: "{{ opentofu.hosts.node002.ipv4_address_vpn }}"
host_backup:
hc_uid: "{{ vault_node002.backup.hc_uid }}"
hc_uid: "{{ opentofu.healthchecksio.backup.node002.id }}"
hc_url: "{{ opentofu.healthchecksio.backup.node002.ping_url }}"
uptime_kuma_token: "{{ vault_node002.backup.uptime_kuma_token }}"
node003:
ansible_host: node003.vpn.serguzim.net
ansible_host: "{{ opentofu.hosts.node003.fqdn_vpn }}"
ansible_port: "{{ vault_node003.ansible_port }}"
ansible_user: "{{ vault_node003.ansible_user }}"
interactive_user: "{{ vault_node003.interactive_user }}"
host_vpn:
domain: node003.vpn.serguzim.net
ip: 100.110.16.30
domain: "{{ opentofu.hosts.node003.fqdn_vpn }}"
ip: "{{ opentofu.hosts.node003.ipv4_address_vpn }}"
host_backup:
hc_uid: "{{ vault_node003.backup.hc_uid }}"
hc_uid: "{{ opentofu.healthchecksio.backup.node003.id }}"
hc_url: "{{ opentofu.healthchecksio.backup.node003.ping_url }}"
uptime_kuma_token: "{{ vault_node003.backup.uptime_kuma_token }}"

View file

@ -42,6 +42,8 @@ module "infrastructure" {
hcloud_token = var.hcloud_token
healthchecksio_api_key = var.healthchecksio_api_key
ovh_application_key = var.ovh_application_key
ovh_application_secret = var.ovh_application_secret
ovh_consumer_key = var.ovh_consumer_key

View file

@ -0,0 +1,32 @@
data "healthchecksio_channel" "email" {
kind = "email"
}
data "healthchecksio_channel" "signal" {
kind = "signal"
}
data "healthchecksio_channel" "ntfy" {
kind = "ntfy"
}
resource "healthchecksio_check" "backup" {
for_each = var.hosts
name = "backup@${each.value.hostname}"
desc = "A check for the backup on ${each.value.hostname}"
tags = [
"backup",
each.value.hostname,
]
channels = [
data.healthchecksio_channel.email.id,
data.healthchecksio_channel.signal.id,
data.healthchecksio_channel.ntfy.id,
]
timeout = 86400
grace = 1800
}

View file

@ -8,6 +8,10 @@ terraform {
source = "hetznercloud/hcloud"
version = "~> 1.45.0"
}
healthchecksio = {
source = "kristofferahl/healthchecksio"
version = "~> 1.6.0"
}
ovh = {
source = "ovh/ovh"
version = "~> 0.48.0"
@ -34,6 +38,10 @@ provider "hcloud" {
token = var.hcloud_token
}
provider "healthchecksio" {
api_key = var.healthchecksio_api_key
}
provider "ovh" {
endpoint = "ovh-eu"
application_key = var.ovh_application_key

View file

@ -1,17 +1,38 @@
output "hosts" {
value = {
for subdomain in distinct([for record in ovh_domain_zone_record.server_records : record.subdomain]) :
subdomain => {
"hostname" = subdomain
"fqdn" = "${subdomain}.${ovh_domain_zone_record.server_records["${subdomain}:ipv4"].zone}"
for key, host in var.hosts :
key => {
"hostname" = host.hostname
"fqdn" = "${host.hostname}.serguzim.net"
"fqdn_vpn" = "${host.hostname}.vpn.serguzim.net"
"ipv4_address" = try(
ovh_domain_zone_record.server_records["${subdomain}:ipv4"].target,
local.server_addresses_separated["${key}:ipv4"].address,
null
)
"ipv6_address" = try(
ovh_domain_zone_record.server_records["${subdomain}:ipv6"].target,
local.server_addresses_separated["${key}:ipv6"].address,
null
)
ipv4_address_vpn = try(
local.tailscale_host_addresses_separated["${key}:ipv4"].address,
null
)
ipv6_address_vpn = try(
local.tailscale_host_addresses_separated["${key}:ipv6"].address,
null
)
}
}
}
output "healthchecksio" {
value = {
backup = {
for key, check in healthchecksio_check.backup : key => {
"id" = check.id
"ping_url" = check.ping_url
}
}
}
}

View file

@ -1,8 +1,9 @@
locals {
server_addresses = flatten([
[
for host in contabo_instance.nodes : [
for key, host in contabo_instance.nodes : [
{
key = key
hostname = host.display_name
ipv4_address = host.ip_config[0].v4[0].ip
ipv6_address = host.ip_config[0].v6[0].ip
@ -10,8 +11,9 @@ locals {
]
],
[
for host in hcloud_server.nodes : [
for key, host in hcloud_server.nodes : [
{
key = key
hostname = host.name
ipv4_address = host.ipv4_address
ipv6_address = host.ipv6_address
@ -20,34 +22,32 @@ locals {
]
])
server_addresses_separated = flatten([
for host in local.server_addresses : [
{
server_addresses_separated = merge([
for host in local.server_addresses : {
"${host.key}:ipv4" = {
hostname = host.hostname
key = "${host.hostname}:ipv4"
address = host.ipv4_address
},
{
"${host.key}:ipv6" = {
hostname = host.hostname
key = "${host.hostname}:ipv6"
address = host.ipv6_address
},
]
])
}
]...)
tailscale_host_addresses = flatten([
for host in data.tailscale_devices.nodes.devices : [
for index, address in host.addresses : {
hostname = host.hostname
key = "${host.hostname}:${index}"
address = address
}
]
])
tailscale_host_addresses_separated = merge([
for host in data.tailscale_devices.nodes.devices : {
for address in host.addresses :
"${host.hostname}:${strcontains(address, ":") ? "ipv6" : "ipv4"}" => {
hostname = host.hostname
address = address
}
}
]...)
}
resource "ovh_domain_zone_record" "server_records" {
for_each = { for entry in local.server_addresses_separated: entry.key => entry }
for_each = local.server_addresses_separated
zone = "serguzim.net"
subdomain = each.value.hostname
fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A"
@ -56,7 +56,7 @@ resource "ovh_domain_zone_record" "server_records" {
}
resource "ovh_domain_zone_record" "tailscale_vpn" {
for_each = { for entry in local.tailscale_host_addresses: entry.key => entry }
for_each = local.tailscale_host_addresses_separated
zone = "serguzim.net"
subdomain = "${each.value.hostname}.vpn"
fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A"

View file

@ -9,3 +9,9 @@ resource "tailscale_tailnet_key" "cloud_init_key" {
data "tailscale_devices" "nodes" {
name_prefix = "node"
}
locals {
tailscale_devices = {
for host in data.tailscale_devices.nodes.devices : host.hostname => host
}
}

View file

@ -20,6 +20,11 @@ variable "hcloud_token" {
}
variable "healthchecksio_api_key" {
sensitive = true
}
variable "ovh_application_key" {
sensitive = true
}

View file

@ -7,6 +7,10 @@ output "authentik_data" {
sensitive = true
}
output "healthchecksio" {
value = module.infrastructure.healthchecksio
}
output "postgresql_data" {
value = module.services.postgresql_data
sensitive = true

View file

@ -13,7 +13,7 @@ backup_msg_success: "Backup successful"
backup_curl_base: 'curl -L -m 10 --retry 5'
backup_hc_curl_base: '{{ backup_curl_base }} -X POST -H "Content-Type: text/plain"'
backup_uk_curl_base: '{{ backup_curl_base }}'
backup_hc_url: 'https://hc-ping.com/{{ host_backup.hc_uid }}'
backup_hc_url: '{{ host_backup.hc_url }}'
backup_uk_url: 'https://status.serguzim.me/api/push/{{ host_backup.uptime_kuma_token }}'
backup_hc_command_start: '{{ backup_hc_curl_base }} --data "{{ backup_msg_start }}" {{ backup_hc_url }}/start'

View file

@ -14,6 +14,8 @@ contabo_pass = ""
hcloud_token = ""
healthchecksio_api_key = ""
ovh_application_key = ""
ovh_application_secret = ""
ovh_consumer_key = ""

View file

@ -50,6 +50,11 @@ variable "hcloud_token" {
}
variable "healthchecksio_api_key" {
sensitive = true
}
variable "ovh_application_key" {
sensitive = true
}