feat(mail): enhance mail configuration with getmail and dovecot settings
- Added getmail configuration generation using template files. - Introduced postfix and dovecot configuration checksums for deployment. - Created new dovecot configuration file and sieve script for email handling. - Updated main.tf to utilize local variables for configuration management. - Removed redundant external password hasher from main.tf. feat(nginx): improve nginx configuration management - Centralized nginx configuration into a local variable with checksum. - Created separate config maps for default website configurations. - Updated deployment to utilize new configuration structure. feat(sftpgo): add SFTPGo application deployment - Introduced SFTPGo with Kubernetes resources including namespace, config maps, and secrets. - Configured SFTPGo with SMTP settings and AWS credentials. - Implemented health checks and volume mounts for persistent storage. refactor(seafile): remove Seafile module - Deleted Seafile module and associated resources as part of cleanup.
This commit is contained in:
@@ -14,8 +14,8 @@ locals {
|
||||
SSH_LISTEN_PORT = 22
|
||||
GITEA__mailer__ENABLED = true
|
||||
GITEA__mailer__FROM = var.from_email
|
||||
GITEA__mailer__SMTP_ADDR = var.relay_smtp_host
|
||||
GITEA__mailer__SMTP_PORT = var.relay_smtp_port
|
||||
GITEA__mailer__SMTP_ADDR = var.smtp_host
|
||||
GITEA__mailer__SMTP_PORT = var.smtp_port
|
||||
GITEA__mailer__PROTOCOL = "smtps"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
module "gitea_database" {
|
||||
source = "../../db/mariadb"
|
||||
|
||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||
app_name = "gitea"
|
||||
|
||||
app_password = var.db_password
|
||||
root_password = var.db_root_password
|
||||
|
||||
retention_days = var.backup_retention_days
|
||||
cron_schedule = var.backup_cron_schedule
|
||||
|
||||
database_folder = local.gitea_db_path
|
||||
backup_folder = var.backup_folder
|
||||
}
|
||||
@@ -18,28 +18,12 @@ resource "kubernetes_secret" "gitea_mail_credentials" {
|
||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
username = var.relay_smtp_username
|
||||
password = var.relay_smtp_password
|
||||
username = var.smtp_username
|
||||
password = var.smtp_password
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
module "gitea_database" {
|
||||
source = "../../db/mariadb"
|
||||
|
||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||
app_name = "gitea"
|
||||
|
||||
app_password = var.db_password
|
||||
root_password = var.db_root_password
|
||||
|
||||
retention_days = var.backup_retention_days
|
||||
cron_schedule = var.backup_cron_schedule
|
||||
|
||||
database_folder = local.gitea_db_path
|
||||
backup_folder = var.backup_folder
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "gitea_service_account" {
|
||||
|
||||
metadata {
|
||||
|
||||
@@ -51,23 +51,23 @@ variable "app_name" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "relay_smtp_host" {
|
||||
variable "smtp_host" {
|
||||
description = "The SMTP relay host"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "relay_smtp_port" {
|
||||
variable "smtp_port" {
|
||||
description = "The SMTP relay port"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "relay_smtp_username" {
|
||||
variable "smtp_username" {
|
||||
description = "The SMTP relay username"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "relay_smtp_password" {
|
||||
variable "smtp_password" {
|
||||
description = "The SMTP relay password"
|
||||
type = string
|
||||
sensitive = true
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
locals {
|
||||
persistent_folder = var.persistent_folder
|
||||
m3uproxy_version = var.tag
|
||||
m3uproxy_fqdn = var.fqdn
|
||||
wireguard_version = "1.0.20210914-r4-ls54"
|
||||
squid_version = "6.1-23.10_edge"
|
||||
persistent_folder = var.persistent_folder
|
||||
m3uproxy_version = var.tag
|
||||
m3uproxy_fqdn = var.fqdn
|
||||
wireguard_version = "1.0.20210914-r4-ls54"
|
||||
squid_version = "6.1-23.10_edge"
|
||||
|
||||
geoip_image = "maxmindinc/geoipupdate"
|
||||
geoip_version = "latest"
|
||||
geoip_cron_schedule = var.geoip_cron_schedule
|
||||
geoip_editions = var.geoip_editions
|
||||
geoip_path = "${local.m3uproxy_path}/geoip"
|
||||
|
||||
m3uproxy_path = "${local.persistent_folder}/m3uproxy"
|
||||
m3uproxy_cache_path = "${local.m3uproxy_path}/cache"
|
||||
squid_app_path = "${local.m3uproxy_path}/squid"
|
||||
geoip_path = "${local.m3uproxy_path}/geoip"
|
||||
wireguard_address = "192.168.5.3/32"
|
||||
wireguard_dns = "192.168.5.1"
|
||||
wireguard_allowed_ips = [
|
||||
@@ -26,5 +27,22 @@ locals {
|
||||
m3uproxy_config = templatefile("${path.module}/resources/m3uproxy/m3uproxy.json", {
|
||||
m3uproxy_secret = var.secret
|
||||
})
|
||||
m3uproxy_config_checksum = nonsensitive(sha256(local.m3uproxy_config))
|
||||
|
||||
m3uproxy_playlist = file("${path.module}/resources/m3uproxy/playlist.json")
|
||||
m3uproxy_playlist_checksum = sha256(local.m3uproxy_playlist)
|
||||
|
||||
wireguard_config = templatefile("${path.module}/resources/wireguard/wireguard.conf.tpl", {
|
||||
wireguard_private_key = var.wireguard_private_key
|
||||
wireguard_public_key = var.wireguard_public_key
|
||||
wireguard_address = local.wireguard_address
|
||||
wireguard_dns = local.wireguard_dns
|
||||
wireguard_allowed_ips = join(", ", local.wireguard_allowed_ips)
|
||||
wireguard_endpoint = "${local.wireguard_endpoint}:${local.wireguard_endpoint_port}"
|
||||
})
|
||||
wireguard_config_checksum = nonsensitive(sha256(local.wireguard_config))
|
||||
|
||||
squid_config = file("${path.module}/resources/squid/squid.conf")
|
||||
squid_config_checksum = sha256(local.squid_config)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
resource "kubernetes_secret" "geoip_maxmind_credentials" {
|
||||
metadata {
|
||||
name = "geoip-maxmind-credentials"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
account_id = var.maxmind_account_id
|
||||
license_key = var.maxmind_license_key
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_cron_job_v1" "geoip_update" {
|
||||
|
||||
metadata {
|
||||
name = "geoip-update"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
schedule = local.geoip_cron_schedule
|
||||
job_template {
|
||||
metadata {
|
||||
name = "geoip-update"
|
||||
}
|
||||
spec {
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "geoip-update"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
container {
|
||||
name = "geoip-update"
|
||||
image = "${local.geoip_image}:${local.geoip_version}"
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_ACCOUNT_ID"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||
key = "account_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_LICENSE_KEY"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||
key = "license_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_EDITION_IDS"
|
||||
value = join(" ", local.geoip_editions)
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "geoip-db"
|
||||
mount_path = "/usr/share/GeoIP"
|
||||
}
|
||||
|
||||
|
||||
security_context {
|
||||
run_as_user = 1000
|
||||
run_as_group = 1000
|
||||
}
|
||||
}
|
||||
|
||||
service_account_name = kubernetes_service_account.m3uproxy_service_account.metadata[0].name
|
||||
|
||||
restart_policy = "OnFailure"
|
||||
|
||||
volume {
|
||||
name = "geoip-db"
|
||||
host_path {
|
||||
path = local.geoip_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,20 +22,6 @@ resource "kubernetes_secret" "m3uproxy_admin_credentials" {
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "geoip_maxmind_credentials" {
|
||||
metadata {
|
||||
name = "geoip-maxmind-credentials"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
account_id = var.maxmind_account_id
|
||||
license_key = var.maxmind_license_key
|
||||
}
|
||||
type = "Opaque"
|
||||
|
||||
}
|
||||
|
||||
|
||||
resource "kubernetes_service_account" "m3uproxy_service_account" {
|
||||
|
||||
metadata {
|
||||
@@ -46,36 +32,6 @@ resource "kubernetes_service_account" "m3uproxy_service_account" {
|
||||
automount_service_account_token = false
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "wireguard_config" {
|
||||
metadata {
|
||||
name = "wireguard-config"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"wireguard.conf" = templatefile("${path.module}/resources/wireguard/wireguard.conf.tpl", {
|
||||
wireguard_private_key = var.wireguard_private_key
|
||||
wireguard_public_key = var.wireguard_public_key
|
||||
wireguard_address = local.wireguard_address
|
||||
wireguard_dns = local.wireguard_dns
|
||||
wireguard_allowed_ips = join(", ", local.wireguard_allowed_ips)
|
||||
wireguard_endpoint = "${local.wireguard_endpoint}:${local.wireguard_endpoint_port}"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "squid_config" {
|
||||
metadata {
|
||||
name = "squid-config"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"squid.conf" = file("${path.module}/resources/squid/squid.conf")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "m3uproxy_config" {
|
||||
metadata {
|
||||
name = "m3uproxy-config"
|
||||
@@ -84,190 +40,10 @@ resource "kubernetes_config_map" "m3uproxy_config" {
|
||||
|
||||
data = {
|
||||
"m3uproxy.json" = local.m3uproxy_config
|
||||
"playlist.json" = file("${path.module}/resources/m3uproxy/playlist.json")
|
||||
"playlist.json" = local.m3uproxy_playlist
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "proxy_pt" {
|
||||
metadata {
|
||||
name = "proxy-pt"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
annotations = {
|
||||
"security.alpha.kubernetes.io/unsafe-sysctls" = "net.ipv4.conf.all.src_valid_mark=1"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
}
|
||||
|
||||
strategy {
|
||||
type = "Recreate"
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
name = "wireguard"
|
||||
image = "linuxserver/wireguard:${local.wireguard_version}"
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
exec {
|
||||
command = [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"wg show | grep -q transfer"
|
||||
]
|
||||
}
|
||||
initial_delay_seconds = 90
|
||||
period_seconds = 90
|
||||
}
|
||||
|
||||
security_context {
|
||||
privileged = true
|
||||
capabilities {
|
||||
add = ["NET_ADMIN"]
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "PUID"
|
||||
value = "1000"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "PGID"
|
||||
value = "1000"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "TZ"
|
||||
value = "Europe/Berlin"
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "wireguard-config"
|
||||
mount_path = "/config/wg_confs"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "lib-modules"
|
||||
mount_path = "/lib/modules"
|
||||
read_only = true
|
||||
}
|
||||
}
|
||||
|
||||
container {
|
||||
name = "squid"
|
||||
image = "ubuntu/squid:${local.squid_version}"
|
||||
|
||||
port {
|
||||
container_port = 3128
|
||||
name = "proxy"
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
readiness_probe {
|
||||
tcp_socket {
|
||||
port = "proxy"
|
||||
}
|
||||
initial_delay_seconds = 10
|
||||
timeout_seconds = 4
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
tcp_socket {
|
||||
port = "proxy"
|
||||
}
|
||||
initial_delay_seconds = 10
|
||||
timeout_seconds = 4
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "256Mi"
|
||||
}
|
||||
}
|
||||
|
||||
security_context {
|
||||
allow_privilege_escalation = false
|
||||
run_as_user = 1000
|
||||
run_as_group = 1000
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "squid-config"
|
||||
mount_path = "/etc/squid"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "squid-data"
|
||||
mount_path = "/var/spol/squid"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "wireguard-config"
|
||||
config_map {
|
||||
name = kubernetes_config_map.wireguard_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "lib-modules"
|
||||
host_path {
|
||||
path = "/lib/modules"
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "squid-config"
|
||||
config_map {
|
||||
name = kubernetes_config_map.squid_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "squid-data"
|
||||
host_path {
|
||||
path = local.squid_app_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
||||
replace_triggered_by = [
|
||||
kubernetes_config_map.wireguard_config,
|
||||
kubernetes_config_map.squid_config
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Create the Deployment
|
||||
resource "kubernetes_deployment" "m3uproxy" {
|
||||
metadata {
|
||||
name = "m3uproxy"
|
||||
@@ -292,6 +68,10 @@ resource "kubernetes_deployment" "m3uproxy" {
|
||||
labels = {
|
||||
app = "m3uproxy"
|
||||
}
|
||||
annotations = {
|
||||
"checksum/m3uproxy" = local.m3uproxy_config_checksum
|
||||
"checksum/playlist" = local.m3uproxy_playlist_checksum
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
@@ -393,96 +173,10 @@ resource "kubernetes_deployment" "m3uproxy" {
|
||||
}
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_cron_job_v1" "geoip_update" {
|
||||
|
||||
metadata {
|
||||
name = "geoip-update"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
schedule = local.geoip_cron_schedule
|
||||
job_template {
|
||||
metadata {
|
||||
name = "geoip-update"
|
||||
}
|
||||
spec {
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "geoip-update"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
container {
|
||||
name = "geoip-update"
|
||||
image = "${local.geoip_image}:${local.geoip_version}"
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_ACCOUNT_ID"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||
key = "account_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_LICENSE_KEY"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||
key = "license_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "GEOIPUPDATE_EDITION_IDS"
|
||||
value = join(" ", local.geoip_editions)
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "geoip-db"
|
||||
mount_path = "/usr/share/GeoIP"
|
||||
}
|
||||
|
||||
|
||||
security_context {
|
||||
run_as_user = 1000
|
||||
run_as_group = 1000
|
||||
}
|
||||
}
|
||||
|
||||
service_account_name = kubernetes_service_account.m3uproxy_service_account.metadata[0].name
|
||||
|
||||
restart_policy = "OnFailure"
|
||||
|
||||
volume {
|
||||
name = "geoip-db"
|
||||
host_path {
|
||||
path = local.geoip_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource "kubernetes_service" "m3uproxy" {
|
||||
metadata {
|
||||
name = "http"
|
||||
@@ -501,23 +195,6 @@ resource "kubernetes_service" "m3uproxy" {
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "proxy_pt" {
|
||||
metadata {
|
||||
name = "proxy-pt"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
selector = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
port {
|
||||
port = 3128
|
||||
}
|
||||
cluster_ip = "None"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_ingress_v1" "m3uproxy_ingress_http" {
|
||||
metadata {
|
||||
name = "m3uproxy-ingress"
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
|
||||
resource "kubernetes_config_map" "wireguard_config" {
|
||||
metadata {
|
||||
name = "wireguard-config"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"wireguard.conf" = local.wireguard_config
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "squid_config" {
|
||||
metadata {
|
||||
name = "squid-config"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"squid.conf" = local.squid_config
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "proxy_pt" {
|
||||
metadata {
|
||||
name = "proxy-pt"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
annotations = {
|
||||
"security.alpha.kubernetes.io/unsafe-sysctls" = "net.ipv4.conf.all.src_valid_mark=1"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
}
|
||||
|
||||
strategy {
|
||||
type = "Recreate"
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
annotations = {
|
||||
"checksum/squid" = local.squid_config_checksum
|
||||
"checksum/wireguard" = local.wireguard_config_checksum
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
name = "wireguard"
|
||||
image = "linuxserver/wireguard:${local.wireguard_version}"
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "64Mi"
|
||||
}
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
exec {
|
||||
command = [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"wg show | grep -q transfer"
|
||||
]
|
||||
}
|
||||
initial_delay_seconds = 90
|
||||
period_seconds = 90
|
||||
}
|
||||
|
||||
security_context {
|
||||
privileged = true
|
||||
capabilities {
|
||||
add = ["NET_ADMIN"]
|
||||
}
|
||||
}
|
||||
|
||||
env {
|
||||
name = "PUID"
|
||||
value = "1000"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "PGID"
|
||||
value = "1000"
|
||||
}
|
||||
|
||||
env {
|
||||
name = "TZ"
|
||||
value = "Europe/Berlin"
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "wireguard-config"
|
||||
mount_path = "/config/wg_confs"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "lib-modules"
|
||||
mount_path = "/lib/modules"
|
||||
read_only = true
|
||||
}
|
||||
}
|
||||
|
||||
container {
|
||||
name = "squid"
|
||||
image = "ubuntu/squid:${local.squid_version}"
|
||||
|
||||
port {
|
||||
container_port = 3128
|
||||
name = "proxy"
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
readiness_probe {
|
||||
tcp_socket {
|
||||
port = "proxy"
|
||||
}
|
||||
initial_delay_seconds = 10
|
||||
timeout_seconds = 4
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
tcp_socket {
|
||||
port = "proxy"
|
||||
}
|
||||
initial_delay_seconds = 10
|
||||
timeout_seconds = 4
|
||||
}
|
||||
|
||||
resources {
|
||||
requests = {
|
||||
memory = "256Mi"
|
||||
}
|
||||
}
|
||||
|
||||
security_context {
|
||||
allow_privilege_escalation = false
|
||||
run_as_user = 1000
|
||||
run_as_group = 1000
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "squid-config"
|
||||
mount_path = "/etc/squid"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "squid-data"
|
||||
mount_path = "/var/spol/squid"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "wireguard-config"
|
||||
config_map {
|
||||
name = kubernetes_config_map.wireguard_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "lib-modules"
|
||||
host_path {
|
||||
path = "/lib/modules"
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "squid-config"
|
||||
config_map {
|
||||
name = kubernetes_config_map.squid_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "squid-data"
|
||||
host_path {
|
||||
path = local.squid_app_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "proxy_pt" {
|
||||
metadata {
|
||||
name = "proxy-pt"
|
||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
selector = {
|
||||
app = "proxy-pt"
|
||||
}
|
||||
port {
|
||||
port = 3128
|
||||
}
|
||||
cluster_ip = "None"
|
||||
}
|
||||
}
|
||||
@@ -51,5 +51,45 @@ locals {
|
||||
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getmail_config = { for job in local.getmail_jobs : "getmailrc_${job.name}" =>
|
||||
|
||||
templatefile("${path.module}/resources/getmail/getmailrc.tpl", {
|
||||
recipient = job.recipient
|
||||
domain = job.domain
|
||||
server = job.server
|
||||
port = job.port
|
||||
username = job.username
|
||||
password = job.password
|
||||
mailbox = job.mailbox
|
||||
delete_after = job.delete_after
|
||||
dovecot_lmtp_address = "dovecot-lmtp.mail.svc.cluster.local"
|
||||
dovecot_lmtp_port = 31024
|
||||
})
|
||||
}
|
||||
|
||||
postfix_run_config = file("${path.module}/resources/postfix/run.config")
|
||||
postfix_bcc_map = join("\n", [for account in var.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
|
||||
|
||||
postfix_run_config_checksum = sha256(local.postfix_run_config)
|
||||
postfix_bcc_map_checksum = sha256(local.postfix_bcc_map)
|
||||
|
||||
dovecot_config = file("${path.module}/resources/dovecot/dovecot.conf")
|
||||
dovecot_users = join("\n", [for account in var.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
|
||||
dovecot_sieve = file("${path.module}/resources/dovecot/sieve")
|
||||
|
||||
dovecot_config_checksum = sha256(local.dovecot_config)
|
||||
dovecot_users_checksum = sha256(local.dovecot_users)
|
||||
dovecot_sieve_checksum = sha256(local.dovecot_sieve)
|
||||
}
|
||||
|
||||
data "external" "password_hasher" {
|
||||
for_each = { for account in var.email_accounts : account.username => account }
|
||||
program = ["python3", "${path.module}/lib/bcrypt_hash.py"]
|
||||
|
||||
query = {
|
||||
password = each.value.password
|
||||
cost = "10"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
data "external" "password_hasher" {
|
||||
for_each = { for account in var.email_accounts : account.username => account }
|
||||
program = ["python3", "${path.module}//lib/bcrypt_hash.py"]
|
||||
|
||||
query = {
|
||||
password = each.value.password
|
||||
cost = "10"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "mail" {
|
||||
metadata {
|
||||
annotations = {
|
||||
@@ -26,7 +16,7 @@ resource "kubernetes_secret" "dovecot_users" {
|
||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
"users" = join("\n", [for account in var.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
|
||||
"users" = local.dovecot_users
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,18 +62,17 @@ resource "kubernetes_config_map" "postfix_config" {
|
||||
}
|
||||
|
||||
data = {
|
||||
"run.config" = file("${path.module}/resources/mail/run.config")
|
||||
"run.config" = local.postfix_run_config
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resource "kubernetes_secret" "bcc_map" {
|
||||
metadata {
|
||||
name = "bcc-map"
|
||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
"bcc_map" = join("\n", [for account in var.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
|
||||
"bcc_map" = local.postfix_bcc_map
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,21 +82,7 @@ resource "kubernetes_config_map" "getmail_config" {
|
||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||
}
|
||||
|
||||
data = { for job in local.getmail_jobs : "getmailrc_${job.name}" =>
|
||||
|
||||
templatefile("${path.module}/resources/mail/getmailrc.tpl", {
|
||||
recipient = job.recipient
|
||||
domain = job.domain
|
||||
server = job.server
|
||||
port = job.port
|
||||
username = job.username
|
||||
password = job.password
|
||||
mailbox = job.mailbox
|
||||
delete_after = job.delete_after
|
||||
dovecot_lmtp_address = "dovecot-lmtp.mail.svc.cluster.local"
|
||||
dovecot_lmtp_port = 31024
|
||||
})
|
||||
}
|
||||
data = local.getmail_config
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "dovecot_config" {
|
||||
@@ -117,7 +92,7 @@ resource "kubernetes_config_map" "dovecot_config" {
|
||||
}
|
||||
|
||||
data = {
|
||||
"dovecot.conf" = file("${path.module}/resources/mail/dovecot.conf")
|
||||
"dovecot.conf" = local.dovecot_config
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +103,7 @@ resource "kubernetes_config_map" "dovecot_sieve" {
|
||||
}
|
||||
|
||||
data = {
|
||||
"sieve" = file("${path.module}/resources/mail/sieve")
|
||||
"sieve" = local.dovecot_sieve
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +222,12 @@ resource "kubernetes_deployment" "dovecot" {
|
||||
labels = {
|
||||
app = "dovecot"
|
||||
}
|
||||
annotations = {
|
||||
"checksum/dovecot" = local.dovecot_config_checksum
|
||||
"checksum/sieve" = local.dovecot_sieve_checksum
|
||||
# Commented out to avoid unnecessary restarts
|
||||
# "checksum/users" = local.dovecot_users_checksum
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
||||
@@ -337,11 +318,7 @@ resource "kubernetes_deployment" "dovecot" {
|
||||
}
|
||||
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
||||
replace_triggered_by = [
|
||||
kubernetes_config_map.dovecot_config,
|
||||
kubernetes_config_map.dovecot_sieve,
|
||||
]
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +345,10 @@ resource "kubernetes_deployment" "postfix" {
|
||||
labels = {
|
||||
app = "postfix"
|
||||
}
|
||||
annotations = {
|
||||
"checksum/runconfig" = local.postfix_run_config_checksum
|
||||
"checksum/bccmap" = local.postfix_bcc_map_checksum
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
||||
@@ -460,12 +441,7 @@ resource "kubernetes_deployment" "postfix" {
|
||||
}
|
||||
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
||||
replace_triggered_by = [
|
||||
kubernetes_config_map.postfix_config,
|
||||
kubernetes_secret.relay_mail_credentials,
|
||||
kubernetes_secret.bcc_map,
|
||||
]
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,8 @@ locals {
|
||||
persistent_folder = var.persistent_folder
|
||||
websites_path = "${local.persistent_folder}/web"
|
||||
websites = var.websites
|
||||
|
||||
nginx_config = file("${path.module}/resources/nginx.conf")
|
||||
nginx_config_checksum = sha256(local.nginx_config)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,19 @@ resource "kubernetes_config_map" "nginx_config" {
|
||||
}
|
||||
|
||||
data = {
|
||||
"nginx.conf" = file("${path.module}/resources/nginx/nginx.conf")
|
||||
"default.conf" = file("${path.module}/resources/nginx/conf.d/default.conf")
|
||||
"nginx.conf" = local.nginx_config
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "nginx_default_config" {
|
||||
for_each = local.websites
|
||||
metadata {
|
||||
name = format("website-%s-default", replace(each.key, ".", "-"))
|
||||
namespace = kubernetes_namespace.website.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"default.conf" = each.value.config
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +122,10 @@ resource "kubernetes_deployment" "website" {
|
||||
labels = {
|
||||
app = format("website-%s", replace(each.key, ".", "-"))
|
||||
}
|
||||
annotations = {
|
||||
"checksum/nginx" = local.nginx_config_checksum
|
||||
"checksum/default" = sha256(each.value.config)
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.website_service_account.metadata[0].name
|
||||
@@ -161,13 +176,13 @@ resource "kubernetes_deployment" "website" {
|
||||
name = "http"
|
||||
}
|
||||
volume_mount {
|
||||
name = "nginx-config"
|
||||
name = "nginx"
|
||||
mount_path = "/etc/nginx/nginx.conf"
|
||||
sub_path = "nginx.conf"
|
||||
read_only = true
|
||||
}
|
||||
volume_mount {
|
||||
name = "nginx-config"
|
||||
name = "default"
|
||||
mount_path = "/etc/nginx/conf.d/default.conf"
|
||||
sub_path = "default.conf"
|
||||
read_only = true
|
||||
@@ -179,11 +194,17 @@ resource "kubernetes_deployment" "website" {
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "nginx-config"
|
||||
name = "nginx"
|
||||
config_map {
|
||||
name = kubernetes_config_map.nginx_config.metadata[0].name
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "default"
|
||||
config_map {
|
||||
name = kubernetes_config_map.nginx_default_config[each.key].metadata[0].name
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "website"
|
||||
host_path {
|
||||
@@ -193,5 +214,8 @@ resource "kubernetes_deployment" "website" {
|
||||
}
|
||||
}
|
||||
}
|
||||
lifecycle {
|
||||
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -8,7 +8,6 @@ events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
@@ -29,6 +28,5 @@ http {
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
@@ -14,5 +14,6 @@ variable "websites" {
|
||||
type = map(object({
|
||||
domain_name = string
|
||||
fqdn = list(string)
|
||||
config = optional(string, "")
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,16 @@ resource "kubernetes_namespace" "rustdesk" {
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "rustdesk" {
|
||||
|
||||
metadata {
|
||||
name = "rustdesk-app-sa"
|
||||
namespace = kubernetes_namespace.rustdesk.metadata[0].name
|
||||
}
|
||||
|
||||
automount_service_account_token = false
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "rustdesk_config" {
|
||||
metadata {
|
||||
name = "rustdesk-config"
|
||||
@@ -58,6 +68,9 @@ resource "kubernetes_deployment" "rustdesk_deploy" {
|
||||
}
|
||||
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.rustdesk.metadata[0].name
|
||||
automount_service_account_token = false
|
||||
|
||||
container {
|
||||
name = "rustdesk-container"
|
||||
image = "rustdesk/rustdesk-server-s6:${local.rustdesk_version}"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
locals {
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
#
|
||||
# Namespace for Seafile
|
||||
#
|
||||
resource "kubernetes_namespace" "seafile" {
|
||||
metadata {
|
||||
annotations = {
|
||||
name = "seafile"
|
||||
}
|
||||
|
||||
labels = {
|
||||
name = "seafile"
|
||||
}
|
||||
|
||||
name = "seafile"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Persistent Volume for Seafile data
|
||||
#
|
||||
resource "kubernetes_persistent_volume" "seafile_data" {
|
||||
metadata {
|
||||
name = "seafile-data"
|
||||
labels = {
|
||||
type = "local" # Example label, adjust as needed
|
||||
}
|
||||
}
|
||||
spec {
|
||||
capacity = {
|
||||
storage = "10Gi"
|
||||
}
|
||||
access_modes = ["ReadWriteOnce"]
|
||||
persistent_volume_source {
|
||||
host_path {
|
||||
path = "/opt/seafile-data" # Consider making this configurable via variables
|
||||
}
|
||||
}
|
||||
persistent_volume_reclaim_policy = "Retain" # Or Delete, depending on desired behavior
|
||||
storage_class_name = "manual" # Or your specific storage class
|
||||
volume_mode = "Filesystem"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Persistent Volume Claim for Seafile data
|
||||
#
|
||||
resource "kubernetes_persistent_volume_claim" "seafile_data" {
|
||||
metadata {
|
||||
name = "seafile-data"
|
||||
namespace = kubernetes_namespace.seafile.metadata[0].name
|
||||
}
|
||||
spec {
|
||||
access_modes = ["ReadWriteOnce"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = "10Gi"
|
||||
}
|
||||
}
|
||||
storage_class_name = "manual" # Must match the PV's storage class
|
||||
volume_name = kubernetes_persistent_volume.seafile_data.metadata[0].name
|
||||
}
|
||||
wait_until_bound = false # Set to true if you need to ensure binding before proceeding
|
||||
}
|
||||
|
||||
#
|
||||
# ConfigMap for Seafile environment variables
|
||||
#
|
||||
resource "kubernetes_config_map" "seafile_env" {
|
||||
metadata {
|
||||
name = "seafile-env"
|
||||
namespace = kubernetes_namespace.seafile.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
# for Seafile server
|
||||
TIME_ZONE = "UTC" # Consider making this configurable
|
||||
SEAFILE_LOG_TO_STDOUT = "false"
|
||||
SITE_ROOT = "/"
|
||||
ENABLE_SEADOC = "false"
|
||||
SEADOC_SERVER_URL = "https://seafile.example.com/sdoc-server" # Replace with actual URL or variable
|
||||
SEAFILE_SERVER_HOSTNAME = "seafile.example.com" # Replace with actual hostname or variable
|
||||
SEAFILE_SERVER_PROTOCOL = "http" # Replace with actual protocol or variable
|
||||
|
||||
# for database - Consider using secrets for credentials
|
||||
SEAFILE_MYSQL_DB_HOST = "<your MySQL host>" # Replace with actual host or variable/secret
|
||||
SEAFILE_MYSQL_DB_PORT = "3306"
|
||||
SEAFILE_MYSQL_DB_USER = "seafile" # Replace with actual user or variable/secret
|
||||
SEAFILE_MYSQL_DB_CCNET_DB_NAME = "ccnet_db"
|
||||
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME = "seafile_db"
|
||||
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME = "seahub_db"
|
||||
|
||||
# Init
|
||||
## for Seafile admin - Consider using secrets
|
||||
INIT_SEAFILE_ADMIN_EMAIL = "<Seafile admin's email>" # Replace with actual email or variable/secret
|
||||
|
||||
## For S3 storage backend (only valid in INIT_S3_STORAGE_BACKEND_CONFIG = true) - Consider using secrets
|
||||
INIT_S3_STORAGE_BACKEND_CONFIG = "false"
|
||||
INIT_S3_COMMIT_BUCKET = ""
|
||||
INIT_S3_FS_BUCKET = ""
|
||||
INIT_S3_BLOCK_BUCKET = ""
|
||||
INIT_S3_KEY_ID = ""
|
||||
INIT_S3_USE_V4_SIGNATURE = "true"
|
||||
INIT_S3_AWS_REGION = "us-east-1"
|
||||
INIT_S3_HOST = "s3.us-east-1.amazonaws.com"
|
||||
INIT_S3_USE_HTTPS = "true"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Service for Seafile
|
||||
#
|
||||
resource "kubernetes_service" "seafile" {
|
||||
metadata {
|
||||
name = "seafile"
|
||||
namespace = kubernetes_namespace.seafile.metadata[0].name
|
||||
}
|
||||
spec {
|
||||
selector = {
|
||||
app = "seafile" # Ensure your Seafile deployment/pod has this label
|
||||
}
|
||||
port {
|
||||
protocol = "TCP"
|
||||
port = 80
|
||||
target_port = 80
|
||||
node_port = 30000 # NodePort might not be ideal for production, consider Ingress or LoadBalancer service type without explicit nodePort
|
||||
}
|
||||
type = "LoadBalancer" # Or ClusterIP/NodePort depending on your needs
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 9;
|
||||
gzip_types
|
||||
text/html
|
||||
text/plain
|
||||
text/css
|
||||
text/js
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/rss+xml
|
||||
image/svg+xml;
|
||||
|
||||
root /tmp/site;
|
||||
|
||||
location / {
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location ~* ^/([^/]+) {
|
||||
index index.html index.htm;
|
||||
error_page 404 = @error;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
location @error {
|
||||
try_files /$1/404.html /404.html =404;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
locals {
|
||||
data_path = "${var.persistent_folder}/sftpgo"
|
||||
|
||||
|
||||
sftpgo_config = {
|
||||
"common" : {
|
||||
"defender" : {
|
||||
"enabled" : false
|
||||
}
|
||||
},
|
||||
"sftpd" : {
|
||||
"bindings" : [
|
||||
{
|
||||
"port" : 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"webdavd" : {
|
||||
"bindings" : [
|
||||
{
|
||||
"port" : 8081,
|
||||
"address" : "0.0.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"data_provider" : {
|
||||
"create_default_admin" : true,
|
||||
"backups_path" : "/var/lib/sftpgo/backup"
|
||||
},
|
||||
"httpd" : {
|
||||
"bindings" : [
|
||||
{
|
||||
"port" : 8080,
|
||||
"address" : "0.0.0.0",
|
||||
"branding" : {
|
||||
"web_client" : {
|
||||
"name" : "alexpires.me cloud",
|
||||
"short_name" : "alexpires.me"
|
||||
},
|
||||
"web_admin" : {
|
||||
"name" : "alexpires.me cloud",
|
||||
"short_name" : "alexpires.me"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"web_root" : "/storage",
|
||||
},
|
||||
"telemetry" : {
|
||||
"bind_port" : 10000,
|
||||
"bind_address" : "0.0.0.0"
|
||||
},
|
||||
"mfa" : {
|
||||
"totp" : [
|
||||
{
|
||||
"name" : "Default",
|
||||
"issuer" : "alexpires.me",
|
||||
"algo" : "sha1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"smtp" : {
|
||||
"host" : var.smtp_host,
|
||||
"port" : var.smtp_port,
|
||||
"from" : var.from_email
|
||||
"encryption" : 1,
|
||||
"domain" : "alexpires.me"
|
||||
},
|
||||
"plugins" : []
|
||||
}
|
||||
|
||||
config = jsonencode(local.sftpgo_config)
|
||||
config_checksum = sha256(local.config)
|
||||
|
||||
credentials = templatefile("${path.module}/resources/aws.tpl", {
|
||||
access_key = var.access_key
|
||||
secret_key = var.secret_key
|
||||
})
|
||||
credentials_checksum = sha256(local.credentials)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
resource "kubernetes_namespace" "sftpgo" {
|
||||
metadata {
|
||||
name = "sftpgo"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "sftpgo" {
|
||||
metadata {
|
||||
name = "sftpgo"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
"sftpgo.json" = local.config
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "admin_credentials" {
|
||||
metadata {
|
||||
name = "admin-credentials"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
admin_username = var.admin_username
|
||||
admin_password = var.admin_password
|
||||
smtp_username = var.smtp_username
|
||||
smtp_password = var.smtp_password
|
||||
}
|
||||
type = "Opaque"
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "object_store_credentials" {
|
||||
metadata {
|
||||
name = "nextcloud-object-store-credentials"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
data = {
|
||||
"credentials" = local.credentials
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service_account" "sftpgo" {
|
||||
metadata {
|
||||
name = "sftpgo-app-sa"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
automount_service_account_token = false
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "sftpgo" {
|
||||
metadata {
|
||||
name = "sftpgo"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "sftpgo"
|
||||
}
|
||||
}
|
||||
strategy {
|
||||
type = "RollingUpdate"
|
||||
}
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "sftpgo"
|
||||
}
|
||||
annotations = {
|
||||
"checksum/config" = local.config_checksum
|
||||
"checksum/credentials" = local.credentials_checksum
|
||||
}
|
||||
}
|
||||
spec {
|
||||
service_account_name = kubernetes_service_account.sftpgo.metadata[0].name
|
||||
automount_service_account_token = false
|
||||
security_context {
|
||||
fs_group = 1000
|
||||
run_as_user = 1000
|
||||
}
|
||||
container {
|
||||
name = "sftpgo"
|
||||
image = "ghcr.io/drakkan/sftpgo:${var.tag}"
|
||||
image_pull_policy = "Always"
|
||||
args = ["sftpgo", "serve"]
|
||||
env {
|
||||
name = "SFTPGO_SMTP__USER"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||
key = "smtp_username"
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "SFTPGO_SMTP__PASSWORD"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||
key = "smtp_password"
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "SFTPGO_DEFAULT_ADMIN_USERNAME"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||
key = "admin_username"
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "SFTPGO_DEFAULT_ADMIN_PASSWORD"
|
||||
value_from {
|
||||
secret_key_ref {
|
||||
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||
key = "admin_password"
|
||||
}
|
||||
}
|
||||
}
|
||||
port {
|
||||
container_port = 8081
|
||||
name = "webdav"
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 8080
|
||||
name = "http"
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 10000
|
||||
name = "telemetry"
|
||||
protocol = "TCP"
|
||||
}
|
||||
liveness_probe {
|
||||
http_get {
|
||||
path = "/healthz"
|
||||
port = "telemetry"
|
||||
}
|
||||
}
|
||||
readiness_probe {
|
||||
http_get {
|
||||
path = "/healthz"
|
||||
port = "telemetry"
|
||||
}
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/etc/sftpgo/sftpgo.json"
|
||||
name = "config"
|
||||
sub_path = "sftpgo.json"
|
||||
read_only = true
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/var/lib/sftpgo"
|
||||
name = "data"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/var/lib/sftpgo/backup"
|
||||
name = "backup"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/var/lib/sftpgo/.aws/credentials"
|
||||
name = "object-store-credentials"
|
||||
sub_path = "credentials"
|
||||
read_only = true
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "config"
|
||||
config_map {
|
||||
name = kubernetes_config_map.sftpgo.metadata[0].name
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "data"
|
||||
host_path {
|
||||
path = local.data_path
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "backup"
|
||||
host_path {
|
||||
path = var.backup_folder
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "object-store-credentials"
|
||||
config_map {
|
||||
name = kubernetes_config_map.object_store_credentials.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "sftpgo_webdav" {
|
||||
metadata {
|
||||
name = "webdav"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
spec {
|
||||
selector = {
|
||||
app = "sftpgo"
|
||||
}
|
||||
port {
|
||||
protocol = "TCP"
|
||||
port = 8081
|
||||
target_port = "webdav"
|
||||
}
|
||||
cluster_ip = "None"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "sftpgo_http" {
|
||||
metadata {
|
||||
name = "http"
|
||||
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
spec {
|
||||
selector = {
|
||||
app = "sftpgo"
|
||||
}
|
||||
port {
|
||||
protocol = "TCP"
|
||||
port = 8080
|
||||
target_port = "http"
|
||||
}
|
||||
cluster_ip = "None"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
output "path" {
|
||||
value = local.data_path
|
||||
}
|
||||
|
||||
output "namespace" {
|
||||
value = kubernetes_namespace.sftpgo.metadata[0].name
|
||||
}
|
||||
|
||||
output "app_name" {
|
||||
value = "sftpgo"
|
||||
}
|
||||
@@ -9,5 +9,9 @@ terraform {
|
||||
source = "scaleway/scaleway"
|
||||
version = "~>2.13"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.7.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
[default]
|
||||
aws_access_key_id=${access_key}
|
||||
aws_secret_access_key=${secret_key}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
variable "persistent_folder" {
|
||||
description = "The path to the persistent folder"
|
||||
type = string
|
||||
}
|
||||
|
||||
|
||||
variable "backup_folder" {
|
||||
description = "The path to the backup folder"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "admin_username" {
|
||||
description = "The admin username for SFTPGo"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "admin_password" {
|
||||
description = "The admin password for SFTPGo"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "tag" {
|
||||
description = "The version of Rustdesk to install"
|
||||
type = string
|
||||
default = "latest"
|
||||
}
|
||||
|
||||
variable "smtp_host" {
|
||||
description = "The SMTP relay host"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "smtp_port" {
|
||||
description = "The SMTP relay port"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "smtp_username" {
|
||||
description = "The SMTP relay username"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "smtp_password" {
|
||||
description = "The SMTP relay password"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "from_email" {
|
||||
description = "The email address to use as the sender"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "access_key" {
|
||||
description = "The access key for the S3 compatible storage"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "secret_key" {
|
||||
description = "The secret key for the S3 compatible storage"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
Reference in New Issue
Block a user