Files
alo-cluster/services/phaseflow.hcl
Petru Paler 8d97d09b07 Add phaseflow-cron job and PocketBase admin credentials
- New periodic job for daily Garmin sync at 6 AM
- Added pocketbase_admin_email and pocketbase_admin_password to
  secrets template for cron job authentication

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 07:13:36 +00:00

136 lines
3.4 KiB
HCL

# ABOUTME: Nomad job for PhaseFlow - menstrual cycle tracking and training app.
# ABOUTME: Runs Next.js app with PocketBase sidecar for data persistence.
# Setup required before running:
# sudo mkdir -p /data/services/phaseflow/pb_data && sudo chown 1000:1000 /data/services/phaseflow /data/services/phaseflow/pb_data
# nomad var put secrets/phaseflow \
# resend_api_key="re_xxxx" \
# encryption_key="$(openssl rand -hex 16)" \
# cron_secret="$(openssl rand -hex 32)" \
# pocketbase_admin_email="admin@example.com" \
# pocketbase_admin_password="your-admin-password"
job "phaseflow" {
datacenters = ["alo"]
# Force re-pull of :latest images on each nomad run
meta {
uuid = uuidv4()
}
update {
max_parallel = 1
health_check = "checks"
min_healthy_time = "30s"
healthy_deadline = "5m"
progress_deadline = "10m"
auto_revert = true
}
group "app" {
network {
port "http" {
to = 3000
}
port "pocketbase" {
to = 8090
}
}
# PocketBase sidecar - starts first, provides database
task "pocketbase" {
driver = "docker"
user = "1000"
lifecycle {
hook = "prestart"
sidecar = true
}
config {
image = "ghcr.io/muchobien/pocketbase:latest"
ports = ["pocketbase"]
volumes = ["/data/services/phaseflow/pb_data:/pb_data"]
}
env {
PB_DATA_DIR = "/pb_data"
}
resources {
memory = 256
}
service {
name = "pocketbase-phaseflow"
port = "pocketbase"
tags = [
"traefik.enable=true",
"traefik.http.routers.pocketbase-phaseflow.entryPoints=websecure",
]
}
}
# Main Next.js application
task "app" {
driver = "docker"
user = "1000"
config {
image = "gitea.v.paler.net/alo/phaseflow:latest"
ports = ["http"]
force_pull = true
}
env {
NODE_ENV = "production"
POCKETBASE_URL = "http://${NOMAD_ADDR_pocketbase}"
NEXT_PUBLIC_POCKETBASE_URL = "https://pocketbase-phaseflow.v.paler.net"
APP_URL = "https://phaseflow.v.paler.net"
EMAIL_FROM = "phaseflow@paler.net"
}
# Secrets from Nomad variables
template {
destination = "secrets/env.env"
env = true
data = <<EOH
RESEND_API_KEY={{ with nomadVar "secrets/phaseflow" }}{{ .resend_api_key }}{{ end }}
ENCRYPTION_KEY={{ with nomadVar "secrets/phaseflow" }}{{ .encryption_key }}{{ end }}
CRON_SECRET={{ with nomadVar "secrets/phaseflow" }}{{ .cron_secret }}{{ end }}
POCKETBASE_ADMIN_EMAIL={{ with nomadVar "secrets/phaseflow" }}{{ .pocketbase_admin_email }}{{ end }}
POCKETBASE_ADMIN_PASSWORD={{ with nomadVar "secrets/phaseflow" }}{{ .pocketbase_admin_password }}{{ end }}
EOH
}
resources {
memory = 512
}
service {
name = "phaseflow"
port = "http"
tags = [
"traefik.enable=true",
"traefik.http.routers.phaseflow.entryPoints=websecure",
"metrics",
]
check {
type = "http"
path = "/api/health"
interval = "10s"
timeout = "5s"
check_restart {
limit = 3
grace = "60s"
}
}
}
}
}
}