From 17acafe6dbd395970034adc8e780023d6f2775f0 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Tue, 28 Oct 2025 14:40:58 +0000 Subject: [PATCH 01/15] DCUSR: add all dcusr services --- jobs/socs/dcusr-bookstack.hcl | 189 ++++++++++++++++++++++++ jobs/socs/dcusr-dev.hcl | 124 ++++++++++++++++ jobs/socs/dcusr-grafana.hcl | 59 ++++++++ jobs/socs/dcusr-hi-events.hcl | 149 +++++++++++++++++++ jobs/socs/dcusr-invoiceninja.hcl | 238 +++++++++++++++++++++++++++++++ jobs/socs/dcusr-openproject.hcl | 79 ++++++++++ jobs/socs/dcusr-rocketchat.hcl | 126 ++++++++++++++++ 7 files changed, 964 insertions(+) create mode 100644 jobs/socs/dcusr-bookstack.hcl create mode 100644 jobs/socs/dcusr-dev.hcl create mode 100644 jobs/socs/dcusr-grafana.hcl create mode 100644 jobs/socs/dcusr-hi-events.hcl create mode 100644 jobs/socs/dcusr-invoiceninja.hcl create mode 100644 jobs/socs/dcusr-openproject.hcl create mode 100644 jobs/socs/dcusr-rocketchat.hcl diff --git a/jobs/socs/dcusr-bookstack.hcl b/jobs/socs/dcusr-bookstack.hcl new file mode 100644 index 0000000..6bd9fdf --- /dev/null +++ b/jobs/socs/dcusr-bookstack.hcl @@ -0,0 +1,189 @@ +job "dcusr-bookstack" { + datacenters = ["aperture"] + type = "service" + + meta { + domain = "wiki.solarracing.ie" + } + + group "bookstack" { + count = 1 + + network { + port "http" { + to = 80 + } + + port "db" { + to = 3306 + } + + port "redis" { + to = 6379 + } + } + + service { + name = "bookstack" + port = "http" + + tags = [ + "traefik.enable=true", + "traefik.http.routers.dcusr-bookstack.rule=Host(`${NOMAD_META_domain}`)", + "traefik.http.routers.dcusr-bookstack.entrypoints=web,websecure", + "traefik.http.routers.dcusr-bookstack.tls.certresolver=lets-encrypt", + ] + } + + task "bookstack" { + driver = "docker" + + config { + image = "lscr.io/linuxserver/bookstack:latest" + ports = ["http"] + + volumes = [ + "/storage/nomad/${NOMAD_JOB_NAME}/${NOMAD_TASK_NAME}:/config", + ] + } + + template { + destination = "local.env" + env = true + data = < Date: Tue, 28 Oct 2025 14:44:19 +0000 Subject: [PATCH 02/15] remove jitsi meta domain --- jobs/socs/dcusr-rocketchat.hcl | 1 - 1 file changed, 1 deletion(-) diff --git a/jobs/socs/dcusr-rocketchat.hcl b/jobs/socs/dcusr-rocketchat.hcl index fb37c29..7421dcd 100644 --- a/jobs/socs/dcusr-rocketchat.hcl +++ b/jobs/socs/dcusr-rocketchat.hcl @@ -4,7 +4,6 @@ job "dcusr-rocketchat" { meta { domain = "chat.solarracing.ie" - jitsi_domain = "meet.solarracing.ie" } group "rocketchat" { From 4224ff47b088e382d1fcdddd32fadefe94c5cf95 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Tue, 28 Oct 2025 15:10:25 +0000 Subject: [PATCH 03/15] move dcusr jobs to a seperate dir --- jobs/socs/dcusr/dcusr-bookstack.hcl | 189 +++++++++++++++ jobs/socs/dcusr/dcusr-dev.hcl | 124 ++++++++++ jobs/socs/dcusr/dcusr-grafana.hcl | 59 +++++ jobs/socs/dcusr/dcusr-hi-events.hcl | 149 ++++++++++++ jobs/socs/dcusr/dcusr-invoiceninja.hcl | 238 +++++++++++++++++++ jobs/socs/dcusr/dcusr-listmonk.hcl | 107 +++++++++ jobs/socs/dcusr/dcusr-openproject-backup.hcl | 133 +++++++++++ jobs/socs/dcusr/dcusr-openproject.hcl | 79 ++++++ jobs/socs/dcusr/dcusr-outline-backup.hcl | 50 ++++ jobs/socs/dcusr/dcusr-outline.hcl | 148 ++++++++++++ jobs/socs/dcusr/dcusr-rocketchat.hcl | 125 ++++++++++ 11 files changed, 1401 insertions(+) create mode 100644 jobs/socs/dcusr/dcusr-bookstack.hcl create mode 100644 jobs/socs/dcusr/dcusr-dev.hcl create mode 100644 jobs/socs/dcusr/dcusr-grafana.hcl create mode 100644 jobs/socs/dcusr/dcusr-hi-events.hcl create mode 100644 jobs/socs/dcusr/dcusr-invoiceninja.hcl create mode 100644 jobs/socs/dcusr/dcusr-listmonk.hcl create mode 100644 jobs/socs/dcusr/dcusr-openproject-backup.hcl create mode 100644 jobs/socs/dcusr/dcusr-openproject.hcl create mode 100644 jobs/socs/dcusr/dcusr-outline-backup.hcl create mode 100644 jobs/socs/dcusr/dcusr-outline.hcl create mode 100644 jobs/socs/dcusr/dcusr-rocketchat.hcl diff --git a/jobs/socs/dcusr/dcusr-bookstack.hcl b/jobs/socs/dcusr/dcusr-bookstack.hcl new file mode 100644 index 0000000..6bd9fdf --- /dev/null +++ b/jobs/socs/dcusr/dcusr-bookstack.hcl @@ -0,0 +1,189 @@ +job "dcusr-bookstack" { + datacenters = ["aperture"] + type = "service" + + meta { + domain = "wiki.solarracing.ie" + } + + group "bookstack" { + count = 1 + + network { + port "http" { + to = 80 + } + + port "db" { + to = 3306 + } + + port "redis" { + to = 6379 + } + } + + service { + name = "bookstack" + port = "http" + + tags = [ + "traefik.enable=true", + "traefik.http.routers.dcusr-bookstack.rule=Host(`${NOMAD_META_domain}`)", + "traefik.http.routers.dcusr-bookstack.entrypoints=web,websecure", + "traefik.http.routers.dcusr-bookstack.tls.certresolver=lets-encrypt", + ] + } + + task "bookstack" { + driver = "docker" + + config { + image = "lscr.io/linuxserver/bookstack:latest" + ports = ["http"] + + volumes = [ + "/storage/nomad/${NOMAD_JOB_NAME}/${NOMAD_TASK_NAME}:/config", + ] + } + + template { + destination = "local.env" + env = true + data = < /tmp/op_backup_response.json || { + echo "Failed to POST backup creation" + exit 1 + } + +status_path="$(jq -r ._links.job_status.href < /tmp/op_backup_response.json 2>/dev/null || true)" +if [ -z "${status_path}" ] || [ "${status_path}" = "null" ]; then + echo "Could not obtain job_status link from API response" + cat /tmp/op_backup_response.json || true + exit 1 +fi + +status_url="https://${OPENPROJECT_DOMAIN}${status_path}" + +while true; do + curl -s -u "apikey:${OPENPROJECT_API_KEY}" "${status_url}" > /tmp/op_status.json || { + echo "Failed to fetch status from ${status_url}" + sleep 5 + continue + } + + status="$(jq -r .status < /tmp/op_status.json 2>/dev/null || true)" + if [ "${status}" = "success" ]; then + echo "Backup ready for download" + break + fi + + if [ "${status}" = "failed" ] || [ "${status}" = "error" ]; then + echo "Backup job failed (status=${status})" + cat /tmp/op_status.json || true + if [ -n "${DISCORD_WEBHOOK}" ]; then + curl -s -H "Content-Type: application/json" -d \ + "{\"content\": \"<@&585512338728419341> \`OpenProject\` backup for **${job_name}** has **FAILED**. Status: ${status}. Date: $(TZ=Europe/Dublin date)\"}" \ + "${DISCORD_WEBHOOK}" || true + fi + exit 2 + fi + + echo "waiting for backup generation (current status=${status})" + sleep 5 +done + +download_path="$(jq -r .payload.download < /tmp/op_status.json 2>/dev/null || true)" +if [ -z "${download_path}" ] || [ "${download_path}" = "null" ]; then + echo "No download path found in status payload" + exit 1 +fi + +download_url="https://${OPENPROJECT_DOMAIN}${download_path}" + +curl -s -u "apikey:${OPENPROJECT_API_KEY}" -L "${download_url}" -o "${outfile}" || { + echo "Failed to download backup to ${outfile}" + [ -f "${outfile}" ] && rm -f "${outfile}" + exit 1 +} + +if [ -s "${outfile}" ]; then + echo "Backup successful: ${outfile}" +else + echo "Downloaded file is empty or missing: ${outfile}" + rm -f "${outfile}" || true + if [ -n "${DISCORD_WEBHOOK}" ]; then + curl -s -H "Content-Type: application/json" -d \ + "{\"content\": \"<@&585512338728419341> \`OpenProject\` backup for **${job_name}** has just **FAILED** (empty file). File: ${outfile} Date: $(TZ=Europe/Dublin date)\"}" \ + "${DISCORD_WEBHOOK}" || true + fi + exit 1 +fi + +find "${BACKUP_BASE}" -name 'openproject-*.zip' -ctime +3 -exec rm {} \; || true + +exit 0 +EOH + } + + template { + destination = "local/consul_env" + env = true + data = < "${file}" + +find /storage/backups/nomad/postgres/dcusr/outline/postgresql-outline* -ctime +3 -exec rm {} \; || true + +if [ -s "$file" ]; then # check if file exists and is not empty + echo "Backup successful" + exit 0 +else + rm $file + curl -H "Content-Type: application/json" -d \ + '{"content": "<@&585512338728419341> `PostgreSQL` backup for **'"${job_name}"'** has just **FAILED**\nFile name: `'"$file"'`\nDate: `'"$(TZ=Europe/Dublin date)"'`\nTurn off this script with `nomad job stop '"${job_name}"'` \n\n## Remember to restart this backup job when fixed!!!"}' \ + {{ key "postgres/webhook/discord" }} +fi +EOH + destination = "local/script.sh" + } + } + } +} + diff --git a/jobs/socs/dcusr/dcusr-outline.hcl b/jobs/socs/dcusr/dcusr-outline.hcl new file mode 100644 index 0000000..5cf438e --- /dev/null +++ b/jobs/socs/dcusr/dcusr-outline.hcl @@ -0,0 +1,148 @@ +job "dcusr-outline" { + datacenters = ["aperture"] + type = "service" + + meta { + domain = "outline.solarracing.ie" + } + + group "outline" { + network { + # mode = "bridge" + port "http" { + static = 3000 + to = 3000 + } + + port "db" { + to = 5432 + } + + port "redis" { + to = 6379 + } + } + + service { + name = "outline" + port = "http" + + check { + type = "http" + path = "/" + interval = "10s" + timeout = "2s" + } + + tags = [ + "traefik.enable=true", + "traefik.port=${NOMAD_PORT_http}", + "traefik.http.routers.dcusr-outline.entrypoints=web,websecure", + "traefik.http.routers.dcusr-outline.rule=Host(`${NOMAD_META_domain}`)", + "traefik.http.routers.dcusr-outline.tls=true", + "traefik.http.routers.dcusr-outline.tls.certresolver=lets-encrypt", + ] + } + + task "app" { + driver = "docker" + + config { + image = "docker.getoutline.com/outlinewiki/outline:latest" + ports = ["http"] + + volumes = [ + "/storage/nomad/outline/data:/var/lib/outline/data" + ] + } + + resources { + cpu = 1000 + memory = 500 + } + + template { + data = < Date: Tue, 28 Oct 2025 15:13:13 +0000 Subject: [PATCH 04/15] remove the old files --- jobs/socs/dcusr-bookstack.hcl | 189 ----------------------- jobs/socs/dcusr-dev.hcl | 124 --------------- jobs/socs/dcusr-grafana.hcl | 59 ------- jobs/socs/dcusr-hi-events.hcl | 149 ------------------ jobs/socs/dcusr-invoiceninja.hcl | 238 ----------------------------- jobs/socs/dcusr-listmonk.hcl | 105 ------------- jobs/socs/dcusr-openproject.hcl | 79 ---------- jobs/socs/dcusr-outline-backup.hcl | 50 ------ jobs/socs/dcusr-outline.hcl | 148 ------------------ jobs/socs/dcusr-pretix.hcl | 137 ----------------- jobs/socs/dcusr-rocketchat.hcl | 125 --------------- jobs/socs/dcusr.hcl | 65 -------- jobs/socs/dcusr/dcusr-listmonk.hcl | 2 - 13 files changed, 1470 deletions(-) delete mode 100644 jobs/socs/dcusr-bookstack.hcl delete mode 100644 jobs/socs/dcusr-dev.hcl delete mode 100644 jobs/socs/dcusr-grafana.hcl delete mode 100644 jobs/socs/dcusr-hi-events.hcl delete mode 100644 jobs/socs/dcusr-invoiceninja.hcl delete mode 100644 jobs/socs/dcusr-listmonk.hcl delete mode 100644 jobs/socs/dcusr-openproject.hcl delete mode 100644 jobs/socs/dcusr-outline-backup.hcl delete mode 100644 jobs/socs/dcusr-outline.hcl delete mode 100644 jobs/socs/dcusr-pretix.hcl delete mode 100644 jobs/socs/dcusr-rocketchat.hcl delete mode 100644 jobs/socs/dcusr.hcl diff --git a/jobs/socs/dcusr-bookstack.hcl b/jobs/socs/dcusr-bookstack.hcl deleted file mode 100644 index 6bd9fdf..0000000 --- a/jobs/socs/dcusr-bookstack.hcl +++ /dev/null @@ -1,189 +0,0 @@ -job "dcusr-bookstack" { - datacenters = ["aperture"] - type = "service" - - meta { - domain = "wiki.solarracing.ie" - } - - group "bookstack" { - count = 1 - - network { - port "http" { - to = 80 - } - - port "db" { - to = 3306 - } - - port "redis" { - to = 6379 - } - } - - service { - name = "bookstack" - port = "http" - - tags = [ - "traefik.enable=true", - "traefik.http.routers.dcusr-bookstack.rule=Host(`${NOMAD_META_domain}`)", - "traefik.http.routers.dcusr-bookstack.entrypoints=web,websecure", - "traefik.http.routers.dcusr-bookstack.tls.certresolver=lets-encrypt", - ] - } - - task "bookstack" { - driver = "docker" - - config { - image = "lscr.io/linuxserver/bookstack:latest" - ports = ["http"] - - volumes = [ - "/storage/nomad/${NOMAD_JOB_NAME}/${NOMAD_TASK_NAME}:/config", - ] - } - - template { - destination = "local.env" - env = true - data = < "${file}" - -find /storage/backups/nomad/postgres/dcusr/outline/postgresql-outline* -ctime +3 -exec rm {} \; || true - -if [ -s "$file" ]; then # check if file exists and is not empty - echo "Backup successful" - exit 0 -else - rm $file - curl -H "Content-Type: application/json" -d \ - '{"content": "<@&585512338728419341> `PostgreSQL` backup for **'"${job_name}"'** has just **FAILED**\nFile name: `'"$file"'`\nDate: `'"$(TZ=Europe/Dublin date)"'`\nTurn off this script with `nomad job stop '"${job_name}"'` \n\n## Remember to restart this backup job when fixed!!!"}' \ - {{ key "postgres/webhook/discord" }} -fi -EOH - destination = "local/script.sh" - } - } - } -} - diff --git a/jobs/socs/dcusr-outline.hcl b/jobs/socs/dcusr-outline.hcl deleted file mode 100644 index 5cf438e..0000000 --- a/jobs/socs/dcusr-outline.hcl +++ /dev/null @@ -1,148 +0,0 @@ -job "dcusr-outline" { - datacenters = ["aperture"] - type = "service" - - meta { - domain = "outline.solarracing.ie" - } - - group "outline" { - network { - # mode = "bridge" - port "http" { - static = 3000 - to = 3000 - } - - port "db" { - to = 5432 - } - - port "redis" { - to = 6379 - } - } - - service { - name = "outline" - port = "http" - - check { - type = "http" - path = "/" - interval = "10s" - timeout = "2s" - } - - tags = [ - "traefik.enable=true", - "traefik.port=${NOMAD_PORT_http}", - "traefik.http.routers.dcusr-outline.entrypoints=web,websecure", - "traefik.http.routers.dcusr-outline.rule=Host(`${NOMAD_META_domain}`)", - "traefik.http.routers.dcusr-outline.tls=true", - "traefik.http.routers.dcusr-outline.tls.certresolver=lets-encrypt", - ] - } - - task "app" { - driver = "docker" - - config { - image = "docker.getoutline.com/outlinewiki/outline:latest" - ports = ["http"] - - volumes = [ - "/storage/nomad/outline/data:/var/lib/outline/data" - ] - } - - resources { - cpu = 1000 - memory = 500 - } - - template { - data = < Date: Tue, 28 Oct 2025 15:18:04 +0000 Subject: [PATCH 05/15] housekeeping --- jobs/socs/dcusr/dcusr-hi-events.hcl | 3 +-- jobs/socs/dcusr/dcusr-rocketchat.hcl | 2 +- jobs/socs/dcusr/{dcusr-dev.hcl => dcusr.hcl} | 10 +++++----- 3 files changed, 7 insertions(+), 8 deletions(-) rename jobs/socs/dcusr/{dcusr-dev.hcl => dcusr.hcl} (96%) diff --git a/jobs/socs/dcusr/dcusr-hi-events.hcl b/jobs/socs/dcusr/dcusr-hi-events.hcl index 9934b0d..5eaf430 100644 --- a/jobs/socs/dcusr/dcusr-hi-events.hcl +++ b/jobs/socs/dcusr/dcusr-hi-events.hcl @@ -1,7 +1,6 @@ job "dcusr-hi-events" { datacenters = ["aperture"] - - type = "service" + type = "service" meta { domain = "tickets.solarracing.ie" diff --git a/jobs/socs/dcusr/dcusr-rocketchat.hcl b/jobs/socs/dcusr/dcusr-rocketchat.hcl index 7421dcd..5f3f80e 100644 --- a/jobs/socs/dcusr/dcusr-rocketchat.hcl +++ b/jobs/socs/dcusr/dcusr-rocketchat.hcl @@ -3,7 +3,7 @@ job "dcusr-rocketchat" { type = "service" meta { - domain = "chat.solarracing.ie" + domain = "chat.solarracing.ie" } group "rocketchat" { diff --git a/jobs/socs/dcusr/dcusr-dev.hcl b/jobs/socs/dcusr/dcusr.hcl similarity index 96% rename from jobs/socs/dcusr/dcusr-dev.hcl rename to jobs/socs/dcusr/dcusr.hcl index f8a3ba8..e22ac58 100644 --- a/jobs/socs/dcusr/dcusr-dev.hcl +++ b/jobs/socs/dcusr/dcusr.hcl @@ -1,12 +1,12 @@ -job "dcusr-dev" { +job "dcusr" { datacenters = ["aperture"] - type = "service" + type = "service" meta { domain = "solarracing.ie" } - group "dcusr-dev" { + group "dcusr" { count = 1 network { @@ -19,7 +19,7 @@ job "dcusr-dev" { } service { - name = "dcusr-dev" + name = "dcusr" port = "http" tags = [ @@ -48,7 +48,7 @@ job "dcusr-dev" { } } template { - destination = "secrets/secret.env" + destination = "local/.env" env = true data = < Date: Thu, 22 Jan 2026 14:07:46 +0000 Subject: [PATCH 06/15] dcusr website: add recaptcha secrets --- jobs/socs/dcusr/dcusr.hcl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jobs/socs/dcusr/dcusr.hcl b/jobs/socs/dcusr/dcusr.hcl index e22ac58..01c7d2c 100644 --- a/jobs/socs/dcusr/dcusr.hcl +++ b/jobs/socs/dcusr/dcusr.hcl @@ -94,6 +94,9 @@ MAIL_BRAND="DCU Solar Racing" MAIL_PRIMARY="#22c55e" PLAUSIBLE_BASE_URL={{ key "socs/dcusr-dev/plausible/url" }} + +NEXT_PUBLIC_RECAPTCHA_SITE_KEY={{ key "socs/dcusr/captcha/site/key"}} +RECAPTCHA_SECRET={{ key "socs/dcusr/captcha/secret/key" }} EOH } } From 7f797210589983fa1f6cce6242d107581f1bc308 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Thu, 22 Jan 2026 18:54:44 +0000 Subject: [PATCH 07/15] openproject: upgrade to v17 --- jobs/socs/dcusr/dcusr-openproject.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jobs/socs/dcusr/dcusr-openproject.hcl b/jobs/socs/dcusr/dcusr-openproject.hcl index 9646a25..1a522af 100644 --- a/jobs/socs/dcusr/dcusr-openproject.hcl +++ b/jobs/socs/dcusr/dcusr-openproject.hcl @@ -40,7 +40,7 @@ job "dcusr-openproject" { driver = "docker" config { - image = "openproject/openproject:16" + image = "openproject/openproject:17" ports = ["http"] volumes = [ "/storage/nomad/${NOMAD_JOB_NAME}/pgdata:/var/openproject/pgdata", From 5fa6bd9dc0f82b14c657241eb895723dd9b67fb9 Mon Sep 17 00:00:00 2001 From: wizzdom Date: Fri, 23 Jan 2026 01:48:53 +0000 Subject: [PATCH 08/15] listmonk: idempotent install, use env over toml, clean db config --- jobs/socs/dcusr/dcusr-listmonk.hcl | 123 +++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 25 deletions(-) diff --git a/jobs/socs/dcusr/dcusr-listmonk.hcl b/jobs/socs/dcusr/dcusr-listmonk.hcl index 3f9ea7b..ad42e5a 100644 --- a/jobs/socs/dcusr/dcusr-listmonk.hcl +++ b/jobs/socs/dcusr/dcusr-listmonk.hcl @@ -10,14 +10,18 @@ job "dcusr-listmonk" { network { port "http" { } + } - port "db" { - to = 5432 - } + update { + max_parallel = 1 + health_check = "checks" + min_healthy_time = "10s" + healthy_deadline = "5m" } + service { - name = "listmonk" + name = "dcusr-listmonk" port = "http" check { @@ -44,12 +48,11 @@ job "dcusr-listmonk" { image = "listmonk/listmonk:latest" ports = ["http"] - entrypoint = ["./listmonk", "--static-dir=/listmonk/static"] + command = "sh" + args = ["-c", "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"] # empty config so envvars are used instead volumes = [ - "/storage/nomad/dcusr-listmonk/static:/listmonk/static", - "/storage/nomad/dcusr-listmonk/postgres/:/var/lib/postgresql/data", - "local/config.toml:/listmonk/config.toml" + "/storage/nomad/${NOMAD_JOB_NAME}/${NOMAD_TASK_NAME}/uploads:/uploads", ] } @@ -59,35 +62,105 @@ job "dcusr-listmonk" { } template { + destination = "local/.env" + env = true data = < Date: Fri, 23 Jan 2026 02:17:54 +0000 Subject: [PATCH 09/15] hievents: add healtchecks, cplit up db --- jobs/socs/dcusr/dcusr-hi-events.hcl | 159 +++++++++++++++++++++------- 1 file changed, 120 insertions(+), 39 deletions(-) diff --git a/jobs/socs/dcusr/dcusr-hi-events.hcl b/jobs/socs/dcusr/dcusr-hi-events.hcl index 5eaf430..6e4f360 100644 --- a/jobs/socs/dcusr/dcusr-hi-events.hcl +++ b/jobs/socs/dcusr/dcusr-hi-events.hcl @@ -12,15 +12,39 @@ job "dcusr-hi-events" { to = 80 } - port "db" { - to = 5432 - } - port "redis" { to = 6379 } } + update { + max_parallel = 1 + health_check = "checks" + min_healthy_time = "10s" + healthy_deadline = "5m" + } + + service { + name = "dcusr-hievents-frontend" + port = "http" + + check { + type = "http" + path = "/" + interval = "10s" + timeout = "2s" + } + + tags = [ + "traefik.enable=true", + "traefik.port=${NOMAD_PORT_http}", + "traefik.http.routers.hievents-frontend.entrypoints=web,websecure", + "traefik.http.routers.hievents-frontend.rule=Host(`${NOMAD_META_domain}`)", + "traefik.http.routers.hievents-frontend.tls=true", + "traefik.http.routers.hievents-frontend.tls.certresolver=lets-encrypt", + ] + } + task "frontend" { driver = "docker" @@ -29,26 +53,14 @@ job "dcusr-hi-events" { ports = ["http"] } - service { - name = "frontend" - port = "http" - - tags = [ - "traefik.enable=true", - "traefik.port=${NOMAD_PORT_http}", - "traefik.http.routers.hievents-frontend.entrypoints=web,websecure", - "traefik.http.routers.hievents-frontend.rule=Host(`${NOMAD_META_domain}`)", - "traefik.http.routers.hievents-frontend.tls=true", - "traefik.http.routers.hievents-frontend.tls.certresolver=lets-encrypt", - ] - } - resources { memory = 3000 cores = 1 } template { + destination = "local/.env" + env = true data = < Date: Fri, 23 Jan 2026 14:35:55 +0000 Subject: [PATCH 10/15] dcusr-site: separate db, add health checks, lifecycle, prefixes --- jobs/socs/dcusr/dcusr.hcl | 106 +++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/jobs/socs/dcusr/dcusr.hcl b/jobs/socs/dcusr/dcusr.hcl index 01c7d2c..05f94c9 100644 --- a/jobs/socs/dcusr/dcusr.hcl +++ b/jobs/socs/dcusr/dcusr.hcl @@ -1,4 +1,4 @@ -job "dcusr" { +job "dcusr-dev" { datacenters = ["aperture"] type = "service" @@ -6,30 +6,43 @@ job "dcusr" { domain = "solarracing.ie" } - group "dcusr" { + group "web" { count = 1 network { port "http" { to = 3000 } - port "db" { - to = 5432 - } } + update { + max_parallel = 1 + health_check = "checks" + min_healthy_time = "10s" + healthy_deadline = "5m" + } + + service { name = "dcusr" port = "http" + check { + type = "http" + path = "/" + interval = "30s" + timeout = "2s" + } + + tags = [ "traefik.enable=true", "traefik.http.routers.dcusr-dev.rule=Host(`solarracing.ie`) || Host(`www.solarracing.ie`)", "traefik.http.routers.dcusr-dev.entrypoints=web,websecure", "traefik.http.routers.dcusr-dev.tls.certresolver=lets-encrypt", - "traefik.http.middlewares.nextauth-headers.headers.sslProxyHeaders.X-Forwarded-Proto=https", - "traefik.http.middlewares.nextauth-headers.headers.customRequestHeaders.X-Forwarded-Host=solarracing.ie", - "traefik.http.routers.dcusr-dev.middlewares=nextauth-headers@consulcatalog", + "traefik.http.routers.dcusr-dev.middlewares=dcusr-nextauth-headers", + "traefik.http.middlewares.dcusr-nextauth-headers.headers.sslProxyHeaders.X-Forwarded-Proto=https", + "traefik.http.middlewares.dcusr-nextauth-headers.headers.customRequestHeaders.X-Forwarded-Host=solarracing.ie", ] } @@ -38,8 +51,8 @@ job "dcusr" { driver = "docker" config { - image = "ghcr.io/dcu-solar-racing/website:main" - ports = ["http"] + image = "ghcr.io/dcu-solar-racing/website:main" + ports = ["http"] force_pull = true auth { @@ -68,7 +81,7 @@ PREVIEW_SECRET={{ key "socs/dcusr-dev/preview/secret" }} SEED_ADMIN_EMAIL={{ key "socs/dcusr-dev/seed/email" }} SEED_ADMIN_PASSWORD={{ key "socs/dcusr-dev/seed/password" }} -DATABASE_URL=postgresql://{{ key "socs/dcusr-dev/db/user" | urlquery }}:{{ key "socs/dcusr-dev/db/password" | urlquery }}@{{ env "NOMAD_ADDR_db" }}/{{ key "socs/dcusr-dev/db/name" | urlquery }}?schema=public +DATABASE_URL=postgresql://{{ key "socs/dcusr-dev/db/user" | urlquery }}:{{ key "socs/dcusr-dev/db/password" | urlquery }}@{{ range service "dcusr-dev-db" }}{{ .Address }}:{{ .Port }}{{ end }}/{{ key "socs/dcusr-dev/db/name" | urlquery }}?schema=public MINIO_ENDPOINT={{ key "socs/dcusr-dev/minio/url" }} MINIO_PORT={{ key "socs/dcusr-dev/minio/port" }} @@ -101,15 +114,82 @@ EOH } } - task "postgres" { + task "wait-for-db" { driver = "docker" + lifecycle { + hook = "prestart" + sidecar = false + } + + config { + image = "postgres:17-alpine" + command = "sh" + args = [ + "-c", + "while ! pg_isready -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER}; do echo 'Waiting for DB...'; sleep 1; done; echo 'DB is ready!'" + ] + } + + template { + destination = "local/wait.env" + env = true + data = < Date: Tue, 3 Feb 2026 17:28:46 +0000 Subject: [PATCH 11/15] dcusr: remove unused jobs --- jobs/socs/dcusr/dcusr-bookstack.hcl | 189 -------------------- jobs/socs/dcusr/dcusr-hi-events.hcl | 229 ------------------------ jobs/socs/dcusr/dcusr-invoiceninja.hcl | 238 ------------------------- jobs/socs/dcusr/dcusr-rocketchat.hcl | 125 ------------- 4 files changed, 781 deletions(-) delete mode 100644 jobs/socs/dcusr/dcusr-bookstack.hcl delete mode 100644 jobs/socs/dcusr/dcusr-hi-events.hcl delete mode 100644 jobs/socs/dcusr/dcusr-invoiceninja.hcl delete mode 100644 jobs/socs/dcusr/dcusr-rocketchat.hcl diff --git a/jobs/socs/dcusr/dcusr-bookstack.hcl b/jobs/socs/dcusr/dcusr-bookstack.hcl deleted file mode 100644 index 6bd9fdf..0000000 --- a/jobs/socs/dcusr/dcusr-bookstack.hcl +++ /dev/null @@ -1,189 +0,0 @@ -job "dcusr-bookstack" { - datacenters = ["aperture"] - type = "service" - - meta { - domain = "wiki.solarracing.ie" - } - - group "bookstack" { - count = 1 - - network { - port "http" { - to = 80 - } - - port "db" { - to = 3306 - } - - port "redis" { - to = 6379 - } - } - - service { - name = "bookstack" - port = "http" - - tags = [ - "traefik.enable=true", - "traefik.http.routers.dcusr-bookstack.rule=Host(`${NOMAD_META_domain}`)", - "traefik.http.routers.dcusr-bookstack.entrypoints=web,websecure", - "traefik.http.routers.dcusr-bookstack.tls.certresolver=lets-encrypt", - ] - } - - task "bookstack" { - driver = "docker" - - config { - image = "lscr.io/linuxserver/bookstack:latest" - ports = ["http"] - - volumes = [ - "/storage/nomad/${NOMAD_JOB_NAME}/${NOMAD_TASK_NAME}:/config", - ] - } - - template { - destination = "local.env" - env = true - data = < Date: Fri, 20 Feb 2026 21:10:46 +0000 Subject: [PATCH 12/15] dcusr outline: dont use static ports --- jobs/socs/dcusr/dcusr-outline.hcl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jobs/socs/dcusr/dcusr-outline.hcl b/jobs/socs/dcusr/dcusr-outline.hcl index 5cf438e..89d9f67 100644 --- a/jobs/socs/dcusr/dcusr-outline.hcl +++ b/jobs/socs/dcusr/dcusr-outline.hcl @@ -10,8 +10,7 @@ job "dcusr-outline" { network { # mode = "bridge" port "http" { - static = 3000 - to = 3000 + to = 3000 } port "db" { From 94fdebf19c11eb9792ffd00a591d4999b54567f0 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Sat, 21 Mar 2026 04:28:46 +0000 Subject: [PATCH 13/15] fix dcusr website failing to start after any restart causing the site to 404 --- jobs/socs/dcusr/dcusr.hcl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/jobs/socs/dcusr/dcusr.hcl b/jobs/socs/dcusr/dcusr.hcl index 05f94c9..04774dc 100644 --- a/jobs/socs/dcusr/dcusr.hcl +++ b/jobs/socs/dcusr/dcusr.hcl @@ -3,7 +3,8 @@ job "dcusr-dev" { type = "service" meta { - domain = "solarracing.ie" + domain = "solarracing.ie" + domain2 = "www.solarracing.ie" } group "web" { @@ -37,12 +38,9 @@ job "dcusr-dev" { tags = [ "traefik.enable=true", - "traefik.http.routers.dcusr-dev.rule=Host(`solarracing.ie`) || Host(`www.solarracing.ie`)", + "traefik.http.routers.dcusr-dev.rule=Host(`${NOMAD_META_domain}`) || Host(`${NOMAD_META_domain2}`)", "traefik.http.routers.dcusr-dev.entrypoints=web,websecure", "traefik.http.routers.dcusr-dev.tls.certresolver=lets-encrypt", - "traefik.http.routers.dcusr-dev.middlewares=dcusr-nextauth-headers", - "traefik.http.middlewares.dcusr-nextauth-headers.headers.sslProxyHeaders.X-Forwarded-Proto=https", - "traefik.http.middlewares.dcusr-nextauth-headers.headers.customRequestHeaders.X-Forwarded-Host=solarracing.ie", ] } @@ -81,7 +79,9 @@ PREVIEW_SECRET={{ key "socs/dcusr-dev/preview/secret" }} SEED_ADMIN_EMAIL={{ key "socs/dcusr-dev/seed/email" }} SEED_ADMIN_PASSWORD={{ key "socs/dcusr-dev/seed/password" }} -DATABASE_URL=postgresql://{{ key "socs/dcusr-dev/db/user" | urlquery }}:{{ key "socs/dcusr-dev/db/password" | urlquery }}@{{ range service "dcusr-dev-db" }}{{ .Address }}:{{ .Port }}{{ end }}/{{ key "socs/dcusr-dev/db/name" | urlquery }}?schema=public +{{ range service "dcusr-dev-db" -}} +DATABASE_URL=postgresql://{{ key "socs/dcusr-dev/db/user" | urlquery }}:{{ key "socs/dcusr-dev/db/password" | urlquery }}@{{ .Address }}:{{ .Port }}/{{ key "socs/dcusr-dev/db/name" | urlquery }}?schema=public +{{- end }} MINIO_ENDPOINT={{ key "socs/dcusr-dev/minio/url" }} MINIO_PORT={{ key "socs/dcusr-dev/minio/port" }} @@ -121,30 +121,30 @@ EOH hook = "prestart" sidecar = false } - config { - image = "postgres:17-alpine" + image = "alpine:3.19" command = "sh" args = [ "-c", - "while ! pg_isready -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER}; do echo 'Waiting for DB...'; sleep 1; done; echo 'DB is ready!'" + "while ! nc -z \"$DB_HOST\" \"$DB_PORT\"; do echo 'Waiting for Postgres...'; sleep 1; done; echo 'DB is ready!'" ] } template { - destination = "local/wait.env" + destination = "local/.env" env = true + change_mode = "restart" data = < Date: Thu, 18 Jun 2026 14:17:48 +0100 Subject: [PATCH 14/15] dcusr: update openproject job --- jobs/socs/dcusr/dcusr-openproject.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jobs/socs/dcusr/dcusr-openproject.hcl b/jobs/socs/dcusr/dcusr-openproject.hcl index 1a522af..364596f 100644 --- a/jobs/socs/dcusr/dcusr-openproject.hcl +++ b/jobs/socs/dcusr/dcusr-openproject.hcl @@ -32,7 +32,6 @@ job "dcusr-openproject" { "traefik.http.routers.dcusr-openproject.entrypoints=web,websecure", "traefik.http.routers.dcusr-openproject.rule=Host(`${NOMAD_META_domain}`)", "traefik.http.routers.dcusr-openproject.tls=true", - "traefik.http.routers.dcusr-openproject.tls.certresolver=lets-encrypt", ] } @@ -56,6 +55,7 @@ OPENPROJECT_HOST__NAME={{ env "NOMAD_META_domain" }} OPENPROJECT_HTTPS=true OPENPROJECT_SECRET_KEY_BASE={{ key "dcusr/openproject/secret_key_base" }} +SECRET_KEY_BASE={{ key "dcusr/openproject/secret_key_base" }} EMAIL_DELIVERY_METHOD=smtp SMTP_ADDRESS={{ key "dcusr/openproject/smtp/address" }} From 661973ecc11fa87ccb34f34dbe1d238abe6d4141 Mon Sep 17 00:00:00 2001 From: Ayden Jahola Date: Thu, 18 Jun 2026 14:49:01 +0100 Subject: [PATCH 15/15] dcusr: add pitwall job --- jobs/socs/dcusr/pitwall.hcl | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 jobs/socs/dcusr/pitwall.hcl diff --git a/jobs/socs/dcusr/pitwall.hcl b/jobs/socs/dcusr/pitwall.hcl new file mode 100644 index 0000000..2b77f84 --- /dev/null +++ b/jobs/socs/dcusr/pitwall.hcl @@ -0,0 +1,69 @@ +job "pitwall" { + datacenters = ["aperture"] + type = "service" + + meta { + domain = "pitwall.solarracing.ie" + } + + group "pitwall" { + count = 1 + shutdown_delay = "5s" + + network { + port "http" { + to = 8080 + } + } + + service { + name = "pitwall" + port = "http" + + check { + type = "http" + path = "/healthz" + interval = "10s" + timeout = "2s" + } + + tags = [ + "traefik.enable=true", + "traefik.http.routers.pitwall.rule=Host(`${NOMAD_META_domain}`)", + "traefik.http.routers.pitwall.entrypoints=web,websecure", + "traefik.http.routers.dcusr-dev.tls=true", + ] + } + + task "pitwall-dashboard" { + driver = "docker" + + config { + image = "ghcr.io/dcu-solar-racing/solarcar-ecs-pit-dashboard:latest" + ports = ["http"] + force_pull = true + + auth { + username = "${DOCKER_USER}" + password = "${DOCKER_PASS}" + } + } + + template { + destination = "secrets/secret.env" + env = true + change_mode = "restart" + data = <