From 4c1e4e12032133f67384fb7b3b43a665f7b6a4dc Mon Sep 17 00:00:00 2001 From: Niklas van Schrick Date: Sat, 28 Dec 2024 17:08:27 +0100 Subject: [PATCH] Setup Outline on administration server --- envs/server_administration/main.tf | 9 ++ envs/server_administration/variables.tf | 5 + modules/docker/outline/main.tf | 12 +++ modules/docker/outline/network.tf | 3 + modules/docker/outline/outline.tf | 136 ++++++++++++++++++++++++ modules/docker/outline/postgres.tf | 46 ++++++++ modules/docker/outline/redis.tf | 30 ++++++ modules/docker/outline/variables.tf | 7 ++ system/administration/main.tf | 11 +- 9 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 modules/docker/outline/main.tf create mode 100644 modules/docker/outline/network.tf create mode 100644 modules/docker/outline/outline.tf create mode 100644 modules/docker/outline/postgres.tf create mode 100644 modules/docker/outline/redis.tf create mode 100644 modules/docker/outline/variables.tf diff --git a/envs/server_administration/main.tf b/envs/server_administration/main.tf index 7dd7a9e..86cc12c 100644 --- a/envs/server_administration/main.tf +++ b/envs/server_administration/main.tf @@ -6,6 +6,10 @@ terraform { source = "cloudflare/cloudflare" version = "4.49.1" } + gitlab = { + source = "gitlabhq/gitlab" + version = "17.7.0" + } docker = { source = "kreuzwerker/docker" version = "3.0.2" @@ -17,6 +21,11 @@ provider "cloudflare" { api_token = var.cloudflare_api_token } +provider "gitlab" { + token = var.gitlab_api_token + base_url = "https://gitlab.com/api/v4/" +} + provider "docker" { host = "ssh://pipeline@${var.server_administration_ip}:${var.server_administration_ssh_port}" diff --git a/envs/server_administration/variables.tf b/envs/server_administration/variables.tf index caeb4a1..05e671c 100644 --- a/envs/server_administration/variables.tf +++ b/envs/server_administration/variables.tf @@ -8,6 +8,11 @@ variable "cloudflare_account_id" { sensitive = true } +variable "gitlab_api_token" { + type = string + sensitive = true +} + variable "server_administration_ip" { type = string sensitive = true diff --git a/modules/docker/outline/main.tf b/modules/docker/outline/main.tf new file mode 100644 index 0000000..53d5d16 --- /dev/null +++ b/modules/docker/outline/main.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + docker = { + source = "kreuzwerker/docker" + version = "3.0.2" + } + gitlab = { + source = "gitlabhq/gitlab" + version = "17.7.0" + } + } +} diff --git a/modules/docker/outline/network.tf b/modules/docker/outline/network.tf new file mode 100644 index 0000000..affecec --- /dev/null +++ b/modules/docker/outline/network.tf @@ -0,0 +1,3 @@ +resource "docker_network" "outline" { + name = "outline" +} diff --git a/modules/docker/outline/outline.tf b/modules/docker/outline/outline.tf new file mode 100644 index 0000000..06ce367 --- /dev/null +++ b/modules/docker/outline/outline.tf @@ -0,0 +1,136 @@ +data "docker_registry_image" "outline" { + name = "outlinewiki/outline:0.81.1" +} + +resource "docker_image" "outline" { + name = data.docker_registry_image.outline.name + pull_triggers = [data.docker_registry_image.outline.sha256_digest] +} + +resource "docker_volume" "outlinedata" { + name = "outline_outlinedata" +} + +resource "random_bytes" "secret_key" { + length = 32 +} + +resource "random_bytes" "utils_key" { + length = 32 +} + +data "gitlab_project_variable" "discord_client_id" { + project = "code0-tech/secret-manager" + key = "OUTLINE_DISCORD_CLIENT_ID" +} + +data "gitlab_project_variable" "discord_client_secret" { + project = "code0-tech/secret-manager" + key = "OUTLINE_DISCORD_CLIENT_SECRET" +} + +data "gitlab_project_variable" "smtp_host" { + project = "code0-tech/secret-manager" + key = "OUTLINE_SMTP_HOST" +} + +data "gitlab_project_variable" "smtp_username" { + project = "code0-tech/secret-manager" + key = "OUTLINE_SMTP_USERNAME" +} + +data "gitlab_project_variable" "smtp_password" { + project = "code0-tech/secret-manager" + key = "OUTLINE_SMTP_PASSWORD" +} + +data "gitlab_project_variable" "smtp_from_email" { + project = "code0-tech/secret-manager" + key = "OUTLINE_SMTP_FROM_EMAIL" +} + +data "gitlab_project_variable" "github_app_id" { + project = "code0-tech/secret-manager" + key = "OUTLINE_GITHUB_APP_ID" +} + +data "gitlab_project_variable" "github_app_private_key" { + project = "code0-tech/secret-manager" + key = "OUTLINE_GITHUB_APP_PRIVATE_KEY" +} + +data "gitlab_project_variable" "github_client_id" { + project = "code0-tech/secret-manager" + key = "OUTLINE_GITHUB_CLIENT_ID" +} + +data "gitlab_project_variable" "github_client_secret" { + project = "code0-tech/secret-manager" + key = "OUTLINE_GITHUB_CLIENT_SECRET" +} + +locals { + //noinspection HILUnresolvedReference + outline_env = [ + "NODE_ENV=production", + "SECRET_KEY=${random_bytes.secret_key.hex}", + "UTILS_SECRET=${random_bytes.utils_key.hex}", + "DATABASE_URL=postgres://outline:${random_password.db.result}@${docker_container.postgres.hostname}:5432/outline", + "PGSSLMODE=disable", + "REDIS_URL=redis://${docker_container.redis.hostname}:6379", + "URL=https://${var.web_url}", + "PORT=3000", + "FILE_STORAGE=local", + "FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data", + "FILE_STORAGE_UPLOAD_MAX_SIZE=262144000", + "DISCORD_CLIENT_ID=${data.gitlab_project_variable.discord_client_id.value}", + "DISCORD_CLIENT_SECRET=${data.gitlab_project_variable.discord_client_secret.value}", + "DISCORD_SERVER_ID=1173625923724124200", + "DISCORD_SERVER_ROLES=1173713224387014696", + "FORCE_HTTPS=false", # terminated at proxy + "SMTP_HOST=${data.gitlab_project_variable.smtp_host.value}", + "SMTP_PORT=587", + "SMTP_USERNAME=${data.gitlab_project_variable.smtp_username.value}", + "SMTP_PASSWORD=${data.gitlab_project_variable.smtp_password.value}", + "SMTP_FROM_EMAIL=${data.gitlab_project_variable.smtp_from_email.value}", + "GITHUB_CLIENT_ID=${data.gitlab_project_variable.github_client_id.value}", + "GITHUB_CLIENT_SECRET=${data.gitlab_project_variable.github_client_secret.value}", + "GITHUB_APP_NAME=Code0 Outline", + "GITHUB_APP_ID=${data.gitlab_project_variable.github_app_id.value}", + "GITHUB_APP_PRIVATE_KEY=${data.gitlab_project_variable.github_app_private_key.value}", + + # Proxy + "VIRTUAL_HOST=${var.web_url}", + ] +} + +//noinspection HILUnresolvedReference +resource "docker_container" "outline" { + image = docker_image.outline.image_id + name = "outline_outline" + restart = "always" + + env = local.outline_env + + volumes { + volume_name = docker_volume.outlinedata.name + container_path = "/var/lib/outline/data" + } + + network_mode = "bridge" + + networks_advanced { + name = docker_network.outline.name + } + + networks_advanced { + name = var.docker_proxy_network_id + } + + lifecycle { + replace_triggered_by = [ + docker_container.postgres.id, + docker_container.redis.id, + ] + } +} diff --git a/modules/docker/outline/postgres.tf b/modules/docker/outline/postgres.tf new file mode 100644 index 0000000..2fce58e --- /dev/null +++ b/modules/docker/outline/postgres.tf @@ -0,0 +1,46 @@ +data "docker_registry_image" "postgres" { + name = "postgres:17.2" +} + +resource "docker_image" "postgres" { + name = data.docker_registry_image.postgres.name + pull_triggers = [data.docker_registry_image.postgres.sha256_digest] +} + +resource "docker_volume" "pgdata" { + name = "outline_pgdata" +} + +resource "random_password" "db" { + length = 32 + special = false +} + +locals { + postgres_env = [ + "POSTGRES_USER=outline", + "POSTGRES_PASSWORD=${random_password.db.result}", + "POSTGRES_DB=outline", + "POSTGRES_PORT=5432", + ] +} + +//noinspection HILUnresolvedReference +resource "docker_container" "postgres" { + image = docker_image.postgres.image_id + name = "outline_postgres" + restart = "always" + + env = local.postgres_env + + volumes { + volume_name = docker_volume.pgdata.name + container_path = "/var/lib/postgresql/data" + } + + network_mode = "bridge" + + networks_advanced { + name = docker_network.outline.name + } +} diff --git a/modules/docker/outline/redis.tf b/modules/docker/outline/redis.tf new file mode 100644 index 0000000..5d53dd6 --- /dev/null +++ b/modules/docker/outline/redis.tf @@ -0,0 +1,30 @@ +data "docker_registry_image" "redis" { + name = "redis:7.4.1" +} + +resource "docker_image" "redis" { + name = data.docker_registry_image.redis.name + pull_triggers = [data.docker_registry_image.redis.sha256_digest] +} + +resource "docker_volume" "redisdata" { + name = "outline_redisdata" +} + +//noinspection HILUnresolvedReference +resource "docker_container" "redis" { + image = docker_image.redis.image_id + name = "outline_redis" + restart = "always" + + volumes { + volume_name = docker_volume.redisdata.name + container_path = "/data" + } + + network_mode = "bridge" + + networks_advanced { + name = docker_network.outline.name + } +} diff --git a/modules/docker/outline/variables.tf b/modules/docker/outline/variables.tf new file mode 100644 index 0000000..0dc91f1 --- /dev/null +++ b/modules/docker/outline/variables.tf @@ -0,0 +1,7 @@ +variable "docker_proxy_network_id" { + type = string +} + +variable "web_url" { + type = string +} diff --git a/system/administration/main.tf b/system/administration/main.tf index 6c1d26a..5f58848 100644 --- a/system/administration/main.tf +++ b/system/administration/main.tf @@ -21,6 +21,7 @@ module "proxy" { certificate_hostnames = [ "plane.code0.tech", + "outline.code0.tech", ] } @@ -31,6 +32,13 @@ module "plane" { docker_proxy_network_id = module.proxy.docker_proxy_network_id } +module "outline" { + source = "../../modules/docker/outline" + + web_url = "outline.code0.tech" + docker_proxy_network_id = module.proxy.docker_proxy_network_id +} + resource "cloudflare_record" "server_ip" { name = "server_administration" type = "A" @@ -43,7 +51,8 @@ resource "cloudflare_record" "server_ip" { resource "cloudflare_record" "server_cname" { for_each = toset([ - "plane" + "plane", + "outline", ]) name = each.value