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
+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"
}
+263
View File
@@ -0,0 +1,263 @@
resource "kubernetes_namespace" "gitea" {
metadata {
annotations = {
name = "gitea"
}
labels = {
name = "gitea"
}
name = "gitea"
}
}
resource "kubernetes_secret" "gitea_mail_credentials" {
metadata {
name = "gitea-mail-credentials"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
data = {
username = var.relay_smtp_username
password = var.relay_smtp_password
}
type = "Opaque"
}
module "gitea_database" {
source = "../k8s_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" {
metadata {
name = "gitea-app-sa"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
automount_service_account_token = false
}
resource "kubernetes_service" "gitea_http" {
metadata {
name = "http"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
spec {
port {
port = 80
target_port = "http"
}
selector = {
app = "gitea"
}
cluster_ip = "None"
}
}
resource "kubernetes_ingress_v1" "gitea_ingress" {
metadata {
name = "gitea-ingress"
namespace = kubernetes_namespace.gitea.metadata[0].name
annotations = {
"kubernetes.io/ingress.class" = "public"
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
"nginx.ingress.kubernetes.io/ssl-redirect" = "true"
"nginx.ingress.kubernetes.io/proxy-body-size" = "8m"
"nginx.ingress.kubernetes.io/proxy-request-buffering" = "on"
"nginx.ingress.kubernetes.io/proxy-buffer-size" = "32k"
"nginx.ingress.kubernetes.io/proxy-buffers-number" = "16"
}
}
spec {
tls {
hosts = [var.fqdn]
secret_name = "gitea-tls"
}
rule {
host = var.fqdn
http {
path {
backend {
service {
name = "http"
port {
number = 80
}
}
}
}
}
}
}
}
resource "kubernetes_deployment" "gitea" {
depends_on = [module.gitea_database]
metadata {
name = "gitea-app"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
spec {
selector {
match_labels = {
app = "gitea"
}
}
strategy {
type = "Recreate"
}
template {
metadata {
labels = {
app = "gitea"
}
}
spec {
service_account_name = kubernetes_service_account.gitea_service_account.metadata[0].name
container {
name = "gitea"
image = "gitea/gitea:${var.tag}"
image_pull_policy = "Always"
resources {
requests = {
memory = "100Mi"
}
limits = {
memory = "300Mi"
}
}
liveness_probe {
http_get {
path = "/api/healthz"
port = "http"
}
initial_delay_seconds = 200
period_seconds = 300
success_threshold = 1
failure_threshold = 5
}
readiness_probe {
tcp_socket {
port = "http"
}
initial_delay_seconds = 5
period_seconds = 10
success_threshold = 1
failure_threshold = 3
}
dynamic "env" {
for_each = local.gitea_env_vars
content {
name = env.key
value = env.value
}
}
security_context {
allow_privilege_escalation = false
}
dynamic "env" {
for_each = local.gitea_secrets
content {
name = env.key
value_from {
secret_key_ref {
key = env.value.key
name = env.value.name
}
}
}
}
port {
container_port = 3000
name = "http"
}
port {
container_port = 22
name = "ssh"
}
volume_mount {
mount_path = "/data"
name = "persistent-storage"
}
}
volume {
name = "persistent-storage"
host_path {
path = local.gitea_path
}
}
}
}
}
}
resource "kubernetes_role" "gitea_ssh_access" {
metadata {
name = "gitea-ssh-access"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
rule {
api_groups = [""]
resources = ["pods", "pods/log"]
verbs = ["get", "list"]
}
rule {
api_groups = [""]
resources = ["pods/exec"]
verbs = ["create"]
}
}
resource "kubernetes_role_binding" "gitea_ssh_access" {
metadata {
name = "gitea-ssh-access"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = kubernetes_role.gitea_ssh_access.metadata[0].name
}
subject {
kind = "ServiceAccount"
name = kubernetes_service_account.gitea_service_account.metadata[0].name
namespace = kubernetes_namespace.gitea.metadata[0].name
}
}
resource "kubernetes_secret" "gitea_access_token" {
metadata {
annotations = {
"kubernetes.io/service-account.name" = kubernetes_service_account.gitea_service_account.metadata[0].name
}
name = "git-token"
namespace = kubernetes_namespace.gitea.metadata[0].name
}
type = "kubernetes.io/service-account-token"
wait_for_service_account_token = true
}
+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
}