Skip to content

Allow the UI to be served on custom hosts (reverse proxy / Tailscale)#1333

Open
mihow wants to merge 4 commits into
mainfrom
feat/vite-preview-allowed-hosts
Open

Allow the UI to be served on custom hosts (reverse proxy / Tailscale)#1333
mihow wants to merge 4 commits into
mainfrom
feat/vite-preview-allowed-hosts

Conversation

@mihow
Copy link
Copy Markdown
Collaborator

@mihow mihow commented Jun 5, 2026

Summary

A recent Vite upgrade (pulled in with the dependency update) tightened Vite's servers so they reject any request whose Host header isn't localhost. That's a reasonable default, but it breaks any setup that serves the UI on a real hostname — behind a reverse proxy, or simply reached over a Tailscale name. Instead of the app, the browser gets a plain-text page saying "This host is not allowed."

This change adds an opt-in UI_ALLOWED_HOSTS environment variable to declare the hostnames the UI should accept. Local development is unchanged — when the variable is unset, Vite keeps its localhost-only default, so contributors running the app locally see no difference.

One variable covers both of Vite's servers, which are configured separately:

  • the dev server (vite / yarn start, used by the ui-dev compose service and by contributors), via server.allowedHosts; and
  • the preview server (vite preview, used by the production-style ui container), via preview.allowedHosts.

A given container only runs one of those, so a single variable is enough and operators don't need to know which server their box runs.

List of Changes

# Change (user-effect) How (implementation)
1 Reach the UI on a custom hostname (reverse proxy, Tailscale name) instead of getting "host not allowed" — on both the dev server and the production preview server. UI_ALLOWED_HOSTS feeds both server.allowedHosts and preview.allowedHosts in ui/vite.config.ts.
2 The value is a comma-separated list; a leading-dot entry like .example.com matches all subdomains. Empty entries (e.g. a trailing comma) are ignored, and leaving it unset preserves Vite's localhost-only default. Shared parseAllowedHosts helper: split on commas, trim, drop empties, return undefined when nothing is configured.
3 Documented for operators/contributors. ui/README.md Configuration section, plus a committed ui/.env.example (copy to the gitignored ui/.env.local).

Detailed Description

Newer Vite versions added a Host-header allowlist to both the dev and preview servers as an SSRF/DNS-rebinding mitigation, defaulting to localhost only. Deployments (or local setups) that reach a Vite server on a custom domain therefore need to declare the allowed hostnames. Rather than hardcode any specific domain, the config reads the list from the environment so each deployment supplies its own.

The existing DJANGO_ALLOWED_HOSTS is intentionally not reused: it belongs to the Django backend (a separate process and container), is not present in the UI service's environment, and frequently contains *, which Vite would treat as a literal hostname rather than "allow all". UI_ALLOWED_HOSTS mirrors its naming while keeping the frontend and backend allowlists independent.

How to Test the Changes

Dev server:

  1. UI_ALLOWED_HOSTS=my-host.example.com yarn start --host 0.0.0.0 --port 4000 (or set it on the ui-dev compose service).
  2. curl -H 'Host: my-host.example.com' http://localhost:4000/ → returns the app (HTTP 200).
  3. curl -H 'Host: other.example.com' http://localhost:4000/ → still HTTP 403 "host not allowed".

Preview server: same as above with yarn build then UI_ALLOWED_HOSTS=… vite preview --host 0.0.0.0 --port 4000.

Verified against the running ui-dev dev server: the configured Tailscale host returned HTTP 200 and served the app, localhost was unaffected, and an unlisted host still returned HTTP 403.

Deployment Notes

Set UI_ALLOWED_HOSTS in the UI service's environment for any setup reached on a non-localhost host (comma-separated hostnames, or a leading-dot wildcard to cover subdomains). The same variable applies whether the container runs vite preview or the yarn start dev server. No effect if left unset.

Summary by CodeRabbit

  • New Features

    • Added support for configurable allowed hosts, enabling the UI to be accessed via custom hostnames instead of being restricted to localhost. Both development and production preview servers now respect this configuration.
  • Documentation

    • Updated README with guidance on configuring custom hostnames.
    • Added example environment configuration file with setup instructions.

…ED_HOSTS

Newer Vite rejects `vite preview` requests whose Host header is not
localhost. Add an env-driven `preview.allowedHosts` so proxied deployments
can declare accepted hostnames. Unset preserves Vite's localhost default;
local dev is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 5, 2026 01:02
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 5, 2026

Deploy Preview for antenna-ssec ready!

Name Link
🔨 Latest commit 9bb91d4
🔍 Latest deploy log https://app.netlify.com/projects/antenna-ssec/deploys/6a236ff8c16c990008d69957
😎 Deploy Preview https://deploy-preview-1333--antenna-ssec.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 5, 2026

Deploy Preview for antenna-preview ready!

Name Link
🔨 Latest commit 9bb91d4
🔍 Latest deploy log https://app.netlify.com/projects/antenna-preview/deploys/6a236ff88168ac000861d4bf
😎 Deploy Preview https://deploy-preview-1333--antenna-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 62 (🔴 down 3 from production)
Accessibility: 81 (🔴 down 8 from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 92 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Need the big picture first? Review this PR in Change Stack to see what changed before going file by file.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b31195e0-f1c0-482d-a7d4-d8c684304bf0

📥 Commits

Reviewing files that changed from the base of the PR and between e3f662d and 9bb91d4.

📒 Files selected for processing (3)
  • ui/.env.example
  • ui/README.md
  • ui/vite.config.ts

📝 Walkthrough

Walkthrough

This pull request adds support for custom hostnames on the Vite UI server via a new UI_ALLOWED_HOSTS environment variable. A helper function parses comma-separated host entries and configures both the dev and preview servers. Documentation and environment example file provide usage guidance.

Changes

UI Allowed Hosts Feature

Layer / File(s) Summary
Vite host allowance configuration
ui/vite.config.ts
parseAllowedHosts helper parses the environment variable, filters empty entries, and returns undefined when no hosts are configured. Both dev server (server.allowedHosts) and preview server (preview.allowedHosts) use this helper to conditionally allow custom hostnames.
Documentation and environment example
ui/.env.example, ui/README.md
.env.example provides a template for the UI_ALLOWED_HOSTS setting, and README documentation explains the variable's purpose (overriding Vite's default localhost-only block), format (comma-separated, supporting leading-dot wildcard), and applicability to both dev and preview servers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A config hops forth with a generous flair,
No more just localhost—hosts everywhere!
With dots and with wildcards, comma-split clean,
The friendliest Vite server ever seen. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: allowing the UI to be served on custom hosts via environment configuration, directly addressing the problem with reverse proxies and Tailscale access.
Description check ✅ Passed The description comprehensively covers all required template sections: a clear summary, detailed list of changes with context, testing instructions with verification details, deployment notes, and a checklist confirming testing and documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vite-preview-allowed-hosts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an opt-in configuration to the UI’s vite preview server so the built frontend can be served behind a reverse proxy on non-localhost hostnames, via a PREVIEW_ALLOWED_HOSTS environment variable.

Changes:

  • Adds preview.allowedHosts to ui/vite.config.ts, sourced from PREVIEW_ALLOWED_HOSTS.
  • Keeps default Vite behavior when PREVIEW_ALLOWED_HOSTS is unset (localhost-only).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui/vite.config.ts Outdated
The initial change only set `preview.allowedHosts`, which covers
`vite preview` (the production-style `ui` container). The local dev
server (`vite` / `yarn start`, used by the `ui-dev` service and by
contributors) is a separate Vite server with its own
`server.allowedHosts`, so it still returned "This host is not allowed"
when reached on a non-localhost hostname such as a Tailscale name.

- Add `server.allowedHosts` sourced from a new `DEV_ALLOWED_HOSTS` env
  var, mirroring `PREVIEW_ALLOWED_HOSTS`.
- Extract a shared `parseAllowedHosts` helper (comma-split, trim, drop
  empty entries from trailing commas; undefined when unset to keep
  Vite's localhost-only default).
- Document both vars in ui/README.md and as commented examples on the
  ui / ui-dev services in docker-compose.yml.

Verified on the dev server: localhost -> 200, allowed host -> 200
(serves the app), unlisted host -> 403.

Co-Authored-By: Claude <noreply@anthropic.com>
@mihow mihow changed the title Allow the built UI to be served behind a reverse proxy on custom hosts Allow the UI to be served on custom hosts (dev server and preview) Jun 6, 2026
Collapse the two host-allowlist variables into a single
`UI_ALLOWED_HOSTS`. A container runs either the dev server
(`yarn start`) or the preview server (`yarn preview`), never both, so
one variable can feed both `server.allowedHosts` and
`preview.allowedHosts` — operators set it once without needing to know
which server their container runs. Mirrors the existing
`DJANGO_ALLOWED_HOSTS` naming.

`DJANGO_ALLOWED_HOSTS` itself isn't reused: it belongs to the Django
backend (a different process and container), isn't present in the UI
service env, and frequently contains `*`, which Vite would treat as a
literal hostname rather than "allow all".

Co-Authored-By: Claude <noreply@anthropic.com>
@mihow mihow changed the title Allow the UI to be served on custom hosts (dev server and preview) Allow the UI to be served on custom hosts (reverse proxy / Tailscale) Jun 6, 2026
…mpose

Move the host-allowlist example out of docker-compose.yml (operators
shouldn't be editing the committed compose file) into a committed
ui/.env.example. Contributors copy it to ui/.env.local (gitignored) and
set their own value.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants