diff --git a/nomad/backups/.terraform.lock.hcl b/nomad/backups/.terraform.lock.hcl new file mode 100644 index 0000000..4a078a2 --- /dev/null +++ b/nomad/backups/.terraform.lock.hcl @@ -0,0 +1,20 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/nomad" { + version = "1.4.16" + hashes = [ + "h1:tyfjD/maKzb0RxxD9KWgLnkJu9lnYziYsQgGw85Giz8=", + "zh:0d4fbb7030d9caac3b123e60afa44f50c83cc2a983e1866aec7f30414abe7b0e", + "zh:0db080228e07c72d6d8ca8c45249d6f97cd0189fce82a77abbdcd49a52e57572", + "zh:0df88393271078533a217654b96f0672c60eb59570d72e6aefcb839eea87a7a0", + "zh:2883b335bb6044b0db6a00e602d6926c047c7f330294a73a90d089f98b24d084", + "zh:390158d928009a041b3a182bdd82376b50530805ae92be2b84ed7c3b0fa902a0", + "zh:7169b8f8df4b8e9659c49043848fd5f7f8473d0471f67815e8b04980f827f5ef", + "zh:9417ee1383b1edd137024882d7035be4dca51fb4f725ca00ed87729086ec1755", + "zh:a22910b5a29eeab5610350700b4899267c1b09b66cf21f7e4d06afc61d425800", + "zh:a6185c9cd7aa458cd81861058ba568b6411fbac344373a20155e20256f4a7557", + "zh:b6260ca9f034df1b47905b4e2a9c33b67dbf77224a694d5b10fb09ae92ffad4c", + "zh:d87c12a6a7768f2b6c2a59495c7dc00f9ecc52b1b868331d4c284f791e278a1e", + ] +} diff --git a/nomad/backups/backup.nomad b/nomad/backups/backup.nomad new file mode 100644 index 0000000..ba9eaf0 --- /dev/null +++ b/nomad/backups/backup.nomad @@ -0,0 +1,130 @@ +variable "nextcloud_backup" { + type = string + description = "HCL config for Restic Scheduler jobs" +} + +job "backup" { + datacenters = ["dc1"] + type = "service" + + group "nomad0" { + count = 1 + + network { + mode = "bridge" + + port "metrics" { + to = 8080 + } + } + + volume "nextcloud-data" { + type = "host" + read_only = true + source = "nextcloud-data" + } + + volume "gitea-data" { + type = "host" + read_only = true + source = "gitea-data" + } + + volume "authentik-data" { + type = "host" + read_only = true + source = "authentik-data" + } + + service { + port = "metrics" + + # Add connect to mysql + connect { + sidecar_service { + proxy { + local_service_port = 8080 + + upstreams { + destination_name = "mysql-server" + local_bind_port = 6060 + } + + config { + protocol = "tcp" + } + } + } + + sidecar_task { + resources { + cpu = 50 + memory = 50 + } + } + } + + meta { + metrics_addr = "${NOMAD_ADDR_metrics}" + } + } + + task "backup" { + driver = "docker" + + volume_mount { + volume = "nextcloud-data" + destination = "/data/nextcloud" + read_only = true + } + + volume_mount { + volume = "gitea-data" + destination = "/data/gitea" + read_only = true + } + + volume_mount { + volume = "authentik-data" + destination = "/data/authentik" + read_only = true + } + + config { + image = "iamthefij/resticscheduler" + ports = ["metrics"] + args = [ + "/jobs/nextcloud.hcl", + ] + + mount { + type = "bind" + target = "/jobs" + source = "jobs" + } + } + + env = { + "MYSQL_HOST" = "${NOMAD_UPSTREAM_IP_mysql_server}" + "MYSQL_PORT" = "${NOMAD_UPSTREAM_PORT_mysql_server}" + # TODO: Add user with access to all databases or variables for each user + "MYSQL_DATABASE" = "nextcloud" + "MYSQL_USER" = "nextcloud" + "MYSQL_PASSWORD" = "nextcloud" + + # TODO: Something from vault + "BACKUP_PASSPHRASE" = "secretpass" + } + + template { + data = var.nextcloud_backup + destination = "jobs/nextcloud.hcl" + } + + resources { + cpu = 50 + memory = 256 + } + } + } +} diff --git a/nomad/backups/backups.tf b/nomad/backups/backups.tf new file mode 100644 index 0000000..7eda315 --- /dev/null +++ b/nomad/backups/backups.tf @@ -0,0 +1,25 @@ +locals { + nextcloud_backup = file("${path.module}/jobs/nextcloud.hcl") +} + +resource "nomad_job" "backups" { + hcl2 { + enabled = true + vars = { + "nextcloud_backup" = "${local.nextcloud_backup}", + } + } + + jobspec = file("${path.module}/backup.nomad") +} + +resource "nomad_job" "backups-oneoff" { + hcl2 { + enabled = true + vars = { + "nextcloud_backup" = "${local.nextcloud_backup}", + } + } + + jobspec = file("${path.module}/oneoff.nomad") +} diff --git a/nomad/backups/jobs/nextcloud.hcl b/nomad/backups/jobs/nextcloud.hcl new file mode 100644 index 0000000..bf18641 --- /dev/null +++ b/nomad/backups/jobs/nextcloud.hcl @@ -0,0 +1,43 @@ +job "Nextcloud" { + schedule = "* * * * *" + + config { + # TODO: Backup to a meaningful location, this is just for testing + repo = "/local/repo" + # Read from secret file + passphrase = env("BACKUP_PASSPHRASE") + } + + # Remove when using a proper backup destination + task "Create dir for repo" { + pre_script { + on_backup = "echo 'Backing up something'" + } + pre_script { + on_backup = "mkdir -p /local/repo" + } + } + + mysql "Backup database" { + hostname = env("MYSQL_HOST") + port = env("MYSQL_PORT") + database = env("MYSQL_DATABASE") + username = env("MYSQL_USER") + password = env("MYSQL_PASSWORD") + no_tablespaces = true + dump_to = "/local/dump.sql" + } + + backup { + paths = ["/data/nextcloud"] + # Because path is absolute + restore_opts { + Target = "/" + } + } + + forget { + KeepLast = 2 + Prune = true + } +} diff --git a/nomad/backups/oneoff.nomad b/nomad/backups/oneoff.nomad new file mode 100644 index 0000000..c14c960 --- /dev/null +++ b/nomad/backups/oneoff.nomad @@ -0,0 +1,131 @@ +variable "nextcloud_backup" { + type = string + description = "HCL config for Restic Scheduler jobs" +} + +job "backup-oneoff" { + datacenters = ["dc1"] + type = "batch" + + parameterized { + meta_required = ["job_name"] + meta_optional = ["task", "snapshot"] + + } + + meta { + task = "backup" + snapshot = "latest" + } + + group "nextcloud" { + count = 1 + + network { + mode = "bridge" + } + + volume "nextcloud-data" { + type = "host" + read_only = true + source = "nextcloud-data" + } + + volume "gitea-data" { + type = "host" + read_only = true + source = "gitea-data" + } + + volume "authentik-data" { + type = "host" + read_only = true + source = "authentik-data" + } + + service { + connect { + sidecar_service { + proxy { + upstreams { + destination_name = "mysql-server" + local_bind_port = 6060 + } + + config { + protocol = "tcp" + } + } + } + + sidecar_task { + resources { + cpu = 50 + memory = 50 + } + } + } + } + + task "backup" { + driver = "docker" + + volume_mount { + volume = "nextcloud-data" + destination = "/data/nextcloud" + read_only = false + } + + volume_mount { + volume = "gitea-data" + destination = "/data/gitea" + read_only = false + } + + volume_mount { + volume = "authentik-data" + destination = "/data/authentik" + read_only = false + } + + config { + image = "iamthefij/resticscheduler" + ports = ["backup"] + args = [ + "-once", + "-${NOMAD_META_task}", + "${NOMAD_META_job_name}", + "/jobs/nextcloud.hcl", + ] + + mount { + type = "bind" + target = "/jobs" + source = "jobs" + } + } + + env = { + "MYSQL_HOST" = "${NOMAD_UPSTREAM_IP_mysql_server}" + "MYSQL_PORT" = "${NOMAD_UPSTREAM_PORT_mysql_server}" + # TODO: Add user with access to all databases or variables for each user + "MYSQL_DATABASE" = "nextcloud" + "MYSQL_USER" = "nextcloud" + "MYSQL_PASSWORD" = "nextcloud" + + # TODO: Something from vault + "BACKUP_PASSPHRASE" = "secretpass" + } + + template { + data = var.nextcloud_backup + destination = "jobs/nextcloud.hcl" + } + + resources { + cpu = 50 + memory = 256 + } + } + } +} diff --git a/nomad/services.tf b/nomad/services.tf index 6704249..136b22e 100644 --- a/nomad/services.tf +++ b/nomad/services.tf @@ -32,6 +32,12 @@ module "nextcloud" { depends_on = [module.mysql-server] } +module "backups" { + source = "./backups" + + depends_on = [module.mysql-server] +} + module "media" { source = "./media" }