Skip to main content

These are the docs for 0.26.0-beta, an older release.

See the current docs (0.26.1-beta) for what Norish does today.

Server & runtime

Most server settings have working defaults. You must provide your own MASTER_KEY.

Core

VariableDescriptionDefault
MASTER_KEY32+ character key for encryption derivation(required)
AUTH_URLPublic URL used for auth callbacks and linkshttp://localhost:3000
NODE_ENVRuntime environmentproduction (set by the Docker image)
HOSTServer bind address0.0.0.0
PORTServer port3000
VALKEY_URLValkey connection URL (valkey:// or valkeys://) for events and jobs(required)

Generate a MASTER_KEY

MASTER_KEY is used to derive encryption keys for stored secrets. Changing it makes those secrets unreadable. Generate one with:

openssl rand -base64 32

Health checks

EndpointAnswers 200 whenUse it for
/api/v1/health/liveThe server responds and its parser answersRestarting Norish: the image's healthcheck, Kubernetes liveness
/api/v1/health/readyThe database and Valkey answer; the parser is reported but never countsSending traffic: Kubernetes readiness, load balancers

/api/v1/health is deprecated and answers like /api/v1/health/ready. Point new probes at live or ready.

Networking & origins

VariableDescriptionDefault
TRUSTED_ORIGINSComma-separated additional trusted origins(empty)
TRUSTED_PROXIESComma-separated IPs or CIDR ranges of your reverse proxies(empty)

Set TRUSTED_ORIGINS when people use more than one server address, for example http://192.168.1.100:3000,https://norish.example.com. The WebSocket refuses origins it doesn't trust, see Origin check.

Set TRUSTED_PROXIES when the server sits behind more than one reverse proxy, such as Cloudflare in front of Nginx Proxy Manager. List the address or range of every proxy; for Cloudflare that is its published ranges. Without it, visitors share one rate limit for sign-in and session checks. Behind a single proxy it is not needed.

Visitors are identified by the X-Forwarded-For header your proxy adds, so only the proxy should be able to reach the app's port. A visitor who connects to the port directly can set that header themselves and get a sign-in rate limit of their own.

Base path

To serve the app under a path such as https://example.com/norish, build it with NEXT_PUBLIC_BASE_PATH.

VariableDescriptionDefault
NEXT_PUBLIC_BASE_PATHThe path the image is built for(empty, the root)

The path is part of the build, so the published image serves the root. Build your own:

docker build -f docker/Dockerfile \
--build-arg NEXT_PUBLIC_BASE_PATH=/norish \
--build-arg NORISH_VERSION_REPORT_JSON="$(node tooling/monorepo/scripts/print-package-versions.mjs)" \
-t norish:base-path .

Set AUTH_URL to the same address and path; a mismatch prevents startup:

AUTH_URL=https://example.com/norish

Have the proxy forward the path unchanged, WebSocket included:

location /norish {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

Auth rate limiting

VariableDescriptionDefault
AUTH_RATE_LIMIT_ENABLEDEnable auth endpoint rate limitingtrue
AUTH_RATE_LIMIT_WINDOWWindow length in seconds60
AUTH_RATE_LIMIT_MAXRequests allowed per window20

Warning

Turning this off removes brute-force protection from sign-in.

Registration

VariableDescriptionDefault
ENABLE_REGISTRATIONAllow new-user registrationfalse

Registration turns off after the first user signs in, see Authentication.

Logging

VariableDescriptionDefault
NEXT_PUBLIC_LOG_LEVELLog verbosity (debug, info, warn, error)info

Uploads

VariableDescriptionDefault
UPLOADS_DIRUpload storage directory./.runtime/uploads (dev), /app/uploads (prod)
MAX_AVATAR_FILE_SIZEMax avatar upload size (bytes)5242880
MAX_IMAGE_FILE_SIZEMax image upload size (bytes)10485760
MAX_VIDEO_FILE_SIZEMax video upload size (bytes)104857600

Scheduler

VariableDescriptionDefault
SCHEDULER_CLEANUP_MONTHSCleanup retention period in months3

Ingredient catalogue

VariableDescriptionDefault
INGREDIENT_CATALOGUE_URLCatalogue seed URL, fetched at startup and nightly. Empty disables fetchingThe Open Food Facts ingredients taxonomy
INGREDIENT_REVIEW_CONCURRENCYConcurrent AI ingredient reviews (1–50). Lower this for self-hosted models that struggle with parallel requests10

The ingredient catalogue is seeded from the Open Food Facts ingredients taxonomy and refreshed every night at midnight.

On a server without internet, serve a copy of ingredients.txt from a local mirror and point INGREDIENT_CATALOGUE_URL at it.