Compare commits

...

5 Commits

Author SHA1 Message Date
d195efdb0e Add phaseflow service
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 10:20:40 +00:00
3277c810a5 Update flake. 2026-01-10 20:04:51 +00:00
f2baf3daf6 Move to new domain. 2026-01-09 06:17:20 +00:00
931470ee0a Remove farmOS service
Egg harvest data (849 logs, 6704 eggs, Nov 2023 - Jan 2026) exported
to CSV before shutdown. Database and user dropped from PostgreSQL.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 13:31:57 +00:00
41b30788fe Update flake. 2026-01-08 13:03:48 +00:00
4 changed files with 194 additions and 83 deletions

105
flake.lock generated
View File

@@ -25,11 +25,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1766518262,
"narHash": "sha256-ITihWSOexQX1a/i8ZiMt3M609KxX7sLhz63F9rnnguY=",
"lastModified": 1767987169,
"narHash": "sha256-HRydj8HYesU+zGVf+g+tS9vTHMZpZU+MgnTjq8AYYXk=",
"owner": "nix-community",
"repo": "browser-previews",
"rev": "1e4c4310443ace75d0df9efaeb4c6fc6f8c8678c",
"rev": "2e9b12d065f95b4c670316baa572376e5d9a8d32",
"type": "github"
},
"original": {
@@ -115,11 +115,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1766221270,
"narHash": "sha256-YDNOESYOfafsoqW7qEM1Gkuv6DZVZyn6Wrs7+/I7u0A=",
"lastModified": 1767776044,
"narHash": "sha256-yNLLrf4qKubvO11vTH6FjfPV2iCcNusivuzngEEuc+w=",
"owner": "nix-community",
"repo": "ethereum.nix",
"rev": "cd43a1333b8a2e519815d468b791b893d103e618",
"rev": "34217e7d20d6ed04170a1347db346df068669090",
"type": "github"
},
"original": {
@@ -258,11 +258,11 @@
]
},
"locked": {
"lastModified": 1766553861,
"narHash": "sha256-ZbnG01yA3O8Yr1vUm3+NQ2qk9iRhS5bloAnuXHHy7+c=",
"lastModified": 1767910483,
"narHash": "sha256-MOU5YdVu4DVwuT5ztXgQpPuRRBjSjUGIdUzOQr9iQOY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "0999ed8f965bbbd991437ad9c5ed3434cecbc30e",
"rev": "82fb7dedaad83e5e279127a38ef410bcfac6d77c",
"type": "github"
},
"original": {
@@ -272,13 +272,38 @@
"type": "github"
}
},
"impermanence": {
"home-manager_2": {
"inputs": {
"nixpkgs": [
"impermanence",
"nixpkgs"
]
},
"locked": {
"lastModified": 1737831083,
"narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=",
"lastModified": 1747978958,
"narHash": "sha256-pQQnbxWpY3IiZqgelXHIe/OAE/Yv4NSQq7fch7M6nXQ=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "7419250703fd5eb50e99bdfb07a86671939103ea",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"inputs": {
"home-manager": "home-manager_2",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1767822991,
"narHash": "sha256-iyrn9AcPZCoyxX4OT8eMkBsjG7SRUQXXS/V1JzxS7rA=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170",
"rev": "82e5bc4508cab9e8d5a136626276eb5bbce5e9c5",
"type": "github"
},
"original": {
@@ -328,11 +353,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1766568855,
"narHash": "sha256-UXVtN77D7pzKmzOotFTStgZBqpOcf8cO95FcupWp4Zo=",
"lastModified": 1767185284,
"narHash": "sha256-ljDBUDpD1Cg5n3mJI81Hz5qeZAwCGxon4kQW3Ho3+6Q=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "c5db9569ac9cc70929c268ac461f4003e3e5ca80",
"rev": "40b1a28dce561bea34858287fbb23052c3ee63fe",
"type": "github"
},
"original": {
@@ -344,16 +369,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1766622938,
"narHash": "sha256-Eovt/DOCYjFFBZuYbbG9j5jhklzxdNbUGVYYxh3lG3s=",
"owner": "NixOS",
"lastModified": 1748026106,
"narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "5900a0a8850cbba98e16d5a7a6ed389402dfcf4f",
"rev": "063f43f2dbdef86376cc29ad646c45c46e93234c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
@@ -406,11 +431,11 @@
},
"nixpkgs-unstable_2": {
"locked": {
"lastModified": 1766651565,
"narHash": "sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU=",
"lastModified": 1767892417,
"narHash": "sha256-dhhvQY67aboBk8b0/u0XB6vwHdgbROZT3fJAjyNh5Ww=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3e2499d5539c16d0d173ba53552a4ff8547f4539",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"type": "github"
},
"original": {
@@ -420,6 +445,22 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1767799921,
"narHash": "sha256-r4GVX+FToWVE2My8VVZH4V0pTIpnu2ZE8/Z4uxGEMBE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d351d0653aeb7877273920cd3e823994e7579b0b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixvim": {
"inputs": {
"flake-parts": "flake-parts_2",
@@ -429,11 +470,11 @@
"systems": "systems_4"
},
"locked": {
"lastModified": 1766721995,
"narHash": "sha256-2qZLSojZFP3AzbC6UNF3ASCIDLahNniR2XP7l/qINm4=",
"lastModified": 1767906546,
"narHash": "sha256-AoSWS8+P+7hQ/jIdv0wBjgH1MvnerdWBFXO4GV3JoQs=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "66a5dc70e2d8433034bccdbb9c3c7bcecd86f9a6",
"rev": "7eb8f36f085b85a2aeff929aff52d0f6aa14e000",
"type": "github"
},
"original": {
@@ -453,7 +494,7 @@
"nix-colors": "nix-colors",
"nix-index-database": "nix-index-database",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs",
"nixpkgs": "nixpkgs_2",
"nixpkgs-unstable": "nixpkgs-unstable_2",
"nixvim": "nixvim",
"sops-nix": "sops-nix"
@@ -466,11 +507,11 @@
]
},
"locked": {
"lastModified": 1766289575,
"narHash": "sha256-BOKCwOQQIP4p9z8DasT5r+qjri3x7sPCOq+FTjY8Z+o=",
"lastModified": 1768032389,
"narHash": "sha256-BVpTd93G0XmAK1iXiBdhUA5Uvt+WmM1YL0mA4REcT68=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "9836912e37aef546029e48c8749834735a6b9dad",
"rev": "a8cfe238b93166f9f96c0df67a94e572554ee624",
"type": "github"
},
"original": {

View File

@@ -68,6 +68,7 @@ EOH
"traefik.enable=true",
"traefik.http.routers.animaltrack.entryPoints=websecure",
"traefik.http.routers.animaltrack.middlewares=oidc-auth@file",
"traefik.http.routers.animaltrack.rule=Host(`farm.alo.land`)",
]
check {

View File

@@ -1,51 +0,0 @@
job "farmos" {
datacenters = ["alo"]
meta {
uuid = uuidv4()
}
group "os" {
network {
port "http" {
to = 80
}
}
task "server" {
driver = "docker"
config {
image = "gitea.v.paler.net/alo/farmos:latest"
ports = ["http"]
volumes = [
"/data/services/farmos/sites:/opt/drupal/web/sites",
"/data/services/farmos/keys:/opt/drupal/keys",
]
}
service {
name = "farmos"
port = "http"
check {
type = "http"
port = "http"
path = "/health"
interval = "30s"
timeout = "2s"
}
tags = [
"traefik.enable=true",
"traefik.http.routers.farmos.entryPoints=websecure",
"traefik.http.routers.farmos.rule=Host(`farm.alo.land`)",
]
}
resources {
cpu = 2000
memory = 1024
}
}
}
}

120
services/phaseflow.hcl Normal file
View File

@@ -0,0 +1,120 @@
# 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)"
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
}
}
# 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://localhost:8090"
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 }}
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"
}
}
}
}
}
}