first
This commit is contained in:
25
cleanup.nomad
Normal file
25
cleanup.nomad
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
job "cleanup-litefs-all" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "batch"
|
||||||
|
|
||||||
|
group "cleanup" {
|
||||||
|
count = 2
|
||||||
|
constraint {
|
||||||
|
attribute = "${attr.unique.hostname}"
|
||||||
|
operator = "regexp"
|
||||||
|
value = "odroid7|odroid8"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "clean" {
|
||||||
|
driver = "docker"
|
||||||
|
config {
|
||||||
|
image = "busybox"
|
||||||
|
volumes = [
|
||||||
|
"/mnt/configs/navidrome_litefs:/mnt/data"
|
||||||
|
]
|
||||||
|
command = "sh"
|
||||||
|
args = ["-c", "rm -rf /mnt/data/* && echo \"Cleaned $(hostname)\""]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
juicefs-controller.nomad
Normal file
38
juicefs-controller.nomad
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
job "jfs-controller" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "system"
|
||||||
|
|
||||||
|
group "controller" {
|
||||||
|
task "plugin" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "juicedata/juicefs-csi-driver:v0.31.1"
|
||||||
|
|
||||||
|
args = [
|
||||||
|
"--endpoint=unix://csi/csi.sock",
|
||||||
|
"--logtostderr",
|
||||||
|
"--nodeid=test",
|
||||||
|
"--v=5",
|
||||||
|
"--by-process=true"
|
||||||
|
]
|
||||||
|
|
||||||
|
privileged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
csi_plugin {
|
||||||
|
id = "juicefs0"
|
||||||
|
type = "controller"
|
||||||
|
mount_dir = "/csi"
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
POD_NAME = "csi-controller"
|
||||||
|
POD_NAMESPACE = "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
juicefs-node.nomad
Normal file
63
juicefs-node.nomad
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
job "jfs-node" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "system"
|
||||||
|
|
||||||
|
group "nodes" {
|
||||||
|
network {
|
||||||
|
port "metrics" {
|
||||||
|
static = 9567
|
||||||
|
to = 8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "juicefs-metrics"
|
||||||
|
port = "metrics"
|
||||||
|
tags = ["prometheus"]
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
path = "/metrics"
|
||||||
|
interval = "10s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task "juicefs-plugin" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "juicedata/juicefs-csi-driver:v0.31.1"
|
||||||
|
memory_hard_limit = 2048
|
||||||
|
ports = ["metrics"]
|
||||||
|
args = [
|
||||||
|
"--endpoint=unix://csi/csi.sock",
|
||||||
|
"--logtostderr",
|
||||||
|
"--v=5",
|
||||||
|
"--nodeid=${node.unique.name}",
|
||||||
|
"--by-process=true",
|
||||||
|
]
|
||||||
|
|
||||||
|
privileged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
csi_plugin {
|
||||||
|
id = "juicefs0"
|
||||||
|
type = "node"
|
||||||
|
mount_dir = "/csi"
|
||||||
|
health_timeout = "3m"
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 100
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
POD_NAME = "csi-node"
|
||||||
|
POD_NAMESPACE = "default"
|
||||||
|
# Aggregates metrics from children onto the 8080 port
|
||||||
|
JFS_METRICS = "0.0.0.0:8080"
|
||||||
|
# Ensures mounts run as background processes managed by the driver
|
||||||
|
JFS_MOUNT_MODE = "process"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
navidrome-juice.nomad
Normal file
92
navidrome-juice.nomad
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
job "navidrome" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "service"
|
||||||
|
|
||||||
|
constraint {
|
||||||
|
attribute = "${attr.unique.hostname}"
|
||||||
|
operator = "regexp"
|
||||||
|
value = "odroid.*"
|
||||||
|
}
|
||||||
|
|
||||||
|
group "navidrome" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
volume "navidrome-csi-vol" {
|
||||||
|
type = "csi"
|
||||||
|
source = "navidrome-volume" # This must match the 'id' in your volume registration
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
access_mode = "multi-node-multi-writer"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Main Navidrome task
|
||||||
|
task "navidrome" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
volume = "navidrome-csi-vol" # Matches the name in the volume block above
|
||||||
|
destination = "/data" # Where it appears inside the container
|
||||||
|
read_only = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "ghcr.io/navidrome/navidrome:latest"
|
||||||
|
memory_hard_limit = "2048"
|
||||||
|
ports = ["http"]
|
||||||
|
volumes = [
|
||||||
|
"/mnt/Public/Downloads/Clean_Music:/music/CleanMusic:ro",
|
||||||
|
"/mnt/Public/Downloads/news/slskd/downloads:/music/slskd:ro",
|
||||||
|
"/mnt/Public/Downloads/incoming_music:/music/incomingmusic:ro"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
ND_DATAFOLDER = "/data"
|
||||||
|
ND_CACHEFOLDER = "/data/cache"
|
||||||
|
ND_CONFIGFILE= "/data/navidrome.toml"
|
||||||
|
ND_DBPATH = "/data/navidrome.db?_busy_timeout=30000&_journal_mode=DELETE&_foreign_keys=on&synchronous=NORMAL&cache=shared&nolock=1"
|
||||||
|
ND_SCANSCHEDULE = "32 8-20 * * *"
|
||||||
|
ND_LOGLEVEL = "trace"
|
||||||
|
ND_REVERSEPROXYWHITELIST = "0.0.0.0/0"
|
||||||
|
ND_REVERSEPROXYUSERHEADER = "X-Forwarded-User"
|
||||||
|
ND_SCANNER_GROUPALBUMRELEASES = "False"
|
||||||
|
ND_BACKUP_PATH = "/data/backups"
|
||||||
|
ND_BACKUP_SCHEDULE = "0 0 * * *"
|
||||||
|
ND_BACKUP_COUNT = "7"
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 128
|
||||||
|
}
|
||||||
|
service {
|
||||||
|
name = "navidrome"
|
||||||
|
tags = [
|
||||||
|
"navidrome",
|
||||||
|
"web",
|
||||||
|
"urlprefix-/navidrome",
|
||||||
|
"tools",
|
||||||
|
"traefik.http.routers.navidromelan.rule=Host(`navidrome.service.dc1.consul`)",
|
||||||
|
"traefik.http.routers.navidromewan.rule=Host(`m.fbleagh.duckdns.org`)",
|
||||||
|
"traefik.http.routers.navidromewan.middlewares=dex@consulcatalog",
|
||||||
|
"traefik.http.routers.navidromewan.tls=true",
|
||||||
|
]
|
||||||
|
port = "http"
|
||||||
|
check {
|
||||||
|
type = "tcp"
|
||||||
|
interval = "10s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
network {
|
||||||
|
port "http" {
|
||||||
|
static = 4533
|
||||||
|
to = 4533
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
184
navidrome-litefs.nomad
Normal file
184
navidrome-litefs.nomad
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
job "navidrome-litefs" {
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "service"
|
||||||
|
|
||||||
|
# We pin to Linux because LiteFS requires FUSE
|
||||||
|
constraint {
|
||||||
|
attribute = "${attr.kernel.name}"
|
||||||
|
value = "linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
group "navidrome" {
|
||||||
|
count = 2
|
||||||
|
|
||||||
|
constraint {
|
||||||
|
distinct_hosts = true
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "host"
|
||||||
|
port "http" {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Setup Task ---
|
||||||
|
task "setup" {
|
||||||
|
driver = "docker"
|
||||||
|
lifecycle {
|
||||||
|
hook = "prestart"
|
||||||
|
sidecar = false
|
||||||
|
}
|
||||||
|
config {
|
||||||
|
image = "busybox"
|
||||||
|
command = "mkdir"
|
||||||
|
args = ["-p", "/alloc/sqlite"]
|
||||||
|
network_mode = "host"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- LiteFS Task ---
|
||||||
|
task "litefs" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "flyio/litefs:0.5"
|
||||||
|
privileged = true # Needed for FUSE
|
||||||
|
ports = ["http"]
|
||||||
|
network_mode = "host"
|
||||||
|
|
||||||
|
# 1. Bind mount for LiteFS internal data (chunks/WAL)
|
||||||
|
# 2. Bind mount for the config
|
||||||
|
# 3. Mount the shared alloc dir so we can mount FUSE on it
|
||||||
|
volumes = [
|
||||||
|
"/mnt/configs/navidrome_litefs:/var/lib/litefs",
|
||||||
|
"local/litefs.yml:/etc/litefs.yml"
|
||||||
|
]
|
||||||
|
|
||||||
|
mounts = [
|
||||||
|
{
|
||||||
|
type = "bind"
|
||||||
|
source = "../alloc/sqlite"
|
||||||
|
target = "/mnt/sqlite"
|
||||||
|
bind_options = {
|
||||||
|
propagation = "shared"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create the config file
|
||||||
|
template {
|
||||||
|
left_delimiter = "[["
|
||||||
|
right_delimiter = "]]"
|
||||||
|
data = <<EOF
|
||||||
|
fuse:
|
||||||
|
# This matches the internal mount point in the container
|
||||||
|
dir: "/mnt/sqlite"
|
||||||
|
|
||||||
|
data:
|
||||||
|
# Internal data storage
|
||||||
|
dir: "/var/lib/litefs"
|
||||||
|
|
||||||
|
# Use Consul for leader election
|
||||||
|
lease:
|
||||||
|
type: "consul"
|
||||||
|
consul:
|
||||||
|
url: "http://[[ env `attr.unique.network.ip-address` ]]:8500"
|
||||||
|
key: "litefs/navidrome"
|
||||||
|
|
||||||
|
# The HTTP Proxy routes traffic
|
||||||
|
proxy:
|
||||||
|
addr: ":[[ env `NOMAD_PORT_http` ]]"
|
||||||
|
target: "127.0.0.1:4533" # Navidrome's internal port
|
||||||
|
db: "navidrome.db" # The DB to track for transaction consistency
|
||||||
|
passthrough: # Paths that don't need write-forwarding (optional optimizations)
|
||||||
|
- "*.js"
|
||||||
|
- "*.css"
|
||||||
|
- "*.png"
|
||||||
|
EOF
|
||||||
|
destination = "local/litefs.yml"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 200
|
||||||
|
memory = 256
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Navidrome Task (The App) ---
|
||||||
|
task "navidrome" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "ghcr.io/navidrome/navidrome:latest"
|
||||||
|
memory_hard_limit = "2048"
|
||||||
|
ports = [] # No ports exposed directly!
|
||||||
|
network_mode = "host"
|
||||||
|
|
||||||
|
# We mount the sqlite dir from the allocation directory
|
||||||
|
mounts = [
|
||||||
|
{
|
||||||
|
type = "bind"
|
||||||
|
source = "../alloc/sqlite"
|
||||||
|
target = "/data"
|
||||||
|
bind_options = {
|
||||||
|
propagation = "shared"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Shared Music and Configs
|
||||||
|
volumes = [
|
||||||
|
"/mnt/Public/Downloads/Clean_Music:/music/CleanMusic:ro",
|
||||||
|
"/mnt/Public/Downloads/news/slskd/downloads:/music/slskd:ro",
|
||||||
|
"/mnt/Public/Downloads/incoming_music:/music/incomingmusic:ro",
|
||||||
|
"/mnt/Public/configs/navidrome:/shared_data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
ND_DATAFOLDER = "/local/data"
|
||||||
|
ND_CACHEFOLDER = "/shared_data/cache"
|
||||||
|
ND_CONFIGFILE= "/local/data/navidrome.toml"
|
||||||
|
|
||||||
|
# Important: LiteFS handles locking, but we still want WAL mode.
|
||||||
|
ND_DBPATH = "/data/navidrome.db?_busy_timeout=30000&_journal_mode=WAL&_foreign_keys=on&synchronous=NORMAL"
|
||||||
|
|
||||||
|
# Disable internal scheduling to prevent redundant scans on secondary nodes.
|
||||||
|
ND_SCANSCHEDULE = "0"
|
||||||
|
ND_SCANNER_FSWATCHER_ENABLED = "false"
|
||||||
|
|
||||||
|
ND_LOGLEVEL = "info"
|
||||||
|
ND_REVERSEPROXYWHITELIST = "0.0.0.0/0"
|
||||||
|
ND_REVERSEPROXYUSERHEADER = "X-Forwarded-User"
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "navidrome"
|
||||||
|
tags = [
|
||||||
|
"navidrome",
|
||||||
|
"web",
|
||||||
|
"traefik.enable=true",
|
||||||
|
"urlprefix-/navidrome",
|
||||||
|
"tools",
|
||||||
|
"traefik.http.routers.navidromelan.rule=Host(`navidrome.service.dc1.consul`)",
|
||||||
|
"traefik.http.routers.navidromewan.rule=Host(`m.fbleagh.duckdns.org`)",
|
||||||
|
"traefik.http.routers.navidromewan.middlewares=dex@consulcatalog",
|
||||||
|
"traefik.http.routers.navidromewan.tls=true",
|
||||||
|
]
|
||||||
|
port = "http" # This maps to the LiteFS proxy port defined in network block
|
||||||
|
|
||||||
|
check {
|
||||||
|
type = "http"
|
||||||
|
path = "/app" # LiteFS proxy passes this through
|
||||||
|
interval = "10s"
|
||||||
|
timeout = "2s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 500
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
navidrome-vol.nomad
Normal file
35
navidrome-vol.nomad
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
type = "csi"
|
||||||
|
id = "navidrome-volume"
|
||||||
|
name = "navidrome-volume"
|
||||||
|
|
||||||
|
# This UUID was generated during the Postgres storage format
|
||||||
|
external_id = "56783f1f-d9c6-45fd-baec-56fa6c33776b"
|
||||||
|
|
||||||
|
capacity_min = "10GiB"
|
||||||
|
capacity_max = "10GiB"
|
||||||
|
|
||||||
|
capability {
|
||||||
|
access_mode = "multi-node-multi-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_id = "juicefs0"
|
||||||
|
|
||||||
|
context {
|
||||||
|
writeback = "false"
|
||||||
|
delayed-write = "true"
|
||||||
|
upload-delay = "1m"
|
||||||
|
cache-size = "1024"
|
||||||
|
buffer-size = "128"
|
||||||
|
attr-cache = "60"
|
||||||
|
entry-cache = "60"
|
||||||
|
enable-mmap = "true"
|
||||||
|
metacache = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets {
|
||||||
|
name = "navidrome-volume"
|
||||||
|
metaurl = "postgres://postgres:postgres@master.postgres.service.dc1.consul:5432/juicefs-navidrome"
|
||||||
|
storage = "postgres"
|
||||||
|
bucket = "postgres://postgres:postgres@master.postgres.service.dc1.consul:5432/juicefs-navidrome-storage"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user