diff --git a/bin/occ b/bin/occ new file mode 100755 index 0000000..b0b128d --- /dev/null +++ b/bin/occ @@ -0,0 +1,3 @@ +#!/bin/bash +POD_NAME=$(kubectl get pods -n nextcloud -l app=nextcloud -o jsonpath="{.items[0].metadata.name}") +kubectl -n nextcloud exec -it $POD_NAME -- /bin/su -s /bin/bash www-data -c "/var/www/html/occ $*" \ No newline at end of file diff --git a/terraform/apps/dev-01/apps.tf b/terraform/apps/dev-01/apps.tf index b1ee77f..46f2f9c 100644 --- a/terraform/apps/dev-01/apps.tf +++ b/terraform/apps/dev-01/apps.tf @@ -15,6 +15,7 @@ module "dns" { source = "../../modules/apps/coredns" forward_dns_servers = local.dns_nameservers + override_hosts = local.override_hosts zones = local.zones } @@ -23,3 +24,16 @@ module "reverse_proxy" { services = local.reverse_proxy_services } + + +module "nextcloud" { + source = "../../modules/apps/nextcloud" + + fqdn = local.nextcloud_fqdn + persistent_folder = local.persistent_folder + app_config = local.nextcloud_config + db_credentials_are_secrets = true + + tls_enabled = true + issuer = local.internal_issuer +} diff --git a/terraform/apps/dev-01/config.tf b/terraform/apps/dev-01/config.tf index c5386a6..4b7a5b0 100644 --- a/terraform/apps/dev-01/config.tf +++ b/terraform/apps/dev-01/config.tf @@ -16,6 +16,13 @@ locals { "185.253.5.0" ] + override_hosts = [ + { + name = "cloud.alexpires.me" + ip = "10.19.4.136" + }, + ] + zones = [ { fqdn = "${local.lab_domain}" @@ -88,4 +95,40 @@ locals { } } + scaleway_smtp_host = "smtp.tem.scw.cloud" + + nextcloud_fqdn = "cloud.alexpires.me" + nextcloud_db_passwd = var.nextcloud_db_passwd + nextcloud_db_root_password = var.nextcloud_db_root_password + nextcloud_db_path = "${local.persistent_folder}/mysql/nextcloud" + backup_folder = "/mnt/usb/backups/nextcloud" + nextcloud_config = { + mail_from = "cloud" + mail_domain = "alexpires.me" + smtp_user = var.scaleway_project_id + smtp_password = local.mail_app_api_secret_key + smtp_host = local.scaleway_smtp_host + admin_password = var.nextcloud_admin_password + db_host = module.nextcloud_db.host + db_name = module.nextcloud_db.db_name + db_user = module.nextcloud_db.app_crendentials_name + db_password = module.nextcloud_db.app_crendentials_name + } + + backup_retention_days = 3 + backup_cron_schedule = "0 2 * * *" # Daily at 2 AM + + backup_bucket_name = data.terraform_remote_state.scaleway.outputs.backup_bucket_name + backup_app_api_secret_key = data.terraform_remote_state.scaleway.outputs.backup_app_api_secret_key + backup_app_api_access_key = data.terraform_remote_state.scaleway.outputs.backup_app_api_access_key + mail_app_api_secret_key = data.terraform_remote_state.scaleway.outputs.mail_app_api_secret_key +} + +data "terraform_remote_state" "scaleway" { + backend = "s3" + config = { + bucket = "a13labs.infra.eu" + key = "scaleway.core.infra.tfstate" + region = "eu-west-1" + } } diff --git a/terraform/apps/dev-01/databases.tf b/terraform/apps/dev-01/databases.tf new file mode 100644 index 0000000..6cecc58 --- /dev/null +++ b/terraform/apps/dev-01/databases.tf @@ -0,0 +1,17 @@ +module "nextcloud_db" { + source = "../../modules/db/mariadb" + + namespace = module.nextcloud.namespace + app_name = "nextcloud" + + app_password = local.nextcloud_db_passwd + root_password = local.nextcloud_db_root_password + retention_days = local.backup_retention_days + cron_schedule = local.backup_cron_schedule + + database_folder = local.nextcloud_db_path + backup_folder = local.backup_folder + + tls_enabled = true + issuer = local.internal_issuer +} diff --git a/terraform/apps/dev-01/secrets.tf b/terraform/apps/dev-01/secrets.tf index 8b13789..70bcf54 100644 --- a/terraform/apps/dev-01/secrets.tf +++ b/terraform/apps/dev-01/secrets.tf @@ -1 +1,17 @@ +variable "nextcloud_db_passwd" { + description = "Password for the Nextcloud database" + type = string + sensitive = true +} +variable "nextcloud_db_root_password" { + description = "Root password for the Nextcloud database" + type = string + sensitive = true +} + +variable "nextcloud_admin_password" { + description = "Password for the Nextcloud admin user" + type = string + sensitive = true +} diff --git a/terraform/apps/dev-01/sectool.env b/terraform/apps/dev-01/sectool.env index 865ddf9..794536d 100644 --- a/terraform/apps/dev-01/sectool.env +++ b/terraform/apps/dev-01/sectool.env @@ -1,2 +1,6 @@ AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY +TF_VAR_nextcloud_db_passwd=$MYSQL_NEXTCLOUD_PASSWORD +TF_VAR_nextcloud_db_root_password=$MYSQL_ROOT_PASSWORD +TF_VAR_nextcloud_admin_password=$NEXTCLOUD_ADMIN_PASSWORD +TF_VAR_scaleway_project_id=$SCALEWAY_PROJECT_ID diff --git a/terraform/apps/dev-01/variables.tf b/terraform/apps/dev-01/variables.tf index 8b13789..e1ff0dc 100644 --- a/terraform/apps/dev-01/variables.tf +++ b/terraform/apps/dev-01/variables.tf @@ -1 +1,4 @@ - +variable "scaleway_project_id" { + description = "Scaleway Project Id" + type = string +} diff --git a/terraform/apps/prod-01/apps.tf b/terraform/apps/prod-01/apps.tf index 6da7328..babbad2 100644 --- a/terraform/apps/prod-01/apps.tf +++ b/terraform/apps/prod-01/apps.tf @@ -46,7 +46,7 @@ module "mail" { relay_smtp_host = local.scaleway_smtp_host relay_smtp_port = 465 relay_smtp_username = var.scaleway_project_id - relay_smtp_password = scaleway_iam_api_key.mail_app_api.secret_key + relay_smtp_password = local.mail_app_api_secret_key fetch_emails_schedule = local.fetch_emails_schedule @@ -84,7 +84,7 @@ module "gitea" { smtp_host = local.scaleway_smtp_host smtp_port = local.scaleway_smtp_port smtp_user = var.scaleway_project_id - smtp_passwd = scaleway_iam_api_key.mail_app_api.secret_key + smtp_passwd = local.mail_app_api_secret_key secret_key = var.gitea_secret_key internal_token = var.gitea_internal_token disable_ssh = false @@ -108,11 +108,11 @@ module "sftpgo" { 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 + smtp_password = local.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 + access_key = local.sftpgo_app_api_access_key + secret_key = local.sftpgo_app_api_secret_key } module "trivy" { @@ -124,7 +124,7 @@ module "trivy" { 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 + smtp_password = local.mail_app_api_secret_key from_email = "trivy@${local.primary_domain}" to_email = "c.alexandre.pires@${local.primary_domain}" } diff --git a/terraform/apps/prod-01/backups.tf b/terraform/apps/prod-01/backups.tf index 8bdd6e5..5385110 100644 --- a/terraform/apps/prod-01/backups.tf +++ b/terraform/apps/prod-01/backups.tf @@ -7,9 +7,9 @@ module "mail_backup" { scaleway_organization_id = var.scaleway_organization_id scaleway_project_id = var.scaleway_organization_id - access_key = scaleway_iam_api_key.backup_app_api.access_key - secret_key = scaleway_iam_api_key.backup_app_api.secret_key - bucket_name = scaleway_object_bucket.backup.name + access_key = local.backup_app_api_access_key + secret_key = local.backup_app_api_secret_key + bucket_name = local.backup_bucket_name retention_days = local.local_backup_retention_days cron_schedule = local.mail_files_backup_cron_schedule @@ -26,9 +26,9 @@ module "gitea_backup" { scaleway_organization_id = var.scaleway_organization_id scaleway_project_id = var.scaleway_organization_id - access_key = scaleway_iam_api_key.backup_app_api.access_key - secret_key = scaleway_iam_api_key.backup_app_api.secret_key - bucket_name = scaleway_object_bucket.backup.name + access_key = local.backup_app_api_access_key + secret_key = local.backup_app_api_secret_key + bucket_name = local.backup_bucket_name retention_days = local.local_backup_retention_days cron_schedule = local.gitea_files_backup_cron_schedule @@ -46,9 +46,9 @@ module "sftpgo_backup" { scaleway_organization_id = var.scaleway_organization_id scaleway_project_id = var.scaleway_organization_id - access_key = scaleway_iam_api_key.backup_app_api.access_key - secret_key = scaleway_iam_api_key.backup_app_api.secret_key - bucket_name = scaleway_object_bucket.backup.name + access_key = local.backup_app_api_access_key + secret_key = local.backup_app_api_secret_key + bucket_name = local.backup_bucket_name retention_days = local.local_backup_retention_days cron_schedule = local.sftpgo_files_backup_cron_schedule diff --git a/terraform/apps/prod-01/buckets.tf b/terraform/apps/prod-01/buckets.tf deleted file mode 100644 index 88a350e..0000000 --- a/terraform/apps/prod-01/buckets.tf +++ /dev/null @@ -1,130 +0,0 @@ -resource "random_string" "bucket_suffix" { - length = 8 - lower = true - upper = false - special = false -} - -resource "scaleway_object_bucket" "backup" { - name = "a13labs-backup-${random_string.bucket_suffix.result}" - project_id = var.scaleway_project_id - region = "fr-par" - - lifecycle_rule { - id = "gitea-clean" - prefix = "gitea-backup/" - enabled = true - - expiration { - days = local.cloud_backup_retention_days - } - } - - lifecycle_rule { - id = "wordpress-clean" - prefix = "wordpress-backup/" - enabled = true - - expiration { - days = local.cloud_backup_retention_days - } - } - - lifecycle_rule { - id = "mail-clean" - prefix = "mail-backup/" - enabled = true - - expiration { - days = local.cloud_backup_retention_days - } - } -} - -resource "scaleway_object_bucket_policy" "backup" { - bucket = scaleway_object_bucket.backup.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.backup.name, - "${scaleway_object_bucket.backup.name}/*", - ] - }, - { - Effect = "Allow" - Action = [ - "s3:*", - ] - Principal = { - SCW = "application_id:${scaleway_iam_application.backup_app.id}" - } - Resource = [ - scaleway_object_bucket.backup.name, - "${scaleway_object_bucket.backup.name}/*", - ], - Condition = { - IpAddress = { - "aws:SourceIp" = local.instance_ips - } - }, - }, - ] - }) -} - -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}/*", - ], - Condition = { - IpAddress = { - "aws:SourceIp" = local.instance_ips - } - }, - }, - ] - }) -} diff --git a/terraform/apps/prod-01/config.tf b/terraform/apps/prod-01/config.tf index d4a7a95..be23b4a 100644 --- a/terraform/apps/prod-01/config.tf +++ b/terraform/apps/prod-01/config.tf @@ -44,7 +44,6 @@ locals { # 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" sftpgo_backup_path = "${local.persistent_folder}/backup.sftpgo" @@ -108,43 +107,47 @@ locals { "Connection" = "upgrade" } }, - # { - # private = true - # path = "/tools/gitea" - # upstream = "http://10.19.4.136:8000" - # rewrite = "^/tools/gitea/(.*)$ /$1 break" - # }, { path = "/" }, ] }, + "nextcloud" = { + http_port = 8081 + https_port = 8444 + custom_ingress_annotations = { + "nginx.ingress.kubernetes.io/proxy-body-size" = "4G" + "nginx.ingress.kubernetes.io/proxy-request-buffering" = "on" + "nginx.ingress.kubernetes.io/proxy-buffer-size" = "32k" + "nginx.ingress.kubernetes.io/proxy-buffers-number" = "16" + } + tls = true + custom_snippet = file("${path.module}/resources/nextcloud.conf") + resolver = "10.19.4.136" + fqdn = ["cloud.alexpires.me"] + upstream = "https://cloud.alexpires.me" + locations = [ + { + path = "/" + }, + ] + }, + } - - # VPS configuration - instance_ips = [ - "${local.vps_1.ip}/32", - ] - - vps_1 = { - id = data.terraform_remote_state.contabo.outputs.instances[0].id - name = data.terraform_remote_state.contabo.outputs.instances[0].name - ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip - } - + backup_bucket_name = data.terraform_remote_state.scaleway.outputs.backup_bucket_name + backup_app_api_secret_key = data.terraform_remote_state.scaleway.outputs.backup_app_api_secret_key + backup_app_api_access_key = data.terraform_remote_state.scaleway.outputs.backup_app_api_access_key + mail_app_api_secret_key = data.terraform_remote_state.scaleway.outputs.mail_app_api_secret_key + sftpgo_app_api_access_key = data.terraform_remote_state.scaleway.outputs.sftpgo_app_api_access_key + sftpgo_app_api_secret_key = data.terraform_remote_state.scaleway.outputs.sftpgo_app_api_secret_key } -data "scaleway_account_project" "default" { - project_id = var.scaleway_project_id - organization_id = var.scaleway_organization_id -} - -data "terraform_remote_state" "contabo" { +data "terraform_remote_state" "scaleway" { backend = "s3" config = { bucket = "a13labs.infra.eu" - key = "contabo.core.infra.tfstate" + key = "scaleway.core.infra.tfstate" region = "eu-west-1" } } diff --git a/terraform/apps/prod-01/provider.tf b/terraform/apps/prod-01/provider.tf index a38af38..ba14014 100644 --- a/terraform/apps/prod-01/provider.tf +++ b/terraform/apps/prod-01/provider.tf @@ -21,10 +21,6 @@ terraform { source = "hashicorp/kubernetes" version = "2.36.0" } - scaleway = { - source = "scaleway/scaleway" - version = "~>2.13" - } } } @@ -34,11 +30,4 @@ provider "kubernetes" { insecure = true } -provider "scaleway" { - zone = "fr-par-2" - region = "fr-par" - access_key = var.scaleway_access_key - secret_key = var.scaleway_secret_key - organization_id = var.scaleway_organization_id -} diff --git a/terraform/apps/prod-01/resources/nextcloud.conf b/terraform/apps/prod-01/resources/nextcloud.conf new file mode 100644 index 0000000..10fd3d0 --- /dev/null +++ b/terraform/apps/prod-01/resources/nextcloud.conf @@ -0,0 +1,32 @@ +server_tokens off; +proxy_hide_header X-Powered-By; + +location = /.well-known/webfinger { + return 301 $scheme://$host/index.php/.well-known/webfinger; +} + +location = /.well-known/nodeinfo { + return 301 $scheme://$host/index.php/.well-known/nodeinfo; +} + +location = /.well-known/carddav { + return 301 $scheme://$host/remote.php/dav; +} + +location = /.well-known/caldav { + return 301 $scheme://$host/remote.php/dav; +} + +location = /robots.txt { + allow all; + log_not_found off; + access_log off; +} + +location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { + deny all; +} + +location ~ ^/(?:autotest|occ|issue|indie|db_|console) { + deny all; +} \ No newline at end of file diff --git a/terraform/apps/prod-01/secrets.tf b/terraform/apps/prod-01/secrets.tf index 0588c8c..c5f5400 100644 --- a/terraform/apps/prod-01/secrets.tf +++ b/terraform/apps/prod-01/secrets.tf @@ -11,18 +11,6 @@ variable "gitea_mysql_password" { sensitive = true } -variable "scaleway_access_key" { - description = "Scaleway Access key" - type = string - sensitive = true -} - -variable "scaleway_secret_key" { - description = "Scaleway Secret key" - type = string - sensitive = true -} - variable "wireguard_private_key" { description = "Wireguard public key" type = string diff --git a/terraform/apps/prod-01/sectool.env b/terraform/apps/prod-01/sectool.env index 76df3bf..e2ab170 100644 --- a/terraform/apps/prod-01/sectool.env +++ b/terraform/apps/prod-01/sectool.env @@ -1,9 +1,6 @@ AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY -TF_VAR_scaleway_access_key=$SCALEWAY_ACCESS_KEY -TF_VAR_scaleway_secret_key=$SCALEWAY_SECRET_KEY TF_VAR_scaleway_project_id=$SCALEWAY_PROJECT_ID -TF_VAR_scaleway_user_id=$SCALEWAY_USER_ID TF_VAR_scaleway_organization_id=$SCALEWAY_ORGANIZATION_ID TF_VAR_mysql_root_password=$MYSQL_ROOT_PASSWORD TF_VAR_wordpress_mysql_password=$MYSQL_WORDPRESS_PASSWORD diff --git a/terraform/apps/prod-01/variables.tf b/terraform/apps/prod-01/variables.tf index 3c1f094..0251eec 100644 --- a/terraform/apps/prod-01/variables.tf +++ b/terraform/apps/prod-01/variables.tf @@ -1,8 +1,3 @@ -variable "scaleway_user_id" { - description = "Scaleway User Id" - type = string -} - variable "scaleway_project_id" { description = "Scaleway Project Id" type = string diff --git a/terraform/iac/scaleway/buckets.tf b/terraform/iac/scaleway/buckets.tf index 82b6475..220c439 100644 --- a/terraform/iac/scaleway/buckets.tf +++ b/terraform/iac/scaleway/buckets.tf @@ -43,3 +43,125 @@ resource "scaleway_object_bucket_policy" "policy" { ] }) } + +resource "random_string" "bucket_suffix" { + length = 8 + lower = true + upper = false + special = false +} + +resource "scaleway_object_bucket" "backup" { + name = "a13labs-backup-${random_string.bucket_suffix.result}" + project_id = var.scaleway_project_id + region = "fr-par" + + lifecycle_rule { + id = "gitea-clean" + prefix = "gitea-backup/" + enabled = true + + expiration { + days = local.cloud_backup_retention_days + } + } + + lifecycle_rule { + id = "mail-clean" + prefix = "mail-backup/" + enabled = true + + expiration { + days = local.cloud_backup_retention_days + } + } +} + +resource "scaleway_object_bucket_policy" "backup" { + bucket = scaleway_object_bucket.backup.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.backup.name, + "${scaleway_object_bucket.backup.name}/*", + ] + }, + { + Effect = "Allow" + Action = [ + "s3:*", + ] + Principal = { + SCW = "application_id:${scaleway_iam_application.backup_app.id}" + } + Resource = [ + scaleway_object_bucket.backup.name, + "${scaleway_object_bucket.backup.name}/*", + ], + Condition = { + IpAddress = { + "aws:SourceIp" = local.instance_ips + } + }, + }, + ] + }) +} + +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}/*", + ], + Condition = { + IpAddress = { + "aws:SourceIp" = local.instance_ips + } + }, + }, + ] + }) +} + diff --git a/terraform/iac/scaleway/config.tf b/terraform/iac/scaleway/config.tf index 5fe00ad..813a871 100644 --- a/terraform/iac/scaleway/config.tf +++ b/terraform/iac/scaleway/config.tf @@ -3,6 +3,8 @@ locals { "${local.vps_1.ip}/32", ] + cloud_backup_retention_days = 3 + vps_1 = { id = data.terraform_remote_state.contabo.outputs.instances[0].id name = data.terraform_remote_state.contabo.outputs.instances[0].name @@ -19,3 +21,7 @@ data "terraform_remote_state" "contabo" { } } +data "scaleway_account_project" "default" { + project_id = var.scaleway_project_id + organization_id = var.scaleway_organization_id +} diff --git a/terraform/apps/prod-01/iam.tf b/terraform/iac/scaleway/iam.tf similarity index 99% rename from terraform/apps/prod-01/iam.tf rename to terraform/iac/scaleway/iam.tf index 4529a99..504efb8 100644 --- a/terraform/apps/prod-01/iam.tf +++ b/terraform/iac/scaleway/iam.tf @@ -2,14 +2,6 @@ resource "scaleway_iam_application" "backup_app" { name = "k8s_backup_app" } -resource "scaleway_iam_application" "mail_app" { - name = "mail_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" @@ -26,6 +18,10 @@ resource "scaleway_iam_policy" "object_read_write_backup" { } } +resource "scaleway_iam_application" "mail_app" { + name = "mail_app" +} + resource "scaleway_iam_policy" "email_full_access" { name = "Email full access policy" description = "Gives access to transactional email in project" @@ -39,6 +35,9 @@ resource "scaleway_iam_policy" "email_full_access" { } } +resource "scaleway_iam_application" "sftpgo_app" { + name = "sftpgo_app" +} resource "scaleway_iam_policy" "object_read_write_sftpgo" { name = "SFtpGo app policy" diff --git a/terraform/iac/scaleway/outputs.tf b/terraform/iac/scaleway/outputs.tf new file mode 100644 index 0000000..8486678 --- /dev/null +++ b/terraform/iac/scaleway/outputs.tf @@ -0,0 +1,34 @@ +output "backup_bucket_name" { + description = "The name of the backup bucket." + value = scaleway_object_bucket.backup.name +} + +output "backup_app_api_secret_key" { + description = "The secret key for the backup API." + value = scaleway_iam_api_key.backup_app_api.secret_key + sensitive = true +} + +output "backup_app_api_access_key" { + description = "The access key for the backup API." + value = scaleway_iam_api_key.backup_app_api.access_key + sensitive = true +} + +output "mail_app_api_secret_key" { + description = "The secret key for the mail app API." + value = scaleway_iam_api_key.mail_app_api.secret_key + sensitive = true +} + +output "sftpgo_app_api_access_key" { + description = "The access key for the SFTPGo app API." + value = scaleway_iam_api_key.sftpgo_app_api.access_key + sensitive = true +} + +output "sftpgo_app_api_secret_key" { + description = "The secret key for the SFTPGo app API." + value = scaleway_iam_api_key.sftpgo_app_api.secret_key + sensitive = true +} diff --git a/terraform/modules/apps/coredns/config.tf b/terraform/modules/apps/coredns/config.tf index 12195f5..ccf6790 100644 --- a/terraform/modules/apps/coredns/config.tf +++ b/terraform/modules/apps/coredns/config.tf @@ -2,6 +2,8 @@ locals { configfile = templatefile("${path.module}/resources/Corefile.tpl", { zones = var.zones + override_hosts = length(var.override_hosts) > 0 + hosts = var.override_hosts forward_dns_servers = join(" ", var.forward_dns_servers) }) configfile_checksum = md5(local.configfile) diff --git a/terraform/modules/apps/coredns/resources/Corefile.tpl b/terraform/modules/apps/coredns/resources/Corefile.tpl index be170ae..84ff828 100644 --- a/terraform/modules/apps/coredns/resources/Corefile.tpl +++ b/terraform/modules/apps/coredns/resources/Corefile.tpl @@ -1,4 +1,12 @@ .:53 { +%{ if override_hosts ~} + hosts { +%{ for h in hosts ~} + ${h.ip} ${h.name} +%{ endfor ~} + fallthrough + } +%{ endif ~} errors health { lameduck 5s diff --git a/terraform/modules/apps/coredns/variables.tf b/terraform/modules/apps/coredns/variables.tf index 4241c9d..b587f79 100644 --- a/terraform/modules/apps/coredns/variables.tf +++ b/terraform/modules/apps/coredns/variables.tf @@ -10,6 +10,15 @@ variable "forward_dns_servers" { default = ["8.8.8.8", "8.8.4.4"] } +variable "override_hosts" { + description = "Override hosts" + type = list(object({ + ip = string + name = string + })) + default = [] +} + variable "zones" { description = "Zones to be managed by coredns" type = list(object({ diff --git a/terraform/modules/apps/nextcloud/config.tf b/terraform/modules/apps/nextcloud/config.tf new file mode 100644 index 0000000..2e402b8 --- /dev/null +++ b/terraform/modules/apps/nextcloud/config.tf @@ -0,0 +1,90 @@ +locals { + persistent_folder = var.persistent_folder + + database_credentials = { + MYSQL_USER = { + key = "username" + name = var.app_config.db_user + } + + MYSQL_PASSWORD = { + key = "password" + name = var.app_config.db_password + } + } + + nextcloud_env_vars = merge({ + # Database configuration + MYSQL_DATABASE = var.app_config.db_name + MYSQL_HOST = var.app_config.db_host + + # Email configuration + SMTP_HOST = var.app_config.smtp_host + SMTP_SECURE = var.app_config.smtp_secure + SMTP_PORT = var.app_config.smtp_port + MAIL_FROM_ADDRESS = var.app_config.mail_from + MAIL_DOMAIN = var.app_config.mail_domain + SMTP_AUTHTYPE = "PLAIN" + + # Redis configuration + REDIS_HOST = "redis" + + # General + NEXTCLOUD_TRUSTED_DOMAINS = var.fqdn + TRUSTED_PROXIES = join(" ", ["10.1.0.0/16"]) + OVERWRITEHOST = var.fqdn + OVERWRITEPROTOCOL = "https" + OVERWRITECLIURL = "https://${var.fqdn}" + + # PHP + PHP_MEMORY_LIMIT = "512M" + }, var.db_credentials_are_secrets ? {} : local.database_credentials) + + nextcloud_secrets = merge({ + + SMTP_NAME = { + key = "username" + name = kubernetes_secret.nextcloud_mail_credentials.metadata[0].name + } + + SMTP_PASSWORD = { + key = "password" + name = kubernetes_secret.nextcloud_mail_credentials.metadata[0].name + } + + NEXTCLOUD_ADMIN_USER = { + key = "username" + name = kubernetes_secret.nextcloud_admin_credentials.metadata[0].name + } + + NEXTCLOUD_ADMIN_PASSWORD = { + key = "password" + name = kubernetes_secret.nextcloud_admin_credentials.metadata[0].name + } + }, var.db_credentials_are_secrets ? local.database_credentials : {}) + + + nextcloud_data = "${local.persistent_folder}/nextcloud" + + apache_confs = { + for f in fileset("${path.module}/resources/apache2/conf-enabled/", "*.conf") : + "${f}" => file("${path.module}/resources/apache2/conf-enabled//${f}") + } + apache_mods_load = { + for f in fileset("${path.module}/resources/apache2/mods-enabled/", "*.cload") : + "${f}" => file("${path.module}/resources/apache2/mods-enabled//${f}") + } + apache_mods_conf = { + for f in fileset("${path.module}/resources/apache2/mods-enabled/", "*.conf") : + "${f}" => file("${path.module}/resources/apache2/mods-enabled//${f}") + } + apache_sites = { + for f in fileset("${path.module}/resources/apache2/sites-enabled/", "*.conf") : + "${f}" => file("${path.module}/resources/apache2/sites-enabled//${f}") + } + + apache_confs_checksum = sha256(jsonencode(local.apache_confs)) + apache_sites_checksum = sha256(jsonencode(local.apache_sites)) + apache_mods_load_checksum = sha256(jsonencode(local.apache_mods_load)) + apache_mods_conf_checksum = sha256(jsonencode(local.apache_mods_conf)) +} diff --git a/terraform/modules/apps/nextcloud/cron.tf b/terraform/modules/apps/nextcloud/cron.tf new file mode 100644 index 0000000..7a14224 --- /dev/null +++ b/terraform/modules/apps/nextcloud/cron.tf @@ -0,0 +1,54 @@ +resource "kubernetes_cron_job_v1" "nextcloud_cron_apache" { + depends_on = [ + kubernetes_deployment.nextcloud_apache + ] + metadata { + namespace = kubernetes_namespace.nextcloud.metadata[0].name + name = "cronjob-trigger" + } + spec { + schedule = "*/15 * * * *" + concurrency_policy = "Forbid" + failed_jobs_history_limit = 2 + successful_jobs_history_limit = 2 + job_template { + metadata { + labels = { + app = "cronjob-trigger" + } + } + spec { + backoff_limit = 1 + parallelism = 1 + completions = 1 + active_deadline_seconds = 300 + template { + metadata { + labels = { + app = "cronjob-trigger" + } + } + spec { + container { + name = "nextcloud" + image = "nextcloud:${var.tag}" + + command = ["curl"] + args = ["--fail", "-L", "http://http/cron.php"] + security_context { + allow_privilege_escalation = false + } + } + restart_policy = "Never" + termination_grace_period_seconds = 30 + } + } + } + } + } + lifecycle { + replace_triggered_by = [ + kubernetes_deployment.nextcloud_apache + ] + } +} diff --git a/terraform/modules/apps/nextcloud/ingress.tf b/terraform/modules/apps/nextcloud/ingress.tf new file mode 100644 index 0000000..958f055 --- /dev/null +++ b/terraform/modules/apps/nextcloud/ingress.tf @@ -0,0 +1,67 @@ +resource "kubernetes_service" "nextcloud_apache" { + metadata { + name = "http" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + spec { + port { + port = var.tls_enabled ? 443 : 80 + target_port = var.tls_enabled ? 443 : 80 + } + selector = { + app = "nextcloud" + } + cluster_ip = "None" + } +} + +resource "kubernetes_ingress_v1" "nextcloud_ingress" { + depends_on = [ + kubernetes_deployment.nextcloud_apache + ] + metadata { + name = "ingress" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + + annotations = merge({ + "kubernetes.io/ingress.class" = "public" + "cert-manager.io/cluster-issuer" = "letsencrypt-prod" + "kubernetes.io/tls-acme" = "true" + "nginx.ingress.kubernetes.io/ssl-redirect" = "true" + "nginx.ingress.kubernetes.io/proxy-body-size" = "4G" + "nginx.ingress.kubernetes.io/proxy-request-buffering" = "on" + "nginx.ingress.kubernetes.io/proxy-buffer-size" = "32k" + "nginx.ingress.kubernetes.io/proxy-buffers-number" = "16" + "nginx.ingress.kubernetes.io/server-snippet" = file("${path.module}/resources/nextcloud-server-snippet.conf") + }, + var.tls_enabled ? { + "nginx.org/ssl-services" = "http" + "nginx.org/ssl-redirect" = "true" + "nginx.org/redirect-to-https" = "true" + "nginx.ingress.kubernetes.io/backend-protocol" = "HTTPS" + } : {} + ) + } + spec { + tls { + hosts = [var.fqdn] + secret_name = "nextcloud-tls" + } + rule { + host = var.fqdn + http { + path { + backend { + service { + name = "http" + port { + number = var.tls_enabled ? 443 : 80 + } + } + } + } + } + } + } +} + diff --git a/terraform/modules/apps/nextcloud/main.tf b/terraform/modules/apps/nextcloud/main.tf new file mode 100644 index 0000000..f3add72 --- /dev/null +++ b/terraform/modules/apps/nextcloud/main.tf @@ -0,0 +1,285 @@ +resource "kubernetes_namespace" "nextcloud" { + metadata { + annotations = { + name = "nextcloud" + } + + labels = { + name = "nextcloud" + } + + name = "nextcloud" + } +} + +resource "kubernetes_manifest" "internal_cert" { + count = var.tls_enabled ? 1 : 0 + manifest = { + apiVersion = "cert-manager.io/v1" + kind = "Certificate" + metadata = { + name = "internal-cert" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + spec = { + secretName = "internal-cert" + issuerRef = { + name = var.issuer + kind = "ClusterIssuer" + } + commonName = var.fqdn + dnsNames = [var.fqdn] + } + } +} + +resource "kubernetes_config_map" "apache_confs" { + metadata { + name = "nextcloud-apache-confs" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = local.apache_confs +} + +resource "kubernetes_config_map" "apache_mods_load" { + metadata { + name = "nextcloud-apache-mods-load" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = local.apache_mods_load +} + +resource "kubernetes_config_map" "apache_mods_conf" { + metadata { + name = "nextcloud-apache-mods-enabled" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = local.apache_mods_conf +} + +resource "kubernetes_config_map" "apache_sites" { + metadata { + name = "nextcloud-apache-sites" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = local.apache_sites +} + +resource "kubernetes_service_account" "nextcloud_service_account" { + + metadata { + name = "nextcloud-app-sa" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + + automount_service_account_token = false +} + + +resource "kubernetes_deployment" "nextcloud_apache" { + + depends_on = [ + kubernetes_deployment.nextcloud_redis + ] + + metadata { + name = "nextcloud-app" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + spec { + selector { + match_labels = { + app = "nextcloud" + } + } + strategy { + type = "Recreate" + } + template { + metadata { + labels = { + app = "nextcloud" + } + annotations = { + "checksum/apache_confs" = local.apache_confs_checksum + "checksum/apache_sites" = local.apache_sites_checksum + "checksum/apache_mods_load" = local.apache_mods_load_checksum + "checksum/apache_mods_conf" = local.apache_mods_conf_checksum + } + } + spec { + service_account_name = kubernetes_service_account.nextcloud_service_account.metadata[0].name + + container { + name = "nextcloud" + image = "nextcloud:${var.tag}" + image_pull_policy = "Always" + + resources { + requests = { + memory = "200Mi" + } + } + + readiness_probe { + http_get { + port = "http" + path = "/status.php" + } + initial_delay_seconds = 30 + period_seconds = 10 + success_threshold = 1 + failure_threshold = 3 + } + + liveness_probe { + tcp_socket { + port = "http" + } + initial_delay_seconds = 5 + period_seconds = 10 + success_threshold = 1 + failure_threshold = 3 + } + + dynamic "env" { + for_each = local.nextcloud_env_vars + content { + name = env.key + value = env.value + } + } + + security_context { + allow_privilege_escalation = false + } + + dynamic "env" { + for_each = local.nextcloud_secrets + content { + name = env.key + value_from { + secret_key_ref { + key = env.value.key + name = env.value.name + } + } + } + } + port { + container_port = 80 + name = "http" + } + dynamic "port" { + for_each = var.tls_enabled ? [1] : [] + content { + container_port = 443 + name = "https" + } + } + volume_mount { + mount_path = "/var/www/html" + name = "html-data" + } + dynamic "volume_mount" { + for_each = local.apache_confs + content { + mount_path = "/etc/apache2/conf-enabled/${volume_mount.key}" + name = "apache-confs" + sub_path = volume_mount.key + read_only = true + } + } + dynamic "volume_mount" { + for_each = local.apache_sites + content { + mount_path = "/etc/apache2/sites-enabled/${volume_mount.key}" + name = "apache-sites" + sub_path = volume_mount.key + read_only = true + } + } + dynamic "volume_mount" { + for_each = local.apache_mods_load + content { + mount_path = "/etc/apache2/mods-enabled/${volume_mount.key}" + name = "apache-mods-load" + sub_path = volume_mount.key + read_only = true + } + } + dynamic "volume_mount" { + for_each = local.apache_mods_conf + content { + mount_path = "/etc/apache2/mods-enabled/${volume_mount.key}" + name = "apache-mods-conf" + sub_path = volume_mount.key + read_only = true + } + } + dynamic "volume_mount" { + for_each = var.tls_enabled ? [1] : [] + content { + mount_path = "/etc/ssl/certs/private" + name = "internal-cert" + read_only = true + } + } + } + volume { + name = "html-data" + host_path { + path = local.nextcloud_data + } + } + volume { + name = "apache-confs" + config_map { + name = kubernetes_config_map.apache_confs.metadata[0].name + } + } + volume { + name = "apache-sites" + config_map { + name = kubernetes_config_map.apache_sites.metadata[0].name + } + } + volume { + name = "apache-mods-load" + config_map { + name = kubernetes_config_map.apache_mods_load.metadata[0].name + } + } + volume { + name = "apache-mods-conf" + config_map { + name = kubernetes_config_map.apache_mods_conf.metadata[0].name + } + } + dynamic "volume" { + for_each = var.tls_enabled ? [1] : [] + content { + name = "internal-cert" + secret { + secret_name = kubernetes_manifest.internal_cert[0].manifest["metadata"]["name"] + items { + key = "tls.crt" + path = "tls.crt" + } + items { + key = "tls.key" + path = "tls.key" + } + } + } + } + } + } + } + lifecycle { + replace_triggered_by = [ + kubernetes_deployment.nextcloud_redis + ] + } +} + diff --git a/terraform/modules/apps/nextcloud/outputs.tf b/terraform/modules/apps/nextcloud/outputs.tf new file mode 100644 index 0000000..ac68835 --- /dev/null +++ b/terraform/modules/apps/nextcloud/outputs.tf @@ -0,0 +1,4 @@ +output "namespace" { + description = "value of namespace" + value = kubernetes_namespace.nextcloud.metadata[0].name +} diff --git a/terraform/modules/apps/nextcloud/provider.tf b/terraform/modules/apps/nextcloud/provider.tf new file mode 100644 index 0000000..2eaa508 --- /dev/null +++ b/terraform/modules/apps/nextcloud/provider.tf @@ -0,0 +1,9 @@ +terraform { + required_version = "~>1.8" + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.36.0" + } + } +} diff --git a/terraform/modules/apps/nextcloud/redis.tf b/terraform/modules/apps/nextcloud/redis.tf new file mode 100644 index 0000000..63da2f6 --- /dev/null +++ b/terraform/modules/apps/nextcloud/redis.tf @@ -0,0 +1,76 @@ +resource "kubernetes_service" "nextcloud_redis" { + metadata { + name = "redis" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + spec { + port { + port = 6379 + name = "redis" + } + selector = { + app = "redis" + } + cluster_ip = "None" + } +} + +resource "kubernetes_deployment" "nextcloud_redis" { + metadata { + name = "redis" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + spec { + selector { + match_labels = { + app = "redis" + } + } + strategy { + type = "RollingUpdate" + } + template { + metadata { + labels = { + app = "redis" + } + } + spec { + container { + name = "redis" + image = "redis:latest" + + security_context { + allow_privilege_escalation = false + } + + readiness_probe { + tcp_socket { + port = "redis" + } + initial_delay_seconds = 10 + period_seconds = 15 + success_threshold = 1 + failure_threshold = 3 + } + + liveness_probe { + tcp_socket { + port = "redis" + } + initial_delay_seconds = 10 + period_seconds = 15 + success_threshold = 1 + failure_threshold = 3 + } + + port { + container_port = 6379 + name = "redis" + protocol = "TCP" + } + } + } + } + } +} diff --git a/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-compression.conf b/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-compression.conf new file mode 100644 index 0000000..2366fb1 --- /dev/null +++ b/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-compression.conf @@ -0,0 +1,14 @@ + + # Enable compression for the following content types + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE application/json + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE image/svg+xml + AddOutputFilterByType DEFLATE text/xml + + +# Do not compress images +SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|woff|woff2)$ no-gzip diff --git a/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-nextcloudworkers.conf b/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-nextcloudworkers.conf new file mode 100644 index 0000000..72e34fe --- /dev/null +++ b/terraform/modules/apps/nextcloud/resources/apache2/conf-enabled/99-nextcloudworkers.conf @@ -0,0 +1 @@ +MaxRequestWorkers 10 \ No newline at end of file diff --git a/terraform/modules/apps/nextcloud/resources/apache2/mods-enabled/ssl.conf b/terraform/modules/apps/nextcloud/resources/apache2/mods-enabled/ssl.conf new file mode 100644 index 0000000..4456743 --- /dev/null +++ b/terraform/modules/apps/nextcloud/resources/apache2/mods-enabled/ssl.conf @@ -0,0 +1,86 @@ +LoadModule socache_shmcb_module /usr/lib/apache2/modules/mod_socache_shmcb.so +LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so + +# Pseudo Random Number Generator (PRNG): +# Configure one or more sources to seed the PRNG of the SSL library. +# The seed data should be of good random quality. +# WARNING! On some platforms /dev/random blocks if not enough entropy +# is available. This means you then cannot use the /dev/random device +# because it would lead to very long connection times (as long as +# it requires to make more entropy available). But usually those +# platforms additionally provide a /dev/urandom device which doesn't +# block. So, if available, use this one instead. Read the mod_ssl User +# Manual for more details. +# +SSLRandomSeed startup builtin +SSLRandomSeed startup file:/dev/urandom 512 +SSLRandomSeed connect builtin +SSLRandomSeed connect file:/dev/urandom 512 + +## +## SSL Global Context +## +## All SSL configuration in this context applies both to +## the main server and all SSL-enabled virtual hosts. +## + +# +# Some MIME-types for downloading Certificates and CRLs +# +AddType application/x-x509-ca-cert .crt +AddType application/x-pkcs7-crl .crl + +# Pass Phrase Dialog: +# Configure the pass phrase gathering process. +# The filtering dialog program (`builtin' is a internal +# terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase + +# Inter-Process Session Cache: +# Configure the SSL Session Cache: First the mechanism +# to use and second the expiring timeout (in seconds). +# (The mechanism dbm has known memory leaks and should not be used). +#SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache +SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000) +SSLSessionCacheTimeout 300 + +# Semaphore: +# Configure the path to the mutual exclusion semaphore the +# SSL engine uses internally for inter-process synchronization. +# (Disabled by default, the global Mutex directive consolidates by default +# this) +#Mutex file:${APACHE_LOCK_DIR}/ssl_mutex ssl-cache + + +# SSL Cipher Suite: +# List the ciphers that the client is permitted to negotiate. See the +# ciphers(1) man page from the openssl package for list of all available +# options. +# Enable only secure ciphers: +SSLCipherSuite HIGH:!aNULL + +# SSL server cipher order preference: +# Use server priorities for cipher algorithm choice. +# Clients may prefer lower grade encryption. You should enable this +# option if you want to enforce stronger encryption, and can afford +# the CPU cost, and did not override SSLCipherSuite in a way that puts +# insecure ciphers first. +# Default: Off +#SSLHonorCipherOrder on + +# The protocols to enable. +# Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2 +# SSL v2 is no longer supported +SSLProtocol all -SSLv3 + +# Allow insecure renegotiation with clients which do not yet support the +# secure renegotiation protocol. Default: Off +#SSLInsecureRenegotiation on + +# Whether to forbid non-SNI clients to access name based virtual hosts. +# Default: Off +#SSLStrictSNIVHostCheck On + +# Warning: Session Tickets require regular reloading of the server! +# Make sure you do this (e.g. via logrotate) before changing this setting! +SSLSessionTickets off diff --git a/terraform/modules/apps/nextcloud/resources/apache2/sites-enabled/999-default.conf b/terraform/modules/apps/nextcloud/resources/apache2/sites-enabled/999-default.conf new file mode 100644 index 0000000..662f3d6 --- /dev/null +++ b/terraform/modules/apps/nextcloud/resources/apache2/sites-enabled/999-default.conf @@ -0,0 +1,11 @@ + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + SSLEngine on + SSLCertificateFile /etc/ssl/certs/private/tls.crt + SSLCertificateKeyFile /etc/ssl/certs/private/tls.key + \ No newline at end of file diff --git a/terraform/modules/apps/nextcloud/resources/enable_ssl.sh b/terraform/modules/apps/nextcloud/resources/enable_ssl.sh new file mode 100644 index 0000000..e69de29 diff --git a/terraform/modules/apps/nextcloud/resources/nextcloud-server-snippet.conf b/terraform/modules/apps/nextcloud/resources/nextcloud-server-snippet.conf new file mode 100644 index 0000000..10fd3d0 --- /dev/null +++ b/terraform/modules/apps/nextcloud/resources/nextcloud-server-snippet.conf @@ -0,0 +1,32 @@ +server_tokens off; +proxy_hide_header X-Powered-By; + +location = /.well-known/webfinger { + return 301 $scheme://$host/index.php/.well-known/webfinger; +} + +location = /.well-known/nodeinfo { + return 301 $scheme://$host/index.php/.well-known/nodeinfo; +} + +location = /.well-known/carddav { + return 301 $scheme://$host/remote.php/dav; +} + +location = /.well-known/caldav { + return 301 $scheme://$host/remote.php/dav; +} + +location = /robots.txt { + allow all; + log_not_found off; + access_log off; +} + +location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { + deny all; +} + +location ~ ^/(?:autotest|occ|issue|indie|db_|console) { + deny all; +} \ No newline at end of file diff --git a/terraform/modules/apps/nextcloud/secrets.tf b/terraform/modules/apps/nextcloud/secrets.tf new file mode 100644 index 0000000..4b123a8 --- /dev/null +++ b/terraform/modules/apps/nextcloud/secrets.tf @@ -0,0 +1,24 @@ +resource "kubernetes_secret" "nextcloud_mail_credentials" { + metadata { + name = "nextcloud-mail-credentials" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = { + username = var.app_config.smtp_user + password = var.app_config.smtp_password + } + type = "Opaque" +} + +resource "kubernetes_secret" "nextcloud_admin_credentials" { + metadata { + name = "nextcloud-admin-credentials" + namespace = kubernetes_namespace.nextcloud.metadata[0].name + } + data = { + username = var.app_config.admin_username + password = var.app_config.admin_password + } + type = "Opaque" +} + diff --git a/terraform/modules/apps/nextcloud/variables.tf b/terraform/modules/apps/nextcloud/variables.tf new file mode 100644 index 0000000..e93ae7b --- /dev/null +++ b/terraform/modules/apps/nextcloud/variables.tf @@ -0,0 +1,52 @@ +variable "persistent_folder" { + description = "The path to the persistent folder" + type = string +} + +variable "tag" { + description = "The version of the websites to install" + type = string + default = "30-apache" +} + +variable "fqdn" { + description = "The fully qualified domain name for the Rustdesk server" + type = string +} + +variable "tls_enabled" { + description = "Enable TLS for the SFTPGo server" + type = bool + default = true +} + +variable "issuer" { + description = "The issuer for the certificate" + type = string + default = "internal-ca" +} + +variable "db_credentials_are_secrets" { + description = "set to true if the database credentials are secrets" + type = bool + default = false +} + +variable "app_config" { + description = "The configuration for the SFTPGo server" + type = object({ + mail_from = string + mail_domain = string + smtp_user = string + smtp_password = string + smtp_host = string + admin_password = string + db_host = string + db_name = string + db_user = string + db_password = string + smtp_port = optional(number, 465) + smtp_secure = optional(string, "ssl") + admin_username = optional(string, "admin") + }) +} diff --git a/terraform/modules/apps/nginx-reverse-proxy/main.tf b/terraform/modules/apps/nginx-reverse-proxy/main.tf index 78b38d8..62f02bc 100644 --- a/terraform/modules/apps/nginx-reverse-proxy/main.tf +++ b/terraform/modules/apps/nginx-reverse-proxy/main.tf @@ -136,12 +136,14 @@ resource "kubernetes_ingress_v1" "reverse-proxy_ingress" { "kubernetes.io/ingress.class" = "public" "cert-manager.io/cluster-issuer" = "letsencrypt-prod" }, + each.value.custom_ingress_annotations, each.value.tls ? { "nginx.org/ssl-services" = format("reverse-proxy-%s", replace(each.key, ".", "-")) "nginx.org/ssl-redirect" = "true" "nginx.org/redirect-to-https" = "true" "nginx.ingress.kubernetes.io/backend-protocol" = "HTTPS" - } : {}) + } : {} + ) } spec { tls { diff --git a/terraform/modules/apps/nginx-reverse-proxy/variables.tf b/terraform/modules/apps/nginx-reverse-proxy/variables.tf index 83f5fcf..b105017 100644 --- a/terraform/modules/apps/nginx-reverse-proxy/variables.tf +++ b/terraform/modules/apps/nginx-reverse-proxy/variables.tf @@ -29,13 +29,15 @@ variable "issuer_name" { variable "services" { description = "A list of services to be deployed" type = map(object({ - fqdn = list(string) - upstream = optional(string, "") - resolver = optional(string, "") - default_headers = optional(map(string), {}), - http_port = optional(number, 80) - https_port = optional(number, 443) - tls = optional(bool, false) + fqdn = list(string) + custom_ingress_annotations = optional(map(string), {}) + annotations = optional(map(string), {}) + upstream = optional(string, "") + resolver = optional(string, "") + default_headers = optional(map(string), {}), + http_port = optional(number, 80) + https_port = optional(number, 443) + tls = optional(bool, false) locations = optional(list(object({ path = string, headers = optional(map(string), {}), diff --git a/terraform/modules/db/mariadb/outputs.tf b/terraform/modules/db/mariadb/outputs.tf index 4940974..5b08838 100644 --- a/terraform/modules/db/mariadb/outputs.tf +++ b/terraform/modules/db/mariadb/outputs.tf @@ -13,3 +13,7 @@ output "root_crendentials_name" { output "app_crendentials_name" { value = kubernetes_secret.app_password.metadata[0].name } + +output "db_name" { + value = var.app_name +}