Add mailcow to terraform

This commit is contained in:
Tobias Reisinger 2024-10-29 22:43:05 +01:00
parent d73462cd90
commit f20b2596d0
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
18 changed files with 135 additions and 35 deletions

View file

@ -28,6 +28,8 @@ TF_VAR_hcloud_token=
TF_VAR_healthchecksio_api_key=
TF_VAR_mailcow_api_key=
TF_VAR_ovh_application_key=
TF_VAR_ovh_application_secret=
TF_VAR_ovh_consumer_key=

View file

@ -69,20 +69,20 @@ provider "registry.opentofu.org/goauthentik/authentik" {
}
provider "registry.opentofu.org/hashicorp/aws" {
version = "5.72.1"
version = "5.73.0"
constraints = "~> 5.0"
hashes = [
"h1:ckDAOn6cqqO2pJ226GYs8gIZif9TRmAuQEqnPL+LCgg=",
"zh:02ee636137e5f8cc9d6900c55a3f3c85e99166b51d17cf96bd62b27182dc7449",
"zh:04877c5ce0a0fef6b355decbfe4941e7d5f22d2b7062cd87f70dafe845d635c7",
"zh:3d129024594dcf2edac180b8276decc946f4f33d653f44d3c04c4c28b3f85dab",
"zh:6fc7ecf746791211d64a38361ce12303dfc3ddf0e609e6d854bc8f3a7f242234",
"zh:8d65352eeba3fef611c90b5161336b0cccf3fed8dc2c710537d6578925e2b189",
"zh:9c99b31104c80d885aad1846e2b2f25371cbc9c23281fb0e213be0101a415f2c",
"zh:b220737d06dc8ef3a6aa32055c1c633d08c27e046b5fb730f93969ef11abb928",
"zh:b741b0e79001765c8d2ffdb569f70c0d8b877b870b660e573f3bb6f42dd55f28",
"zh:d2434f271f261ccd28a85aa15627ee9cfc9c319a48eb6c0aeb1ffaf80b6ede20",
"zh:df4b2338e3e89d66c1697fae9be378db94cb0d7d309c9dc537024cb755b7e21a",
"h1:pQKtkpKb4hzErmZakSW+HHXeJubUlBKu1/p0C/b1UuI=",
"zh:16a345cb7265937b13f999d644a38c68661844462f5ac7fda33b5aa35d3fdb9f",
"zh:1a28b36980e55c430faf6dfd93744b42fedd455ec53e5d848d89f503b8f7808e",
"zh:4303bc542d832ced373f64f8f154989affebc04704ae55f00b404167a512891d",
"zh:6079983b35df36c0980c6a7eabc17e9697e573ed0359bb07dc8004c40341ee5d",
"zh:711419826ce136e64fa172faffcdd23c25ad47e05a2b55be5deb5ae663ae399a",
"zh:7ac9ddb634dc98040b8db683b9d829c6654bcbd2cb6c15edaa85029780ea9d57",
"zh:8ce89e19e7e1ae84fa9eae98f79dd8654d774daabe2cc73e85d05d2dd00fcd08",
"zh:be420d05ec4d31a3a393c19831da10664a109a5ad527b7043f7a75059d694008",
"zh:c6552f1c4246afd1b8607edc4c29639846a530487c82663c51ddfb998a259eca",
"zh:d5a2a931f83625105c9502398f391165add5a886d950f193fc5721ad18dec273",
]
}
@ -172,6 +172,29 @@ provider "registry.opentofu.org/kristofferahl/healthchecksio" {
]
}
provider "registry.opentofu.org/l-with/mailcow" {
version = "0.7.5"
constraints = "~> 0.7.5"
hashes = [
"h1:gEiN/SOJl+T1V585/Pqk/Y3FkX8+An/M3zbztdEfmWk=",
"zh:0919018dfdab37f86b61dfe2ecd8d4b6a6532983edc6deab9e7f3d5ec1a45375",
"zh:16e513369e37f2d8fab43545940991c3ce2b140bb37c92bc77ec84240235ad26",
"zh:19bcf3660ac7545103cf999e0066442f9d6350db9654e1496726520cef287246",
"zh:1f6d827f5c0a2253550def77d2473bf62b72355930b5d00f59dc1b0af5aff953",
"zh:242d5cb545f1b20be24672e984fb78c27bf21da27c25ccbac8cd8c3142d32d83",
"zh:40a17c3734c330f2d0e11adb377b04d8bf11e799e78f4bacf2797ee589312756",
"zh:475ac6440db8cb80df1e8e5bb475f7dd73548fabd50e60e78e66ccd2e6e63baf",
"zh:48a67a019575ca784275dbcd9f7ee209012c0b311db8b82b91511f7970e1f9d2",
"zh:6dc3f2a073264cf79230811f528d3a916b8753031c0dad80b9999f64aa6951ba",
"zh:71d64c63cb4abca1fc920d694785551dd9ef15b5b601a6682ec647bae4acc881",
"zh:7a7fa7621ac582802329565a010a96114a1c8a5638b8aefe62095bdbefc1c988",
"zh:a11f6332a9d5e2d1ca01a906576d48dcf99e9f75c6e376157e35c24aef1039b9",
"zh:bec618cd75e300a8ae98852a70b1b56cd0c2bc61e4e1b11178029822fffc32b4",
"zh:c8132e507938516f2595a00b1bc19e666fe8a3df0077ca3bbeb9107dacd4fd2d",
"zh:cfff5048bc75345eda1bc6067e4e92c8b7c24d5fdd985fdb5d2e30997d644d15",
]
}
provider "registry.opentofu.org/ovh/ovh" {
version = "0.48.0"
constraints = "~> 0.48.0"

View file

@ -33,6 +33,10 @@ terraform {
source = "goauthentik/authentik"
version = "~> 2024.8.0"
}
mailcow = {
source = "l-with/mailcow"
version = "~> 0.7.5"
}
postgresql = {
source = "cyrilgdn/postgresql"
version = "~> 1.23.0"
@ -132,6 +136,11 @@ provider "authentik" {
token = var.authentik_token
}
provider "mailcow" {
host_name = var.mailcow_host_name
api_key = var.mailcow_api_key
}
provider "postgresql" {
host = var.postgresql_host
port = var.postgresql_port

View file

@ -0,0 +1,17 @@
resource "random_password" "mailcow_service_passwords" {
for_each = local.services_mail
length = 32
special = false
}
resource "mailcow_mailbox" "services" {
for_each = local.services_mail
domain = "serguzim.me"
full_name = each.value.mail
local_part = each.value.mail
password = random_password.mailcow_service_passwords[each.key].result
imap_access = false
pop3_access = false
sogo_access = false
quota = 128
}

View file

@ -4,6 +4,10 @@ terraform {
source = "goauthentik/authentik"
version = "~> 2024.8.0"
}
mailcow = {
source = "l-with/mailcow"
version = "~> 0.7.5"
}
postgresql = {
source = "cyrilgdn/postgresql"
version = "~> 1.23.0"
@ -15,4 +19,5 @@ locals {
services_auth = {for key, val in var.services : key => val if val.auth}
services_database = {for key, val in var.services : key => val if val.database}
services_s3 = {for key, val in var.services : key => val if val.s3}
services_mail = {for key, val in var.services : key => val if val.mail != null}
}

View file

@ -19,3 +19,13 @@ output "postgresql_data" {
}
sensitive = true
}
output "mailcow_data" {
value = {
for key in keys(mailcow_mailbox.services) : key => {
"address" = mailcow_mailbox.services[key].address
"password" = mailcow_mailbox.services[key].password
}
}
sensitive = true
}

View file

@ -18,5 +18,6 @@ variable "services" {
auth_redirects = optional(list(string))
s3 = bool
database = bool
mail = optional(string)
}))
}

View file

@ -17,6 +17,11 @@ output "healthchecksio" {
sensitive = true
}
output "mailcow_data" {
value = module.services.mailcow_data
sensitive = true
}
output "postgresql_data" {
value = module.services.postgresql_data
sensitive = true

View file

@ -14,12 +14,12 @@ authentik_env:
AUTHENTIK_EMAIL__HOST: "{{ mailer.host }}"
AUTHENTIK_EMAIL__PORT: "{{ mailer.port }}"
AUTHENTIK_EMAIL__USERNAME: "{{ vault_authentik.mail.user }}"
AUTHENTIK_EMAIL__PASSWORD: "{{ vault_authentik.mail.pass }}"
AUTHENTIK_EMAIL__USERNAME: "{{ opentofu.mailcow_data.authentik.address }}"
AUTHENTIK_EMAIL__PASSWORD: "{{ opentofu.mailcow_data.authentik.password }}"
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: false
AUTHENTIK_EMAIL__TIMEOUT: 10
AUTHENTIK_EMAIL__FROM: auth@serguzim.me
AUTHENTIK_EMAIL__FROM: "{{ opentofu.mailcow_data.authentik.address }}"
AUTHENTIK_AVATARS: none

View file

@ -51,11 +51,11 @@ forgejo_env:
FORGEJO__mailer__ENABLED: true
FORGEJO__mailer__PROTOCOL: smtp+starttls
FORGEJO__mailer__SMTP_ADDR: mail.serguzim.me
FORGEJO__mailer__SMTP_PORT: 587
FORGEJO__mailer__FROM: Forgejo <git@serguzim.me>
FORGEJO__mailer__USER: git@serguzim.me
FORGEJO__mailer__PASSWD: "{{ vault_forgejo.mailer_passwd }}"
FORGEJO__mailer__SMTP_ADDR: "{{ mailer.host }}"
FORGEJO__mailer__SMTP_PORT: "{{ mailer.post }}"
FORGEJO__mailer__FROM: "git <{{ opentofu.mailcow_data.forgejo.address }}>"
FORGEJO__mailer__USER: "{{ opentofu.mailcow_data.forgejo.address }}"
FORGEJO__mailer__PASSWD: "{{ opentofu.mailcow_data.forgejo.password }}"
FORGEJO__mailer__SEND_AS_PLAIN_TEXT: true
FORGEJO__picture__DISABLE_GRAVATAR: true

View file

@ -5,11 +5,11 @@ homebox_svc:
homebox_env:
HBOX_OPTIONS_ALLOW_REGISTRATION: false
HBOX_MAILER_HOST: mail.serguzim.me
HBOX_MAILER_PORT: 587
HBOX_MAILER_USERNAME: inventory@serguzim.me
HBOX_MAILER_PASSWORD: "{{ vault_homebox.mailer_passwd }}"
HBOX_MAILER_FROM: Homebox <inventory@serguzim.me>
HBOX_MAILER_HOST: "{{ mailer.host }}"
HBOX_MAILER_PORT: "{{ mailer.port }}"
HBOX_MAILER_USERNAME: "{{ opentofu.mailcow_data.homebox.address }}"
HBOX_MAILER_PASSWORD: "{{ opentofu.mailcow_data.homebox.password }}"
HBOX_MAILER_FROM: "homebox <{{ opentofu.mailcow_data.homebox.address }}>"
HBOX_SWAGGER_SCHEMA: https
homebox_compose:

View file

@ -92,10 +92,10 @@ synapse_yml:
email:
smtp_host: mail.serguzim.me
smtp_port: 587
smtp_user: matrix@serguzim.me
smtp_pass: "{{ vault_synapse.mail.pass }}"
smtp_user: "{{ opentofu.mailcow_data.synapse.address }}"
smtp_pass: "{{ opentofu.mailcow_data.synapse.password }}"
require_transport_security: true
notif_from: Matrix <matrix@serguzim.me>
notif_from: "matrix <{{ opentofu.mailcow_data.synapse.address }}>"
synapse_compose:
watchtower: true

View file

@ -28,9 +28,9 @@ vikunja_yml:
enabled: true
host: "{{ mailer.host }}"
port: "{{ mailer.port }}"
username: "{{ vault_vikunja.mailer.user }}"
password: "{{ vault_vikunja.mailer.pass }}"
fromemail: "{{ vault_vikunja.mailer.user }}"
username: "{{ opentofu.mailcow_data.vikunja.address }}"
password: "{{ opentofu.mailcow_data.vikunja.password }}"
fromemail: "{{ opentofu.mailcow_data.vikunja.address }}"
auth:
local:

View file

@ -8,12 +8,12 @@ watchtower_env:
# WATCHTOWER_NO_PULL: true
WATCHTOWER_NOTIFICATIONS: email
WATCHTOWER_NOTIFICATION_EMAIL_FROM: "watchtower@serguzim.me"
WATCHTOWER_NOTIFICATION_EMAIL_FROM: "{{ opentofu.mailcow_data.watchtower.address }}"
WATCHTOWER_NOTIFICATION_EMAIL_TO: "{{ admin_email }}"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER: "{{ mailer.host }}"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: "{{ mailer.port }}"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: "watchtower@serguzim.me"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: "{{ vault_watchtower.mailer.pass }}"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: "{{ opentofu.mailcow_data.watchtower.address }}"
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: "{{ opentofu.mailcow_data.watchtower.password }}"
WATCHTOWER_NOTIFICATION_EMAIL_DELAY: 5
watchtower_compose:

View file

@ -26,6 +26,7 @@ services = {
auth = false
database = true
s3 = false
mail = "auth"
},
"backup" = {
@ -119,6 +120,7 @@ services = {
auth_redirects = ["https://git.serguzim.me/user/oauth2/auth.serguzim.me/callback"]
database = true
s3 = true
mail = "git"
},
"forgejo_runner" = {
@ -148,6 +150,7 @@ services = {
auth_redirects = ["https://status.serguzim.me/authorization-code/callback"]
database = false
s3 = false
mail = "status"
},
"homebox" = {
@ -170,6 +173,7 @@ services = {
auth = false
database = false
s3 = false
mail = "inventory"
},
"immich" = {
@ -436,6 +440,7 @@ services = {
auth_redirects = ["https://matrix.serguzim.me/_synapse/client/oidc/callback"]
database = true
s3 = false
mail = "matrix"
},
"tandoor" = {
@ -532,6 +537,7 @@ services = {
auth_redirects = ["https://todo.serguzim.me/auth/openid/authserguzimme"]
database = true
s3 = false
mail = "todo"
},
"watchtower" = {
@ -539,6 +545,7 @@ services = {
auth = false
database = false
s3 = false
mail = "watchtower"
},
"wiki_js" = {
@ -553,6 +560,7 @@ services = {
auth_redirects = ["https://wiki.serguzim.me/login/f792bc7d-1a25-4437-944e-55eaf0111102/callback"]
database = true
s3 = false
mail = "wiki"
},
"woodpecker" = {

View file

@ -74,6 +74,13 @@ external: {
external.scaleway.s3.{{ svc.name }}
{% endif %}
{% if svc.mail %}
{{ svc.key }} -> {{ mail_key }}: {
style.stroke: "#C9B81F"
}
{{ mail_key }}.{{ svc.name }}
{% endif %}
{% endfor %}{# svc #}
{% for svc in grid_svcs %}

View file

@ -72,6 +72,15 @@ variable "healthchecksio_api_key" {
}
variable "mailcow_host_name" {
default = "mail.serguzim.me"
}
variable "mailcow_api_key" {
sensitive = true
}
variable "ovh_application_key" {
sensitive = true
}
@ -169,6 +178,7 @@ variable "services" {
auth_redirects = optional(list(string))
s3 = bool
database = bool
mail = optional(string)
}))
}

View file

@ -63,6 +63,7 @@ def parse_service(svc, data, hosts):
for dns in data.get("dns") or []:
domains.append(f"- {dns['domain']}")
data['name'] = svc
data['key'] = svc_key
data['host_key'] = host_key(data["host"], hosts)
data['label'] = "\\n".join([svc] + domains)
@ -98,15 +99,17 @@ if __name__ == '__main__':
db_key = service_key_find("postgresql", services, hosts)
auth_key = service_key_find("authentik", services, hosts)
monitoring_key = service_key_find("gatus", services, hosts)
mail_key = service_key_find("mailcowdockerized", services, hosts)
jinja_loader = jinja2.FileSystemLoader(searchpath="./templates")
jinja_env = jinja2.Environment(loader=jinja_loader)
template = jinja_env.get_template("infrastructure.d2.j2")
print(template.render(
grid_svcs=[db_key, auth_key],
grid_svcs=[db_key, auth_key, mail_key],
svcs=parse_services(services, hosts),
hosts=parse_hosts(hosts),
db_key=db_key,
auth_key=auth_key,
monitoring_key=monitoring_key,
mail_key=mail_key,
))