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:
2025-06-09 23:49:43 +02:00
parent cac269f160
commit 826959c903
41 changed files with 1186 additions and 219 deletions
+14
View File
@@ -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
}
+43
View File
@@ -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"
}
}
+17
View File
@@ -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
}
+16
View File
@@ -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
}
+4
View File
@@ -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
+4 -1
View File
@@ -1 +1,4 @@
variable "scaleway_project_id" {
description = "Scaleway Project Id"
type = string
}
+6 -6
View File
@@ -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}"
}
+9 -9
View File
@@ -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
-130
View File
@@ -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
}
},
},
]
})
}
+29 -26
View File
@@ -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"
}
}
-73
View File
@@ -1,73 +0,0 @@
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"
application_id = scaleway_iam_application.backup_app.id
rule {
project_ids = [data.scaleway_account_project.default.id]
permission_set_names = [
"ObjectStorageObjectsWrite",
"ObjectStorageObjectsRead",
"ObjectStorageObjectsDelete",
"ObjectStorageBucketsRead"
]
}
}
resource "scaleway_iam_policy" "email_full_access" {
name = "Email full access policy"
description = "Gives access to transactional email in project"
application_id = scaleway_iam_application.mail_app.id
rule {
project_ids = [data.scaleway_account_project.default.id]
permission_set_names = [
"TransactionalEmailFullAccess",
]
}
}
resource "scaleway_iam_policy" "object_read_write_sftpgo" {
name = "SFtpGo app policy"
description = "Gives sftpgo job access to object storage in project"
application_id = scaleway_iam_application.sftpgo_app.id
rule {
project_ids = [data.scaleway_account_project.default.id]
permission_set_names = [
"ObjectStorageObjectsWrite",
"ObjectStorageObjectsRead",
"ObjectStorageBucketsRead",
"ObjectStorageBucketsWrite",
"ObjectStorageObjectsDelete"
]
}
}
resource "scaleway_iam_api_key" "backup_app_api" {
application_id = scaleway_iam_application.backup_app.id
description = "k8s backup app API key"
}
resource "scaleway_iam_api_key" "mail_app_api" {
application_id = scaleway_iam_application.mail_app.id
description = "mail access API key"
}
resource "scaleway_iam_api_key" "sftpgo_app_api" {
application_id = scaleway_iam_application.sftpgo_app.id
description = "sftpgo access API key"
}
-11
View File
@@ -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;
}
-12
View File
@@ -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
-3
View File
@@ -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
-5
View File
@@ -1,8 +1,3 @@
variable "scaleway_user_id" {
description = "Scaleway User Id"
type = string
}
variable "scaleway_project_id" {
description = "Scaleway Project Id"
type = string