Add Gitea and Mail modules with configuration and resources

- Created Gitea module with outputs, provider, and variables for deployment.
- Implemented Mail module including configuration for Dovecot and Postfix, along with necessary resources such as secrets, config maps, and deployments.
- Added Python script for bcrypt password hashing and integrated it into the Mail module.
- Defined persistent volumes and claims for Seafile module, along with Nginx configuration for serving content.
- Established necessary variables for all modules to ensure flexibility and configurability.
This commit is contained in:
2025-04-27 22:36:18 +02:00
parent 58fb1ea167
commit b7408fb4d8
25 changed files with 715 additions and 207 deletions
+44
View File
@@ -35,3 +35,47 @@ module "m3uproxy" {
wireguard_private_key = var.wireguard_private_key
wireguard_public_key = var.wireguard_public_key
}
module "mail" {
source = "../modules/mail"
persistent_folder = local.persistent_folder
primary_domain = local.primary_domain
email_accounts = local.email_accounts
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
fetch_emails_schedule = local.fetch_emails_schedule
mail_crypt_private_key = var.mail_crypt_private_key
mail_crypt_public_key = var.mail_crypt_public_key
}
module "gitea" {
source = "../modules/gitea"
persistent_folder = local.persistent_folder
database_folder = local.database_folder
backup_folder = local.gitea_backup_path
backup_retention_days = local.local_backup_retention_days
backup_cron_schedule = local.gitea_sql_backup_cron_schedule
db_password = var.gitea_mysql_password
db_root_password = var.mysql_root_password
tag = local.gitea_version
fqdn = local.gitea_fqdn
app_name = "A13Labs git repository"
relay_smtp_host = local.scaleway_smtp_host
relay_smtp_port = local.scaleway_smtp_port
relay_smtp_username = var.scaleway_project_id
relay_smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
from_email = "gitea@${local.primary_domain}"
}
+58
View File
@@ -0,0 +1,58 @@
module "mail_backup" {
source = "../modules/scw_backup_job"
namespace = module.mail.namespace
app_name = module.mail.app_name
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
retention_days = local.local_backup_retention_days
cron_schedule = local.mail_files_backup_cron_schedule
source_folder = module.mail.path
target_folder = local.mail_backup_path
}
module "gitea_backup" {
source = "../modules/scw_backup_job"
namespace = module.gitea.namespace
app_name = module.gitea.app_name
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
retention_days = local.local_backup_retention_days
cron_schedule = local.gitea_files_backup_cron_schedule
source_folder = module.gitea.path
target_folder = local.gitea_backup_path
}
module "nextcloud_backup" {
source = "../modules/scw_backup_job"
namespace = kubernetes_namespace.nextcloud.metadata[0].name
app_name = "nextcloud"
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
retention_days = local.local_backup_retention_days
cron_schedule = local.nextcloud_files_backup_cron_schedule
source_folder = local.nextcloud_path
target_folder = local.nextcloud_backup_path
}
+5 -3
View File
@@ -16,8 +16,6 @@ locals {
gitea_version = "1.23.4"
gitea_fqdn = "code.${local.primary_domain}"
gitea_sql_backup_cron_schedule = "20 2 * * *"
gitea_files_backup_cron_schedule = "30 2 * * *"
nextcloud_version = "30.0.0-apache"
nextcloud_fqdn = "cloud.${local.primary_domain}"
@@ -53,11 +51,15 @@ 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"
gitea_sql_backup_cron_schedule = "20 2 * * *"
gitea_files_backup_cron_schedule = "30 2 * * *"
mail_files_backup_cron_schedule = "0 3 * * *"
# mail settings
getmail_version = "v0.0.1-6.19.07"
fetch_emails_schedule = "*/2 * * * *"
mail_files_backup_cron_schedule = "0 3 * * *"
# email settings
scaleway_smtp_host = "smtp.tem.scw.cloud"
-23
View File
@@ -169,29 +169,6 @@ module "nextcloud_database" {
backup_folder = local.nextcloud_backup_path
}
#
# Setup rsync backup job to scaleway bucket
#
module "nextcloud_backup" {
source = "../modules/scw_backup_job"
namespace = kubernetes_namespace.nextcloud.metadata[0].name
app_name = "nextcloud"
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
retention_days = local.local_backup_retention_days
cron_schedule = local.nextcloud_files_backup_cron_schedule
source_folder = local.nextcloud_path
target_folder = local.nextcloud_backup_path
}
#
# Nextcloud service, ingress, deployment and file backup job
#
+43
View File
@@ -0,0 +1,43 @@
locals {
gitea_env_vars = {
APP_NAME = var.app_name
HTTP_PORT = "3000"
RUN_MODE = "prod"
LFS_START_SERVER = "true"
SSH_DOMAIN = var.fqdn
DISABLE_REGISTRATION = true
INSTALL_LOCK = "true"
DB_TYPE = "mysql"
DB_NAME = "gitea"
DB_HOST = module.gitea_database.host
SSH_LISTEN_PORT = 22
GITEA__mailer__ENABLED = true
GITEA__mailer__FROM = var.from_email
GITEA__mailer__SMTP_ADDR = var.relay_smtp_host
GITEA__mailer__SMTP_PORT = var.relay_smtp_port
GITEA__mailer__PROTOCOL = "smtps"
}
gitea_secrets = {
DB_USER = {
key = "username"
name = module.gitea_database.app_crendentials_name
}
DB_PASSWD = {
key = "password"
name = module.gitea_database.app_crendentials_name
}
GITEA__mailer__USER = {
key = "username"
name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
}
GITEA__mailer__PASSWD = {
key = "password"
name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
}
}
gitea_path = "${var.persistent_folder}/gitea"
gitea_db_path = "${var.database_folder}/mysql.gitea"
}
@@ -1,50 +1,3 @@
locals {
gitea_env_vars = {
APP_NAME = "A13Labs git repository"
HTTP_PORT = "3000"
RUN_MODE = "prod"
LFS_START_SERVER = "true"
SSH_DOMAIN = local.gitea_fqdn
DISABLE_REGISTRATION = true
INSTALL_LOCK = "true"
DB_TYPE = "mysql"
DB_NAME = "gitea"
DB_HOST = module.gitea_database.host
SSH_LISTEN_PORT = 22
GITEA__mailer__ENABLED = true
GITEA__mailer__FROM = "gitea@alexpires.me"
GITEA__mailer__SMTP_ADDR = local.scaleway_smtp_host
GITEA__mailer__SMTP_PORT = local.scaleway_smtp_port
GITEA__mailer__PROTOCOL = "smtps"
}
gitea_secrets = {
DB_USER = {
key = "username"
name = module.gitea_database.app_crendentials_name
}
DB_PASSWD = {
key = "password"
name = module.gitea_database.app_crendentials_name
}
GITEA__mailer__USER = {
key = "username"
name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
}
GITEA__mailer__PASSWD = {
key = "password"
name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
}
}
gitea_path = "${local.persistent_folder}/gitea"
gitea_db_path = "${local.database_folder}/mysql.gitea"
gitea_backup_path = "${local.persistent_folder}/backup.gitea"
}
#
# Namespace
#
resource "kubernetes_namespace" "gitea" {
metadata {
annotations = {
@@ -59,65 +12,35 @@ resource "kubernetes_namespace" "gitea" {
}
}
#
# Mail credentials
#
resource "kubernetes_secret" "gitea_mail_credentials" {
metadata {
name = "gitea-mail-credentials"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
data = {
username = var.scaleway_project_id
password = scaleway_iam_api_key.mail_app_api.secret_key
username = var.relay_smtp_username
password = var.relay_smtp_password
}
type = "Opaque"
}
#
# Setup MariaDB database
#
module "gitea_database" {
source = "../modules/k8s_mariadb"
source = "../k8s_mariadb"
namespace = kubernetes_namespace.gitea.metadata[0].name
app_name = "gitea"
app_password = var.gitea_mysql_password
root_password = var.mysql_root_password
app_password = var.db_password
root_password = var.db_root_password
retention_days = local.local_backup_retention_days
cron_schedule = local.gitea_sql_backup_cron_schedule
retention_days = var.backup_retention_days
cron_schedule = var.backup_cron_schedule
database_folder = local.gitea_db_path
backup_folder = local.gitea_backup_path
backup_folder = var.backup_folder
}
#
# Setup rsync backup job to scaleway bucket
#
module "gitea_backup" {
source = "../modules/scw_backup_job"
namespace = kubernetes_namespace.gitea.metadata[0].name
app_name = "gitea"
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
retention_days = local.local_backup_retention_days
cron_schedule = local.gitea_files_backup_cron_schedule
source_folder = local.gitea_path
target_folder = local.gitea_backup_path
}
#
# Gitea service, ingress, deployment and file backup job
#
resource "kubernetes_service_account" "gitea_service_account" {
metadata {
@@ -162,11 +85,11 @@ resource "kubernetes_ingress_v1" "gitea_ingress" {
}
spec {
tls {
hosts = [local.gitea_fqdn]
hosts = [var.fqdn]
secret_name = "gitea-tls"
}
rule {
host = local.gitea_fqdn
host = var.fqdn
http {
path {
backend {
@@ -210,7 +133,7 @@ resource "kubernetes_deployment" "gitea" {
service_account_name = kubernetes_service_account.gitea_service_account.metadata[0].name
container {
name = "gitea"
image = "gitea/gitea:${local.gitea_version}"
image = "gitea/gitea:${var.tag}"
image_pull_policy = "Always"
resources {
+15
View File
@@ -0,0 +1,15 @@
output "path" {
value = local.gitea_path
}
output "db_path" {
value = local.gitea_db_path
}
output "namespace" {
value = kubernetes_namespace.gitea.metadata[0].name
}
output "app_name" {
value = "gitea"
}
+13
View File
@@ -0,0 +1,13 @@
terraform {
required_version = "~>1.8"
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~>2.18"
}
scaleway = {
source = "scaleway/scaleway"
version = "~>2.13"
}
}
}
+79
View File
@@ -0,0 +1,79 @@
variable "persistent_folder" {
description = "The path to the persistent folder"
type = string
}
variable "database_folder" {
description = "The path to the database folder"
type = string
}
variable "backup_folder" {
description = "The path to the backup folder"
type = string
}
variable "backup_retention_days" {
description = "The number of days to retain backups"
type = number
}
variable "backup_cron_schedule" {
description = "The cron schedule for backups"
type = string
}
variable "db_password" {
description = "The password for the Gitea MySQL database"
type = string
sensitive = true
}
variable "db_root_password" {
description = "The root password for the MySQL database"
type = string
sensitive = true
}
variable "tag" {
description = "The version of the websites to install"
type = string
default = "1.23.4"
}
variable "fqdn" {
description = "The fully qualified domain name for the Rustdesk server"
type = string
}
variable "app_name" {
description = "The name of the application"
type = string
}
variable "relay_smtp_host" {
description = "The SMTP relay host"
type = string
}
variable "relay_smtp_port" {
description = "The SMTP relay port"
type = number
}
variable "relay_smtp_username" {
description = "The SMTP relay username"
type = string
sensitive = true
}
variable "relay_smtp_password" {
description = "The SMTP relay password"
type = string
sensitive = true
}
variable "from_email" {
description = "The email address to use as the sender"
type = string
}
+56
View File
@@ -0,0 +1,56 @@
locals {
persistent_folder = var.persistent_folder
mail_path = "${local.persistent_folder}/mail"
mailboxes_path = "${local.mail_path}/mailboxes"
getmail_path = "${local.mail_path}/getmail"
postfix_path = "${local.mail_path}/postfix"
mail_backup_path = "${local.persistent_folder}/backup.mail"
getmail_jobs = flatten([
for account in var.email_accounts : [
for mailbox in account.mailboxes : {
name = "${account.recipient}-${mailbox}"
recipient = "${account.recipient}+${mailbox}"
domain = account.domain
server = account.receive.server
port = account.receive.port
username = account.username
password = account.password
mailbox = mailbox
delete_after = coalesce(account.delete_after, 30)
}
]
])
postfix_env_vars = {
# Email configuration
SMTP_HOST = var.relay_smtp_host
SMTP_PORT = var.relay_smtp_port
MY_PRIMARY_DOMAIN = var.primary_domain
MY_DESTINATION = join(",", [for account in var.email_accounts : account.domain])
MY_NETWORKS = "127.0.0.0/8"
MAILNAME = "smtp.${var.primary_domain}"
DOVECOT_AUTH_ADDRESS = "dovecot-auth.mail.svc.cluster.local"
DOVECOT_AUTH_PORT = 31000
DOVECOT_LMTP_ADDRESS = "dovecot-lmtp.mail.svc.cluster.local"
DOVECOT_LMTP_PORT = 31024
LOG_TO_STDOUT = 0
}
password_hashes = {
for account in var.email_accounts : account.username => data.external.password_hasher[account.username].result.hex_encoded_bcrypt_hash
}
postfix_secrets = {
SMTP_USER = {
key = "username"
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
}
SMTP_PASSWORD = {
key = "password"
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
}
}
}
+27
View File
@@ -0,0 +1,27 @@
import sys
import json
import bcrypt
import binascii
# Read input JSON from stdin
input_data = json.load(sys.stdin)
password = input_data.get("password")
cost = int(input_data.get("cost", "10")) # Default cost 10
if not password:
print(json.dumps({"error": "Password is required"}), file=sys.stderr)
sys.exit(1)
# Generate bcrypt hash
hashed_bytes = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=cost))
hashed_string = hashed_bytes.decode('utf-8')
# Hex encode for Glauth
hex_encoded_hash = binascii.hexlify(hashed_string.encode('utf-8')).decode('utf-8')
# Output JSON to stdout
output_data = {
"bcrypt_hash": hashed_string,
"hex_encoded_bcrypt_hash": hex_encoded_hash
}
print(json.dumps(output_data))
@@ -1,61 +1,6 @@
locals {
mail_path = "${local.persistent_folder}/mail"
mailboxes_path = "${local.mail_path}/mailboxes"
getmail_path = "${local.mail_path}/getmail"
postfix_path = "${local.mail_path}/postfix"
mail_backup_path = "${local.persistent_folder}/backup.mail"
getmail_jobs = flatten([
for account in local.email_accounts : [
for mailbox in account.mailboxes : {
name = "${account.recipient}-${mailbox}"
recipient = "${account.recipient}+${mailbox}"
domain = account.domain
server = account.receive.server
port = account.receive.port
username = account.username
password = account.password
mailbox = mailbox
delete_after = try(account.delete_after, 30)
}
]
])
postfix_env_vars = {
# Email configuration
SMTP_HOST = local.scaleway_smtp_host
SMTP_PORT = 465
MY_PRIMARY_DOMAIN = local.primary_domain
MY_DESTINATION = join(",", [for account in local.email_accounts : account.domain])
MY_NETWORKS = "127.0.0.0/8"
MAILNAME = "smtp.${local.primary_domain}"
DOVECOT_AUTH_ADDRESS = "dovecot-auth.mail.svc.cluster.local"
DOVECOT_AUTH_PORT = 31000
DOVECOT_LMTP_ADDRESS = "dovecot-lmtp.mail.svc.cluster.local"
DOVECOT_LMTP_PORT = 31024
LOG_TO_STDOUT = 0
}
password_hashes = {
for account in local.email_accounts : account.username => data.external.password_hasher[account.username].result.hex_encoded_bcrypt_hash
}
postfix_secrets = {
SMTP_USER = {
key = "username"
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
}
SMTP_PASSWORD = {
key = "password"
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
}
}
}
data "external" "password_hasher" {
for_each = { for account in local.email_accounts : account.username => account }
program = ["python3", "${path.module}/../../lib/bcrypt_hash.py"]
for_each = { for account in var.email_accounts : account.username => account }
program = ["python3", "${path.module}//lib/bcrypt_hash.py"]
query = {
password = each.value.password
@@ -81,7 +26,7 @@ resource "kubernetes_secret" "dovecot_users" {
namespace = kubernetes_namespace.mail.metadata[0].name
}
data = {
"users" = join("\n", [for account in local.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
"users" = join("\n", [for account in var.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
}
}
@@ -91,8 +36,8 @@ resource "kubernetes_secret" "relay_mail_credentials" {
namespace = kubernetes_namespace.mail.metadata[0].name
}
data = {
username = var.scaleway_project_id
password = scaleway_iam_api_key.mail_app_api.secret_key
username = var.relay_smtp_username
password = var.relay_smtp_password
}
type = "Opaque"
}
@@ -138,7 +83,7 @@ resource "kubernetes_secret" "bcc_map" {
namespace = kubernetes_namespace.mail.metadata[0].name
}
data = {
"bcc_map" = join("\n", [for account in local.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
"bcc_map" = join("\n", [for account in var.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
}
}
@@ -201,32 +146,12 @@ resource "kubernetes_manifest" "mail_certificate" {
name = "letsencrypt-prod"
kind = "ClusterIssuer"
}
commonName = "imap.${local.primary_domain}"
dnsNames = flatten([for account in local.email_accounts : ["imap.${account.domain}", "smtp.${account.domain}"]])
commonName = "imap.${var.primary_domain}"
dnsNames = flatten([for account in var.email_accounts : ["imap.${account.domain}", "smtp.${account.domain}"]])
}
}
}
module "mail_backup" {
source = "../modules/scw_backup_job"
namespace = kubernetes_namespace.mail.metadata[0].name
app_name = "mail"
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
retention_days = local.local_backup_retention_days
cron_schedule = local.mail_files_backup_cron_schedule
source_folder = local.mail_path
target_folder = local.mail_backup_path
}
resource "kubernetes_cron_job_v1" "fetch_emails" {
metadata {
namespace = kubernetes_namespace.mail.metadata[0].name
@@ -234,7 +159,7 @@ resource "kubernetes_cron_job_v1" "fetch_emails" {
}
spec {
schedule = local.fetch_emails_schedule
schedule = var.fetch_emails_schedule
job_template {
metadata {
@@ -256,7 +181,7 @@ resource "kubernetes_cron_job_v1" "fetch_emails" {
spec {
container {
name = "getmail"
image = "a13labs/getmail6:${local.getmail_version}"
image = "a13labs/getmail6:${var.getmail_tag}"
args = concat(["--getmaildir", "/var/getmail"], flatten([for job in local.getmail_jobs : ["-r", "/getmail/getmailrc_${job.name}"]]))
volume_mount {
@@ -327,7 +252,7 @@ resource "kubernetes_deployment" "dovecot" {
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
container {
name = "dovecot"
image = "dovecot/dovecot:latest"
image = "dovecot/dovecot:${var.dovecot_tag}"
port {
container_port = 31993
host_port = 993
@@ -448,7 +373,7 @@ resource "kubernetes_deployment" "postfix" {
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
container {
name = "postfix"
image = "tozd/postfix:alpine-316"
image = "tozd/postfix:${var.postfix_tag}"
port {
container_port = 465
host_port = 465
+11
View File
@@ -0,0 +1,11 @@
output "path" {
value = local.mail_path
}
output "namespace" {
value = kubernetes_namespace.mail.metadata[0].name
}
output "app_name" {
value = "mail"
}
+13
View File
@@ -0,0 +1,13 @@
terraform {
required_version = "~>1.8"
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~>2.18"
}
scaleway = {
source = "scaleway/scaleway"
version = "~>2.13"
}
}
}
+82
View File
@@ -0,0 +1,82 @@
variable "persistent_folder" {
description = "The path to the persistent folder"
type = string
}
variable "primary_domain" {
description = "The primary domain for the websites"
type = string
}
variable "email_accounts" {
description = "List of email accounts to be created"
type = list(object({
recipient = string
domain = string
username = string
password = string
delete_after = optional(number)
mailboxes = list(string)
receive = object({
server = string
port = number
})
}))
}
variable "relay_smtp_host" {
description = "The SMTP relay host"
type = string
}
variable "relay_smtp_port" {
description = "The SMTP relay port"
type = number
}
variable "relay_smtp_username" {
description = "The SMTP relay username"
type = string
sensitive = true
}
variable "relay_smtp_password" {
description = "The SMTP relay password"
type = string
sensitive = true
}
variable "fetch_emails_schedule" {
description = "The cron schedule for fetching emails"
type = string
}
variable "getmail_tag" {
description = "The version of getmail to install"
type = string
default = "v0.0.1-6.19.07"
}
variable "postfix_tag" {
description = "The version of postfix to install"
type = string
default = "alpine-316"
}
variable "dovecot_tag" {
description = "The version of dovecot to install"
type = string
default = "latest"
}
variable "mail_crypt_private_key" {
description = "The private key for mail encryption"
type = string
sensitive = true
}
variable "mail_crypt_public_key" {
description = "The public key for mail encryption"
type = string
sensitive = true
}
+7
View File
@@ -0,0 +1,7 @@
locals {
persistent_folder = var.persistent_folder
websites_path = "${local.persistent_folder}/web"
primary_domain = var.primary_domain
websites = var.websites
}
+128
View File
@@ -0,0 +1,128 @@
#
# Namespace for Seafile
#
resource "kubernetes_namespace" "seafile" {
metadata {
annotations = {
name = "seafile"
}
labels = {
name = "seafile"
}
name = "seafile"
}
}
#
# Persistent Volume for Seafile data
#
resource "kubernetes_persistent_volume" "seafile_data" {
metadata {
name = "seafile-data"
labels = {
type = "local" # Example label, adjust as needed
}
}
spec {
capacity = {
storage = "10Gi"
}
access_modes = ["ReadWriteOnce"]
persistent_volume_source {
host_path {
path = "/opt/seafile-data" # Consider making this configurable via variables
}
}
persistent_volume_reclaim_policy = "Retain" # Or Delete, depending on desired behavior
storage_class_name = "manual" # Or your specific storage class
volume_mode = "Filesystem"
}
}
#
# Persistent Volume Claim for Seafile data
#
resource "kubernetes_persistent_volume_claim" "seafile_data" {
metadata {
name = "seafile-data"
namespace = kubernetes_namespace.seafile.metadata[0].name
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "10Gi"
}
}
storage_class_name = "manual" # Must match the PV's storage class
volume_name = kubernetes_persistent_volume.seafile_data.metadata[0].name
}
wait_until_bound = false # Set to true if you need to ensure binding before proceeding
}
#
# ConfigMap for Seafile environment variables
#
resource "kubernetes_config_map" "seafile_env" {
metadata {
name = "seafile-env"
namespace = kubernetes_namespace.seafile.metadata[0].name
}
data = {
# for Seafile server
TIME_ZONE = "UTC" # Consider making this configurable
SEAFILE_LOG_TO_STDOUT = "false"
SITE_ROOT = "/"
ENABLE_SEADOC = "false"
SEADOC_SERVER_URL = "https://seafile.example.com/sdoc-server" # Replace with actual URL or variable
SEAFILE_SERVER_HOSTNAME = "seafile.example.com" # Replace with actual hostname or variable
SEAFILE_SERVER_PROTOCOL = "http" # Replace with actual protocol or variable
# for database - Consider using secrets for credentials
SEAFILE_MYSQL_DB_HOST = "<your MySQL host>" # Replace with actual host or variable/secret
SEAFILE_MYSQL_DB_PORT = "3306"
SEAFILE_MYSQL_DB_USER = "seafile" # Replace with actual user or variable/secret
SEAFILE_MYSQL_DB_CCNET_DB_NAME = "ccnet_db"
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME = "seafile_db"
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME = "seahub_db"
# Init
## for Seafile admin - Consider using secrets
INIT_SEAFILE_ADMIN_EMAIL = "<Seafile admin's email>" # Replace with actual email or variable/secret
## For S3 storage backend (only valid in INIT_S3_STORAGE_BACKEND_CONFIG = true) - Consider using secrets
INIT_S3_STORAGE_BACKEND_CONFIG = "false"
INIT_S3_COMMIT_BUCKET = ""
INIT_S3_FS_BUCKET = ""
INIT_S3_BLOCK_BUCKET = ""
INIT_S3_KEY_ID = ""
INIT_S3_USE_V4_SIGNATURE = "true"
INIT_S3_AWS_REGION = "us-east-1"
INIT_S3_HOST = "s3.us-east-1.amazonaws.com"
INIT_S3_USE_HTTPS = "true"
}
}
#
# Service for Seafile
#
resource "kubernetes_service" "seafile" {
metadata {
name = "seafile"
namespace = kubernetes_namespace.seafile.metadata[0].name
}
spec {
selector = {
app = "seafile" # Ensure your Seafile deployment/pod has this label
}
port {
protocol = "TCP"
port = 80
target_port = 80
node_port = 30000 # NodePort might not be ideal for production, consider Ingress or LoadBalancer service type without explicit nodePort
}
type = "LoadBalancer" # Or ClusterIP/NodePort depending on your needs
}
}
+13
View File
@@ -0,0 +1,13 @@
terraform {
required_version = "~>1.8"
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~>2.18"
}
scaleway = {
source = "scaleway/scaleway"
version = "~>2.13"
}
}
}
@@ -0,0 +1,35 @@
server {
listen 8080;
server_name localhost;
gzip on;
gzip_comp_level 9;
gzip_types
text/html
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
root /tmp/site;
location / {
index index.html index.htm;
}
location ~* ^/([^/]+) {
index index.html index.htm;
error_page 404 = @error;
}
error_page 404 /404.html;
location @error {
try_files /$1/404.html /404.html =404;
}
}
@@ -0,0 +1,34 @@
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
proxy_temp_path /tmp/proxy_temp;
client_body_temp_path /tmp/client_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
+23
View File
@@ -0,0 +1,23 @@
variable "persistent_folder" {
description = "The path to the persistent folder"
type = string
}
variable "primary_domain" {
description = "The primary domain for the websites"
type = string
}
variable "tag" {
description = "The version of the websites to install"
type = string
default = "stable-alpine"
}
variable "websites" {
description = "A list of websites to be deployed"
type = map(object({
domain_name = string
fqdn = list(string)
}))
}