feat(mail): enhance mail configuration with getmail and dovecot settings
- Added getmail configuration generation using template files. - Introduced postfix and dovecot configuration checksums for deployment. - Created new dovecot configuration file and sieve script for email handling. - Updated main.tf to utilize local variables for configuration management. - Removed redundant external password hasher from main.tf. feat(nginx): improve nginx configuration management - Centralized nginx configuration into a local variable with checksum. - Created separate config maps for default website configurations. - Updated deployment to utilize new configuration structure. feat(sftpgo): add SFTPGo application deployment - Introduced SFTPGo with Kubernetes resources including namespace, config maps, and secrets. - Configured SFTPGo with SMTP settings and AWS credentials. - Implemented health checks and volume mounts for persistent storage. refactor(seafile): remove Seafile module - Deleted Seafile module and associated resources as part of cleanup.
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
- name: SFTPGo Playbook (K8s)
|
||||||
|
hosts: sftpgo
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
# Specific tasks for this playbook
|
||||||
|
tasks:
|
||||||
|
- name: Set required facts
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
sftpgo_home: "{{ persistent_data | default('/var/lib') }}/sftpgo"
|
||||||
|
sftpgo_mysql_home: "{{ database_path | default('/var/lib') }}/mysql.sftpgo"
|
||||||
|
sftpgo_user_id: 1000
|
||||||
|
sftpgo_group_id: 1000
|
||||||
|
mysql_user_id: 999
|
||||||
|
mysql_group_id: 107
|
||||||
|
tags: always
|
||||||
|
|
||||||
|
- name: Create required sftpgo data folder
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: directory
|
||||||
|
path: "{{ sftpgo_home }}"
|
||||||
|
mode: "0750"
|
||||||
|
owner: "{{ sftpgo_user_id }}"
|
||||||
|
group: "{{ sftpgo_group_id }}"
|
||||||
|
tags:
|
||||||
|
- tasks
|
||||||
|
- tasks::folders
|
||||||
|
|
||||||
|
- name: Create required mysql data folder
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: directory
|
||||||
|
path: "{{ sftpgo_mysql_home }}"
|
||||||
|
mode: "0755"
|
||||||
|
owner: "{{ mysql_user_id }}"
|
||||||
|
group: "{{ mysql_group_id }}"
|
||||||
|
tags:
|
||||||
|
- tasks
|
||||||
|
- tasks::folders
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
become: true
|
become: true
|
||||||
ansible.posix.synchronize:
|
ansible.posix.synchronize:
|
||||||
mode: push
|
mode: push
|
||||||
src: "{{ lookup('env', 'GITHUB_WORKSPACE') + '/websites/releases/'+ item }}/"
|
src: "{{ lookup('env', 'GITHUB_WORKSPACE') + '/websites/releases/' + item }}/"
|
||||||
dest: "{{ web_home }}/{{ item }}"
|
dest: "{{ web_home }}/{{ item }}"
|
||||||
delete: yes
|
delete: true
|
||||||
recursive: yes
|
recursive: true
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ websites | default([]) }}"
|
- "{{ websites | default([]) }}"
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ prod-01.alexpires.me
|
|||||||
[nextcloud]
|
[nextcloud]
|
||||||
prod-01.alexpires.me
|
prod-01.alexpires.me
|
||||||
|
|
||||||
|
[sftpgo]
|
||||||
|
prod-01.alexpires.me
|
||||||
|
|
||||||
[m3uproxy]
|
[m3uproxy]
|
||||||
prod-01.alexpires.me
|
prod-01.alexpires.me
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,11 @@ locals {
|
|||||||
type = "TXT"
|
type = "TXT"
|
||||||
value = "v=DKIM1; h=sha256; k=rsa; p=${var.alexpires_me_scaleway_dkim_value}"
|
value = "v=DKIM1; h=sha256; k=rsa; p=${var.alexpires_me_scaleway_dkim_value}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name = "webdav"
|
||||||
|
type = "CNAME"
|
||||||
|
value = "${local.vps_1.name}.alexpires.me"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,10 +71,31 @@ module "gitea" {
|
|||||||
fqdn = local.gitea_fqdn
|
fqdn = local.gitea_fqdn
|
||||||
app_name = "A13Labs git repository"
|
app_name = "A13Labs git repository"
|
||||||
|
|
||||||
relay_smtp_host = local.scaleway_smtp_host
|
smtp_host = local.scaleway_smtp_host
|
||||||
relay_smtp_port = local.scaleway_smtp_port
|
smtp_port = local.scaleway_smtp_port
|
||||||
relay_smtp_username = var.scaleway_project_id
|
smtp_username = var.scaleway_project_id
|
||||||
relay_smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
|
smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
|
||||||
|
|
||||||
from_email = "gitea@${local.primary_domain}"
|
from_email = "gitea@${local.primary_domain}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module "sftpgo" {
|
||||||
|
source = "../modules/apps/sftpgo"
|
||||||
|
|
||||||
|
persistent_folder = local.persistent_folder
|
||||||
|
backup_folder = local.sftpgo_backup_path
|
||||||
|
|
||||||
|
admin_username = "admin"
|
||||||
|
admin_password = var.sftpgo_admin_password
|
||||||
|
|
||||||
|
tag = local.sftpgo_version
|
||||||
|
|
||||||
|
smtp_host = local.scaleway_smtp_host
|
||||||
|
smtp_port = local.scaleway_smtp_port
|
||||||
|
smtp_username = var.scaleway_project_id
|
||||||
|
smtp_password = scaleway_iam_api_key.mail_app_api.secret_key
|
||||||
|
from_email = "sftpgo@${local.primary_domain}"
|
||||||
|
|
||||||
|
access_key = scaleway_iam_api_key.sftpgo_app_api.access_key
|
||||||
|
secret_key = scaleway_iam_api_key.sftpgo_app_api.secret_key
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ module "gitea_backup" {
|
|||||||
target_folder = local.gitea_backup_path
|
target_folder = local.gitea_backup_path
|
||||||
}
|
}
|
||||||
|
|
||||||
module "nextcloud_backup" {
|
module "sftpgo_backup" {
|
||||||
|
|
||||||
source = "../modules/utils/scw_rclone"
|
source = "../modules/utils/scw_rclone"
|
||||||
|
|
||||||
namespace = kubernetes_namespace.nextcloud.metadata[0].name
|
namespace = module.sftpgo.namespace
|
||||||
app_name = "nextcloud"
|
app_name = module.sftpgo.app_name
|
||||||
|
|
||||||
scaleway_organization_id = var.scaleway_organization_id
|
scaleway_organization_id = var.scaleway_organization_id
|
||||||
scaleway_project_id = var.scaleway_organization_id
|
scaleway_project_id = var.scaleway_organization_id
|
||||||
@@ -51,8 +51,8 @@ module "nextcloud_backup" {
|
|||||||
bucket_name = scaleway_object_bucket.backup.name
|
bucket_name = scaleway_object_bucket.backup.name
|
||||||
|
|
||||||
retention_days = local.local_backup_retention_days
|
retention_days = local.local_backup_retention_days
|
||||||
cron_schedule = local.nextcloud_files_backup_cron_schedule
|
cron_schedule = local.sftpgo_files_backup_cron_schedule
|
||||||
|
|
||||||
source_folder = local.nextcloud_path
|
source_folder = module.sftpgo.path
|
||||||
target_folder = local.nextcloud_backup_path
|
target_folder = local.sftpgo_backup_path
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,3 +170,45 @@ resource "scaleway_object_bucket_policy" "dovecot" {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "scaleway_object_bucket" "sftpgo" {
|
||||||
|
name = "a13labs-sftpgo-${random_string.bucket_suffix.result}"
|
||||||
|
project_id = var.scaleway_project_id
|
||||||
|
region = "fr-par"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "scaleway_object_bucket_policy" "sftpgo" {
|
||||||
|
bucket = scaleway_object_bucket.sftpgo.name
|
||||||
|
policy = jsonencode({
|
||||||
|
Version = "2023-04-17",
|
||||||
|
Id = "AllowAccess",
|
||||||
|
Statement = [
|
||||||
|
{
|
||||||
|
Effect = "Allow"
|
||||||
|
Action = [
|
||||||
|
"s3:*",
|
||||||
|
]
|
||||||
|
Principal = {
|
||||||
|
SCW = "user_id:${var.scaleway_user_id}"
|
||||||
|
}
|
||||||
|
Resource = [
|
||||||
|
scaleway_object_bucket.sftpgo.name,
|
||||||
|
"${scaleway_object_bucket.sftpgo.name}/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Effect = "Allow"
|
||||||
|
Action = [
|
||||||
|
"s3:*",
|
||||||
|
]
|
||||||
|
Principal = {
|
||||||
|
SCW = "application_id:${scaleway_iam_application.sftpgo_app.id}"
|
||||||
|
}
|
||||||
|
Resource = [
|
||||||
|
scaleway_object_bucket.sftpgo.name,
|
||||||
|
"${scaleway_object_bucket.sftpgo.name}/*",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,22 +11,22 @@ locals {
|
|||||||
"alexpires.me" = {
|
"alexpires.me" = {
|
||||||
domain_name = "alexpires.me"
|
domain_name = "alexpires.me"
|
||||||
fqdn = ["blog.alexpires.me", "www.alexpires.me", "alexpires.me"]
|
fqdn = ["blog.alexpires.me", "www.alexpires.me", "alexpires.me"]
|
||||||
|
config = file("${path.module}/resources/alexpires.me.conf")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# gitea
|
||||||
gitea_version = "1.23.4"
|
gitea_version = "1.23.4"
|
||||||
gitea_fqdn = "code.${local.primary_domain}"
|
gitea_fqdn = "code.${local.primary_domain}"
|
||||||
|
|
||||||
nextcloud_version = "30.0.0-apache"
|
# sftpgo
|
||||||
nextcloud_fqdn = "cloud.${local.primary_domain}"
|
sftpgo_version = "2.6.x"
|
||||||
nextcloud_sql_backup_cron_schedule = "40 2 * * *"
|
|
||||||
nextcloud_files_backup_cron_schedule = "50 2 * * *"
|
|
||||||
|
|
||||||
|
|
||||||
# m3uproxy
|
# m3uproxy
|
||||||
m3uproxy_version = "latest"
|
m3uproxy_version = "latest"
|
||||||
m3uproxy_fqdn = "tv.${local.primary_domain}"
|
m3uproxy_fqdn = "tv.${local.primary_domain}"
|
||||||
|
|
||||||
|
# geoip
|
||||||
geoip_cron_schedule = "0 0 * * *"
|
geoip_cron_schedule = "0 0 * * *"
|
||||||
geoip_editions = [
|
geoip_editions = [
|
||||||
"GeoLite2-Country",
|
"GeoLite2-Country",
|
||||||
@@ -41,13 +41,15 @@ locals {
|
|||||||
cloud_backup_retention_days = 3
|
cloud_backup_retention_days = 3
|
||||||
mail_backup_path = "${local.persistent_folder}/backup.mail"
|
mail_backup_path = "${local.persistent_folder}/backup.mail"
|
||||||
gitea_backup_path = "${local.persistent_folder}/backup.gitea"
|
gitea_backup_path = "${local.persistent_folder}/backup.gitea"
|
||||||
|
sftpgo_backup_path = "${local.persistent_folder}/backup.sftpgo"
|
||||||
gitea_sql_backup_cron_schedule = "20 2 * * *"
|
gitea_sql_backup_cron_schedule = "20 2 * * *"
|
||||||
gitea_files_backup_cron_schedule = "30 2 * * *"
|
gitea_files_backup_cron_schedule = "30 2 * * *"
|
||||||
|
sftpgo_files_backup_cron_schedule = "50 2 * * *"
|
||||||
mail_files_backup_cron_schedule = "0 3 * * *"
|
mail_files_backup_cron_schedule = "0 3 * * *"
|
||||||
|
|
||||||
fetch_emails_schedule = "*/2 * * * *"
|
|
||||||
|
|
||||||
# email settings
|
# email settings
|
||||||
|
fetch_emails_schedule = "*/2 * * * *"
|
||||||
scaleway_smtp_host = "smtp.tem.scw.cloud"
|
scaleway_smtp_host = "smtp.tem.scw.cloud"
|
||||||
scaleway_smtp_port = 587
|
scaleway_smtp_port = 587
|
||||||
email_accounts = [
|
email_accounts = [
|
||||||
|
|||||||
+12
-1
@@ -1,6 +1,9 @@
|
|||||||
server {
|
server {
|
||||||
listen 8080;
|
listen 8080;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
root /tmp/site;
|
||||||
|
|
||||||
|
resolver kube-dns.kube-system.svc.cluster.local valid=10s;
|
||||||
|
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_comp_level 9;
|
gzip_comp_level 9;
|
||||||
@@ -17,7 +20,15 @@ server {
|
|||||||
application/rss+xml
|
application/rss+xml
|
||||||
image/svg+xml;
|
image/svg+xml;
|
||||||
|
|
||||||
root /tmp/site;
|
location ^~ /storage {
|
||||||
|
proxy_pass http://http.sftpgo.svc.cluster.local:8080/storage;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Port $server_port;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
index index.html index.htm;
|
index index.html index.htm;
|
||||||
@@ -14,6 +14,10 @@ resource "scaleway_iam_application" "dovecot_app" {
|
|||||||
name = "dovecot_app"
|
name = "dovecot_app"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "scaleway_iam_application" "sftpgo_app" {
|
||||||
|
name = "sftpgo_app"
|
||||||
|
}
|
||||||
|
|
||||||
resource "scaleway_iam_policy" "object_read_write_backup" {
|
resource "scaleway_iam_policy" "object_read_write_backup" {
|
||||||
name = "K8s backup app policy"
|
name = "K8s backup app policy"
|
||||||
description = "Gives k8s backup job access to object storage in project"
|
description = "Gives k8s backup job access to object storage in project"
|
||||||
@@ -77,6 +81,24 @@ resource "scaleway_iam_policy" "object_read_write_dovecot" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
resource "scaleway_iam_policy" "object_read_write_sftpgo" {
|
||||||
|
name = "SFtpGo app policy"
|
||||||
|
description = "Gives sftpgo job access to object storage in project"
|
||||||
|
application_id = scaleway_iam_application.sftpgo_app.id
|
||||||
|
|
||||||
|
rule {
|
||||||
|
project_ids = [data.scaleway_account_project.default.id]
|
||||||
|
permission_set_names = [
|
||||||
|
"ObjectStorageObjectsWrite",
|
||||||
|
"ObjectStorageObjectsRead",
|
||||||
|
"ObjectStorageBucketsRead",
|
||||||
|
"ObjectStorageBucketsWrite",
|
||||||
|
"ObjectStorageObjectsDelete"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resource "scaleway_iam_api_key" "backup_app_api" {
|
resource "scaleway_iam_api_key" "backup_app_api" {
|
||||||
application_id = scaleway_iam_application.backup_app.id
|
application_id = scaleway_iam_application.backup_app.id
|
||||||
description = "k8s backup app API key"
|
description = "k8s backup app API key"
|
||||||
@@ -96,3 +118,8 @@ resource "scaleway_iam_api_key" "dovecot_app_api" {
|
|||||||
application_id = scaleway_iam_application.dovecot_app.id
|
application_id = scaleway_iam_application.dovecot_app.id
|
||||||
description = "dovecot access API key"
|
description = "dovecot access API key"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "scaleway_iam_api_key" "sftpgo_app_api" {
|
||||||
|
application_id = scaleway_iam_application.sftpgo_app.id
|
||||||
|
description = "sftpgo access API key"
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name localhost;
|
||||||
|
root /tmp/site;
|
||||||
|
|
||||||
|
resolver kube-dns.kube-system.svc.cluster.local valid=10s;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_comp_level 9;
|
||||||
|
gzip_types
|
||||||
|
text/html
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
text/js
|
||||||
|
text/xml
|
||||||
|
text/javascript
|
||||||
|
application/javascript
|
||||||
|
application/json
|
||||||
|
application/xml
|
||||||
|
application/rss+xml
|
||||||
|
image/svg+xml;
|
||||||
|
|
||||||
|
location ^~ /storage {
|
||||||
|
proxy_pass http://http.sftpgo.svc.cluster.local:8080/storage;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Port $server_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
index index.html index.htm;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* ^/([^/]+) {
|
||||||
|
index index.html index.htm;
|
||||||
|
error_page 404 = @error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 404 /404.html;
|
||||||
|
location @error {
|
||||||
|
try_files /$1/404.html /404.html =404;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,3 +76,10 @@ variable "mail_crypt_private_key" {
|
|||||||
type = string
|
type = string
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "sftpgo_admin_password" {
|
||||||
|
description = "SFTPGo admin password"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,3 +23,4 @@ TF_VAR_alexpires_me_email_username=$ALEXPIRES_ME_EMAIL_USERNAME
|
|||||||
TF_VAR_alexpires_me_email_password=$ALEXPIRES_ME_EMAIL_PASSWORD
|
TF_VAR_alexpires_me_email_password=$ALEXPIRES_ME_EMAIL_PASSWORD
|
||||||
TF_VAR_mail_crypt_private_key=$DOVECOT_CRYPT_PRIVATE_KEY_FILE
|
TF_VAR_mail_crypt_private_key=$DOVECOT_CRYPT_PRIVATE_KEY_FILE
|
||||||
TF_VAR_mail_crypt_public_key=$DOVECOT_CRYPT_PUB_KEY_FILE
|
TF_VAR_mail_crypt_public_key=$DOVECOT_CRYPT_PUB_KEY_FILE
|
||||||
|
TF_VAR_sftpgo_admin_password=$SFTPGO_ADMIN_PASSWORD
|
||||||
@@ -14,8 +14,8 @@ locals {
|
|||||||
SSH_LISTEN_PORT = 22
|
SSH_LISTEN_PORT = 22
|
||||||
GITEA__mailer__ENABLED = true
|
GITEA__mailer__ENABLED = true
|
||||||
GITEA__mailer__FROM = var.from_email
|
GITEA__mailer__FROM = var.from_email
|
||||||
GITEA__mailer__SMTP_ADDR = var.relay_smtp_host
|
GITEA__mailer__SMTP_ADDR = var.smtp_host
|
||||||
GITEA__mailer__SMTP_PORT = var.relay_smtp_port
|
GITEA__mailer__SMTP_PORT = var.smtp_port
|
||||||
GITEA__mailer__PROTOCOL = "smtps"
|
GITEA__mailer__PROTOCOL = "smtps"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
module "gitea_database" {
|
||||||
|
source = "../../db/mariadb"
|
||||||
|
|
||||||
|
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||||
|
app_name = "gitea"
|
||||||
|
|
||||||
|
app_password = var.db_password
|
||||||
|
root_password = var.db_root_password
|
||||||
|
|
||||||
|
retention_days = var.backup_retention_days
|
||||||
|
cron_schedule = var.backup_cron_schedule
|
||||||
|
|
||||||
|
database_folder = local.gitea_db_path
|
||||||
|
backup_folder = var.backup_folder
|
||||||
|
}
|
||||||
@@ -18,28 +18,12 @@ resource "kubernetes_secret" "gitea_mail_credentials" {
|
|||||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
namespace = kubernetes_namespace.gitea.metadata[0].name
|
||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
username = var.relay_smtp_username
|
username = var.smtp_username
|
||||||
password = var.relay_smtp_password
|
password = var.smtp_password
|
||||||
}
|
}
|
||||||
type = "Opaque"
|
type = "Opaque"
|
||||||
}
|
}
|
||||||
|
|
||||||
module "gitea_database" {
|
|
||||||
source = "../../db/mariadb"
|
|
||||||
|
|
||||||
namespace = kubernetes_namespace.gitea.metadata[0].name
|
|
||||||
app_name = "gitea"
|
|
||||||
|
|
||||||
app_password = var.db_password
|
|
||||||
root_password = var.db_root_password
|
|
||||||
|
|
||||||
retention_days = var.backup_retention_days
|
|
||||||
cron_schedule = var.backup_cron_schedule
|
|
||||||
|
|
||||||
database_folder = local.gitea_db_path
|
|
||||||
backup_folder = var.backup_folder
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_service_account" "gitea_service_account" {
|
resource "kubernetes_service_account" "gitea_service_account" {
|
||||||
|
|
||||||
metadata {
|
metadata {
|
||||||
|
|||||||
@@ -51,23 +51,23 @@ variable "app_name" {
|
|||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "relay_smtp_host" {
|
variable "smtp_host" {
|
||||||
description = "The SMTP relay host"
|
description = "The SMTP relay host"
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "relay_smtp_port" {
|
variable "smtp_port" {
|
||||||
description = "The SMTP relay port"
|
description = "The SMTP relay port"
|
||||||
type = number
|
type = number
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "relay_smtp_username" {
|
variable "smtp_username" {
|
||||||
description = "The SMTP relay username"
|
description = "The SMTP relay username"
|
||||||
type = string
|
type = string
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "relay_smtp_password" {
|
variable "smtp_password" {
|
||||||
description = "The SMTP relay password"
|
description = "The SMTP relay password"
|
||||||
type = string
|
type = string
|
||||||
sensitive = true
|
sensitive = true
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ locals {
|
|||||||
m3uproxy_fqdn = var.fqdn
|
m3uproxy_fqdn = var.fqdn
|
||||||
wireguard_version = "1.0.20210914-r4-ls54"
|
wireguard_version = "1.0.20210914-r4-ls54"
|
||||||
squid_version = "6.1-23.10_edge"
|
squid_version = "6.1-23.10_edge"
|
||||||
|
|
||||||
geoip_image = "maxmindinc/geoipupdate"
|
geoip_image = "maxmindinc/geoipupdate"
|
||||||
geoip_version = "latest"
|
geoip_version = "latest"
|
||||||
geoip_cron_schedule = var.geoip_cron_schedule
|
geoip_cron_schedule = var.geoip_cron_schedule
|
||||||
geoip_editions = var.geoip_editions
|
geoip_editions = var.geoip_editions
|
||||||
|
geoip_path = "${local.m3uproxy_path}/geoip"
|
||||||
|
|
||||||
m3uproxy_path = "${local.persistent_folder}/m3uproxy"
|
m3uproxy_path = "${local.persistent_folder}/m3uproxy"
|
||||||
m3uproxy_cache_path = "${local.m3uproxy_path}/cache"
|
m3uproxy_cache_path = "${local.m3uproxy_path}/cache"
|
||||||
squid_app_path = "${local.m3uproxy_path}/squid"
|
squid_app_path = "${local.m3uproxy_path}/squid"
|
||||||
geoip_path = "${local.m3uproxy_path}/geoip"
|
|
||||||
wireguard_address = "192.168.5.3/32"
|
wireguard_address = "192.168.5.3/32"
|
||||||
wireguard_dns = "192.168.5.1"
|
wireguard_dns = "192.168.5.1"
|
||||||
wireguard_allowed_ips = [
|
wireguard_allowed_ips = [
|
||||||
@@ -26,5 +27,22 @@ locals {
|
|||||||
m3uproxy_config = templatefile("${path.module}/resources/m3uproxy/m3uproxy.json", {
|
m3uproxy_config = templatefile("${path.module}/resources/m3uproxy/m3uproxy.json", {
|
||||||
m3uproxy_secret = var.secret
|
m3uproxy_secret = var.secret
|
||||||
})
|
})
|
||||||
|
m3uproxy_config_checksum = nonsensitive(sha256(local.m3uproxy_config))
|
||||||
|
|
||||||
|
m3uproxy_playlist = file("${path.module}/resources/m3uproxy/playlist.json")
|
||||||
|
m3uproxy_playlist_checksum = sha256(local.m3uproxy_playlist)
|
||||||
|
|
||||||
|
wireguard_config = templatefile("${path.module}/resources/wireguard/wireguard.conf.tpl", {
|
||||||
|
wireguard_private_key = var.wireguard_private_key
|
||||||
|
wireguard_public_key = var.wireguard_public_key
|
||||||
|
wireguard_address = local.wireguard_address
|
||||||
|
wireguard_dns = local.wireguard_dns
|
||||||
|
wireguard_allowed_ips = join(", ", local.wireguard_allowed_ips)
|
||||||
|
wireguard_endpoint = "${local.wireguard_endpoint}:${local.wireguard_endpoint_port}"
|
||||||
|
})
|
||||||
|
wireguard_config_checksum = nonsensitive(sha256(local.wireguard_config))
|
||||||
|
|
||||||
|
squid_config = file("${path.module}/resources/squid/squid.conf")
|
||||||
|
squid_config_checksum = sha256(local.squid_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
resource "kubernetes_secret" "geoip_maxmind_credentials" {
|
||||||
|
metadata {
|
||||||
|
name = "geoip-maxmind-credentials"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
account_id = var.maxmind_account_id
|
||||||
|
license_key = var.maxmind_license_key
|
||||||
|
}
|
||||||
|
type = "Opaque"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_cron_job_v1" "geoip_update" {
|
||||||
|
|
||||||
|
metadata {
|
||||||
|
name = "geoip-update"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
schedule = local.geoip_cron_schedule
|
||||||
|
job_template {
|
||||||
|
metadata {
|
||||||
|
name = "geoip-update"
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
template {
|
||||||
|
metadata {
|
||||||
|
labels = {
|
||||||
|
app = "geoip-update"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
container {
|
||||||
|
name = "geoip-update"
|
||||||
|
image = "${local.geoip_image}:${local.geoip_version}"
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "GEOIPUPDATE_ACCOUNT_ID"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||||
|
key = "account_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "GEOIPUPDATE_LICENSE_KEY"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
||||||
|
key = "license_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "GEOIPUPDATE_EDITION_IDS"
|
||||||
|
value = join(" ", local.geoip_editions)
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
memory = "64Mi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "geoip-db"
|
||||||
|
mount_path = "/usr/share/GeoIP"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
security_context {
|
||||||
|
run_as_user = 1000
|
||||||
|
run_as_group = 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service_account_name = kubernetes_service_account.m3uproxy_service_account.metadata[0].name
|
||||||
|
|
||||||
|
restart_policy = "OnFailure"
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "geoip-db"
|
||||||
|
host_path {
|
||||||
|
path = local.geoip_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -22,20 +22,6 @@ resource "kubernetes_secret" "m3uproxy_admin_credentials" {
|
|||||||
type = "Opaque"
|
type = "Opaque"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_secret" "geoip_maxmind_credentials" {
|
|
||||||
metadata {
|
|
||||||
name = "geoip-maxmind-credentials"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
account_id = var.maxmind_account_id
|
|
||||||
license_key = var.maxmind_license_key
|
|
||||||
}
|
|
||||||
type = "Opaque"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resource "kubernetes_service_account" "m3uproxy_service_account" {
|
resource "kubernetes_service_account" "m3uproxy_service_account" {
|
||||||
|
|
||||||
metadata {
|
metadata {
|
||||||
@@ -46,36 +32,6 @@ resource "kubernetes_service_account" "m3uproxy_service_account" {
|
|||||||
automount_service_account_token = false
|
automount_service_account_token = false
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_config_map" "wireguard_config" {
|
|
||||||
metadata {
|
|
||||||
name = "wireguard-config"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"wireguard.conf" = templatefile("${path.module}/resources/wireguard/wireguard.conf.tpl", {
|
|
||||||
wireguard_private_key = var.wireguard_private_key
|
|
||||||
wireguard_public_key = var.wireguard_public_key
|
|
||||||
wireguard_address = local.wireguard_address
|
|
||||||
wireguard_dns = local.wireguard_dns
|
|
||||||
wireguard_allowed_ips = join(", ", local.wireguard_allowed_ips)
|
|
||||||
wireguard_endpoint = "${local.wireguard_endpoint}:${local.wireguard_endpoint_port}"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_config_map" "squid_config" {
|
|
||||||
metadata {
|
|
||||||
name = "squid-config"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"squid.conf" = file("${path.module}/resources/squid/squid.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_config_map" "m3uproxy_config" {
|
resource "kubernetes_config_map" "m3uproxy_config" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "m3uproxy-config"
|
name = "m3uproxy-config"
|
||||||
@@ -84,190 +40,10 @@ resource "kubernetes_config_map" "m3uproxy_config" {
|
|||||||
|
|
||||||
data = {
|
data = {
|
||||||
"m3uproxy.json" = local.m3uproxy_config
|
"m3uproxy.json" = local.m3uproxy_config
|
||||||
"playlist.json" = file("${path.module}/resources/m3uproxy/playlist.json")
|
"playlist.json" = local.m3uproxy_playlist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_deployment" "proxy_pt" {
|
|
||||||
metadata {
|
|
||||||
name = "proxy-pt"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
annotations = {
|
|
||||||
"security.alpha.kubernetes.io/unsafe-sysctls" = "net.ipv4.conf.all.src_valid_mark=1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
replicas = 1
|
|
||||||
|
|
||||||
selector {
|
|
||||||
match_labels = {
|
|
||||||
app = "proxy-pt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strategy {
|
|
||||||
type = "Recreate"
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
metadata {
|
|
||||||
labels = {
|
|
||||||
app = "proxy-pt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
container {
|
|
||||||
name = "wireguard"
|
|
||||||
image = "linuxserver/wireguard:${local.wireguard_version}"
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
memory = "64Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
liveness_probe {
|
|
||||||
exec {
|
|
||||||
command = [
|
|
||||||
"/bin/sh",
|
|
||||||
"-c",
|
|
||||||
"wg show | grep -q transfer"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
initial_delay_seconds = 90
|
|
||||||
period_seconds = 90
|
|
||||||
}
|
|
||||||
|
|
||||||
security_context {
|
|
||||||
privileged = true
|
|
||||||
capabilities {
|
|
||||||
add = ["NET_ADMIN"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "PUID"
|
|
||||||
value = "1000"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "PGID"
|
|
||||||
value = "1000"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "TZ"
|
|
||||||
value = "Europe/Berlin"
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "wireguard-config"
|
|
||||||
mount_path = "/config/wg_confs"
|
|
||||||
read_only = true
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "lib-modules"
|
|
||||||
mount_path = "/lib/modules"
|
|
||||||
read_only = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
container {
|
|
||||||
name = "squid"
|
|
||||||
image = "ubuntu/squid:${local.squid_version}"
|
|
||||||
|
|
||||||
port {
|
|
||||||
container_port = 3128
|
|
||||||
name = "proxy"
|
|
||||||
protocol = "TCP"
|
|
||||||
}
|
|
||||||
|
|
||||||
readiness_probe {
|
|
||||||
tcp_socket {
|
|
||||||
port = "proxy"
|
|
||||||
}
|
|
||||||
initial_delay_seconds = 10
|
|
||||||
timeout_seconds = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
liveness_probe {
|
|
||||||
tcp_socket {
|
|
||||||
port = "proxy"
|
|
||||||
}
|
|
||||||
initial_delay_seconds = 10
|
|
||||||
timeout_seconds = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
memory = "256Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
security_context {
|
|
||||||
allow_privilege_escalation = false
|
|
||||||
run_as_user = 1000
|
|
||||||
run_as_group = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "squid-config"
|
|
||||||
mount_path = "/etc/squid"
|
|
||||||
read_only = true
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "squid-data"
|
|
||||||
mount_path = "/var/spol/squid"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "wireguard-config"
|
|
||||||
config_map {
|
|
||||||
name = kubernetes_config_map.wireguard_config.metadata[0].name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "lib-modules"
|
|
||||||
host_path {
|
|
||||||
path = "/lib/modules"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "squid-config"
|
|
||||||
config_map {
|
|
||||||
name = kubernetes_config_map.squid_config.metadata[0].name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "squid-data"
|
|
||||||
host_path {
|
|
||||||
path = local.squid_app_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
|
||||||
replace_triggered_by = [
|
|
||||||
kubernetes_config_map.wireguard_config,
|
|
||||||
kubernetes_config_map.squid_config
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Create the Deployment
|
|
||||||
resource "kubernetes_deployment" "m3uproxy" {
|
resource "kubernetes_deployment" "m3uproxy" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "m3uproxy"
|
name = "m3uproxy"
|
||||||
@@ -292,6 +68,10 @@ resource "kubernetes_deployment" "m3uproxy" {
|
|||||||
labels = {
|
labels = {
|
||||||
app = "m3uproxy"
|
app = "m3uproxy"
|
||||||
}
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/m3uproxy" = local.m3uproxy_config_checksum
|
||||||
|
"checksum/playlist" = local.m3uproxy_playlist_checksum
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec {
|
spec {
|
||||||
@@ -393,96 +173,10 @@ resource "kubernetes_deployment" "m3uproxy" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_cron_job_v1" "geoip_update" {
|
|
||||||
|
|
||||||
metadata {
|
|
||||||
name = "geoip-update"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
schedule = local.geoip_cron_schedule
|
|
||||||
job_template {
|
|
||||||
metadata {
|
|
||||||
name = "geoip-update"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
template {
|
|
||||||
metadata {
|
|
||||||
labels = {
|
|
||||||
app = "geoip-update"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
container {
|
|
||||||
name = "geoip-update"
|
|
||||||
image = "${local.geoip_image}:${local.geoip_version}"
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "GEOIPUPDATE_ACCOUNT_ID"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
|
||||||
key = "account_id"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "GEOIPUPDATE_LICENSE_KEY"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = kubernetes_secret.geoip_maxmind_credentials.metadata[0].name
|
|
||||||
key = "license_key"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "GEOIPUPDATE_EDITION_IDS"
|
|
||||||
value = join(" ", local.geoip_editions)
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
memory = "64Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "geoip-db"
|
|
||||||
mount_path = "/usr/share/GeoIP"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
security_context {
|
|
||||||
run_as_user = 1000
|
|
||||||
run_as_group = 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service_account_name = kubernetes_service_account.m3uproxy_service_account.metadata[0].name
|
|
||||||
|
|
||||||
restart_policy = "OnFailure"
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "geoip-db"
|
|
||||||
host_path {
|
|
||||||
path = local.geoip_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resource "kubernetes_service" "m3uproxy" {
|
resource "kubernetes_service" "m3uproxy" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "http"
|
name = "http"
|
||||||
@@ -501,23 +195,6 @@ resource "kubernetes_service" "m3uproxy" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_service" "proxy_pt" {
|
|
||||||
metadata {
|
|
||||||
name = "proxy-pt"
|
|
||||||
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
selector = {
|
|
||||||
app = "proxy-pt"
|
|
||||||
}
|
|
||||||
port {
|
|
||||||
port = 3128
|
|
||||||
}
|
|
||||||
cluster_ip = "None"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_ingress_v1" "m3uproxy_ingress_http" {
|
resource "kubernetes_ingress_v1" "m3uproxy_ingress_http" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "m3uproxy-ingress"
|
name = "m3uproxy-ingress"
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
|
||||||
|
resource "kubernetes_config_map" "wireguard_config" {
|
||||||
|
metadata {
|
||||||
|
name = "wireguard-config"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"wireguard.conf" = local.wireguard_config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_config_map" "squid_config" {
|
||||||
|
metadata {
|
||||||
|
name = "squid-config"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"squid.conf" = local.squid_config
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_deployment" "proxy_pt" {
|
||||||
|
metadata {
|
||||||
|
name = "proxy-pt"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
annotations = {
|
||||||
|
"security.alpha.kubernetes.io/unsafe-sysctls" = "net.ipv4.conf.all.src_valid_mark=1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
replicas = 1
|
||||||
|
|
||||||
|
selector {
|
||||||
|
match_labels = {
|
||||||
|
app = "proxy-pt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strategy {
|
||||||
|
type = "Recreate"
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
metadata {
|
||||||
|
labels = {
|
||||||
|
app = "proxy-pt"
|
||||||
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/squid" = local.squid_config_checksum
|
||||||
|
"checksum/wireguard" = local.wireguard_config_checksum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
container {
|
||||||
|
name = "wireguard"
|
||||||
|
image = "linuxserver/wireguard:${local.wireguard_version}"
|
||||||
|
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
memory = "64Mi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
liveness_probe {
|
||||||
|
exec {
|
||||||
|
command = [
|
||||||
|
"/bin/sh",
|
||||||
|
"-c",
|
||||||
|
"wg show | grep -q transfer"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
initial_delay_seconds = 90
|
||||||
|
period_seconds = 90
|
||||||
|
}
|
||||||
|
|
||||||
|
security_context {
|
||||||
|
privileged = true
|
||||||
|
capabilities {
|
||||||
|
add = ["NET_ADMIN"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "PUID"
|
||||||
|
value = "1000"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "PGID"
|
||||||
|
value = "1000"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "TZ"
|
||||||
|
value = "Europe/Berlin"
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "wireguard-config"
|
||||||
|
mount_path = "/config/wg_confs"
|
||||||
|
read_only = true
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "lib-modules"
|
||||||
|
mount_path = "/lib/modules"
|
||||||
|
read_only = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container {
|
||||||
|
name = "squid"
|
||||||
|
image = "ubuntu/squid:${local.squid_version}"
|
||||||
|
|
||||||
|
port {
|
||||||
|
container_port = 3128
|
||||||
|
name = "proxy"
|
||||||
|
protocol = "TCP"
|
||||||
|
}
|
||||||
|
|
||||||
|
readiness_probe {
|
||||||
|
tcp_socket {
|
||||||
|
port = "proxy"
|
||||||
|
}
|
||||||
|
initial_delay_seconds = 10
|
||||||
|
timeout_seconds = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
liveness_probe {
|
||||||
|
tcp_socket {
|
||||||
|
port = "proxy"
|
||||||
|
}
|
||||||
|
initial_delay_seconds = 10
|
||||||
|
timeout_seconds = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
memory = "256Mi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
security_context {
|
||||||
|
allow_privilege_escalation = false
|
||||||
|
run_as_user = 1000
|
||||||
|
run_as_group = 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "squid-config"
|
||||||
|
mount_path = "/etc/squid"
|
||||||
|
read_only = true
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "squid-data"
|
||||||
|
mount_path = "/var/spol/squid"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "wireguard-config"
|
||||||
|
config_map {
|
||||||
|
name = kubernetes_config_map.wireguard_config.metadata[0].name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "lib-modules"
|
||||||
|
host_path {
|
||||||
|
path = "/lib/modules"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "squid-config"
|
||||||
|
config_map {
|
||||||
|
name = kubernetes_config_map.squid_config.metadata[0].name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "squid-data"
|
||||||
|
host_path {
|
||||||
|
path = local.squid_app_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service" "proxy_pt" {
|
||||||
|
metadata {
|
||||||
|
name = "proxy-pt"
|
||||||
|
namespace = kubernetes_namespace.m3uproxy.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
selector = {
|
||||||
|
app = "proxy-pt"
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
port = 3128
|
||||||
|
}
|
||||||
|
cluster_ip = "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,5 +51,45 @@ locals {
|
|||||||
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
|
name = kubernetes_secret.relay_mail_credentials.metadata[0].name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getmail_config = { for job in local.getmail_jobs : "getmailrc_${job.name}" =>
|
||||||
|
|
||||||
|
templatefile("${path.module}/resources/getmail/getmailrc.tpl", {
|
||||||
|
recipient = job.recipient
|
||||||
|
domain = job.domain
|
||||||
|
server = job.server
|
||||||
|
port = job.port
|
||||||
|
username = job.username
|
||||||
|
password = job.password
|
||||||
|
mailbox = job.mailbox
|
||||||
|
delete_after = job.delete_after
|
||||||
|
dovecot_lmtp_address = "dovecot-lmtp.mail.svc.cluster.local"
|
||||||
|
dovecot_lmtp_port = 31024
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
postfix_run_config = file("${path.module}/resources/postfix/run.config")
|
||||||
|
postfix_bcc_map = join("\n", [for account in var.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
|
||||||
|
|
||||||
|
postfix_run_config_checksum = sha256(local.postfix_run_config)
|
||||||
|
postfix_bcc_map_checksum = sha256(local.postfix_bcc_map)
|
||||||
|
|
||||||
|
dovecot_config = file("${path.module}/resources/dovecot/dovecot.conf")
|
||||||
|
dovecot_users = join("\n", [for account in var.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
|
||||||
|
dovecot_sieve = file("${path.module}/resources/dovecot/sieve")
|
||||||
|
|
||||||
|
dovecot_config_checksum = sha256(local.dovecot_config)
|
||||||
|
dovecot_users_checksum = sha256(local.dovecot_users)
|
||||||
|
dovecot_sieve_checksum = sha256(local.dovecot_sieve)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data "external" "password_hasher" {
|
||||||
|
for_each = { for account in var.email_accounts : account.username => account }
|
||||||
|
program = ["python3", "${path.module}/lib/bcrypt_hash.py"]
|
||||||
|
|
||||||
|
query = {
|
||||||
|
password = each.value.password
|
||||||
|
cost = "10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
data "external" "password_hasher" {
|
|
||||||
for_each = { for account in var.email_accounts : account.username => account }
|
|
||||||
program = ["python3", "${path.module}//lib/bcrypt_hash.py"]
|
|
||||||
|
|
||||||
query = {
|
|
||||||
password = each.value.password
|
|
||||||
cost = "10"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "kubernetes_namespace" "mail" {
|
resource "kubernetes_namespace" "mail" {
|
||||||
metadata {
|
metadata {
|
||||||
annotations = {
|
annotations = {
|
||||||
@@ -26,7 +16,7 @@ resource "kubernetes_secret" "dovecot_users" {
|
|||||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
"users" = join("\n", [for account in var.email_accounts : "${account.username}:{BLF-CRYPT.HEX}${local.password_hashes[account.username]}:1000:1000::/var/mail/${account.username}::"])
|
"users" = local.dovecot_users
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,18 +62,17 @@ resource "kubernetes_config_map" "postfix_config" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"run.config" = file("${path.module}/resources/mail/run.config")
|
"run.config" = local.postfix_run_config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
resource "kubernetes_secret" "bcc_map" {
|
resource "kubernetes_secret" "bcc_map" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "bcc-map"
|
name = "bcc-map"
|
||||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
"bcc_map" = join("\n", [for account in var.email_accounts : "/([^@]+)@${replace(account.domain, ".", "\\.")}/ $${1}+Sent@${account.domain}"])
|
"bcc_map" = local.postfix_bcc_map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,21 +82,7 @@ resource "kubernetes_config_map" "getmail_config" {
|
|||||||
namespace = kubernetes_namespace.mail.metadata[0].name
|
namespace = kubernetes_namespace.mail.metadata[0].name
|
||||||
}
|
}
|
||||||
|
|
||||||
data = { for job in local.getmail_jobs : "getmailrc_${job.name}" =>
|
data = local.getmail_config
|
||||||
|
|
||||||
templatefile("${path.module}/resources/mail/getmailrc.tpl", {
|
|
||||||
recipient = job.recipient
|
|
||||||
domain = job.domain
|
|
||||||
server = job.server
|
|
||||||
port = job.port
|
|
||||||
username = job.username
|
|
||||||
password = job.password
|
|
||||||
mailbox = job.mailbox
|
|
||||||
delete_after = job.delete_after
|
|
||||||
dovecot_lmtp_address = "dovecot-lmtp.mail.svc.cluster.local"
|
|
||||||
dovecot_lmtp_port = 31024
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "kubernetes_config_map" "dovecot_config" {
|
resource "kubernetes_config_map" "dovecot_config" {
|
||||||
@@ -117,7 +92,7 @@ resource "kubernetes_config_map" "dovecot_config" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"dovecot.conf" = file("${path.module}/resources/mail/dovecot.conf")
|
"dovecot.conf" = local.dovecot_config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +103,7 @@ resource "kubernetes_config_map" "dovecot_sieve" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"sieve" = file("${path.module}/resources/mail/sieve")
|
"sieve" = local.dovecot_sieve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +222,12 @@ resource "kubernetes_deployment" "dovecot" {
|
|||||||
labels = {
|
labels = {
|
||||||
app = "dovecot"
|
app = "dovecot"
|
||||||
}
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/dovecot" = local.dovecot_config_checksum
|
||||||
|
"checksum/sieve" = local.dovecot_sieve_checksum
|
||||||
|
# Commented out to avoid unnecessary restarts
|
||||||
|
# "checksum/users" = local.dovecot_users_checksum
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
||||||
@@ -337,11 +318,7 @@ resource "kubernetes_deployment" "dovecot" {
|
|||||||
}
|
}
|
||||||
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||||
replace_triggered_by = [
|
|
||||||
kubernetes_config_map.dovecot_config,
|
|
||||||
kubernetes_config_map.dovecot_sieve,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +345,10 @@ resource "kubernetes_deployment" "postfix" {
|
|||||||
labels = {
|
labels = {
|
||||||
app = "postfix"
|
app = "postfix"
|
||||||
}
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/runconfig" = local.postfix_run_config_checksum
|
||||||
|
"checksum/bccmap" = local.postfix_bcc_map_checksum
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
service_account_name = kubernetes_service_account.mail_app.metadata[0].name
|
||||||
@@ -460,12 +441,7 @@ resource "kubernetes_deployment" "postfix" {
|
|||||||
}
|
}
|
||||||
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [spec[0].template[0].metadata[0].annotations]
|
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||||
replace_triggered_by = [
|
|
||||||
kubernetes_config_map.postfix_config,
|
|
||||||
kubernetes_secret.relay_mail_credentials,
|
|
||||||
kubernetes_secret.bcc_map,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,8 @@ locals {
|
|||||||
persistent_folder = var.persistent_folder
|
persistent_folder = var.persistent_folder
|
||||||
websites_path = "${local.persistent_folder}/web"
|
websites_path = "${local.persistent_folder}/web"
|
||||||
websites = var.websites
|
websites = var.websites
|
||||||
|
|
||||||
|
nginx_config = file("${path.module}/resources/nginx.conf")
|
||||||
|
nginx_config_checksum = sha256(local.nginx_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,19 @@ resource "kubernetes_config_map" "nginx_config" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"nginx.conf" = file("${path.module}/resources/nginx/nginx.conf")
|
"nginx.conf" = local.nginx_config
|
||||||
"default.conf" = file("${path.module}/resources/nginx/conf.d/default.conf")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_config_map" "nginx_default_config" {
|
||||||
|
for_each = local.websites
|
||||||
|
metadata {
|
||||||
|
name = format("website-%s-default", replace(each.key, ".", "-"))
|
||||||
|
namespace = kubernetes_namespace.website.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"default.conf" = each.value.config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +122,10 @@ resource "kubernetes_deployment" "website" {
|
|||||||
labels = {
|
labels = {
|
||||||
app = format("website-%s", replace(each.key, ".", "-"))
|
app = format("website-%s", replace(each.key, ".", "-"))
|
||||||
}
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/nginx" = local.nginx_config_checksum
|
||||||
|
"checksum/default" = sha256(each.value.config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
service_account_name = kubernetes_service_account.website_service_account.metadata[0].name
|
service_account_name = kubernetes_service_account.website_service_account.metadata[0].name
|
||||||
@@ -161,13 +176,13 @@ resource "kubernetes_deployment" "website" {
|
|||||||
name = "http"
|
name = "http"
|
||||||
}
|
}
|
||||||
volume_mount {
|
volume_mount {
|
||||||
name = "nginx-config"
|
name = "nginx"
|
||||||
mount_path = "/etc/nginx/nginx.conf"
|
mount_path = "/etc/nginx/nginx.conf"
|
||||||
sub_path = "nginx.conf"
|
sub_path = "nginx.conf"
|
||||||
read_only = true
|
read_only = true
|
||||||
}
|
}
|
||||||
volume_mount {
|
volume_mount {
|
||||||
name = "nginx-config"
|
name = "default"
|
||||||
mount_path = "/etc/nginx/conf.d/default.conf"
|
mount_path = "/etc/nginx/conf.d/default.conf"
|
||||||
sub_path = "default.conf"
|
sub_path = "default.conf"
|
||||||
read_only = true
|
read_only = true
|
||||||
@@ -179,11 +194,17 @@ resource "kubernetes_deployment" "website" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
volume {
|
volume {
|
||||||
name = "nginx-config"
|
name = "nginx"
|
||||||
config_map {
|
config_map {
|
||||||
name = kubernetes_config_map.nginx_config.metadata[0].name
|
name = kubernetes_config_map.nginx_config.metadata[0].name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
volume {
|
||||||
|
name = "default"
|
||||||
|
config_map {
|
||||||
|
name = kubernetes_config_map.nginx_default_config[each.key].metadata[0].name
|
||||||
|
}
|
||||||
|
}
|
||||||
volume {
|
volume {
|
||||||
name = "website"
|
name = "website"
|
||||||
host_path {
|
host_path {
|
||||||
@@ -193,5 +214,8 @@ resource "kubernetes_deployment" "website" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-2
@@ -8,7 +8,6 @@ events {
|
|||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
http {
|
http {
|
||||||
proxy_temp_path /tmp/proxy_temp;
|
proxy_temp_path /tmp/proxy_temp;
|
||||||
client_body_temp_path /tmp/client_temp;
|
client_body_temp_path /tmp/client_temp;
|
||||||
@@ -29,6 +28,5 @@ http {
|
|||||||
|
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
include /etc/nginx/conf.d/*.conf;
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@ variable "websites" {
|
|||||||
type = map(object({
|
type = map(object({
|
||||||
domain_name = string
|
domain_name = string
|
||||||
fqdn = list(string)
|
fqdn = list(string)
|
||||||
|
config = optional(string, "")
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,16 @@ resource "kubernetes_namespace" "rustdesk" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service_account" "rustdesk" {
|
||||||
|
|
||||||
|
metadata {
|
||||||
|
name = "rustdesk-app-sa"
|
||||||
|
namespace = kubernetes_namespace.rustdesk.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
automount_service_account_token = false
|
||||||
|
}
|
||||||
|
|
||||||
resource "kubernetes_config_map" "rustdesk_config" {
|
resource "kubernetes_config_map" "rustdesk_config" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "rustdesk-config"
|
name = "rustdesk-config"
|
||||||
@@ -58,6 +68,9 @@ resource "kubernetes_deployment" "rustdesk_deploy" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spec {
|
spec {
|
||||||
|
service_account_name = kubernetes_service_account.rustdesk.metadata[0].name
|
||||||
|
automount_service_account_token = false
|
||||||
|
|
||||||
container {
|
container {
|
||||||
name = "rustdesk-container"
|
name = "rustdesk-container"
|
||||||
image = "rustdesk/rustdesk-server-s6:${local.rustdesk_version}"
|
image = "rustdesk/rustdesk-server-s6:${local.rustdesk_version}"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
locals {
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#
|
|
||||||
# Namespace for Seafile
|
|
||||||
#
|
|
||||||
resource "kubernetes_namespace" "seafile" {
|
|
||||||
metadata {
|
|
||||||
annotations = {
|
|
||||||
name = "seafile"
|
|
||||||
}
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
name = "seafile"
|
|
||||||
}
|
|
||||||
|
|
||||||
name = "seafile"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Persistent Volume for Seafile data
|
|
||||||
#
|
|
||||||
resource "kubernetes_persistent_volume" "seafile_data" {
|
|
||||||
metadata {
|
|
||||||
name = "seafile-data"
|
|
||||||
labels = {
|
|
||||||
type = "local" # Example label, adjust as needed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
capacity = {
|
|
||||||
storage = "10Gi"
|
|
||||||
}
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
persistent_volume_source {
|
|
||||||
host_path {
|
|
||||||
path = "/opt/seafile-data" # Consider making this configurable via variables
|
|
||||||
}
|
|
||||||
}
|
|
||||||
persistent_volume_reclaim_policy = "Retain" # Or Delete, depending on desired behavior
|
|
||||||
storage_class_name = "manual" # Or your specific storage class
|
|
||||||
volume_mode = "Filesystem"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# Persistent Volume Claim for Seafile data
|
|
||||||
#
|
|
||||||
resource "kubernetes_persistent_volume_claim" "seafile_data" {
|
|
||||||
metadata {
|
|
||||||
name = "seafile-data"
|
|
||||||
namespace = kubernetes_namespace.seafile.metadata[0].name
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
storage = "10Gi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storage_class_name = "manual" # Must match the PV's storage class
|
|
||||||
volume_name = kubernetes_persistent_volume.seafile_data.metadata[0].name
|
|
||||||
}
|
|
||||||
wait_until_bound = false # Set to true if you need to ensure binding before proceeding
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# ConfigMap for Seafile environment variables
|
|
||||||
#
|
|
||||||
resource "kubernetes_config_map" "seafile_env" {
|
|
||||||
metadata {
|
|
||||||
name = "seafile-env"
|
|
||||||
namespace = kubernetes_namespace.seafile.metadata[0].name
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
# for Seafile server
|
|
||||||
TIME_ZONE = "UTC" # Consider making this configurable
|
|
||||||
SEAFILE_LOG_TO_STDOUT = "false"
|
|
||||||
SITE_ROOT = "/"
|
|
||||||
ENABLE_SEADOC = "false"
|
|
||||||
SEADOC_SERVER_URL = "https://seafile.example.com/sdoc-server" # Replace with actual URL or variable
|
|
||||||
SEAFILE_SERVER_HOSTNAME = "seafile.example.com" # Replace with actual hostname or variable
|
|
||||||
SEAFILE_SERVER_PROTOCOL = "http" # Replace with actual protocol or variable
|
|
||||||
|
|
||||||
# for database - Consider using secrets for credentials
|
|
||||||
SEAFILE_MYSQL_DB_HOST = "<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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
worker_processes auto;
|
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log notice;
|
|
||||||
pid /tmp/nginx.pid;
|
|
||||||
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
http {
|
|
||||||
proxy_temp_path /tmp/proxy_temp;
|
|
||||||
client_body_temp_path /tmp/client_temp;
|
|
||||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
|
||||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
|
||||||
scgi_temp_path /tmp/scgi_temp;
|
|
||||||
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
locals {
|
||||||
|
data_path = "${var.persistent_folder}/sftpgo"
|
||||||
|
|
||||||
|
|
||||||
|
sftpgo_config = {
|
||||||
|
"common" : {
|
||||||
|
"defender" : {
|
||||||
|
"enabled" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sftpd" : {
|
||||||
|
"bindings" : [
|
||||||
|
{
|
||||||
|
"port" : 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"webdavd" : {
|
||||||
|
"bindings" : [
|
||||||
|
{
|
||||||
|
"port" : 8081,
|
||||||
|
"address" : "0.0.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"data_provider" : {
|
||||||
|
"create_default_admin" : true,
|
||||||
|
"backups_path" : "/var/lib/sftpgo/backup"
|
||||||
|
},
|
||||||
|
"httpd" : {
|
||||||
|
"bindings" : [
|
||||||
|
{
|
||||||
|
"port" : 8080,
|
||||||
|
"address" : "0.0.0.0",
|
||||||
|
"branding" : {
|
||||||
|
"web_client" : {
|
||||||
|
"name" : "alexpires.me cloud",
|
||||||
|
"short_name" : "alexpires.me"
|
||||||
|
},
|
||||||
|
"web_admin" : {
|
||||||
|
"name" : "alexpires.me cloud",
|
||||||
|
"short_name" : "alexpires.me"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"web_root" : "/storage",
|
||||||
|
},
|
||||||
|
"telemetry" : {
|
||||||
|
"bind_port" : 10000,
|
||||||
|
"bind_address" : "0.0.0.0"
|
||||||
|
},
|
||||||
|
"mfa" : {
|
||||||
|
"totp" : [
|
||||||
|
{
|
||||||
|
"name" : "Default",
|
||||||
|
"issuer" : "alexpires.me",
|
||||||
|
"algo" : "sha1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"smtp" : {
|
||||||
|
"host" : var.smtp_host,
|
||||||
|
"port" : var.smtp_port,
|
||||||
|
"from" : var.from_email
|
||||||
|
"encryption" : 1,
|
||||||
|
"domain" : "alexpires.me"
|
||||||
|
},
|
||||||
|
"plugins" : []
|
||||||
|
}
|
||||||
|
|
||||||
|
config = jsonencode(local.sftpgo_config)
|
||||||
|
config_checksum = sha256(local.config)
|
||||||
|
|
||||||
|
credentials = templatefile("${path.module}/resources/aws.tpl", {
|
||||||
|
access_key = var.access_key
|
||||||
|
secret_key = var.secret_key
|
||||||
|
})
|
||||||
|
credentials_checksum = sha256(local.credentials)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
resource "kubernetes_namespace" "sftpgo" {
|
||||||
|
metadata {
|
||||||
|
name = "sftpgo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_config_map" "sftpgo" {
|
||||||
|
metadata {
|
||||||
|
name = "sftpgo"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"sftpgo.json" = local.config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_secret" "admin_credentials" {
|
||||||
|
metadata {
|
||||||
|
name = "admin-credentials"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
admin_username = var.admin_username
|
||||||
|
admin_password = var.admin_password
|
||||||
|
smtp_username = var.smtp_username
|
||||||
|
smtp_password = var.smtp_password
|
||||||
|
}
|
||||||
|
type = "Opaque"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_config_map" "object_store_credentials" {
|
||||||
|
metadata {
|
||||||
|
name = "nextcloud-object-store-credentials"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"credentials" = local.credentials
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service_account" "sftpgo" {
|
||||||
|
metadata {
|
||||||
|
name = "sftpgo-app-sa"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
automount_service_account_token = false
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_deployment" "sftpgo" {
|
||||||
|
metadata {
|
||||||
|
name = "sftpgo"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
replicas = 1
|
||||||
|
selector {
|
||||||
|
match_labels = {
|
||||||
|
app = "sftpgo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strategy {
|
||||||
|
type = "RollingUpdate"
|
||||||
|
}
|
||||||
|
template {
|
||||||
|
metadata {
|
||||||
|
labels = {
|
||||||
|
app = "sftpgo"
|
||||||
|
}
|
||||||
|
annotations = {
|
||||||
|
"checksum/config" = local.config_checksum
|
||||||
|
"checksum/credentials" = local.credentials_checksum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
service_account_name = kubernetes_service_account.sftpgo.metadata[0].name
|
||||||
|
automount_service_account_token = false
|
||||||
|
security_context {
|
||||||
|
fs_group = 1000
|
||||||
|
run_as_user = 1000
|
||||||
|
}
|
||||||
|
container {
|
||||||
|
name = "sftpgo"
|
||||||
|
image = "ghcr.io/drakkan/sftpgo:${var.tag}"
|
||||||
|
image_pull_policy = "Always"
|
||||||
|
args = ["sftpgo", "serve"]
|
||||||
|
env {
|
||||||
|
name = "SFTPGO_SMTP__USER"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||||
|
key = "smtp_username"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
name = "SFTPGO_SMTP__PASSWORD"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||||
|
key = "smtp_password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
name = "SFTPGO_DEFAULT_ADMIN_USERNAME"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||||
|
key = "admin_username"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
name = "SFTPGO_DEFAULT_ADMIN_PASSWORD"
|
||||||
|
value_from {
|
||||||
|
secret_key_ref {
|
||||||
|
name = kubernetes_secret.admin_credentials.metadata[0].name
|
||||||
|
key = "admin_password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
container_port = 8081
|
||||||
|
name = "webdav"
|
||||||
|
protocol = "TCP"
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
container_port = 8080
|
||||||
|
name = "http"
|
||||||
|
protocol = "TCP"
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
container_port = 10000
|
||||||
|
name = "telemetry"
|
||||||
|
protocol = "TCP"
|
||||||
|
}
|
||||||
|
liveness_probe {
|
||||||
|
http_get {
|
||||||
|
path = "/healthz"
|
||||||
|
port = "telemetry"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readiness_probe {
|
||||||
|
http_get {
|
||||||
|
path = "/healthz"
|
||||||
|
port = "telemetry"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume_mount {
|
||||||
|
mount_path = "/etc/sftpgo/sftpgo.json"
|
||||||
|
name = "config"
|
||||||
|
sub_path = "sftpgo.json"
|
||||||
|
read_only = true
|
||||||
|
}
|
||||||
|
volume_mount {
|
||||||
|
mount_path = "/var/lib/sftpgo"
|
||||||
|
name = "data"
|
||||||
|
}
|
||||||
|
volume_mount {
|
||||||
|
mount_path = "/var/lib/sftpgo/backup"
|
||||||
|
name = "backup"
|
||||||
|
}
|
||||||
|
volume_mount {
|
||||||
|
mount_path = "/var/lib/sftpgo/.aws/credentials"
|
||||||
|
name = "object-store-credentials"
|
||||||
|
sub_path = "credentials"
|
||||||
|
read_only = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume {
|
||||||
|
name = "config"
|
||||||
|
config_map {
|
||||||
|
name = kubernetes_config_map.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume {
|
||||||
|
name = "data"
|
||||||
|
host_path {
|
||||||
|
path = local.data_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume {
|
||||||
|
name = "backup"
|
||||||
|
host_path {
|
||||||
|
path = var.backup_folder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume {
|
||||||
|
name = "object-store-credentials"
|
||||||
|
config_map {
|
||||||
|
name = kubernetes_config_map.object_store_credentials.metadata[0].name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service" "sftpgo_webdav" {
|
||||||
|
metadata {
|
||||||
|
name = "webdav"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
selector = {
|
||||||
|
app = "sftpgo"
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
protocol = "TCP"
|
||||||
|
port = 8081
|
||||||
|
target_port = "webdav"
|
||||||
|
}
|
||||||
|
cluster_ip = "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service" "sftpgo_http" {
|
||||||
|
metadata {
|
||||||
|
name = "http"
|
||||||
|
namespace = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
selector = {
|
||||||
|
app = "sftpgo"
|
||||||
|
}
|
||||||
|
port {
|
||||||
|
protocol = "TCP"
|
||||||
|
port = 8080
|
||||||
|
target_port = "http"
|
||||||
|
}
|
||||||
|
cluster_ip = "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
output "path" {
|
||||||
|
value = local.data_path
|
||||||
|
}
|
||||||
|
|
||||||
|
output "namespace" {
|
||||||
|
value = kubernetes_namespace.sftpgo.metadata[0].name
|
||||||
|
}
|
||||||
|
|
||||||
|
output "app_name" {
|
||||||
|
value = "sftpgo"
|
||||||
|
}
|
||||||
@@ -9,5 +9,9 @@ terraform {
|
|||||||
source = "scaleway/scaleway"
|
source = "scaleway/scaleway"
|
||||||
version = "~>2.13"
|
version = "~>2.13"
|
||||||
}
|
}
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = "3.7.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[default]
|
||||||
|
aws_access_key_id=${access_key}
|
||||||
|
aws_secret_access_key=${secret_key}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
variable "persistent_folder" {
|
||||||
|
description = "The path to the persistent folder"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
variable "backup_folder" {
|
||||||
|
description = "The path to the backup folder"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "admin_username" {
|
||||||
|
description = "The admin username for SFTPGo"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "admin_password" {
|
||||||
|
description = "The admin password for SFTPGo"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tag" {
|
||||||
|
description = "The version of Rustdesk to install"
|
||||||
|
type = string
|
||||||
|
default = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "smtp_host" {
|
||||||
|
description = "The SMTP relay host"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "smtp_port" {
|
||||||
|
description = "The SMTP relay port"
|
||||||
|
type = number
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "smtp_username" {
|
||||||
|
description = "The SMTP relay username"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "smtp_password" {
|
||||||
|
description = "The SMTP relay password"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "from_email" {
|
||||||
|
description = "The email address to use as the sender"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "access_key" {
|
||||||
|
description = "The access key for the S3 compatible storage"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "secret_key" {
|
||||||
|
description = "The secret key for the S3 compatible storage"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user