mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 17:05:56 -04:00
Introduce DATA_DIR env var for consistent data path configuration
Replace separate DATABASE_URL and IMAGE_CACHE_DIR env vars with a single DATA_DIR root (default: ./data, Docker: /data). DATABASE_URL and CACHE_DIR are derived from it but can still be overridden individually. Also: - Pin pnpm to @10 for reproducible Docker builds - Add --link to COPY instructions for better BuildKit cache reuse - Add syntax directive for BuildKit features - Simplify Dockerfile mkdir to just /data (ensureImageDirs handles subdirs) - Remove redundant DATABASE_URL from docker-compose.yml Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-7
@@ -1,10 +1,10 @@
|
||||
# ─── Database ───────────────────────────────────────────────────────────
|
||||
# SQLite database URL (Docker: file:/data/sqlite.db, local dev: file:sqlite.db)
|
||||
# DATABASE_URL=file:/data/sqlite.db
|
||||
# ─── Data Directory ──────────────────────────────────────────────────────
|
||||
# Root directory for SQLite database and image cache (default: ./data, Docker: /data)
|
||||
# DATA_DIR=./data
|
||||
|
||||
# ─── TMDB (required) ───────────────────────────────────────────────────────
|
||||
# API Read Access Token — get one at https://www.themoviedb.org/settings/api
|
||||
TMDB_API_READ_ACCESS_TOKEN=your_tmdb_api_read_access_token_here
|
||||
TMDB_API_READ_ACCESS_TOKEN=
|
||||
|
||||
# Optional: override TMDB base URLs (advanced)
|
||||
# TMDB_API_BASE_URL=https://api.themoviedb.org/3
|
||||
@@ -13,7 +13,7 @@ TMDB_API_READ_ACCESS_TOKEN=your_tmdb_api_read_access_token_here
|
||||
# ─── Auth (required) ───────────────────────────────────────────────────────
|
||||
# Random secret for session encryption (min 32 chars)
|
||||
# Generate one with `npx @better-auth/cli secret` or `openssl rand -base64 32`
|
||||
BETTER_AUTH_SECRET=your_secret_here
|
||||
BETTER_AUTH_SECRET=
|
||||
# Public URL of your instance, especially important if reverse proxy is used
|
||||
BETTER_AUTH_URL=http://localhost:3000
|
||||
|
||||
@@ -28,7 +28,5 @@ BETTER_AUTH_URL=http://localhost:3000
|
||||
# DISABLE_PASSWORD_LOGIN=false # Set to "true" to hide email/password form when OIDC is configured
|
||||
|
||||
# ─── Image Caching ─────────────────────────────────────────────────────
|
||||
# Downloads TMDB images to local disk for faster serving (default: /data/images)
|
||||
# IMAGE_CACHE_DIR=/data/images
|
||||
# Set IMAGE_CACHE_ENABLED to "false" to use TMDB CDN directly (default: enabled)
|
||||
# IMAGE_CACHE_ENABLED=true
|
||||
|
||||
@@ -80,7 +80,7 @@ All app tables use UUID text primary keys generated via the `uuid` package. Bett
|
||||
|
||||
Only paths are stored in DB. Image URLs are resolved **server-side only** — API routes and server components call `tmdbImageUrl()` from `lib/tmdb/image.ts` before sending data to clients. Client components never import `tmdbImageUrl`; they receive ready-to-use URLs.
|
||||
|
||||
When `IMAGE_CACHE_ENABLED` is set (default), images are downloaded to local disk (`IMAGE_CACHE_DIR`, defaults to `/data/images`) and served via `app/api/images/[...path]/route.ts`. Categories: `posters` (w500), `backdrops` (w1280), `stills` (w1280), `logos` (w92). When disabled, `tmdbImageUrl()` returns direct TMDB CDN URLs using `TMDB_IMAGE_BASE_URL` (defaults to `https://image.tmdb.org/t/p`).
|
||||
When `IMAGE_CACHE_ENABLED` is set (default), images are downloaded to local disk (`CACHE_DIR`, derived from `DATA_DIR/images`) and served via `app/api/images/[...path]/route.ts`. Categories: `posters` (w500), `backdrops` (w1280), `stills` (w1280), `logos` (w92). When disabled, `tmdbImageUrl()` returns direct TMDB CDN URLs using `TMDB_IMAGE_BASE_URL` (defaults to `https://image.tmdb.org/t/p`).
|
||||
|
||||
Core files: `lib/services/image-cache.ts` (caching logic), `lib/tmdb/image.ts` (URL construction), `app/api/images/[...path]/route.ts` (proxy route).
|
||||
|
||||
@@ -90,7 +90,7 @@ Registered in `lib/jobs/registry.ts`, started via Next.js instrumentation hook (
|
||||
|
||||
### Environment variables
|
||||
|
||||
See `.env.example`: `DATABASE_URL`, `TMDB_API_READ_ACCESS_TOKEN`, `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`.
|
||||
See `.env.example`: `DATA_DIR` (root for DB + cache, default `./data`), `TMDB_API_READ_ACCESS_TOKEN`, `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`. `DATABASE_URL` and `CACHE_DIR` are derived from `DATA_DIR` but can be overridden individually.
|
||||
|
||||
## Browser Automation
|
||||
|
||||
|
||||
+8
-6
@@ -1,5 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:24-alpine AS base
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
RUN corepack enable && corepack prepare pnpm@10 --activate
|
||||
|
||||
# --- Dependencies ---
|
||||
FROM base AS deps
|
||||
@@ -25,16 +26,17 @@ WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
ENV HOSTNAME=0.0.0.0
|
||||
ENV PORT=3000
|
||||
ENV DATA_DIR=/data
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs \
|
||||
&& adduser --system --uid 1001 nextjs \
|
||||
&& mkdir -p /data/images/posters /data/images/backdrops /data/images/stills /data/images/logos \
|
||||
&& mkdir -p /data \
|
||||
&& chown -R nextjs:nodejs /data
|
||||
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/drizzle ./drizzle
|
||||
COPY --from=builder --link --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder --link --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --link --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
COPY --from=builder --link --chown=nextjs:nodejs /app/drizzle ./drizzle
|
||||
|
||||
USER nextjs
|
||||
EXPOSE 3000
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
sofa:
|
||||
image: ghcr.io/jakejarvis/sofa:latest
|
||||
image: ghcr.io/jakejarvis/sofa:edge
|
||||
container_name: sofa
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
@@ -8,7 +8,6 @@ services:
|
||||
volumes:
|
||||
- sofa-data:/data
|
||||
environment:
|
||||
- DATABASE_URL=file:/data/sqlite.db
|
||||
- TMDB_API_READ_ACCESS_TOKEN=${TMDB_API_READ_ACCESS_TOKEN}
|
||||
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
|
||||
- BETTER_AUTH_URL=${BETTER_AUTH_URL:-http://localhost:3000}
|
||||
|
||||
+4
-1
@@ -1,10 +1,13 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
const DATA_DIR = process.env.DATA_DIR || "./data";
|
||||
const DATABASE_URL = process.env.DATABASE_URL || `file:${DATA_DIR}/sqlite.db`;
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "turso",
|
||||
schema: "./lib/db/schema.ts",
|
||||
out: "./drizzle",
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL ?? "file:./data/sqlite.db",
|
||||
url: DATABASE_URL,
|
||||
},
|
||||
});
|
||||
|
||||
+4
-1
@@ -7,10 +7,13 @@ const globalForDb = globalThis as unknown as {
|
||||
_client: ReturnType<typeof createClient> | undefined;
|
||||
};
|
||||
|
||||
const DATA_DIR = process.env.DATA_DIR || "./data";
|
||||
const DATABASE_URL = process.env.DATABASE_URL || `file:${DATA_DIR}/sqlite.db`;
|
||||
|
||||
function getClient() {
|
||||
if (!globalForDb._client) {
|
||||
globalForDb._client = createClient({
|
||||
url: process.env.DATABASE_URL ?? "file:./data/sqlite.db",
|
||||
url: DATABASE_URL,
|
||||
});
|
||||
globalForDb._client.execute("PRAGMA journal_mode = WAL");
|
||||
globalForDb._client.execute("PRAGMA foreign_keys = ON");
|
||||
|
||||
@@ -17,7 +17,10 @@ const CATEGORY_SIZES: Record<ImageCategory, string> = {
|
||||
const IMAGE_BASE_URL =
|
||||
process.env.TMDB_IMAGE_BASE_URL || "https://image.tmdb.org/t/p";
|
||||
|
||||
const CACHE_DIR = process.env.IMAGE_CACHE_DIR || "/data/images";
|
||||
const DATA_DIR = process.env.DATA_DIR || "./data";
|
||||
const CACHE_DIR = process.env.CACHE_DIR
|
||||
? path.join(process.env.CACHE_DIR, "images")
|
||||
: path.join(DATA_DIR, "images");
|
||||
|
||||
export function imageCacheEnabled(): boolean {
|
||||
return process.env.IMAGE_CACHE_ENABLED !== "false";
|
||||
|
||||
Reference in New Issue
Block a user