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 = { name = "gitea" } labels = { name = "gitea" } name = "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 } type = "Opaque" } # # Setup MariaDB database # module "gitea_database" { source = "./modules/k8s_mariadb" namespace = kubernetes_namespace.gitea.metadata[0].name app_name = "gitea" app_password = var.gitea_mysql_password root_password = var.mysql_root_password retention_days = local.local_backup_retention_days cron_schedule = local.gitea_sql_backup_cron_schedule database_folder = local.gitea_db_path backup_folder = local.gitea_backup_path } # # 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 { 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 = [local.gitea_fqdn] secret_name = "gitea-tls" } rule { host = local.gitea_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:${local.gitea_version}" 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 }