Add healthchecksio provider and refactor ip-for-host collection
This commit is contained in:
parent
ed51a86935
commit
6fdfd338a1
14 changed files with 147 additions and 49 deletions
|
@ -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" {
|
provider "registry.opentofu.org/ovh/ovh" {
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
constraints = "~> 0.48.0"
|
constraints = "~> 0.48.0"
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -22,12 +22,17 @@ PWD := $(shell pwd)
|
||||||
| yq -y '{opentofu: with_entries(.value |= .value)}' \
|
| yq -y '{opentofu: with_entries(.value |= .value)}' \
|
||||||
> ./inventory/group_vars/all/opentofu.yaml
|
> ./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:
|
./types-dnscontrol.d.ts:
|
||||||
dnscontrol write-types
|
dnscontrol write-types
|
||||||
|
|
||||||
|
tofu:
|
||||||
|
tofu apply
|
||||||
|
echo "\n=====\n"
|
||||||
|
$(MAKE) output
|
||||||
|
|
||||||
dns: ./types-dnscontrol.d.ts ./dns/hosts.json ./dns/services.json
|
dns: ./types-dnscontrol.d.ts ./dns/hosts.json ./dns/services.json
|
||||||
dnscontrol push
|
dnscontrol push
|
||||||
|
|
||||||
|
|
|
@ -8,38 +8,28 @@ all:
|
||||||
local-dev:
|
local-dev:
|
||||||
ansible_connection: local
|
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:
|
node002:
|
||||||
ansible_host: node002.vpn.serguzim.net
|
ansible_host: "{{ opentofu.hosts.node002.fqdn_vpn }}"
|
||||||
ansible_port: "{{ vault_node002.ansible_port }}"
|
ansible_port: "{{ vault_node002.ansible_port }}"
|
||||||
ansible_user: "{{ vault_node002.ansible_user }}"
|
ansible_user: "{{ vault_node002.ansible_user }}"
|
||||||
interactive_user: "{{ vault_node002.interactive_user }}"
|
interactive_user: "{{ vault_node002.interactive_user }}"
|
||||||
host_vpn:
|
host_vpn:
|
||||||
domain: node002.vpn.serguzim.net
|
domain: "{{ opentofu.hosts.node002.fqdn_vpn }}"
|
||||||
ip: 100.64.0.2
|
ip: "{{ opentofu.hosts.node002.ipv4_address_vpn }}"
|
||||||
host_backup:
|
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 }}"
|
uptime_kuma_token: "{{ vault_node002.backup.uptime_kuma_token }}"
|
||||||
|
|
||||||
node003:
|
node003:
|
||||||
ansible_host: node003.vpn.serguzim.net
|
ansible_host: "{{ opentofu.hosts.node003.fqdn_vpn }}"
|
||||||
ansible_port: "{{ vault_node003.ansible_port }}"
|
ansible_port: "{{ vault_node003.ansible_port }}"
|
||||||
ansible_user: "{{ vault_node003.ansible_user }}"
|
ansible_user: "{{ vault_node003.ansible_user }}"
|
||||||
interactive_user: "{{ vault_node003.interactive_user }}"
|
interactive_user: "{{ vault_node003.interactive_user }}"
|
||||||
host_vpn:
|
host_vpn:
|
||||||
domain: node003.vpn.serguzim.net
|
domain: "{{ opentofu.hosts.node003.fqdn_vpn }}"
|
||||||
ip: 100.110.16.30
|
ip: "{{ opentofu.hosts.node003.ipv4_address_vpn }}"
|
||||||
host_backup:
|
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 }}"
|
uptime_kuma_token: "{{ vault_node003.backup.uptime_kuma_token }}"
|
||||||
|
|
2
main.tf
2
main.tf
|
@ -42,6 +42,8 @@ module "infrastructure" {
|
||||||
|
|
||||||
hcloud_token = var.hcloud_token
|
hcloud_token = var.hcloud_token
|
||||||
|
|
||||||
|
healthchecksio_api_key = var.healthchecksio_api_key
|
||||||
|
|
||||||
ovh_application_key = var.ovh_application_key
|
ovh_application_key = var.ovh_application_key
|
||||||
ovh_application_secret = var.ovh_application_secret
|
ovh_application_secret = var.ovh_application_secret
|
||||||
ovh_consumer_key = var.ovh_consumer_key
|
ovh_consumer_key = var.ovh_consumer_key
|
||||||
|
|
32
modules/infrastructure/healthchecksio.tf
Normal file
32
modules/infrastructure/healthchecksio.tf
Normal 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
|
||||||
|
}
|
|
@ -8,6 +8,10 @@ terraform {
|
||||||
source = "hetznercloud/hcloud"
|
source = "hetznercloud/hcloud"
|
||||||
version = "~> 1.45.0"
|
version = "~> 1.45.0"
|
||||||
}
|
}
|
||||||
|
healthchecksio = {
|
||||||
|
source = "kristofferahl/healthchecksio"
|
||||||
|
version = "~> 1.6.0"
|
||||||
|
}
|
||||||
ovh = {
|
ovh = {
|
||||||
source = "ovh/ovh"
|
source = "ovh/ovh"
|
||||||
version = "~> 0.48.0"
|
version = "~> 0.48.0"
|
||||||
|
@ -34,6 +38,10 @@ provider "hcloud" {
|
||||||
token = var.hcloud_token
|
token = var.hcloud_token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
provider "healthchecksio" {
|
||||||
|
api_key = var.healthchecksio_api_key
|
||||||
|
}
|
||||||
|
|
||||||
provider "ovh" {
|
provider "ovh" {
|
||||||
endpoint = "ovh-eu"
|
endpoint = "ovh-eu"
|
||||||
application_key = var.ovh_application_key
|
application_key = var.ovh_application_key
|
||||||
|
|
|
@ -1,17 +1,38 @@
|
||||||
output "hosts" {
|
output "hosts" {
|
||||||
value = {
|
value = {
|
||||||
for subdomain in distinct([for record in ovh_domain_zone_record.server_records : record.subdomain]) :
|
for key, host in var.hosts :
|
||||||
subdomain => {
|
key => {
|
||||||
"hostname" = subdomain
|
"hostname" = host.hostname
|
||||||
"fqdn" = "${subdomain}.${ovh_domain_zone_record.server_records["${subdomain}:ipv4"].zone}"
|
"fqdn" = "${host.hostname}.serguzim.net"
|
||||||
|
"fqdn_vpn" = "${host.hostname}.vpn.serguzim.net"
|
||||||
"ipv4_address" = try(
|
"ipv4_address" = try(
|
||||||
ovh_domain_zone_record.server_records["${subdomain}:ipv4"].target,
|
local.server_addresses_separated["${key}:ipv4"].address,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
"ipv6_address" = try(
|
"ipv6_address" = try(
|
||||||
ovh_domain_zone_record.server_records["${subdomain}:ipv6"].target,
|
local.server_addresses_separated["${key}:ipv6"].address,
|
||||||
null
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
locals {
|
locals {
|
||||||
server_addresses = flatten([
|
server_addresses = flatten([
|
||||||
[
|
[
|
||||||
for host in contabo_instance.nodes : [
|
for key, host in contabo_instance.nodes : [
|
||||||
{
|
{
|
||||||
|
key = key
|
||||||
hostname = host.display_name
|
hostname = host.display_name
|
||||||
ipv4_address = host.ip_config[0].v4[0].ip
|
ipv4_address = host.ip_config[0].v4[0].ip
|
||||||
ipv6_address = host.ip_config[0].v6[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
|
hostname = host.name
|
||||||
ipv4_address = host.ipv4_address
|
ipv4_address = host.ipv4_address
|
||||||
ipv6_address = host.ipv6_address
|
ipv6_address = host.ipv6_address
|
||||||
|
@ -20,34 +22,32 @@ locals {
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
server_addresses_separated = flatten([
|
server_addresses_separated = merge([
|
||||||
for host in local.server_addresses : [
|
for host in local.server_addresses : {
|
||||||
{
|
"${host.key}:ipv4" = {
|
||||||
hostname = host.hostname
|
hostname = host.hostname
|
||||||
key = "${host.hostname}:ipv4"
|
|
||||||
address = host.ipv4_address
|
address = host.ipv4_address
|
||||||
},
|
},
|
||||||
{
|
"${host.key}:ipv6" = {
|
||||||
hostname = host.hostname
|
hostname = host.hostname
|
||||||
key = "${host.hostname}:ipv6"
|
|
||||||
address = host.ipv6_address
|
address = host.ipv6_address
|
||||||
},
|
},
|
||||||
]
|
}
|
||||||
])
|
]...)
|
||||||
|
|
||||||
tailscale_host_addresses = flatten([
|
tailscale_host_addresses_separated = merge([
|
||||||
for host in data.tailscale_devices.nodes.devices : [
|
for host in data.tailscale_devices.nodes.devices : {
|
||||||
for index, address in host.addresses : {
|
for address in host.addresses :
|
||||||
|
"${host.hostname}:${strcontains(address, ":") ? "ipv6" : "ipv4"}" => {
|
||||||
hostname = host.hostname
|
hostname = host.hostname
|
||||||
key = "${host.hostname}:${index}"
|
|
||||||
address = address
|
address = address
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
])
|
]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "ovh_domain_zone_record" "server_records" {
|
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"
|
zone = "serguzim.net"
|
||||||
subdomain = each.value.hostname
|
subdomain = each.value.hostname
|
||||||
fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A"
|
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" {
|
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"
|
zone = "serguzim.net"
|
||||||
subdomain = "${each.value.hostname}.vpn"
|
subdomain = "${each.value.hostname}.vpn"
|
||||||
fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A"
|
fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A"
|
||||||
|
|
|
@ -9,3 +9,9 @@ resource "tailscale_tailnet_key" "cloud_init_key" {
|
||||||
data "tailscale_devices" "nodes" {
|
data "tailscale_devices" "nodes" {
|
||||||
name_prefix = "node"
|
name_prefix = "node"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
tailscale_devices = {
|
||||||
|
for host in data.tailscale_devices.nodes.devices : host.hostname => host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ variable "hcloud_token" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
variable "healthchecksio_api_key" {
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
variable "ovh_application_key" {
|
variable "ovh_application_key" {
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@ output "authentik_data" {
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "healthchecksio" {
|
||||||
|
value = module.infrastructure.healthchecksio
|
||||||
|
}
|
||||||
|
|
||||||
output "postgresql_data" {
|
output "postgresql_data" {
|
||||||
value = module.services.postgresql_data
|
value = module.services.postgresql_data
|
||||||
sensitive = true
|
sensitive = true
|
||||||
|
|
|
@ -13,7 +13,7 @@ backup_msg_success: "Backup successful"
|
||||||
backup_curl_base: 'curl -L -m 10 --retry 5'
|
backup_curl_base: 'curl -L -m 10 --retry 5'
|
||||||
backup_hc_curl_base: '{{ backup_curl_base }} -X POST -H "Content-Type: text/plain"'
|
backup_hc_curl_base: '{{ backup_curl_base }} -X POST -H "Content-Type: text/plain"'
|
||||||
backup_uk_curl_base: '{{ backup_curl_base }}'
|
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_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'
|
backup_hc_command_start: '{{ backup_hc_curl_base }} --data "{{ backup_msg_start }}" {{ backup_hc_url }}/start'
|
||||||
|
|
|
@ -14,6 +14,8 @@ contabo_pass = ""
|
||||||
|
|
||||||
hcloud_token = ""
|
hcloud_token = ""
|
||||||
|
|
||||||
|
healthchecksio_api_key = ""
|
||||||
|
|
||||||
ovh_application_key = ""
|
ovh_application_key = ""
|
||||||
ovh_application_secret = ""
|
ovh_application_secret = ""
|
||||||
ovh_consumer_key = ""
|
ovh_consumer_key = ""
|
||||||
|
|
|
@ -50,6 +50,11 @@ variable "hcloud_token" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
variable "healthchecksio_api_key" {
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
variable "ovh_application_key" {
|
variable "ovh_application_key" {
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue