feat: migrate to LiteFS-supervised container architecture
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m2s

This commit is contained in:
2026-02-07 16:38:38 -08:00
parent 11ebd95956
commit 21598113e4
4 changed files with 196 additions and 0 deletions

60
.github/workflows/build-and-push.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Build and Push Docker Image
on:
workflow_dispatch:
push:
branches:
- main
- master
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
container_sha: ${{ github.sha }}
registry_url: ${{ steps.registry.outputs.url }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set registry URL
id: registry
run: |
if [ "${{ github.server_url }}" = "https://github.com" ]; then
echo "url=ghcr.io" >> $GITHUB_OUTPUT
else
# Extract domain from server_url (e.g. gitea.service.dc1.fbleagh.duckdns.org)
echo "url=${{ github.server_url }}" | sed 's|https://||' >> $GITHUB_OUTPUT
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ steps.registry.outputs.url }}
username: ${{ github.actor }}
password: ${{ secrets.PACKAGE_TOKEN || secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push multi-arch Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ steps.registry.outputs.url }}/${{ github.repository }}:latest
${{ steps.registry.outputs.url }}/${{ github.repository }}:${{ github.sha }}
build-args: |
COMMIT_SHA=${{ github.sha }}
cache-from: type=registry,ref=${{ steps.registry.outputs.url }}/${{ github.repository }}:buildcache
cache-to: type=registry,ref=${{ steps.registry.outputs.url }}/${{ github.repository }}:buildcache,mode=max
labels: org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}

20
Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
# Stage 1: Get LiteFS binary
FROM flyio/litefs:0.5 AS litefs
# Stage 2: Final image
FROM ghcr.io/navidrome/navidrome:latest
# Install FUSE and CA certificates (needed for LiteFS)
USER root
RUN apk add --no-cache fuse3 ca-certificates
# Copy LiteFS binary
COPY --from=litefs /usr/local/bin/litefs /usr/local/bin/litefs
# Copy LiteFS configuration
COPY litefs.yml /etc/litefs.yml
# We'll use environment variables for most LiteFS settings,
# but the baked-in config provides the structure.
# LiteFS will mount the FUSE fs and then execute Navidrome.
ENTRYPOINT ["litefs", "mount", "--", "/app/navidrome"]

27
litefs.yml Normal file
View File

@@ -0,0 +1,27 @@
# LiteFS configuration for Navidrome
fuse:
dir: "/data"
data:
dir: "/var/lib/litefs"
# Use Consul for leader election
lease:
type: "consul"
consul:
url: "${CONSUL_URL}"
key: "litefs/navidrome"
# The HTTP Proxy routes traffic to handle write-forwarding
proxy:
addr: ":${PORT}"
target: "localhost:4533"
db: "navidrome.db"
passthrough:
- "*.js"
- "*.css"
- "*.png"
- "*.jpg"
- "*.jpeg"
- "*.gif"
- "*.svg"

89
navidrome-litefs-v2.nomad Normal file
View File

@@ -0,0 +1,89 @@
job "navidrome-litefs" {
datacenters = ["dc1"]
type = "service"
constraint {
attribute = "${attr.kernel.name}"
value = "linux"
}
group "navidrome" {
count = 2
constraint {
distinct_hosts = true
}
network {
mode = "host"
port "http" {}
}
task "navidrome" {
driver = "docker"
config {
# Update this to match your actual registry and image name
image = "gitea.service.dc1.fbleagh.duckdns.org/sstent/navidrome-litefs:latest"
privileged = true # Needed for FUSE
network_mode = "host"
volumes = [
"/mnt/configs/navidrome_litefs:/var/lib/litefs",
"/mnt/Public/configs/navidrome:/shared_data",
"/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 {
# LiteFS Config
CONSUL_URL = "http://${attr.unique.network.ip-address}:8500"
PORT = "${NOMAD_PORT_http}"
# Navidrome Config
ND_DATAFOLDER = "/local/data"
ND_CACHEFOLDER = "/shared_data/cache"
ND_CONFIGFILE = "/local/data/navidrome.toml"
# Database is on the LiteFS FUSE mount
ND_DBPATH = "/data/navidrome.db?_busy_timeout=30000&_journal_mode=WAL&_foreign_keys=on&synchronous=NORMAL"
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"
check {
type = "http"
path = "/app"
interval = "10s"
timeout = "2s"
}
}
resources {
cpu = 500
memory = 512
}
}
}
}