Files
mule-image/sidecar/config.go
dtoro 4362e475a7 build(sidecar): containerize + delete the Node prototype
- New sidecar/Dockerfile: multi-stage golang:1.25-alpine → distroless/
  static, ~12 MB final image, static CGO-free binary.
- Wire pp-sidecar into docker-compose.photoprism.yml so the whole
  stack (mariadb + photoprism + sidecar) starts with one
  `podman-compose up`. Container reaches mariadb + photoprism on the
  internal network; the host gets 127.0.0.1:8000 for Vite's proxy.
- New SIDECAR_LISTEN_ADDR env var (default 127.0.0.1 for the host-mode
  dev loop) so the container can bind 0.0.0.0:8000 and let the port
  mapping reach it. Without this the loopback bind was invisible to
  the host.
- Delete sidecar/legacy/server.mjs — the Node prototype's archival
  window is over; git history is its home now.
- Update sidecar/README with compose-first bringup; keep the host
  `go build` flow as the fast-iteration loop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 17:23:36 +02:00

63 lines
1.9 KiB
Go

package main
import (
"os"
"path/filepath"
"strconv"
)
// Config aggregates every runtime knob the sidecar reads from the
// environment. Held in one struct so the rest of the package can take a
// pointer instead of poking os.Getenv at use-sites.
type Config struct {
OriginalsRoot string // absolute path to PhotoPrism's originals dir
PhotoprismBaseURL string // e.g. http://localhost:2342
ListenAddr string // bind interface — 127.0.0.1 for host mode, 0.0.0.0 in containers
Port int // HTTP listen port
DSN string // GORM/MySQL connection string for mule_sidecar
}
func loadConfig() (*Config, error) {
root := envOr("ORIGINALS_ROOT", "/photoprism/originals")
abs, err := filepath.Abs(root)
if err != nil {
return nil, err
}
portStr := envOr("SIDECAR_PORT", "8000")
port, err := strconv.Atoi(portStr)
if err != nil {
return nil, err
}
dsn := os.Getenv("SIDECAR_DSN")
if dsn == "" {
// Default matches the user that mariadb/init/01-sidecar.sql provisions
// on first boot. The literal placeholder password is intentional: the
// SQL ships with it and an env-templating step is left for whoever
// runs this in a non-local context.
user := envOr("SIDECAR_DB_USER", "sidecar")
pass := envOr("SIDECAR_DB_PASSWORD", "replace-at-m4-bringup")
host := envOr("SIDECAR_DB_HOST", "127.0.0.1")
dbPort := envOr("SIDECAR_DB_PORT", "3306")
name := envOr("SIDECAR_DB_NAME", "mule_sidecar")
dsn = user + ":" + pass + "@tcp(" + host + ":" + dbPort + ")/" + name +
"?charset=utf8mb4&parseTime=true&loc=Local"
}
return &Config{
OriginalsRoot: abs,
PhotoprismBaseURL: envOr("PHOTOPRISM_BASE_URL", "http://localhost:2342"),
ListenAddr: envOr("SIDECAR_LISTEN_ADDR", "127.0.0.1"),
Port: port,
DSN: dsn,
}, nil
}
func envOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}