fix(infra): move Redis to prod, fix LibreTranslate config loading
All checks were successful
CI / Backend (push) Successful in 46s
CI / UI (push) Successful in 52s
Release / Docker / caddy (push) Successful in 34s
Release / Test backend (push) Successful in 48s
Release / Check ui (push) Successful in 49s
CI / Backend (pull_request) Successful in 25s
CI / UI (pull_request) Successful in 56s
Release / Docker / runner (push) Successful in 1m46s
Release / Docker / ui (push) Successful in 2m30s
Release / Docker / backend (push) Successful in 2m47s
Release / Gitea Release (push) Successful in 13s
All checks were successful
CI / Backend (push) Successful in 46s
CI / UI (push) Successful in 52s
Release / Docker / caddy (push) Successful in 34s
Release / Test backend (push) Successful in 48s
Release / Check ui (push) Successful in 49s
CI / Backend (pull_request) Successful in 25s
CI / UI (pull_request) Successful in 56s
Release / Docker / runner (push) Successful in 1m46s
Release / Docker / ui (push) Successful in 2m30s
Release / Docker / backend (push) Successful in 2m47s
Release / Gitea Release (push) Successful in 13s
- Add Redis sidecar to prod docker-compose; backend connects locally (redis:6379) - Caddy layer4 now proxies redis.libnovel.cc:6380 → local redis:6379 (not homelab LAN) - Remove HOMELAB_REDIS_ADDR; homelab runner connects out to prod Redis via rediss:// - Remove local Redis from homelab runner compose; drop redis_data volume - Fix config.Load() missing LibreTranslate section — LIBRETRANSLATE_URL was never read
This commit is contained in:
@@ -58,9 +58,9 @@
|
|||||||
|
|
||||||
# ── Redis TCP proxy via layer4 ────────────────────────────────────────────
|
# ── Redis TCP proxy via layer4 ────────────────────────────────────────────
|
||||||
# Exposes prod Redis over TLS for Asynq job enqueueing from the homelab runner.
|
# Exposes prod Redis over TLS for Asynq job enqueueing from the homelab runner.
|
||||||
# Listens on :6380 (all interfaces). TLS is terminated here using the cert
|
# Listens on :6380 (all interfaces). TLS is terminated here using the cert
|
||||||
# for redis.libnovel.cc; traffic is proxied to the local Redis sidecar.
|
# for redis.libnovel.cc; traffic is proxied to the local Redis sidecar.
|
||||||
# Requires the caddy-l4 module in the custom Caddy build.
|
# Requires the caddy-l4 module in the custom Caddy build.
|
||||||
layer4 {
|
layer4 {
|
||||||
:6380 {
|
:6380 {
|
||||||
route {
|
route {
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
proxy {
|
proxy {
|
||||||
upstream redis:6379
|
upstream redis:6379
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,6 +203,11 @@ func Load() Config {
|
|||||||
URL: envOr("POCKET_TTS_URL", ""),
|
URL: envOr("POCKET_TTS_URL", ""),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
LibreTranslate: LibreTranslate{
|
||||||
|
URL: envOr("LIBRETRANSLATE_URL", ""),
|
||||||
|
APIKey: envOr("LIBRETRANSLATE_API_KEY", ""),
|
||||||
|
},
|
||||||
|
|
||||||
HTTP: HTTP{
|
HTTP: HTTP{
|
||||||
Addr: envOr("BACKEND_HTTP_ADDR", ":8080"),
|
Addr: envOr("BACKEND_HTTP_ADDR", ":8080"),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -126,6 +126,26 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
|
# ─── Redis (Asynq task queue — accessed locally by backend, remotely by homelab runner) ──
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
command: >
|
||||||
|
redis-server
|
||||||
|
--appendonly yes
|
||||||
|
--requirepass "${REDIS_PASSWORD}"
|
||||||
|
# No public port — backend reaches it via internal network.
|
||||||
|
# Homelab runner reaches it via Caddy TLS proxy on :6380 → redis:6379.
|
||||||
|
expose:
|
||||||
|
- "6379"
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
# ─── Backend API ──────────────────────────────────────────────────────────────
|
# ─── Backend API ──────────────────────────────────────────────────────────────
|
||||||
backend:
|
backend:
|
||||||
image: kalekber/libnovel-backend:${GIT_TAG:-latest}
|
image: kalekber/libnovel-backend:${GIT_TAG:-latest}
|
||||||
@@ -151,6 +171,8 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
valkey:
|
valkey:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
# No public port — all traffic is routed via Caddy.
|
# No public port — all traffic is routed via Caddy.
|
||||||
expose:
|
expose:
|
||||||
- "8080"
|
- "8080"
|
||||||
@@ -164,10 +186,9 @@ services:
|
|||||||
GLITCHTIP_DSN: "${GLITCHTIP_DSN}"
|
GLITCHTIP_DSN: "${GLITCHTIP_DSN}"
|
||||||
OTEL_EXPORTER_OTLP_ENDPOINT: "${OTEL_EXPORTER_OTLP_ENDPOINT}"
|
OTEL_EXPORTER_OTLP_ENDPOINT: "${OTEL_EXPORTER_OTLP_ENDPOINT}"
|
||||||
OTEL_SERVICE_NAME: "backend"
|
OTEL_SERVICE_NAME: "backend"
|
||||||
# Asynq task queue — backend enqueues jobs to homelab Redis via Caddy TLS proxy.
|
# Asynq task queue — backend enqueues jobs to local Redis sidecar.
|
||||||
# Set to "rediss://:password@redis.libnovel.cc:6380" in Doppler prd config.
|
# Homelab runner connects to the same Redis via Caddy TLS proxy on :6380.
|
||||||
# Leave empty to fall back to PocketBase polling.
|
REDIS_ADDR: "redis:6379"
|
||||||
REDIS_ADDR: "${REDIS_ADDR}"
|
|
||||||
REDIS_PASSWORD: "${REDIS_PASSWORD}"
|
REDIS_PASSWORD: "${REDIS_PASSWORD}"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "/healthcheck", "http://localhost:8080/health"]
|
test: ["CMD", "/healthcheck", "http://localhost:8080/health"]
|
||||||
@@ -382,12 +403,10 @@ services:
|
|||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "443:443/udp" # HTTP/3 (QUIC)
|
- "443:443/udp" # HTTP/3 (QUIC)
|
||||||
- "6380:6380" # Redis TCP proxy (TLS) for homelab → Asynq
|
- "6380:6380" # Redis TCP proxy (TLS) for homelab runner → Asynq
|
||||||
environment:
|
environment:
|
||||||
DOMAIN: "${DOMAIN}"
|
DOMAIN: "${DOMAIN}"
|
||||||
CADDY_ACME_EMAIL: "${CADDY_ACME_EMAIL}"
|
CADDY_ACME_EMAIL: "${CADDY_ACME_EMAIL}"
|
||||||
# Homelab Redis address — Caddy TCP-proxies inbound :6380 to this.
|
|
||||||
HOMELAB_REDIS_ADDR: "${HOMELAB_REDIS_ADDR:?HOMELAB_REDIS_ADDR required for Redis TCP proxy}"
|
|
||||||
env_file:
|
env_file:
|
||||||
- path: ./crowdsec/.crowdsec.env
|
- path: ./crowdsec/.crowdsec.env
|
||||||
required: false
|
required: false
|
||||||
@@ -421,6 +440,7 @@ volumes:
|
|||||||
pb_data:
|
pb_data:
|
||||||
meili_data:
|
meili_data:
|
||||||
valkey_data:
|
valkey_data:
|
||||||
|
redis_data:
|
||||||
caddy_data:
|
caddy_data:
|
||||||
caddy_config:
|
caddy_config:
|
||||||
caddy_logs:
|
caddy_logs:
|
||||||
|
|||||||
@@ -11,25 +11,10 @@
|
|||||||
# - MEILI_URL → https://search.libnovel.cc (Caddy-proxied)
|
# - MEILI_URL → https://search.libnovel.cc (Caddy-proxied)
|
||||||
# - VALKEY_ADDR → unset (not exposed publicly)
|
# - VALKEY_ADDR → unset (not exposed publicly)
|
||||||
# - RUNNER_SKIP_INITIAL_CATALOGUE_REFRESH=true
|
# - RUNNER_SKIP_INITIAL_CATALOGUE_REFRESH=true
|
||||||
# - Redis service for Asynq task queue (local to homelab, exposed to prod via Caddy TCP proxy)
|
# - REDIS_ADDR → rediss://redis.libnovel.cc:6380 (prod Redis via Caddy TLS proxy)
|
||||||
# - LibreTranslate service for machine translation (internal network only)
|
# - LibreTranslate service for machine translation (internal network only)
|
||||||
|
|
||||||
services:
|
services:
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
command: >
|
|
||||||
redis-server
|
|
||||||
--appendonly yes
|
|
||||||
--requirepass "${REDIS_PASSWORD}"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
libretranslate:
|
libretranslate:
|
||||||
image: libretranslate/libretranslate:latest
|
image: libretranslate/libretranslate:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -55,8 +40,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
stop_grace_period: 135s
|
stop_grace_period: 135s
|
||||||
depends_on:
|
depends_on:
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
libretranslate:
|
libretranslate:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
@@ -91,9 +74,10 @@ services:
|
|||||||
LIBRETRANSLATE_URL: "http://libretranslate:5000"
|
LIBRETRANSLATE_URL: "http://libretranslate:5000"
|
||||||
LIBRETRANSLATE_API_KEY: "${LIBRETRANSLATE_API_KEY}"
|
LIBRETRANSLATE_API_KEY: "${LIBRETRANSLATE_API_KEY}"
|
||||||
|
|
||||||
# ── Asynq / Redis (local service) ───────────────────────────────────────
|
# ── Asynq / Redis (prod Redis via Caddy TLS proxy) ──────────────────────
|
||||||
# The runner connects to the local Redis sidecar.
|
# The runner connects to prod Redis over TLS: rediss://redis.libnovel.cc:6380.
|
||||||
REDIS_ADDR: "redis:6379"
|
# Caddy on prod terminates TLS and proxies to the local redis:6379 sidecar.
|
||||||
|
REDIS_ADDR: "${REDIS_ADDR}"
|
||||||
REDIS_PASSWORD: "${REDIS_PASSWORD}"
|
REDIS_PASSWORD: "${REDIS_PASSWORD}"
|
||||||
|
|
||||||
# ── Runner tuning ───────────────────────────────────────────────────────
|
# ── Runner tuning ───────────────────────────────────────────────────────
|
||||||
@@ -117,6 +101,5 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
redis_data:
|
|
||||||
libretranslate_models:
|
libretranslate_models:
|
||||||
libretranslate_db:
|
libretranslate_db:
|
||||||
|
|||||||
Reference in New Issue
Block a user