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:
2025-05-05 00:47:36 +02:00
parent 6adbd50c6d
commit e6e85b00f7
60 changed files with 1107 additions and 604 deletions
+40
View File
@@ -0,0 +1,40 @@
---
- name: SFTPGo Playbook (K8s)
hosts: sftpgo
gather_facts: true
# Specific tasks for this playbook
tasks:
- name: Set required facts
ansible.builtin.set_fact:
sftpgo_home: "{{ persistent_data | default('/var/lib') }}/sftpgo"
sftpgo_mysql_home: "{{ database_path | default('/var/lib') }}/mysql.sftpgo"
sftpgo_user_id: 1000
sftpgo_group_id: 1000
mysql_user_id: 999
mysql_group_id: 107
tags: always
- name: Create required sftpgo data folder
become: true
ansible.builtin.file:
state: directory
path: "{{ sftpgo_home }}"
mode: "0750"
owner: "{{ sftpgo_user_id }}"
group: "{{ sftpgo_group_id }}"
tags:
- tasks
- tasks::folders
- name: Create required mysql data folder
become: true
ansible.builtin.file:
state: directory
path: "{{ sftpgo_mysql_home }}"
mode: "0755"
owner: "{{ mysql_user_id }}"
group: "{{ mysql_group_id }}"
tags:
- tasks
- tasks::folders
+3 -3
View File
@@ -42,9 +42,9 @@
become: true
ansible.posix.synchronize:
mode: push
src: "{{ lookup('env', 'GITHUB_WORKSPACE') + '/websites/releases/'+ item }}/"
src: "{{ lookup('env', 'GITHUB_WORKSPACE') + '/websites/releases/' + item }}/"
dest: "{{ web_home }}/{{ item }}"
delete: yes
recursive: yes
delete: true
recursive: true
with_items:
- "{{ websites | default([]) }}"
+3
View File
@@ -22,6 +22,9 @@ prod-01.alexpires.me
[nextcloud]
prod-01.alexpires.me
[sftpgo]
prod-01.alexpires.me
[m3uproxy]
prod-01.alexpires.me
+5
View File
@@ -170,6 +170,11 @@ locals {
type = "TXT"
value = "v=DKIM1; h=sha256; k=rsa; p=${var.alexpires_me_scaleway_dkim_value}"
},
{
name = "webdav"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
]
}
+25 -4
View File
@@ -71,10 +71,31 @@ module "gitea" {
fqdn = local.gitea_fqdn
app_name = "A13Labs git repository"
relay_smtp_host = local.scaleway_smtp_host
relay_smtp_port = local.scaleway_smtp_port
relay_smtp_username = var.scaleway_project_id
relay_smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
smtp_host = local.scaleway_smtp_host
smtp_port = local.scaleway_smtp_port
smtp_username = var.scaleway_project_id
smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
from_email = "gitea@${local.primary_domain}"
}
module "sftpgo" {
source = "../modules/apps/sftpgo"
persistent_folder = local.persistent_folder
backup_folder = local.sftpgo_backup_path
admin_username = "admin"
admin_password = var.sftpgo_admin_password
tag = local.sftpgo_version
smtp_host = local.scaleway_smtp_host
smtp_port = local.scaleway_smtp_port
smtp_username = var.scaleway_project_id
smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
from_email = "sftpgo@${local.primary_domain}"
access_key = scaleway_iam_api_key.sftpgo_app_api.access_key
secret_key = scaleway_iam_api_key.sftpgo_app_api.secret_key
}
+6 -6
View File
@@ -37,12 +37,12 @@ module "gitea_backup" {
target_folder = local.gitea_backup_path
}
module "nextcloud_backup" {
module "sftpgo_backup" {
source = "../modules/utils/scw_rclone"
namespace = kubernetes_namespace.nextcloud.metadata[0].name
app_name = "nextcloud"
namespace = module.sftpgo.namespace
app_name = module.sftpgo.app_name
scaleway_organization_id = var.scaleway_organization_id
scaleway_project_id = var.scaleway_organization_id
@@ -51,8 +51,8 @@ module "nextcloud_backup" {
bucket_name = scaleway_object_bucket.backup.name
retention_days = local.local_backup_retention_days
cron_schedule = local.nextcloud_files_backup_cron_schedule
cron_schedule = local.sftpgo_files_backup_cron_schedule
source_folder = local.nextcloud_path
target_folder = local.nextcloud_backup_path
source_folder = module.sftpgo.path
target_folder = local.sftpgo_backup_path
}
+42
View File
@@ -170,3 +170,45 @@ resource "scaleway_object_bucket_policy" "dovecot" {
]
})
}
resource "scaleway_object_bucket" "sftpgo" {
name = "a13labs-sftpgo-${random_string.bucket_suffix.result}"
project_id = var.scaleway_project_id
region = "fr-par"
}
resource "scaleway_object_bucket_policy" "sftpgo" {
bucket = scaleway_object_bucket.sftpgo.name
policy = jsonencode({
Version = "2023-04-17",
Id = "AllowAccess",
Statement = [
{
Effect = "Allow"
Action = [
"s3:*",
]
Principal = {
SCW = "user_id:${var.scaleway_user_id}"
}
Resource = [
scaleway_object_bucket.sftpgo.name,
"${scaleway_object_bucket.sftpgo.name}/*",
]
},
{
Effect = "Allow"
Action = [
"s3:*",
]
Principal = {
SCW = "application_id:${scaleway_iam_application.sftpgo_app.id}"
}
Resource = [
scaleway_object_bucket.sftpgo.name,
"${scaleway_object_bucket.sftpgo.name}/*",
]
},
]
})
}
+17 -15
View File
@@ -11,22 +11,22 @@ locals {
"alexpires.me" = {
domain_name = "alexpires.me"
fqdn = ["blog.alexpires.me", "www.alexpires.me", "alexpires.me"]
config = file("${path.module}/resources/alexpires.me.conf")
}
}
# gitea
gitea_version = "1.23.4"
gitea_fqdn = "code.${local.primary_domain}"
nextcloud_version = "30.0.0-apache"
nextcloud_fqdn = "cloud.${local.primary_domain}"
nextcloud_sql_backup_cron_schedule = "40 2 * * *"
nextcloud_files_backup_cron_schedule = "50 2 * * *"
# sftpgo
sftpgo_version = "2.6.x"
# m3uproxy
m3uproxy_version = "latest"
m3uproxy_fqdn = "tv.${local.primary_domain}"
# geoip
geoip_cron_schedule = "0 0 * * *"
geoip_editions = [
"GeoLite2-Country",
@@ -37,19 +37,21 @@ locals {
rustdesk_fqdn = "rustdesk.${local.primary_domain}"
# backup
local_backup_retention_days = 2
cloud_backup_retention_days = 3
mail_backup_path = "${local.persistent_folder}/backup.mail"
gitea_backup_path = "${local.persistent_folder}/backup.gitea"
gitea_sql_backup_cron_schedule = "20 2 * * *"
gitea_files_backup_cron_schedule = "30 2 * * *"
mail_files_backup_cron_schedule = "0 3 * * *"
local_backup_retention_days = 2
cloud_backup_retention_days = 3
mail_backup_path = "${local.persistent_folder}/backup.mail"
gitea_backup_path = "${local.persistent_folder}/backup.gitea"
sftpgo_backup_path = "${local.persistent_folder}/backup.sftpgo"
gitea_sql_backup_cron_schedule = "20 2 * * *"
gitea_files_backup_cron_schedule = "30 2 * * *"
sftpgo_files_backup_cron_schedule = "50 2 * * *"
mail_files_backup_cron_schedule = "0 3 * * *"
fetch_emails_schedule = "*/2 * * * *"
# email settings
scaleway_smtp_host = "smtp.tem.scw.cloud"
scaleway_smtp_port = 587
fetch_emails_schedule = "*/2 * * * *"
scaleway_smtp_host = "smtp.tem.scw.cloud"
scaleway_smtp_port = 587
email_accounts = [
{
domain = "alexpires.me"
@@ -1,6 +1,9 @@
server {
listen 8080;
server_name localhost;
root /tmp/site;
resolver kube-dns.kube-system.svc.cluster.local valid=10s;
gzip on;
gzip_comp_level 9;
@@ -17,7 +20,15 @@ server {
application/rss+xml
image/svg+xml;
root /tmp/site;
location ^~ /storage {
proxy_pass http://http.sftpgo.svc.cluster.local:8080/storage;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
location / {
index index.html index.htm;
+27
View File
@@ -14,6 +14,10 @@ resource "scaleway_iam_application" "dovecot_app" {
name = "dovecot_app"
}
resource "scaleway_iam_application" "sftpgo_app" {
name = "sftpgo_app"
}
resource "scaleway_iam_policy" "object_read_write_backup" {
name = "K8s backup app policy"
description = "Gives k8s backup job access to object storage in project"
@@ -77,6 +81,24 @@ resource "scaleway_iam_policy" "object_read_write_dovecot" {
}
}
resource "scaleway_iam_policy" "object_read_write_sftpgo" {
name = "SFtpGo app policy"
description = "Gives sftpgo job access to object storage in project"
application_id = scaleway_iam_application.sftpgo_app.id
rule {
project_ids = [data.scaleway_account_project.default.id]
permission_set_names = [
"ObjectStorageObjectsWrite",
"ObjectStorageObjectsRead",
"ObjectStorageBucketsRead",
"ObjectStorageBucketsWrite",
"ObjectStorageObjectsDelete"
]
}
}
resource "scaleway_iam_api_key" "backup_app_api" {
application_id = scaleway_iam_application.backup_app.id
description = "k8s backup app API key"
@@ -96,3 +118,8 @@ resource "scaleway_iam_api_key" "dovecot_app_api" {
application_id = scaleway_iam_application.dovecot_app.id
description = "dovecot access API key"
}
resource "scaleway_iam_api_key" "sftpgo_app_api" {
application_id = scaleway_iam_application.sftpgo_app.id
description = "sftpgo access API key"
}
@@ -0,0 +1,46 @@
server {
listen 8080;
server_name localhost;
root /tmp/site;
resolver kube-dns.kube-system.svc.cluster.local valid=10s;
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;
location ^~ /storage {
proxy_pass http://http.sftpgo.svc.cluster.local:8080/storage;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
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;
}
}
+7
View File
@@ -76,3 +76,10 @@ variable "mail_crypt_private_key" {
type = string
sensitive = true
}
variable "sftpgo_admin_password" {
description = "SFTPGo admin password"
type = string
sensitive = true
}
+2 -1
View File
@@ -22,4 +22,5 @@ TF_VAR_rustdesk_public_key=$RUSTDESK_PUBLIC_KEY
TF_VAR_alexpires_me_email_username=$ALEXPIRES_ME_EMAIL_USERNAME
TF_VAR_alexpires_me_email_password=$ALEXPIRES_ME_EMAIL_PASSWORD
TF_VAR_mail_crypt_private_key=$DOVECOT_CRYPT_PRIVATE_KEY_FILE
TF_VAR_mail_crypt_public_key=$DOVECOT_CRYPT_PUB_KEY_FILE
TF_VAR_mail_crypt_public_key=$DOVECOT_CRYPT_PUB_KEY_FILE
TF_VAR_sftpgo_admin_password=$SFTPGO_ADMIN_PASSWORD
+2 -2
View File
@@ -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"
}
+15
View File
@@ -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
}
+2 -18
View File
@@ -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 {
+4 -4
View File
@@ -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
+24 -6
View File
@@ -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)
}
+97
View File
@@ -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
}
}
}
}
}
}
}
}
+6 -329
View File
@@ -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"
+218
View File
@@ -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"
}
}
+40
View File
@@ -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"
}
}
+18 -42
View File
@@ -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"]]
}
}
+3
View File
@@ -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)
}
+29 -5
View File
@@ -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"]]
}
}
@@ -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, "")
}))
}
+13
View File
@@ -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}"
-3
View File
@@ -1,3 +0,0 @@
locals {
}
-128
View File
@@ -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,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 @@
+81
View File
@@ -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)
}
+233
View File
@@ -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"
}
}
+11
View File
@@ -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
}