diff --git a/docs/installation/docker.md b/docs/installation/docker.md index 500f39dda..639cf536a 100644 --- a/docs/installation/docker.md +++ b/docs/installation/docker.md @@ -15,8 +15,6 @@ services: volumes: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations - environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ``` ### Running as non-root @@ -38,7 +36,6 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations, see alternative methods environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts PUID: $PUID PGID: $PGID ``` @@ -46,7 +43,7 @@ services: ### With Docker Run ```bash -docker run -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest +docker run -p 3000:3000 -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest ``` ### Using Environment Secrets diff --git a/docs/installation/index.md b/docs/installation/index.md index 02245faeb..996b9a23d 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -27,21 +27,9 @@ You have a few options for deploying homepage, depending on your needs. We offer -### `HOMEPAGE_ALLOWED_HOSTS` +### Authentication -As of v1.0 there is one required environment variable to access homepage via a URL other than `localhost`, HOMEPAGE_ALLOWED_HOSTS. The setting helps prevent certain kinds of attacks when retrieving data from the homepage API proxy. - -The value is a comma-separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md), [kubernetes](k8s.md) and [source](source.md) installation pages for more information about where / how to set the variable. - -`localhost:3000` and `127.0.0.1:3000` are always included, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. - -If you are seeing errors about host validation, check the homepage logs and ensure that the host exactly as output in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list. - -This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. Public deployments must rely on a reverse proxy (and/or VPN) that enforces authentication, TLS, and blocks direct-IP access and unexpected Host headers; the built-in host check is a best-effort guard for local setups and is not a substitute for edge protections. - -### Built-in OIDC authentication (optional, opt-in) - -Homepage now supports a minimal OIDC login flow (no per-user roles or personalization) so you can deploy without a reverse proxy handling auth. Enable it with: +Public deployments of Homepage should be secured via a reverse proxy, VPN, or similar. As of version 2.0, Homepage supports a simple OIDC login flow for built-in authorization. Enable it with the following environment variables: - `HOMEPAGE_AUTH_ENABLED=true` - `HOMEPAGE_OIDC_ISSUER` (OIDC issuer URL, e.g., `https://auth.example.com/realms/homepage`) diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index 172b9b295..a8cdc8d67 100644 --- a/docs/installation/k8s.md +++ b/docs/installation/k8s.md @@ -223,9 +223,6 @@ spec: - name: homepage image: "ghcr.io/gethomepage/homepage:latest" imagePullPolicy: Always - env: - - name: HOMEPAGE_ALLOWED_HOSTS - value: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ports: - name: http containerPort: 3000 diff --git a/docs/installation/source.md b/docs/installation/source.md index fd0275a75..a4d1d57a8 100644 --- a/docs/installation/source.md +++ b/docs/installation/source.md @@ -27,9 +27,7 @@ If this is your first time starting, copy the `src/skeleton` directory to `confi Finally, run the server: ```bash -HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 pnpm start +pnpm start ``` When updating homepage versions you will need to re-build the static files i.e. repeat the process above. - -See [HOMEPAGE_ALLOWED_HOSTS](index.md#homepage_allowed_hosts) for more information on this environment variable. diff --git a/src/middleware.js b/src/middleware.js index 704af9c25..b4b0bfcf4 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -1,23 +1,17 @@ import { getToken } from "next-auth/jwt"; import { NextResponse } from "next/server"; -const authEnabled = process.env.HOMEPAGE_AUTH_ENABLED === "true"; +const authEnabled = Boolean(process.env.HOMEPAGE_AUTH_ENABLED); const authSecret = process.env.NEXTAUTH_SECRET || process.env.HOMEPAGE_AUTH_SECRET; +let warnedAllowedHosts = false; export async function middleware(req) { - // Host validation (status quo) - const host = req.headers.get("host"); - const port = process.env.PORT || 3000; - let allowedHosts = [`localhost:${port}`, `127.0.0.1:${port}`, `[::1]:${port}`]; - const allowAll = process.env.HOMEPAGE_ALLOWED_HOSTS === "*"; - if (process.env.HOMEPAGE_ALLOWED_HOSTS) { - allowedHosts = allowedHosts.concat(process.env.HOMEPAGE_ALLOWED_HOSTS.split(",")); - } - if (!allowAll && (!host || !allowedHosts.includes(host))) { - console.error( - `Host validation failed for: ${host}. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.`, + if (!warnedAllowedHosts && process.env.HOMEPAGE_ALLOWED_HOSTS) { + warnedAllowedHosts = true; + // eslint-disable-next-line no-console + console.warn( + "HOMEPAGE_ALLOWED_HOSTS is deprecated. To secure a publicly accessible homepage, configure authentication instead.", ); - return NextResponse.json({ error: "Host validation failed. See logs for more details." }, { status: 400 }); } if (authEnabled) { diff --git a/src/pages/api/auth/[...nextauth].js b/src/pages/api/auth/[...nextauth].js index bfb6be510..7d4325090 100644 --- a/src/pages/api/auth/[...nextauth].js +++ b/src/pages/api/auth/[...nextauth].js @@ -1,13 +1,13 @@ import NextAuth from "next-auth"; -const authEnabled = process.env.HOMEPAGE_AUTH_ENABLED === "true"; +const authEnabled = Boolean(process.env.HOMEPAGE_AUTH_ENABLED); const issuer = process.env.HOMEPAGE_OIDC_ISSUER; const clientId = process.env.HOMEPAGE_OIDC_CLIENT_ID; const clientSecret = process.env.HOMEPAGE_OIDC_CLIENT_SECRET; const homepageAuthSecret = process.env.HOMEPAGE_AUTH_SECRET; const homepageExternalUrl = process.env.HOMEPAGE_EXTERNAL_URL; -// Map HOMEPAGE_* envs to what NextAuth expects so users don’t need NEXTAUTH_* explicitly. +// Map HOMEPAGE_* envs to what NextAuth expects if (!process.env.NEXTAUTH_SECRET && homepageAuthSecret) { process.env.NEXTAUTH_SECRET = homepageAuthSecret; } @@ -22,9 +22,7 @@ if ( authEnabled && (!issuer || !clientId || !clientSecret || !process.env.NEXTAUTH_SECRET || !process.env.NEXTAUTH_URL) ) { - throw new Error( - "OIDC auth is enabled but required settings are missing. Please set HOMEPAGE_OIDC_ISSUER, HOMEPAGE_OIDC_CLIENT_ID, HOMEPAGE_OIDC_CLIENT_SECRET, HOMEPAGE_AUTH_SECRET, and HOMEPAGE_EXTERNAL_URL.", - ); + throw new Error("OIDC auth is enabled but required settings are missing."); } let providers = [];