
Keep Vite host validation enabled while securely sharing your development server
A Localtonet HTTP tunnel can successfully reach your machine while Vite still rejects the request because its public hostname is not trusted by the development server. This guide explains how to distinguish that application-level rejection from tunnel connectivity problems, allow only the required public hostname, verify the change locally and remotely, and avoid weakening Vite's DNS rebinding protection. We also cover changing tunnel hostnames, preview mode, hot module replacement symptoms, and the situations where a local reverse proxy creates a cleaner trust boundary.
๐ What's in this guide
Why Vite blocks a public tunnel hostname
When you open a Vite application locally, the browser normally requests a URL whose hostname is associated with the local machine, such as localhost. Opening the same application through a Localtonet HTTP tunnel changes the browser-facing address. The request now uses the public hostname assigned to the tunnel, while the Vite process still runs on your computer.
That difference matters because HTTP requests include a Host header. For a public address such as https://demo.example.invalid, the hostname presented to the application is conceptually demo.example.invalid, not localhost. If that name is outside Vite's trusted host set, Vite can reject the request before serving the application.
This behavior is separate from whether a tunnel can reach the local port. The Localtonet client establishes an outbound connection to our relay, so inbound router port forwarding, a public IP address, VPN setup, and inbound firewall changes are not required for the normal tunnel workflow. The client then forwards traffic to the local IP address and port configured for the HTTP tunnel. Vite remains responsible for deciding whether the resulting application request is acceptable.
Why the restriction exists
Host validation helps reduce exposure to DNS rebinding attacks. In a rebinding scenario, a hostile website can attempt to make a browser contact a service on a private or loopback address while using a hostname controlled by the attacker. Development servers are particularly sensitive because they can expose source files, development-only endpoints, debugging behavior, or privileged browser interactions that were never intended for arbitrary public access.
An allowlist tells Vite which hostnames are expected. Adding the exact Localtonet hostname is therefore materially safer than accepting every possible hostname. The objective is not to make host validation disappear. It is to extend the trust boundary by one deliberate hostname for as long as remote access is needed.
Some Vite versions accept a broad setting that disables normal hostname restrictions. Avoid that approach for a tunnel-exposed development server. It increases the set of hostnames Vite will trust and weakens the protection that produced the warning. Add only the exact public hostname required for this tunnel, or use a narrowly scoped domain rule when there is a justified operational need.
Determine whether Vite or the tunnel is rejecting the request

Start by identifying which layer produced the failure. A Vite message saying that a host is blocked or not allowed is strong evidence that the request reached the Vite process. In that case, the tunnel path, client connection, and local target may already be working. The remaining problem is Vite's application-level hostname policy.
A connection timeout, connection refusal, generic upstream error, or a public address that never becomes reachable points in a different direction. Those symptoms can occur when the Vite process is stopped, the tunnel targets the wrong port, the Localtonet client is disconnected, or the tunnel has been created but not started.
| Symptom | Likely layer | First check |
|---|---|---|
| Vite explicitly says the host is blocked or not allowed | Vite host validation | Compare the public URL hostname with server.allowedHosts |
| The application fails on its local URL | Vite process or project | Confirm the development command is still running and use the exact URL printed by Vite |
| The local URL works, but the public address cannot connect | Tunnel lifecycle or local target | Confirm our client is connected, the tunnel is started, and its target port matches Vite |
| HTML loads, but hot updates do not work | WebSocket or HMR configuration | Inspect the browser console and WebSocket connection separately from host validation |
| The page loads, but API calls fail | Application routing, CORS, cookies, or API configuration | Inspect the failed API request rather than changing Vite's host allowlist again |
| The tunnel previously worked but now shows as unavailable | Tunnel or client state | Remember that the tunnel is available only while the selected device is connected and the tunnel is running |
Host validation is not the same as CORS
A host rejection and a Cross-Origin Resource Sharing failure are different controls. Host validation concerns the hostname used to contact the Vite server. CORS concerns whether browser JavaScript running under one origin may read a response from another origin. Adding a public hostname to allowedHosts does not automatically permit cross-origin API requests, repair cookie policies, or change an API server's origin allowlist.
This distinction prevents a common troubleshooting loop. If Vite serves its page successfully but the browser console reports a CORS error for an API request, the Vite host fix has already done its job. The next investigation belongs in the API, Vite proxy configuration, cookie settings, or application environment values.
Prerequisites and information to collect
Before editing the Vite configuration, collect the exact values used by both sides of the connection. Do not assume the local port from a tutorial or a previous session. Use the address printed by the currently running Vite process, because project configuration and port conflicts can change it.
You need a Vite-based project that starts successfully, permission to modify its Vite configuration or launch environment, a Localtonet account and client device, and the public hostname assigned to the HTTP tunnel. The Localtonet client must run on a device that can reach the Vite server's local IP address and port.
Confirm the project command
Inspect the scripts section in the project's package.json. Many Vite projects use a script named dev, but the project is free to name or wrap that command differently. Run the script through the package manager used by the project. Common examples are shown below, but only the command matching the project's lockfile and documented workflow should be used.
npm run dev
pnpm dev
yarn dev
Keep the process running and record the local URL it prints. Open that URL directly on the development machine. If it does not work locally, resolve the Vite startup or project error before creating a public tunnel.
Identify the installed Vite version
Host configuration has changed across Vite releases, so the installed version matters more than a globally installed tool or a random online snippet. Check the version recorded in the project manifest and lockfile. You can also ask the project-local executable for its version when the project's package manager supports that workflow:
npx vite --version
The configuration examples in this guide use the documented server.allowedHosts interface found in current Vite releases. If an older project does not recognize this option, do not substitute an unrelated flag or disable security checks. Confirm the host configuration supported by that exact Vite version, or upgrade through the project's normal dependency review process.
When the Localtonet client runs on the same machine as Vite, the tunnel can normally target Vite through its loopback address. You do not need to expose Vite to the entire local network merely to make the tunnel work. If our client runs on another device, Vite must instead be reachable from that device, and the corresponding LAN binding and firewall implications should be reviewed deliberately.
Allow the exact Localtonet hostname in Vite

Copy the hostname portion of the public tunnel URL. If the address is https://my-preview.example, the value needed by Vite is my-preview.example. Do not include https://, a path, query parameters, or a trailing slash. A port is also not part of the hostname entry.
Open the project's Vite configuration file. Depending on the project, this can be a JavaScript or TypeScript configuration. Preserve the existing plugins and options, then add the exact hostname under server.allowedHosts.
import { defineConfig } from 'vite'
export default defineConfig({
server: {
allowedHosts: ['PUBLIC_TUNNEL_HOSTNAME']
}
})
Replace PUBLIC_TUNNEL_HOSTNAME with the actual hostname shown in the Localtonet public URL. For example, if our dashboard gives you https://preview-name.example, enter only preview-name.example. The example domain above is illustrative and is not a Localtonet hostname to copy.
If the project already has a server object or an allowedHosts array, merge the value instead of creating a duplicate property. JavaScript object keys defined more than once can hide earlier settings and make the configuration misleading.
import { defineConfig } from 'vite'
export default defineConfig({
server: {
port: 4178,
allowedHosts: [
'existing-development-host.example',
'PUBLIC_TUNNEL_HOSTNAME'
]
}
})
The port in this second example is only an illustration of preserving an existing project option. Do not change your project's port to match it. The Localtonet target must use whatever port the active Vite process actually listens on.
Restart Vite after changing the configuration
Stop and restart the development process after saving the configuration. A browser refresh cannot apply a server-side configuration file that the running process has not reloaded. Watch the terminal during startup for syntax errors, plugin failures, or a different selected port.
Use the additional-host environment setting when appropriate
Current Vite documentation also defines __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS for adding one trusted host through the process environment. This can be useful when the public hostname should not be committed to the shared project configuration, or when each developer receives a different tunnel hostname.
__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS=PUBLIC_TUNNEL_HOSTNAME npm run dev
Shell syntax differs between operating systems and automation environments. Set the variable using the mechanism appropriate for your shell, terminal, container, or CI runner. The value remains a hostname only, without a URL scheme or path. Because this setting is version-dependent, confirm that the installed Vite version documents it before relying on it.
A public tunnel hostname is not a credential, but authentication tokens are. Never put a Localtonet device token, API key, password, or private endpoint into a variable exposed to browser code. Vite variables intentionally exposed to application code can become part of the client bundle. Keep Localtonet authentication in our client or secure server-side configuration.
Avoid unnecessarily broad suffix rules
Vite supports hostname patterns in versions that document this behavior, including dot-prefixed values that can cover a base domain and its subdomains. Such a rule is broader than a single-host entry. Only use it when you control the relevant domain boundary and intentionally want to trust all matching names.
Never add a broad suffix for a shared domain that can be used by people outside your control. Another user who can obtain a sibling subdomain may then fall within your Vite trust rule. For one Localtonet tunnel, the exact assigned hostname is the clearest and narrowest configuration.
Create and start the Localtonet HTTP tunnel
Configure the tunnel only after Vite works locally and you know its listening address. An HTTP tunnel is the appropriate family for a browser-based Vite development server. HTTP and File Server tunnels can provide public HTTPS addresses using a random subdomain, a selected subdomain where supported, or a custom domain. Availability and domain requirements can vary, so use only the options currently shown for your account and selected server.
For current product details, consult our Localtonet HTTP tunnel documentation alongside the fields displayed in the dashboard. Do not copy a relay identifier from someone else's configuration. Available relay server or region values must come from the current dashboard.
Install and run the Localtonet client
Run our client on the Vite machine or on another device that can reach the Vite listening address. The client establishes the outbound connection used by the tunnel.
Authenticate or select the client device
Use the device-specific token through the supported Localtonet workflow, or select the corresponding authenticated device in the dashboard. Keep the token private and never place it in Vite source code, screenshots, logs, or a public repository.
Select an available relay server
Choose from the relay server or region values currently available in the product. Do not hardcode a server code from this article because available choices can vary.
Create an HTTP tunnel for the Vite target
Set the local target to the IP address and exact port where Vite is listening. If Vite and our client run on the same machine, use the loopback target that works from that machine. If they run on different devices, use an address reachable from the client device and review the local network exposure separately.
Record the assigned public hostname
Copy the hostname from the public HTTPS address and add that exact value to Vite's allowlist. If you configured Vite before creating the tunnel, replace the placeholder with this real hostname and restart Vite.
Start the tunnel
Creating a tunnel does not make it active. Use the Start button, then keep the selected client device connected and the tunnel running. The public address is available only while both conditions remain true.
Treat the public URL as sensitive even when it is temporary. Do not expose projects containing private data, unrestricted administrative functions, development-only secrets, or destructive actions without suitable application authentication and authorization. Stop the tunnel when remote access is no longer required, and apply least-privilege controls wherever the application supports them.
Verify the complete path locally and remotely

Verification should progress one layer at a time. This makes the result easier to interpret and avoids changing several unrelated settings at once.
1. Verify the ordinary local URL
Open the exact local address printed by Vite. Confirm that the page renders and that the terminal shows no startup failure. If the browser cannot open this address, the tunnel cannot repair the underlying application problem.
2. Simulate the public Host header locally
A local request with a custom Host header can test Vite's hostname decision without depending on the public relay path. Replace PORT with the actual Vite port and PUBLIC_TUNNEL_HOSTNAME with the hostname from the tunnel URL:
curl -i http://127.0.0.1:PORT/ -H "Host: PUBLIC_TUNNEL_HOSTNAME"
If Vite listens on a different local address, use that address instead of 127.0.0.1. A successful application response indicates that Vite accepts the hostname. A Vite-generated blocked-host response means the allowlist value is absent, malformed, unsupported by the installed version, or not loaded by the current process.
This command tests HTTP host handling at the local server. It does not test Localtonet connectivity, public DNS, edge TLS, browser behavior, hot module replacement, or application authentication.
3. Open the public HTTPS URL
Start the Localtonet tunnel and open its assigned HTTPS address in a browser. Test from a device or network outside the development machine when practical. This confirms that the public URL resolves, reaches our relay, traverses the outbound client connection, and arrives at the configured local target.
You can also inspect the initial public response from a terminal after replacing the placeholder:
curl -i https://PUBLIC_TUNNEL_HOSTNAME/
Do not add a manual Host override to this public test. The objective is to reproduce the hostname a normal remote browser sends.
4. Test application behavior, not only the first page
Navigate between routes, refresh a nested client-side route, trigger representative API calls, and edit a source file to observe hot updates. Initial HTML success proves only part of the workflow. A Vite application can pass host validation while API origins, WebSocket behavior, callback URLs, cookie rules, or client-side environment settings remain incorrect.
5. Recheck the security boundary
Confirm that the allowlist contains only expected hosts, remove temporary debugging changes, and make sure no token or credential was added to a client-visible file. When the sharing session ends, stop or delete the tunnel and remove temporary hostname entries that are no longer needed.
Handle changing hostnames, preview mode, and team workflows
When the public hostname changes
Vite compares the incoming hostname with the configured trust list. If you create a different tunnel or otherwise receive a different public hostname, the previous exact entry will not authorize the new one. Update server.allowedHosts, restart Vite, and repeat the local custom-host test.
For developer-specific or temporary addresses, the additional-host environment variable can keep personal tunnel names out of shared source control. A team can store only non-sensitive configuration guidance in its repository while each developer supplies the assigned hostname at launch time.
Do not automatically scrape a public URL from untrusted output and inject it into the allowlist. Treat allowlist modification as a trust decision. The person starting the environment should be able to see which hostname is being authorized.
Development server versus preview server
Vite's development server and preview server are separate operating modes. The development command serves the source-oriented development environment, while the preview command serves a built application for local inspection. A setting under server should not be assumed to configure every preview behavior in every Vite version.
Current Vite versions document preview-specific configuration under preview, including preview.allowedHosts. If you expose the preview server instead of the development server, configure the exact hostname in the preview section supported by the installed version:
import { defineConfig } from 'vite'
export default defineConfig({
preview: {
allowedHosts: ['PUBLIC_TUNNEL_HOSTNAME']
}
})
Use the port printed by the active preview process as the Localtonet target. Do not assume it matches the development server port. Also remember that Vite preview is intended for locally previewing a build, not as a production application server. A successful tunnel test does not convert it into a production deployment architecture.
Hot module replacement requires a separate check
Vite's hot module replacement channel commonly uses a WebSocket connection. If the page loads but edits no longer update, inspect the browser developer console and Network panel. Determine which WebSocket URL the browser attempts, whether it uses the correct public scheme and hostname, and whether the connection is rejected.
Do not respond to an HMR-only failure by broadening allowedHosts if ordinary page requests are already accepted. Depending on the Vite version and deployment shape, HMR can require its own client or server configuration. Use the exact options documented for the installed release, because hardcoding an unsupported HMR port or scheme can make the setup less reliable.
When a local reverse proxy creates a cleaner trust boundary
Directly targeting Vite is the simplest setup for a short sharing session. A local reverse proxy can be useful when several local services need one entry point, when the team already maintains proxy configuration, or when Vite should accept requests only from a controlled local intermediary.
In that architecture, the flow becomes public browser to Localtonet HTTP tunnel, then to a local reverse proxy, then to Vite. The tunnel targets the proxy's local address and port instead of Vite directly. The proxy can apply local routing, authentication, header policy, request limits, or path separation before forwarding traffic.
| Architecture | Best fit | Trade-off |
|---|---|---|
| Localtonet directly to Vite | Short-lived previews and a single development service | Vite must directly recognize the public hostname |
| Localtonet to a local reverse proxy to Vite | Multiple services, centralized authentication, or managed header policy | Adds another configuration and diagnostic layer |
| Built application on a production server | Persistent public access and production workloads | Requires a production deployment workflow rather than a Vite development tunnel |
Choose a deliberate Host header policy
A reverse proxy can preserve the original public Host header or replace it with a controlled upstream value. Both are architectural decisions. Preserving the public host means Vite still needs to trust that hostname. Replacing it can keep Vite's accepted hostname local to the proxy, but the proxy then becomes responsible for validating the public hostname before forwarding the request.
Never rewrite every incoming host to an accepted local value without first restricting which public hosts the proxy serves. That would merely move the missing validation from Vite to the proxy. Configure an explicit virtual host, reject unknown names, and forward only to the intended Vite endpoint.
Do not add a proxy without a concrete need
A proxy introduces more places for WebSocket upgrades, forwarded headers, path handling, and ports to be misconfigured. If the only issue is one blocked public hostname, adding that exact hostname to Vite is usually easier to understand. Use a proxy when it provides a real boundary or shared operational benefit, not as a way to hide an unexplained error.
Troubleshooting Vite and Localtonet tunnel errors
Vite still says the host is blocked
Recopy the hostname directly from the public URL. Remove the scheme, slash, path, and port. Confirm that you edited the configuration file used by the running project, not a similarly named file in another directory. Restart Vite and watch for configuration errors.
If the project uses a function-based configuration, modes, a framework wrapper, or configuration merging, inspect the final branch selected by the current command. A correct entry in an inactive configuration branch has no effect. Also confirm that the installed Vite version supports the option shown here.
The local custom-host test works, but the public URL fails
Check our client and tunnel state. The device must be connected, and the tunnel must be running. Verify that the local target port still matches the port printed by Vite. If Vite selected another port after a restart, update the tunnel target or configure the project to use an intentionally fixed available port.
If our client runs in a container, virtual machine, or another physical device, 127.0.0.1 refers to that environment itself. It does not automatically refer to the host machine running Vite. Use an address that is genuinely reachable from the client environment, and apply only the minimum local network exposure required.
The public page loads, but assets return errors
Inspect the failed asset URLs. Absolute base paths, framework adapters, development plugins, and environment-defined public origins can produce URLs that still point to localhost or another hostname. Host validation is already passing if Vite serves the main page. Correct the application's URL construction or Vite base configuration using the documentation for the installed version and framework integration.
API calls still target localhost
Browser code runs on the remote user's device. From that browser, localhost means the remote device, not your development computer. Use an intentional public API route, a Vite development proxy, or another separately secured tunnel according to the application's architecture. Do not expose a database or privileged internal service merely to repair a browser URL.
Authentication cookies do not work remotely
Cookies can depend on domain, path, Secure, and SameSite attributes. Moving from a local URL to a public HTTPS origin changes the browser context. Inspect the browser's cookie diagnostics and the server's Set-Cookie response. Adding a hostname to Vite does not rewrite application cookie policy.
Hot reload connects to the wrong address
Check the attempted WebSocket URL in developer tools. If it references a local hostname from a remote browser, review the HMR options documented by the installed Vite release. Avoid copying a configuration that assumes a particular public port, edge protocol, or proxy behavior without validating it against the current setup.
The tunnel works only while a terminal or device stays online
This is expected lifecycle behavior. A Localtonet tunnel is available only while the selected client device is connected and the tunnel is running. Creating the tunnel in the dashboard is not sufficient by itself. For a sharing session, keep Vite, our client, and the tunnel active. Stop the tunnel when the session is complete.
Test the Vite local URL, then a local request with the public Host header, then the public HTTPS URL, and finally browser features such as API requests and HMR. This sequence reveals whether the failure belongs to Vite startup, hostname validation, the tunnel target, or application behavior.
Frequently asked questions
Why does Vite work on localhost but fail through the Localtonet URL?
The public request uses the hostname from the Localtonet HTTPS URL rather than localhost. If Vite does not trust that hostname, it can reject the request even though our tunnel successfully reached the local process. Add the exact public hostname to the allowlist supported by the installed Vite version, restart Vite, and retest.
Should I set Vite allowedHosts to accept every host?
No. Allowing every hostname weakens Vite's DNS rebinding protection. Add only the exact tunnel hostname you intend to use. If a broader suffix rule is operationally necessary, use it only for a domain boundary you control and understand.
Do I include https:// in Vite allowedHosts?
No. Enter only the hostname. Do not include the URL scheme, port, path, query string, or trailing slash. For a URL such as https://preview.example/path, the hostname value is preview.example.
Does a Vite blocked-host message mean the Localtonet tunnel is broken?
Usually it indicates the opposite: the request reached Vite, and Vite rejected the hostname. Confirm this with the local custom Host header test. Tunnel connectivity should be investigated separately when the response is a timeout, connection failure, or upstream reachability error.
Do I need to bind Vite to every network interface?
Not when our client runs on the same machine and can reach Vite through loopback. Binding to all interfaces can expose the development server to the local network and should not be done without a reason. A different binding may be required when the client runs on another device or inside an isolated environment, but that decision should include firewall and LAN exposure review.
Can I keep a temporary tunnel hostname out of vite.config?
Current Vite documentation provides __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS for adding one trusted hostname through the process environment. Verify that your installed version supports it. Set only the hostname and never use the environment mechanism to expose Localtonet tokens or other credentials to browser code.
Why does the page work while hot module replacement fails?
Page delivery and the HMR WebSocket are related but separate connections. Host validation may already be fixed while the HMR client still attempts the wrong scheme, hostname, or port. Inspect the browser's WebSocket request and apply only the HMR configuration documented for the installed Vite version.
Should I tunnel Vite preview for production traffic?
No. Vite preview is intended to inspect a built application locally, not to serve as a production deployment server. It can be useful for controlled remote review, but persistent production access should use an appropriate production build, server, authentication model, and deployment architecture.
Share your Vite development server with a narrow trust policy
Start Vite locally, allow only the assigned public hostname, then create and start a Localtonet HTTP tunnel to the verified local port. Keep host validation enabled, protect the application itself, and stop the tunnel when the remote review is complete.
Get Started Free โ