Environment Variables and URLs

Purpose and Scope

This page explains the URL and environment-variable decisions that most often affect deployed Cal.diy instances. In a self-hosted deployment, the application must know its public browser URL, its authentication callback URL, and sometimes a different service-to-service URL used inside Docker or an internal network. When these values drift apart, users commonly see redirects back to a local development address, failed login callbacks, broken internal links, or service startup failures. The repository documentation treats these problems as deployment configuration issues rather than application code changes, so the safest fix is usually to correct the environment files, rebuild when required, and restart the relevant services.

Sources: apps/docs/content/troubleshooting.mdx, apps/docs/content/docker.mdx, apps/docs/content/installation.mdx

Relevant Source Files

  • apps/docs/content/troubleshooting.mdx — Documents the common redirect-to-localhost symptom, the required public URL variables, Docker timing requirements for build-time values, Vercel-specific behavior, SSL edge termination, client fetch behavior, and API v2 environment requirements.
  • apps/docs/content/docker.mdx — Defines the Docker setup flow, the .env preparation step, the distinction between build-time and run-time variables, the first-run browser URL, update workflow, and Docker-specific troubleshooting notes.
  • apps/docs/content/installation.mdx — Covers source installation, copying .env.example to .env, generating NEXTAUTH_SECRET, filling .env.appStore, preview-deployment exceptions for Vercel, and the production build sequence.

Core URL Variables

Cal.diy uses two closely related public URL settings in the self-hosting docs. NEXT_PUBLIC_WEBAPP_URL is the browser-facing base URL for the web app, and the troubleshooting guide says it must be set to the production domain when login redirects or internal links still point to a local address. NEXTAUTH_URL is the authentication base URL used by NextAuth. The troubleshooting guide also says NEXTAUTH_URL is optional if the public web app URL is set, because NextAuth can infer a base URL from the incoming request host when the variable is not explicitly configured.

The most important formatting rule is that the public URL should be the actual scheme and host users type into the browser, without a trailing slash. For example, a deployment under a subdomain should use the HTTPS origin for that subdomain rather than a container name, private IP address, or development port. A wrong value can be surprisingly persistent because some Next.js public variables are inlined during the build. In Docker deployments, changing the URL in an environment file may not be enough if the image was already built with a different value.

Sources: apps/docs/content/troubleshooting.mdx, apps/docs/content/docker.mdx

Setup and Deployment Flow

During source installation, the documented setup starts by cloning the repository, installing dependencies, copying .env.example to .env, and then editing that file for the local or deployed environment. The installation guide specifically calls out NEXTAUTH_SECRET, generated with a secret-generation command, and recommends filling .env.appStore as well when apps are enabled. This matters for URL work because authentication and integrations often fail together: the main web app needs a stable public origin, while app integrations may have callbacks and secrets stored in a separate app-store environment file.

For production builds from source, set the final deployment URL before running the build and start commands. The installation guide places environment setup before the production build, and the Docker guide is even more explicit that NEXT_PUBLIC_WEBAPP_URL is a build-time variable. Treat the public URL as part of the artifact you are building, not as a cosmetic label that can always be changed later. If a production instance was built with localhost, rebuild it after correcting the variable so generated client-side code and server-side assumptions agree.

Sources: apps/docs/content/installation.mdx, apps/docs/content/docker.mdx

# Replace with your deployed origin, without a trailing slash
NEXT_PUBLIC_WEBAPP_URL=https://cal.yourdomain.com
NEXTAUTH_URL=https://cal.yourdomain.com
NEXTAUTH_SECRET=generated_random_secret

Docker Build-Time and Run-Time Behavior

The Docker documentation separates build-time variables from important run-time variables. NEXT_PUBLIC_WEBAPP_URL appears in the build-time list along with telemetry and license-consent variables, so it must be present before building a custom image when the production domain differs from the default. NEXTAUTH_SECRET is listed as an important run-time variable, so it must be available when the service starts. This split explains a common failure mode: administrators update .env, restart containers, and still see old browser-facing URLs because the public URL was compiled into the web image earlier.

A Docker first run begins by copying .env.example to .env, optionally pulling images, and starting the stack with docker compose up -d. The docs describe three service combinations: the complete stack, the web app plus Prisma Studio against a remote database, or only the web app against a configured database. After startup, users should open either the local address or the defined public web app URL. If the first-run setup wizard appears at one address but redirects to another, verify whether the container was built with the right public URL and whether the authentication URL matches the same public origin.

Sources: apps/docs/content/docker.mdx

cp .env.example .env
docker compose up -d

Redirect, Host, and Callback Troubleshooting

The clearest URL symptom in the troubleshooting guide is a deployed instance that redirects back to http://localhost:3000. The documented cause is that NEXTAUTH_URL and NEXT_PUBLIC_WEBAPP_URL were not set to the production domain. The fix is to set both values to the real domain, omit a trailing slash, and then rebuild the Docker image if Docker is being used. For Vercel deployments, the docs give a special exception: NEXTAUTH_URL does not need to be set because Vercel can infer the deployment URL through its own environment.

The installation guide adds another Vercel-specific rule for preview deployments: leave NEXTAUTH_URL, NEXT_PUBLIC_WEBSITE_URL, and NEXT_PUBLIC_WEBAPP_URL empty. That guidance prevents preview builds from baking a fixed production URL into deployments that should instead use the platform-provided preview host. For non-Vercel platforms, such as manually managed servers or cloud virtual machines, the deployment guide pattern is to update .env with the resource details and public domain after infrastructure is created. The practical rule is to avoid mixing platform-inferred URLs with manually hardcoded production URLs unless the platform documentation says to do so.

Sources: apps/docs/content/troubleshooting.mdx, apps/docs/content/installation.mdx

Reverse Proxy and Internal Network Edge Cases

A public URL is not always the same address that a container can use internally. The Docker troubleshooting notes mention CLIENT_FETCH_ERROR and explain that the default auth callback can use WEBAPP_URL as a base URL while the container may not have access to the same DNS name that browser users use. This is common behind reverse proxies, private Docker networks, and split-horizon DNS. When diagnosing this class of issue, confirm both directions: a browser must reach the public URL, and the server process must be able to resolve and connect to any URL it uses for internal callbacks.

The Docker troubleshooting section also documents an SSL edge-termination workaround: when a load balancer handles certificates, setting NODE_TLS_REJECT_UNAUTHORIZED=0 can prevent requests from being rejected. The docs warn that this should only be used when the administrator understands and trusts the services directing traffic. In practice, prefer a correct HTTPS configuration and trusted certificates first. Use that variable only as a targeted workaround for a known proxy or load-balancer trust boundary, because it weakens TLS verification for the process that receives it.

Sources: apps/docs/content/docker.mdx, apps/docs/content/troubleshooting.mdx

Compact Reference

Use this reference as a deployment checklist before rebuilding or restarting Cal.diy. The names below come from the repository docs and are grouped by the problem they address. Public browser URL values should point to the origin users visit. Authentication secrets should be unique random values. Docker build-time values should be present before the image is built, while run-time values must be present when the service starts. If an integration or API service has its own variables, configure those separately rather than assuming the web app variables are reused automatically.

NameRoleTiming or note
NEXT_PUBLIC_WEBAPP_URLPublic web app originDocker build-time variable; no trailing slash
NEXTAUTH_URLNextAuth callback/base URLOptional when inferred; set to production domain when redirects are wrong
NEXTAUTH_SECRETAuthentication secretImportant run-time variable; generate a strong random value
NEXT_PUBLIC_WEBSITE_URLWebsite URL used in some deploymentsLeave empty for Vercel preview deployments per installation docs
WEB_APP_URLAPI or internal service web app URLOptional API v2 value in troubleshooting notes; can affect service callbacks
NODE_TLS_REJECT_UNAUTHORIZEDTLS verification overrideOnly for trusted SSL edge termination scenarios

Sources: apps/docs/content/troubleshooting.mdx, apps/docs/content/docker.mdx, apps/docs/content/installation.mdx

Practical Recovery Flow

When a deployed instance has URL or redirect problems, start by writing down the intended public origin and checking every environment file that can influence it, especially .env and .env.appStore when integrations are enabled. Remove trailing slashes, avoid localhost in production, and decide whether the platform should infer the URL or whether you should set it explicitly. For Docker, rebuild when a build-time public variable changes, then restart the stack. For source deployments, rebuild after changing values used during the production build. Finally, retest login, onboarding, app callbacks, and any API v2 endpoints that rely on service URLs.

Next, read the Docker troubleshooting and deployment pages that match your hosting model. URL bugs are often symptoms of a larger mismatch among DNS, reverse proxy headers, container networking, and environment files. If the web app works but an API service or integration fails, compare the variables consumed by that service instead of repeatedly changing only the browser-facing URL. A clean recovery usually means aligning the public origin, authentication base URL, secrets, database connectivity, and service-specific variables, then rebuilding only the components whose build-time configuration changed.

Sources: apps/docs/content/troubleshooting.mdx, apps/docs/content/docker.mdx, apps/docs/content/installation.mdx