From e6e85b00f787d90cb84c293d012ad8292355c884 Mon Sep 17 00:00:00 2001 From: Alexandre Pires Date: Mon, 5 May 2025 00:47:36 +0200 Subject: [PATCH] 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. --- ansible/playbook_sftpgo.yml | 40 +++ ansible/playbook_websites.yml | 6 +- inventory/hosts | 3 + terraform/cloudns-iac/config.tf | 5 + terraform/k8sapps/apps.tf | 29 +- terraform/k8sapps/backups.tf | 12 +- terraform/k8sapps/buckets.tf | 42 +++ terraform/k8sapps/config.tf | 32 +- .../nextcloud.tf.bak} | 0 .../disabled/resources/alexpires.me.conf} | 13 +- .../resources/apache2/99-compression.conf | 0 .../apache2/99-nextcloudworkers.conf | 0 .../1_host_compute_performance.dashboard | 0 .../dashboards/2_disk_capacity.dashboard | 0 .../3_system_metrics.dashboard.disabled | 0 .../4_net_interface_metric_explorer.dashboard | 0 .../5_net_interface_performance.dashboard | 0 .../resources/chronograf/default.org | 0 .../resources/chronograf/internal.kap | 0 .../resources/chronograf/internal.src | 0 .../resources/collabora/coolwsd.xml | 0 .../resources/fluent-bit/fluent-bit.conf | 0 .../resources/fluent-bit/parsers.conf | 0 .../resources/influxdb/init.iql | 0 .../resources/nextcloud-server-snippet.conf | 0 .../resources/telegraf/telegraf.conf | 0 terraform/k8sapps/iam.tf | 27 ++ terraform/k8sapps/resources/alexpires.me.conf | 46 +++ terraform/k8sapps/secrets.tf | 7 + terraform/k8sapps/sectool.env | 3 +- terraform/modules/apps/gitea/config.tf | 4 +- terraform/modules/apps/gitea/database.tf | 15 + terraform/modules/apps/gitea/main.tf | 20 +- terraform/modules/apps/gitea/variables.tf | 8 +- terraform/modules/apps/m3uproxy/config.tf | 30 +- terraform/modules/apps/m3uproxy/geoip.tf | 97 +++++ terraform/modules/apps/m3uproxy/main.tf | 335 +----------------- terraform/modules/apps/m3uproxy/vpn.tf | 218 ++++++++++++ terraform/modules/apps/mail/config.tf | 40 +++ terraform/modules/apps/mail/main.tf | 60 +--- .../resources/{mail => dovecot}/dovecot.conf | 0 .../mail/resources/{mail => dovecot}/sieve | 0 .../resources/{mail => getmail}/getmailrc.tpl | 0 .../resources/{mail => postfix}/run.config | 0 terraform/modules/apps/nginx/config.tf | 3 + terraform/modules/apps/nginx/main.tf | 34 +- .../resources/{nginx => }/conf.d/default.conf | 0 .../nginx/resources/{nginx => }/nginx.conf | 2 - terraform/modules/apps/nginx/variables.tf | 1 + terraform/modules/apps/rustdesk/main.tf | 13 + terraform/modules/apps/seafile/config.tf | 3 - terraform/modules/apps/seafile/main.tf | 128 ------- .../apps/seafile/resources/nginx/nginx.conf | 34 -- terraform/modules/apps/seafile/variables.tf | 1 - terraform/modules/apps/sftpgo/config.tf | 81 +++++ terraform/modules/apps/sftpgo/main.tf | 233 ++++++++++++ terraform/modules/apps/sftpgo/outputs.tf | 11 + .../apps/{seafile => sftpgo}/provider.tf | 4 + .../modules/apps/sftpgo/resources/aws.tpl | 3 + terraform/modules/apps/sftpgo/variables.tf | 68 ++++ 60 files changed, 1107 insertions(+), 604 deletions(-) create mode 100644 ansible/playbook_sftpgo.yml rename terraform/k8sapps/{nextcloud.tf => disabled/nextcloud.tf.bak} (100%) rename terraform/{modules/apps/seafile/resources/nginx/conf.d/default.conf => k8sapps/disabled/resources/alexpires.me.conf} (55%) rename terraform/k8sapps/{ => disabled}/resources/apache2/99-compression.conf (100%) rename terraform/k8sapps/{ => disabled}/resources/apache2/99-nextcloudworkers.conf (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/dashboards/1_host_compute_performance.dashboard (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/dashboards/2_disk_capacity.dashboard (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/dashboards/3_system_metrics.dashboard.disabled (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/dashboards/4_net_interface_metric_explorer.dashboard (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/dashboards/5_net_interface_performance.dashboard (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/default.org (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/internal.kap (100%) rename terraform/k8sapps/{ => disabled}/resources/chronograf/internal.src (100%) rename terraform/k8sapps/{ => disabled}/resources/collabora/coolwsd.xml (100%) rename terraform/k8sapps/{ => disabled}/resources/fluent-bit/fluent-bit.conf (100%) rename terraform/k8sapps/{ => disabled}/resources/fluent-bit/parsers.conf (100%) rename terraform/k8sapps/{ => disabled}/resources/influxdb/init.iql (100%) rename terraform/k8sapps/{ => disabled}/resources/nextcloud-server-snippet.conf (100%) rename terraform/k8sapps/{ => disabled}/resources/telegraf/telegraf.conf (100%) create mode 100644 terraform/k8sapps/resources/alexpires.me.conf create mode 100644 terraform/modules/apps/gitea/database.tf create mode 100644 terraform/modules/apps/m3uproxy/geoip.tf create mode 100644 terraform/modules/apps/m3uproxy/vpn.tf rename terraform/modules/apps/mail/resources/{mail => dovecot}/dovecot.conf (100%) rename terraform/modules/apps/mail/resources/{mail => dovecot}/sieve (100%) rename terraform/modules/apps/mail/resources/{mail => getmail}/getmailrc.tpl (100%) rename terraform/modules/apps/mail/resources/{mail => postfix}/run.config (100%) rename terraform/modules/apps/nginx/resources/{nginx => }/conf.d/default.conf (100%) rename terraform/modules/apps/nginx/resources/{nginx => }/nginx.conf (99%) delete mode 100644 terraform/modules/apps/seafile/config.tf delete mode 100644 terraform/modules/apps/seafile/main.tf delete mode 100644 terraform/modules/apps/seafile/resources/nginx/nginx.conf delete mode 100644 terraform/modules/apps/seafile/variables.tf create mode 100644 terraform/modules/apps/sftpgo/config.tf create mode 100644 terraform/modules/apps/sftpgo/main.tf create mode 100644 terraform/modules/apps/sftpgo/outputs.tf rename terraform/modules/apps/{seafile => sftpgo}/provider.tf (75%) create mode 100644 terraform/modules/apps/sftpgo/resources/aws.tpl create mode 100644 terraform/modules/apps/sftpgo/variables.tf diff --git a/ansible/playbook_sftpgo.yml b/ansible/playbook_sftpgo.yml new file mode 100644 index 0000000..1a2938f --- /dev/null +++ b/ansible/playbook_sftpgo.yml @@ -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 diff --git a/ansible/playbook_websites.yml b/ansible/playbook_websites.yml index b81cbd0..cd468d1 100644 --- a/ansible/playbook_websites.yml +++ b/ansible/playbook_websites.yml @@ -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([]) }}" diff --git a/inventory/hosts b/inventory/hosts index d211561..dae9c0c 100644 --- a/inventory/hosts +++ b/inventory/hosts @@ -22,6 +22,9 @@ prod-01.alexpires.me [nextcloud] prod-01.alexpires.me +[sftpgo] +prod-01.alexpires.me + [m3uproxy] prod-01.alexpires.me diff --git a/terraform/cloudns-iac/config.tf b/terraform/cloudns-iac/config.tf index efbfd4e..d0b953f 100644 --- a/terraform/cloudns-iac/config.tf +++ b/terraform/cloudns-iac/config.tf @@ -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" + }, ] } diff --git a/terraform/k8sapps/apps.tf b/terraform/k8sapps/apps.tf index 1de9ed7..25743bc 100644 --- a/terraform/k8sapps/apps.tf +++ b/terraform/k8sapps/apps.tf @@ -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 +} diff --git a/terraform/k8sapps/backups.tf b/terraform/k8sapps/backups.tf index 8b643b6..f70567c 100644 --- a/terraform/k8sapps/backups.tf +++ b/terraform/k8sapps/backups.tf @@ -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 } diff --git a/terraform/k8sapps/buckets.tf b/terraform/k8sapps/buckets.tf index fbb0fe2..1a671cd 100644 --- a/terraform/k8sapps/buckets.tf +++ b/terraform/k8sapps/buckets.tf @@ -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}/*", + ] + }, + ] + }) +} diff --git a/terraform/k8sapps/config.tf b/terraform/k8sapps/config.tf index f048841..62119f4 100644 --- a/terraform/k8sapps/config.tf +++ b/terraform/k8sapps/config.tf @@ -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" diff --git a/terraform/k8sapps/nextcloud.tf b/terraform/k8sapps/disabled/nextcloud.tf.bak similarity index 100% rename from terraform/k8sapps/nextcloud.tf rename to terraform/k8sapps/disabled/nextcloud.tf.bak diff --git a/terraform/modules/apps/seafile/resources/nginx/conf.d/default.conf b/terraform/k8sapps/disabled/resources/alexpires.me.conf similarity index 55% rename from terraform/modules/apps/seafile/resources/nginx/conf.d/default.conf rename to terraform/k8sapps/disabled/resources/alexpires.me.conf index d352c7b..f59dc33 100644 --- a/terraform/modules/apps/seafile/resources/nginx/conf.d/default.conf +++ b/terraform/k8sapps/disabled/resources/alexpires.me.conf @@ -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; diff --git a/terraform/k8sapps/resources/apache2/99-compression.conf b/terraform/k8sapps/disabled/resources/apache2/99-compression.conf similarity index 100% rename from terraform/k8sapps/resources/apache2/99-compression.conf rename to terraform/k8sapps/disabled/resources/apache2/99-compression.conf diff --git a/terraform/k8sapps/resources/apache2/99-nextcloudworkers.conf b/terraform/k8sapps/disabled/resources/apache2/99-nextcloudworkers.conf similarity index 100% rename from terraform/k8sapps/resources/apache2/99-nextcloudworkers.conf rename to terraform/k8sapps/disabled/resources/apache2/99-nextcloudworkers.conf diff --git a/terraform/k8sapps/resources/chronograf/dashboards/1_host_compute_performance.dashboard b/terraform/k8sapps/disabled/resources/chronograf/dashboards/1_host_compute_performance.dashboard similarity index 100% rename from terraform/k8sapps/resources/chronograf/dashboards/1_host_compute_performance.dashboard rename to terraform/k8sapps/disabled/resources/chronograf/dashboards/1_host_compute_performance.dashboard diff --git a/terraform/k8sapps/resources/chronograf/dashboards/2_disk_capacity.dashboard b/terraform/k8sapps/disabled/resources/chronograf/dashboards/2_disk_capacity.dashboard similarity index 100% rename from terraform/k8sapps/resources/chronograf/dashboards/2_disk_capacity.dashboard rename to terraform/k8sapps/disabled/resources/chronograf/dashboards/2_disk_capacity.dashboard diff --git a/terraform/k8sapps/resources/chronograf/dashboards/3_system_metrics.dashboard.disabled b/terraform/k8sapps/disabled/resources/chronograf/dashboards/3_system_metrics.dashboard.disabled similarity index 100% rename from terraform/k8sapps/resources/chronograf/dashboards/3_system_metrics.dashboard.disabled rename to terraform/k8sapps/disabled/resources/chronograf/dashboards/3_system_metrics.dashboard.disabled diff --git a/terraform/k8sapps/resources/chronograf/dashboards/4_net_interface_metric_explorer.dashboard b/terraform/k8sapps/disabled/resources/chronograf/dashboards/4_net_interface_metric_explorer.dashboard similarity index 100% rename from terraform/k8sapps/resources/chronograf/dashboards/4_net_interface_metric_explorer.dashboard rename to terraform/k8sapps/disabled/resources/chronograf/dashboards/4_net_interface_metric_explorer.dashboard diff --git a/terraform/k8sapps/resources/chronograf/dashboards/5_net_interface_performance.dashboard b/terraform/k8sapps/disabled/resources/chronograf/dashboards/5_net_interface_performance.dashboard similarity index 100% rename from terraform/k8sapps/resources/chronograf/dashboards/5_net_interface_performance.dashboard rename to terraform/k8sapps/disabled/resources/chronograf/dashboards/5_net_interface_performance.dashboard diff --git a/terraform/k8sapps/resources/chronograf/default.org b/terraform/k8sapps/disabled/resources/chronograf/default.org similarity index 100% rename from terraform/k8sapps/resources/chronograf/default.org rename to terraform/k8sapps/disabled/resources/chronograf/default.org diff --git a/terraform/k8sapps/resources/chronograf/internal.kap b/terraform/k8sapps/disabled/resources/chronograf/internal.kap similarity index 100% rename from terraform/k8sapps/resources/chronograf/internal.kap rename to terraform/k8sapps/disabled/resources/chronograf/internal.kap diff --git a/terraform/k8sapps/resources/chronograf/internal.src b/terraform/k8sapps/disabled/resources/chronograf/internal.src similarity index 100% rename from terraform/k8sapps/resources/chronograf/internal.src rename to terraform/k8sapps/disabled/resources/chronograf/internal.src diff --git a/terraform/k8sapps/resources/collabora/coolwsd.xml b/terraform/k8sapps/disabled/resources/collabora/coolwsd.xml similarity index 100% rename from terraform/k8sapps/resources/collabora/coolwsd.xml rename to terraform/k8sapps/disabled/resources/collabora/coolwsd.xml diff --git a/terraform/k8sapps/resources/fluent-bit/fluent-bit.conf b/terraform/k8sapps/disabled/resources/fluent-bit/fluent-bit.conf similarity index 100% rename from terraform/k8sapps/resources/fluent-bit/fluent-bit.conf rename to terraform/k8sapps/disabled/resources/fluent-bit/fluent-bit.conf diff --git a/terraform/k8sapps/resources/fluent-bit/parsers.conf b/terraform/k8sapps/disabled/resources/fluent-bit/parsers.conf similarity index 100% rename from terraform/k8sapps/resources/fluent-bit/parsers.conf rename to terraform/k8sapps/disabled/resources/fluent-bit/parsers.conf diff --git a/terraform/k8sapps/resources/influxdb/init.iql b/terraform/k8sapps/disabled/resources/influxdb/init.iql similarity index 100% rename from terraform/k8sapps/resources/influxdb/init.iql rename to terraform/k8sapps/disabled/resources/influxdb/init.iql diff --git a/terraform/k8sapps/resources/nextcloud-server-snippet.conf b/terraform/k8sapps/disabled/resources/nextcloud-server-snippet.conf similarity index 100% rename from terraform/k8sapps/resources/nextcloud-server-snippet.conf rename to terraform/k8sapps/disabled/resources/nextcloud-server-snippet.conf diff --git a/terraform/k8sapps/resources/telegraf/telegraf.conf b/terraform/k8sapps/disabled/resources/telegraf/telegraf.conf similarity index 100% rename from terraform/k8sapps/resources/telegraf/telegraf.conf rename to terraform/k8sapps/disabled/resources/telegraf/telegraf.conf diff --git a/terraform/k8sapps/iam.tf b/terraform/k8sapps/iam.tf index 3b57a50..9e5eb46 100644 --- a/terraform/k8sapps/iam.tf +++ b/terraform/k8sapps/iam.tf @@ -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" +} diff --git a/terraform/k8sapps/resources/alexpires.me.conf b/terraform/k8sapps/resources/alexpires.me.conf new file mode 100644 index 0000000..f59dc33 --- /dev/null +++ b/terraform/k8sapps/resources/alexpires.me.conf @@ -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; + } +} diff --git a/terraform/k8sapps/secrets.tf b/terraform/k8sapps/secrets.tf index 899deca..0763f59 100644 --- a/terraform/k8sapps/secrets.tf +++ b/terraform/k8sapps/secrets.tf @@ -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 +} + diff --git a/terraform/k8sapps/sectool.env b/terraform/k8sapps/sectool.env index 5fbd136..fdd2d95 100644 --- a/terraform/k8sapps/sectool.env +++ b/terraform/k8sapps/sectool.env @@ -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 \ No newline at end of file +TF_VAR_mail_crypt_public_key=$DOVECOT_CRYPT_PUB_KEY_FILE +TF_VAR_sftpgo_admin_password=$SFTPGO_ADMIN_PASSWORD \ No newline at end of file diff --git a/terraform/modules/apps/gitea/config.tf b/terraform/modules/apps/gitea/config.tf index ec522f6..103c782 100644 --- a/terraform/modules/apps/gitea/config.tf +++ b/terraform/modules/apps/gitea/config.tf @@ -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" } diff --git a/terraform/modules/apps/gitea/database.tf b/terraform/modules/apps/gitea/database.tf new file mode 100644 index 0000000..59ac4d9 --- /dev/null +++ b/terraform/modules/apps/gitea/database.tf @@ -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 +} diff --git a/terraform/modules/apps/gitea/main.tf b/terraform/modules/apps/gitea/main.tf index 26c117b..0a0c1bd 100644 --- a/terraform/modules/apps/gitea/main.tf +++ b/terraform/modules/apps/gitea/main.tf @@ -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 { diff --git a/terraform/modules/apps/gitea/variables.tf b/terraform/modules/apps/gitea/variables.tf index f894477..99ef261 100644 --- a/terraform/modules/apps/gitea/variables.tf +++ b/terraform/modules/apps/gitea/variables.tf @@ -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 diff --git a/terraform/modules/apps/m3uproxy/config.tf b/terraform/modules/apps/m3uproxy/config.tf index a57f61b..0dbd956 100644 --- a/terraform/modules/apps/m3uproxy/config.tf +++ b/terraform/modules/apps/m3uproxy/config.tf @@ -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) } diff --git a/terraform/modules/apps/m3uproxy/geoip.tf b/terraform/modules/apps/m3uproxy/geoip.tf new file mode 100644 index 0000000..7130a9e --- /dev/null +++ b/terraform/modules/apps/m3uproxy/geoip.tf @@ -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 + } + } + } + } + } + } + } +} + diff --git a/terraform/modules/apps/m3uproxy/main.tf b/terraform/modules/apps/m3uproxy/main.tf index 8589962..651973c 100644 --- a/terraform/modules/apps/m3uproxy/main.tf +++ b/terraform/modules/apps/m3uproxy/main.tf @@ -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" diff --git a/terraform/modules/apps/m3uproxy/vpn.tf b/terraform/modules/apps/m3uproxy/vpn.tf new file mode 100644 index 0000000..c835314 --- /dev/null +++ b/terraform/modules/apps/m3uproxy/vpn.tf @@ -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" + } +} diff --git a/terraform/modules/apps/mail/config.tf b/terraform/modules/apps/mail/config.tf index 6099a9b..741b8d2 100644 --- a/terraform/modules/apps/mail/config.tf +++ b/terraform/modules/apps/mail/config.tf @@ -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" + } +} diff --git a/terraform/modules/apps/mail/main.tf b/terraform/modules/apps/mail/main.tf index b9c7beb..b2a7081 100644 --- a/terraform/modules/apps/mail/main.tf +++ b/terraform/modules/apps/mail/main.tf @@ -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"]] } } diff --git a/terraform/modules/apps/mail/resources/mail/dovecot.conf b/terraform/modules/apps/mail/resources/dovecot/dovecot.conf similarity index 100% rename from terraform/modules/apps/mail/resources/mail/dovecot.conf rename to terraform/modules/apps/mail/resources/dovecot/dovecot.conf diff --git a/terraform/modules/apps/mail/resources/mail/sieve b/terraform/modules/apps/mail/resources/dovecot/sieve similarity index 100% rename from terraform/modules/apps/mail/resources/mail/sieve rename to terraform/modules/apps/mail/resources/dovecot/sieve diff --git a/terraform/modules/apps/mail/resources/mail/getmailrc.tpl b/terraform/modules/apps/mail/resources/getmail/getmailrc.tpl similarity index 100% rename from terraform/modules/apps/mail/resources/mail/getmailrc.tpl rename to terraform/modules/apps/mail/resources/getmail/getmailrc.tpl diff --git a/terraform/modules/apps/mail/resources/mail/run.config b/terraform/modules/apps/mail/resources/postfix/run.config similarity index 100% rename from terraform/modules/apps/mail/resources/mail/run.config rename to terraform/modules/apps/mail/resources/postfix/run.config diff --git a/terraform/modules/apps/nginx/config.tf b/terraform/modules/apps/nginx/config.tf index 116c7c0..492abef 100644 --- a/terraform/modules/apps/nginx/config.tf +++ b/terraform/modules/apps/nginx/config.tf @@ -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) } diff --git a/terraform/modules/apps/nginx/main.tf b/terraform/modules/apps/nginx/main.tf index 4b1abe3..076a19e 100644 --- a/terraform/modules/apps/nginx/main.tf +++ b/terraform/modules/apps/nginx/main.tf @@ -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"]] + } } diff --git a/terraform/modules/apps/nginx/resources/nginx/conf.d/default.conf b/terraform/modules/apps/nginx/resources/conf.d/default.conf similarity index 100% rename from terraform/modules/apps/nginx/resources/nginx/conf.d/default.conf rename to terraform/modules/apps/nginx/resources/conf.d/default.conf diff --git a/terraform/modules/apps/nginx/resources/nginx/nginx.conf b/terraform/modules/apps/nginx/resources/nginx.conf similarity index 99% rename from terraform/modules/apps/nginx/resources/nginx/nginx.conf rename to terraform/modules/apps/nginx/resources/nginx.conf index 12c02fa..c258d44 100644 --- a/terraform/modules/apps/nginx/resources/nginx/nginx.conf +++ b/terraform/modules/apps/nginx/resources/nginx.conf @@ -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; } \ No newline at end of file diff --git a/terraform/modules/apps/nginx/variables.tf b/terraform/modules/apps/nginx/variables.tf index ddbacb1..131df0b 100644 --- a/terraform/modules/apps/nginx/variables.tf +++ b/terraform/modules/apps/nginx/variables.tf @@ -14,5 +14,6 @@ variable "websites" { type = map(object({ domain_name = string fqdn = list(string) + config = optional(string, "") })) } diff --git a/terraform/modules/apps/rustdesk/main.tf b/terraform/modules/apps/rustdesk/main.tf index 37fc53d..bd7aa2c 100644 --- a/terraform/modules/apps/rustdesk/main.tf +++ b/terraform/modules/apps/rustdesk/main.tf @@ -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}" diff --git a/terraform/modules/apps/seafile/config.tf b/terraform/modules/apps/seafile/config.tf deleted file mode 100644 index 3545ab4..0000000 --- a/terraform/modules/apps/seafile/config.tf +++ /dev/null @@ -1,3 +0,0 @@ -locals { -} - diff --git a/terraform/modules/apps/seafile/main.tf b/terraform/modules/apps/seafile/main.tf deleted file mode 100644 index 7d02c6b..0000000 --- a/terraform/modules/apps/seafile/main.tf +++ /dev/null @@ -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 = "" # 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 = "" # 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 - } -} diff --git a/terraform/modules/apps/seafile/resources/nginx/nginx.conf b/terraform/modules/apps/seafile/resources/nginx/nginx.conf deleted file mode 100644 index 12c02fa..0000000 --- a/terraform/modules/apps/seafile/resources/nginx/nginx.conf +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/terraform/modules/apps/seafile/variables.tf b/terraform/modules/apps/seafile/variables.tf deleted file mode 100644 index 8b13789..0000000 --- a/terraform/modules/apps/seafile/variables.tf +++ /dev/null @@ -1 +0,0 @@ - diff --git a/terraform/modules/apps/sftpgo/config.tf b/terraform/modules/apps/sftpgo/config.tf new file mode 100644 index 0000000..e09ee7e --- /dev/null +++ b/terraform/modules/apps/sftpgo/config.tf @@ -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) +} + diff --git a/terraform/modules/apps/sftpgo/main.tf b/terraform/modules/apps/sftpgo/main.tf new file mode 100644 index 0000000..37e56d9 --- /dev/null +++ b/terraform/modules/apps/sftpgo/main.tf @@ -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" + } +} diff --git a/terraform/modules/apps/sftpgo/outputs.tf b/terraform/modules/apps/sftpgo/outputs.tf new file mode 100644 index 0000000..5d03ed4 --- /dev/null +++ b/terraform/modules/apps/sftpgo/outputs.tf @@ -0,0 +1,11 @@ +output "path" { + value = local.data_path +} + +output "namespace" { + value = kubernetes_namespace.sftpgo.metadata[0].name +} + +output "app_name" { + value = "sftpgo" +} diff --git a/terraform/modules/apps/seafile/provider.tf b/terraform/modules/apps/sftpgo/provider.tf similarity index 75% rename from terraform/modules/apps/seafile/provider.tf rename to terraform/modules/apps/sftpgo/provider.tf index 8b9fe2f..17ea632 100644 --- a/terraform/modules/apps/seafile/provider.tf +++ b/terraform/modules/apps/sftpgo/provider.tf @@ -9,5 +9,9 @@ terraform { source = "scaleway/scaleway" version = "~>2.13" } + random = { + source = "hashicorp/random" + version = "3.7.2" + } } } diff --git a/terraform/modules/apps/sftpgo/resources/aws.tpl b/terraform/modules/apps/sftpgo/resources/aws.tpl new file mode 100644 index 0000000..585ac94 --- /dev/null +++ b/terraform/modules/apps/sftpgo/resources/aws.tpl @@ -0,0 +1,3 @@ +[default] +aws_access_key_id=${access_key} +aws_secret_access_key=${secret_key} \ No newline at end of file diff --git a/terraform/modules/apps/sftpgo/variables.tf b/terraform/modules/apps/sftpgo/variables.tf new file mode 100644 index 0000000..c004ace --- /dev/null +++ b/terraform/modules/apps/sftpgo/variables.tf @@ -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 +}