Add Nextcloud deployment and configuration
- Introduced Nextcloud module with Kubernetes resources including deployment, service, ingress, and cron job. - Configured Apache settings for Nextcloud with SSL support and compression. - Created secrets for mail and admin credentials. - Added necessary environment variables for Nextcloud configuration. - Removed unused Scaleway access and secret keys from secrets and variables. - Updated CoreDNS module to support custom host overrides. - Implemented backup bucket policies and lifecycle rules for Scaleway object storage. - Enhanced IAM policies and applications for backup and email services. - Added outputs for backup bucket and API keys.
This commit is contained in:
@@ -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 $*"
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
|
||||
variable "scaleway_project_id" {
|
||||
description = "Scaleway Project Id"
|
||||
type = string
|
||||
}
|
||||
|
||||
@@ -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}"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
variable "scaleway_user_id" {
|
||||
description = "Scaleway User Id"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "scaleway_project_id" {
|
||||
description = "Scaleway Project Id"
|
||||
type = string
|
||||
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
.:53 {
|
||||
%{ if override_hosts ~}
|
||||
hosts {
|
||||
%{ for h in hosts ~}
|
||||
${h.ip} ${h.name}
|
||||
%{ endfor ~}
|
||||
fallthrough
|
||||
}
|
||||
%{ endif ~}
|
||||
errors
|
||||
health {
|
||||
lameduck 5s
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
output "namespace" {
|
||||
description = "value of namespace"
|
||||
value = kubernetes_namespace.nextcloud.metadata[0].name
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
terraform {
|
||||
required_version = "~>1.8"
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "2.36.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<IfModule mod_deflate.c>
|
||||
# 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
|
||||
</IfModule>
|
||||
|
||||
# Do not compress images
|
||||
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|woff|woff2)$ no-gzip
|
||||
+1
@@ -0,0 +1 @@
|
||||
MaxRequestWorkers 10
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
<VirtualHost *:443>
|
||||
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
|
||||
</VirtualHost>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
})
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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), {}),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user