From 9cd5455378117cd47c9b4fda3d5bca5e83f08e0f Mon Sep 17 00:00:00 2001 From: sstent Date: Sun, 8 Feb 2026 13:59:37 -0800 Subject: [PATCH] feat(entrypoint): Refactor entrypoint for leadership-aware process management and clean up register.sh --- Dockerfile | 3 +- entrypoint.sh | 80 +++++++++++++++++++++++++++++++++++++++++++++++---- register.sh | 73 ---------------------------------------------- 3 files changed, 76 insertions(+), 80 deletions(-) delete mode 100644 register.sh diff --git a/Dockerfile b/Dockerfile index 88e2da4..90b8316 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,9 +12,8 @@ RUN apk add --no-cache fuse3 ca-certificates bash curl COPY --from=litefs /usr/local/bin/litefs /usr/local/bin/litefs # Copy scripts -COPY register.sh /usr/local/bin/register.sh COPY entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod +x /usr/local/bin/register.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh # Copy LiteFS configuration COPY litefs.yml /etc/litefs.yml diff --git a/entrypoint.sh b/entrypoint.sh index 6306967..b902f3e 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,8 +1,78 @@ #!/bin/bash +set -e -# Start the registration loop in the background, redirecting output to stderr so we see it in Nomad logs -/usr/local/bin/register.sh >&2 & +# Configuration from environment +SERVICE_NAME="navidrome" +PORT=4533 +CONSUL_HTTP_ADDR="${CONSUL_URL:-http://localhost:8500}" +NODE_IP="${ADVERTISE_IP}" -# Start Navidrome -echo "Starting Navidrome..." -/app/navidrome \ No newline at end of file +# Tags for the Primary service (Traefik enabled) +PRIMARY_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"]' + +NAVIDROME_PID="" +SERVICE_ID="navidrome-${NODE_IP}-${SERVICE_NAME}" + +cleanup() { + echo "Caught signal, shutting down..." + if [ -n "$NAVIDROME_PID" ]; then + echo "Stopping Navidrome (PID: $NAVIDROME_PID)..." + kill -TERM "$NAVIDROME_PID" + wait "$NAVIDROME_PID" || true + fi + echo "Deregistering service ${SERVICE_ID} from Consul..." + curl -s -X PUT "${CONSUL_HTTP_ADDR}/v1/agent/service/deregister/${SERVICE_ID}" || true + exit 0 +} + +trap cleanup SIGTERM SIGINT + +echo "Starting leadership-aware entrypoint..." +echo "Node IP: $NODE_IP" +echo "Consul: $CONSUL_HTTP_ADDR" + +while true; do + # In LiteFS 0.5, .primary file exists ONLY on replicas. + if [ ! -f /data/.primary ]; then + # PRIMARY STATE + if [ -z "$NAVIDROME_PID" ] || ! kill -0 "$NAVIDROME_PID" 2>/dev/null; then + echo "Node is Primary. Initializing Navidrome..." + + # Register in Consul + echo "Registering as primary in Consul..." + curl -s -X PUT -d "{ + \"ID\": \"${SERVICE_ID}\", + \"Name\": \"${SERVICE_NAME}\", + \"Tags\": ${PRIMARY_TAGS}, + \"Address\": \"${NODE_IP}\", + \"Port\": ${PORT}, + \"Check\": { + \"HTTP\": \"http://${NODE_IP}:${PORT}/app\", + \"Interval\": \"10s\", + \"Timeout\": \"2s\" + } + }" "${CONSUL_HTTP_ADDR}/v1/agent/service/register" + + # Start Navidrome + /app/navidrome & + NAVIDROME_PID=$! + echo "Navidrome started with PID $NAVIDROME_PID" + fi + else + # REPLICA STATE + if [ -n "$NAVIDROME_PID" ] && kill -0 "$NAVIDROME_PID" 2>/dev/null; then + echo "Node transitioned to Replica. Stopping Navidrome..." + kill -TERM "$NAVIDROME_PID" + wait "$NAVIDROME_PID" || true + NAVIDROME_PID="" + + echo "Deregistering primary service from Consul..." + curl -s -X PUT "${CONSUL_HTTP_ADDR}/v1/agent/service/deregister/${SERVICE_ID}" || true + fi + + # We don't register anything for replicas in this version to keep it simple. + # But we stay alive so LiteFS keeps running. + fi + + sleep 5 +done diff --git a/register.sh b/register.sh deleted file mode 100644 index bda375b..0000000 --- a/register.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -set -x - -# Configuration -SERVICE_NAME="navidrome" -REPLICA_SERVICE_NAME="replica-navidrome" -PORT=4533 -CONSUL_HTTP_ADDR="${CONSUL_URL:-http://localhost:8500}" -NODE_IP="${ADVERTISE_IP}" -CHECK_INTERVAL="10s" - -# Tags for the Primary service (Traefik enabled) -PRIMARY_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"]' - -# Tags for the Replica service -REPLICA_TAGS='["navidrome-replica"]' - -register_service() { - local name=$1 - local tags=$2 - local id="navidrome-${NODE_IP}-${name}" - - echo "Registering as ${name} with ID ${id} at ${NODE_IP}:${PORT}..." - curl -v -X PUT -d "{ - \"ID\": \"${id}\", - \"Name\": \"${name}\", - \"Tags\": ${tags}, - \"Address\": \"${NODE_IP}\", - \"Port\": ${PORT}, - \"Check\": { - \"HTTP\": \"http://${NODE_IP}:${PORT}/app\", - \"Interval\": \"${CHECK_INTERVAL}\", - \"Timeout\": \"2s\" - } - }" "${CONSUL_HTTP_ADDR}/v1/agent/service/register" -} - -deregister_service() { - local name=$1 - local id="navidrome-${NODE_IP}-${name}" - echo "Deregistering ${name} with ID ${id}..." - curl -v -X PUT "${CONSUL_HTTP_ADDR}/v1/agent/service/deregister/${id}" -} - -echo "Starting Consul registration loop..." - -LAST_STATE="unknown" - -while true; do - # In LiteFS 0.5, .primary file exists ONLY on replicas. - # We check /data/.primary because /data is our mount point. - if [ ! -f /data/.primary ]; then - CURRENT_STATE="primary" - else - CURRENT_STATE="replica" - fi - - echo "Current node state: ${CURRENT_STATE}" - - if [ "$CURRENT_STATE" != "$LAST_STATE" ]; then - echo "State change detected: ${LAST_STATE} -> ${CURRENT_STATE}" - if [ "$CURRENT_STATE" == "primary" ]; then - deregister_service "$REPLICA_SERVICE_NAME" - register_service "$SERVICE_NAME" "$PRIMARY_TAGS" - else - deregister_service "$SERVICE_NAME" - register_service "$REPLICA_SERVICE_NAME" "$REPLICA_TAGS" - fi - LAST_STATE="$CURRENT_STATE" - fi - - sleep 15 -done