Skip to main content

Configure a public domain and TLS for Nora

Step-by-step guide to exposing Nora on a public domain with HTTP or Let’s Encrypt TLS, including nginx config, CORS, and NextAuth URL setup.
By default, Nora listens on localhost:8080 and is only reachable from the machine it runs on. To make your deployment accessible over the internet — whether for a staging environment, a production rollout, or a PaaS offering — you need to update several environment variables, create an nginx configuration file for your domain, and optionally provision a TLS certificate. This page walks through each step.

Deployment mode comparison

Local (default)Public domain (HTTP)Public domain (TLS)
NGINX_CONFIG_FILEnginx.confnginx.public.confnginx.public.conf (TLS version)
NGINX_HTTP_PORT80808080 and 443
NEXTAUTH_URLhttp://localhost:8080http://app.example.comhttps://app.example.com
CORS_ORIGINShttp://localhost:8080http://app.example.comhttps://app.example.com
TLS certificateNoneNoneLet’s Encrypt via setup-tls.sh
DNS requiredNoYesYes

Set up public-domain access with HTTP

1

Update your .env file

Open your .env file and change the access and URL variables to match your public domain. Replace app.example.com with your actual domain.
NGINX_CONFIG_FILE=nginx.public.conf
NGINX_HTTP_PORT=80
NEXTAUTH_URL=http://app.example.com
CORS_ORIGINS=http://app.example.com
CORS_ORIGINS accepts a comma-separated list. If your domain is reachable on multiple origins (for example, with and without www), include all of them:
CORS_ORIGINS=https://app.example.com,https://www.app.example.com
2

Create the nginx configuration file

Copy the public-domain nginx template from the infra/ directory to produce nginx.public.conf in your project root:
cp infra/nginx_public.conf.template nginx.public.conf
Open nginx.public.conf and replace the placeholder server name with your domain:
server_name app.example.com;
This file is volume-mounted into the nginx container at startup using the NGINX_CONFIG_FILE value you set above.
3

Start the stack

Bring the stack up (or restart it if it is already running):
docker compose up -d
Nora is now accessible at http://app.example.com (port 80 must be open on your host firewall and the DNS A record must point to your server’s public IP).

Add TLS with Let’s Encrypt

1

Ensure DNS is resolving

Before running the TLS setup script, confirm your domain’s DNS A record points to your server’s public IP address. Let’s Encrypt performs a domain ownership check that requires the domain to resolve correctly.
dig +short app.example.com
# Should return your server's public IP
2

Run the TLS setup script

The infra/setup-tls.sh script requests a Let’s Encrypt certificate and writes a TLS-ready nginx.public.conf. Nora’s tracked TLS compose layer is infra/docker-compose.public-tls.yml; the setup script also writes a local docker-compose.override.yml convenience file so plain docker compose up uses the same TLS/prod settings.
DOMAIN=app.example.com EMAIL=admin@example.com ./infra/setup-tls.sh
Replace app.example.com with your domain and admin@example.com with an address that should receive Let’s Encrypt expiry notices.The script produces:
  • An updated nginx.public.conf with ssl_certificate and ssl_certificate_key directives
  • A local docker-compose.override.yml convenience file generated from infra/docker-compose.public-tls.yml
3

Update .env for HTTPS

Update NEXTAUTH_URL and CORS_ORIGINS to use https://:
NGINX_CONFIG_FILE=nginx.public.conf
NGINX_HTTP_PORT=80
NEXTAUTH_URL=https://app.example.com
CORS_ORIGINS=https://app.example.com
NEXTAUTH_URL must exactly match the origin your browser uses. If it is set to http:// but your site loads over https://, NextAuth redirect flows will fail.
4

Restart the stack

Bring the stack down and back up to apply the new nginx config. For a standard single-file Compose run, Docker Compose auto-loads the generated docker-compose.override.yml:
docker compose up -d
If you are using explicit Compose overlays, include the tracked TLS layer directly:
docker compose \
  -f docker-compose.yml \
  -f infra/docker-compose.public-tls.yml \
  -f <your-backend-overlay>.yml \
  up -d --build
Nora is now available at https://app.example.com with a valid Let’s Encrypt certificate.

Certificate renewal

Let’s Encrypt certificates expire after 90 days. Set up a cron job on your host to renew the certificate and reload nginx:
# Run at 3 AM on the 1st and 15th of each month
0 3 1,15 * * DOMAIN=app.example.com EMAIL=admin@example.com /path/to/nora/infra/setup-tls.sh && docker compose -f /path/to/nora/docker-compose.yml up -d
If you prefer to terminate TLS at a load balancer or reverse proxy in front of Nora (for example, AWS ALB or Cloudflare), keep NEXTAUTH_URL and CORS_ORIGINS set to your https:// origin but use the plain HTTP nginx config internally. Nora does not need to handle TLS itself when termination happens upstream.