32 min read

How To Host A Web Server On Android

In this module, we will have a look at how we can host a web server on Android and port forward it using localtonet so that we can have a flexible webserver on the go.

Android phone hosting a local web server connected through a Localtonet tunnel to a remote HTTPS browser.
The Android-hosted service remains local while the tunnel provides a public HTTPS path.
Android ยท Termux ยท Web Server ยท Localtonet ยท 2026

Run a website or API on your phone, verify it locally, and publish it through a controlled HTTPS tunnel

An Android device can host a static website, development API, webhook receiver, or small demonstration service without root access. Termux provides the command-line environment for running Python, Node.js, and common development tools. Our Android client can then connect that local service to a public HTTPS address without inbound router port forwarding, firewall changes, VPN setup, or a public IP address. This guide covers installation, three working server examples, staged verification, HTTP tunnel configuration, Android process limitations, routine maintenance, security, and cleanup.

๐Ÿ“ฑ No root required for the documented ports ๐ŸŒ Public access through an outbound tunnel ๐Ÿ”’ Loopback binding and access-control guidance

What hosting a web server on Android means

A web server is a process that listens for HTTP requests on a network port and returns files or generated responses. In this tutorial, that process runs inside Termux and listens on an unprivileged port such as 3000, 5000, or 8080. A browser on the same Android device can access it through an address such as http://127.0.0.1:8080.

The address 127.0.0.1 is the IPv4 loopback address. Binding a server to it limits direct connections to applications on the same device. This is preferable to binding a temporary development server to 0.0.0.0, which can make it reachable from other devices on the same Wi-Fi network. Our Android client can still connect to the loopback service because the client and server run on the same phone.

Local access does not automatically provide internet access. Mobile carriers commonly place devices behind carrier-grade NAT, while Wi-Fi networks usually place them behind a router. Localtonet solves that connectivity problem by having the Android client establish an outbound connection to one of our relay servers. After an HTTP tunnel is created and started, requests follow this path:

Public browser
      |
      | HTTPS request
      v
Localtonet public endpoint
      |
      | Existing outbound tunnel connection
      v
Localtonet Android client
      |
      | HTTP request to 127.0.0.1 and the configured port
      v
Python, Express, or Flask server inside Termux

The local application remains on the phone. The tunnel supplies a public route to it while the selected Android client is connected and the tunnel is running. Creating a tunnel configuration does not start it automatically, and a saved tunnel does not remain reachable if Android terminates either Termux or the Localtonet client.

๐Ÿงช Development previews Share a temporary preview with a teammate or test a page from a device outside the phone's local network.
๐Ÿ”— Webhook testing Receive test callbacks at a public HTTPS endpoint while observing how the local application handles each request.
๐Ÿ“ Static content Serve a dedicated directory containing only the HTML, CSS, JavaScript, images, and test files you intend to expose.
โš™๏ธ Small APIs Run a Node.js or Python endpoint for learning, demonstrations, prototypes, or controlled personal workflows.
Use the right hosting environment for the workload

An Android phone is useful for learning, temporary previews, and portable demonstrations. It is not automatically an always-on production host. Reboots, battery policies, thermal limits, memory pressure, application updates, and network transitions can interrupt the server or tunnel.

Prerequisites and a safe Termux installation

You need an Android device capable of running a current Termux build, sufficient storage for your packages and project, internet access for package installation, a Localtonet account, and the official Localtonet Android application. The examples use user-space ports and do not require root access.

Install Termux from a maintained official source

Follow the official Termux installation guidance before installing the application. Current Termux builds support Android 7.0 or later. Older Android releases are not supported by the current application and package ecosystem in the same way, so an obsolete APK is not a suitable foundation for an internet-facing project.

For most users, the official guidance recommends the Termux package on F-Droid, preferably installed through the F-Droid client so update notifications and normal package updates are available. Official GitHub releases are another documented installation path, but users must choose the correct APK and understand that GitHub builds use their own signing source.

Do not mix Termux signing sources

The main Termux application and any Termux add-ons must come from the same distribution source. For example, do not install the main application from F-Droid and an add-on from GitHub. Builds from different sources can use different signing keys and may be incompatible. If changing sources, back up the files you need, uninstall the existing Termux application and add-ons, and then install a consistent set from the new source.

Open Termux after installation and update its package metadata before adding tools:

pkg update
pkg upgrade

Read the proposed package changes before accepting them. The examples in this guide store projects under the Termux home directory, so they do not need access to Android shared storage. If you intentionally need shared storage, run termux-setup-storage and approve the Android permission prompt. Granting that permission increases the set of files Termux can reach, so continue to serve only a dedicated project directory.

Install and prepare the Localtonet Android client

Install the official Localtonet application from Google Play. Register for an account if needed, then create or obtain the device-specific AuthToken from your Localtonet account. Enter that token into the Android client to authenticate the device. The AuthToken identifies the client that will run the tunnel, so treat it as a credential.

Keep the Android application open during initial setup and confirm that the authenticated device appears as connected in our dashboard. Do not paste the AuthToken into source code, shell history examples, screenshots, public issue reports, or files served by the web application. If a real token is exposed, stop using it and replace it through the account workflow rather than attempting to conceal only the published copy.

Choose one local port

Example Local address Expected response
Python static server http://127.0.0.1:8080 The contents of the project's index.html file
Express API http://127.0.0.1:3000/api/status JSON containing "status":"ok" and "platform":"android"
Flask application http://127.0.0.1:5000/api/status JSON containing "status":"running" and "platform":"android"
Use an unprivileged local port

In a normal non-root Termux environment, use a port above 1024. Binding directly to a privileged port such as port 80 generally requires elevated privileges. The public HTTPS endpoint does not need to use the same port number as the local server.

Create a web server in Termux

Choose one of the following methods. You do not need to run all three. Python's built-in server is the shortest route to a static page, Express provides a basic JavaScript API, and Flask provides a basic Python application. Each example binds explicitly to 127.0.0.1.

Method 1: Serve a static website with Python

Python includes a simple HTTP server that is useful for local development and temporary demonstrations. It does not provide application authentication, detailed authorization, production hardening, or a complete operational logging system. Serve only a dedicated directory containing files you intentionally want visitors to access.

1

Install Python

pkg update
pkg install python

Confirm the installation with python --version. A version string indicates that the executable is available.

2

Create a dedicated website directory

mkdir -p ~/android-site
cd ~/android-site
nano index.html

Do not use the Termux home directory itself as the document root. The dedicated directory should contain no tokens, private photographs, shell configuration, SSH material, or unrelated files.

3

Add a recognizable test page

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Android Test Server</title>
</head>
<body>
  <h2>Android server is running</h2>
  <p>Served from Termux with Python.</p>
</body>
</html>

Save the file in Nano with Ctrl+O, confirm the filename, and exit with Ctrl+X.

4

Start the loopback server

cd ~/android-site
python -m http.server 8080 --bind 127.0.0.1

Leave this command running while testing. The terminal should report that it is serving HTTP on 127.0.0.1 at port 8080.

Directory listings can reveal unintended files

Python's simple HTTP server can display a directory listing when no index file is present. Never run it from ~, the root of shared storage, or a directory containing credentials or application configuration. Python's http.server is appropriate for temporary controlled use, not as a hardened permanent public server.

Method 2: Run a Node.js and Express API

This Express example provides two routes and suppresses the default X-Powered-By header. It is still a learning example rather than a complete production API. A real application needs authentication, authorization, request validation, appropriate request-size limits, dependency review, safe error handling, and its own logging policy.

1

Install Node.js

pkg update
pkg install nodejs-lts
node -v
npm -v

The final two commands should print the installed Node.js and npm versions.

2

Create the project and install Express

mkdir -p ~/myserver
cd ~/myserver
npm init -y
npm install express

Keep the generated package.json and lock file. The lock file helps preserve the dependency versions selected for this project.

3

Create the server file

nano server.js
const express = require('express');
const app = express();

app.disable('x-powered-by');

app.get('/', (req, res) => {
  res.json({ message: 'Android server is running' });
});

app.get('/api/status', (req, res) => {
  res.json({ status: 'ok', platform: 'android' });
});

app.listen(3000, '127.0.0.1', () => {
  console.log('Server running at http://127.0.0.1:3000');
});
4

Run the API

cd ~/myserver
node server.js

The terminal should print Server running at http://127.0.0.1:3000. Leave the process running while completing the verification steps.

Method 3: Build a small Flask application

Flask is useful for learning Python web development and building prototypes. Flask's built-in server is explicitly a development server. It should not be treated as a hardened production server, particularly when an application handles private information, credentials, uploads, administrative functions, or untrusted input.

1

Install Python and Flask

pkg update
pkg install python
python -m pip install flask

Using python -m pip ensures that pip belongs to the Python interpreter invoked by the example.

2

Create the application

mkdir -p ~/flaskapp
cd ~/flaskapp
nano app.py
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def home():
    return '<h2>Hello from Android</h2>'

@app.route('/api/status')
def status():
    return jsonify({'status': 'running', 'platform': 'android'})

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=False)
3

Run the application

cd ~/flaskapp
python app.py

Flask should report that it is running on http://127.0.0.1:5000. Keep debug=False whenever another person could reach the service.

Never expose Flask's interactive debugger

Debug mode can disclose application internals, and an interactive debugger can create a severe remote-code-execution risk if it becomes reachable. Disabling debug mode is necessary for this tutorial, but it does not convert Flask's development server into a production deployment.

Verify the server locally before creating a tunnel

Termux server status beside an Android browser successfully loading the local service.
A successful localhost test confirms that the server works before tunneling is introduced.

Separate local application testing from tunnel testing. If the application does not answer on 127.0.0.1, changing the relay server, public hostname, or tunnel Process Type will not repair it. First confirm that the process is running, then request the exact route you intend to expose.

Stage 1: Confirm that the process is still running

Return to the Termux terminal where the server was started. A running foreground process normally keeps control of that terminal. If the shell prompt has returned, read the error shown above it. Typical causes include a syntax error, missing dependency, incorrect working directory, or a port already in use.

Install the standard networking and HTTP test tools if they are not already present:

pkg install iproute2 curl

Inspect listening TCP sockets:

ss -ltn

Look for the selected loopback address and port, such as 127.0.0.1:8080, 127.0.0.1:3000, or 127.0.0.1:5000. A listening socket confirms that a process has opened the port, but it does not prove that the application returns the correct content.

Stage 2: Check the expected application response

Open a second Termux session or use the Android browser while the server remains running. Test the matching example:

Python static server:

curl -i http://127.0.0.1:8080/

Expect an HTTP success response and HTML containing Android server is running. If a directory listing appears instead, verify that index.html exists in ~/android-site and that the server was started from that directory.

Express API:

curl -i http://127.0.0.1:3000/api/status

Expect an HTTP success response with JSON containing "status":"ok" and "platform":"android". Also test the root route if it will be shared:

curl -i http://127.0.0.1:3000/

The root response should contain "message":"Android server is running".

Flask application:

curl -i http://127.0.0.1:5000/api/status
curl -i http://127.0.0.1:5000/

The status route should contain "status":"running" and "platform":"android". The root route should return the Hello from Android heading.

Record the exact working target

The IP address and port that work locally are the values to enter in the Localtonet HTTP tunnel. Do not substitute localhost, a Wi-Fi address, or a different port unless you intentionally changed the server configuration and verified the new target.

Configure the Localtonet HTTP tunnel

HTTP requests traveling from a public HTTPS endpoint through Localtonet to a web server on Android.
The tunnel maps the public endpoint to the web server listening on the Android device.

Our Android client must run on the Android device hosting the Termux server. It establishes the outbound relay connection, so this workflow does not require an inbound router rule, a public IP address, a firewall exception, or a VPN. Complete the local verification first, then follow the HTTP tunnel sequence below.

1

Authenticate the Android device

Sign in to your Localtonet account, obtain the device-specific AuthToken, and enter it in the official Android client. Keep the client running and confirm that the token or device reports a connected state. The token must remain private because it identifies the device that will carry the tunnel.

2

Open the HTTP tunnel page

Open the Localtonet HTTP tunnel page while signed in. This is where the public HTTP configuration is associated with the connected Android client.

3

Choose the Process Type

Select Random Sub Domain, Custom Sub Domain, or Custom Domain according to the public address you need and the options shown for your account. These Process Types publish the same local HTTP content through a public HTTPS address. They differ in how that public hostname is selected.

4

Select the connected AuthToken

Select the AuthToken belonging to the Android device running Termux. Do not select a token for another computer or phone, because the local target 127.0.0.1 is resolved on the selected client device.

5

Select an available relay server

Choose a server or region from the values currently available in the dashboard. Available relays can vary, so do not rely on a server code copied from an older tutorial.

6

Enter the verified local target

Set the local IP address to 127.0.0.1. Set the local port to 8080 for Python, 3000 for Express, or 5000 for Flask. Use only the port you already confirmed with the local browser or curl.

7

Create the tunnel configuration

Create or save the HTTP tunnel after reviewing the selected client, relay, Process Type, local IP, and local port. Creation stores the configuration but does not mean that the tunnel is running.

8

Press Start

Use the Start control for the newly created tunnel. Wait until the tunnel reports a running or connected state and displays its public HTTPS address.

9

Verify, stop, and delete when appropriate

Test the assigned HTTPS address as described in the next section. When public access is no longer needed, press Stop. Delete the saved tunnel as well if you do not intend to reuse that configuration.

Understand the three HTTP Process Types

Process Type Public hostname behavior When to choose it
Random Sub Domain Localtonet assigns a generated public subdomain. Temporary testing, demonstrations, and situations where you do not need to choose the hostname.
Custom Sub Domain You select a subdomain through the supported dashboard workflow. A more recognizable Localtonet-hosted address where this option is available for the account and configuration.
Custom Domain You associate a domain you control and complete the DNS instructions shown by the current workflow. Using your own hostname when the option is available and you can manage its DNS.

Do not assume that every Process Type, relay, hostname choice, or access-control option is included with every account or subscription. Use the choices displayed in the current dashboard. For a Custom Domain, follow the DNS values shown there rather than copying nameservers or records from an older article. DNS requirements and account availability can change.

Local binding and public tunneling are compatible

Binding the application to 127.0.0.1 prevents direct connections from other devices on the local Wi-Fi network. Our Android client can still forward tunnel traffic to that address because it runs on the same device.

Verify the public HTTPS endpoint in stages

A public test should prove more than the presence of a hostname. Verify the Android client, tunnel state, response content, and external network path separately. This makes it easier to distinguish an application failure from a tunnel failure.

1

Recheck the local application

Repeat the matching curl request to 127.0.0.1. If it now fails, repair or restart the local process before changing the tunnel.

2

Confirm the Localtonet client state

Verify that the Android client remains open or active and that its AuthToken or device is shown as connected. If Android terminated the application or the phone changed networks, allow the client to reconnect before continuing.

3

Confirm the tunnel state

Check that the correct HTTP tunnel is running, not merely saved. Review its local target and confirm that the displayed port matches the active server.

4

Test from another network

Open the public HTTPS address from another device using a different network, such as a computer on another connection or a phone using mobile data instead of the host phone's Wi-Fi. This confirms that the request is using the public endpoint rather than local connectivity.

5

Compare the public and local responses

The Python endpoint should show the same test page. Express should return the same JSON at /api/status. Flask should return its expected HTML and status JSON. A matching response confirms that the tunnel reaches the intended application rather than another process on the phone.

An HTTP error generated by the application, such as a route-specific 404, shows that a request reached a web server but requested the wrong path. A connection failure at both the local and public addresses usually points to the application. A working local response combined with a failed public response points toward the client connection, tunnel state, selected AuthToken, relay configuration, or public access controls.

Run, stop, maintain, and recover the service

Android can suspend or terminate applications to conserve battery and memory. A terminal multiplexer makes routine shell management easier, but it cannot override Android's process lifecycle. Treat both the Termux server and Localtonet tunnel as processes that may need to be checked and restarted.

Manage the server with tmux

1

Install tmux

pkg install tmux
2

Create a named session

tmux new -s myserver

A descriptive name makes it easier to find the correct session later.

3

Start one server inside the session

node ~/myserver/server.js

For Flask, use python ~/flaskapp/app.py. For the static server, change to ~/android-site and run the Python HTTP server command from that directory.

4

Detach without stopping the process

Press Ctrl+B, release both keys, and then press D. Detaching returns to the ordinary Termux shell while the server continues inside tmux, provided Android keeps the Termux process alive.

5

List and reattach to sessions

tmux ls
tmux attach -t myserver

If tmux ls says no server is running, Android or a manual action may have ended Termux, or the session was closed.

Stop the local server safely

Reattach to the tmux session and press Ctrl+C in the terminal running the server. Wait for the shell prompt to return, then confirm that the port is no longer listening:

ss -ltn

To terminate an entire tmux session after the application has stopped, run:

tmux kill-session -t myserver

Avoid immediately killing the session while an application is writing files or processing a request. A normal interrupt gives the process an opportunity to exit cleanly. If a process does not respond, diagnose it before escalating to forced termination.

Review output and keep simple logs

Reattach with tmux attach -t myserver to review live application output. You can also print the visible tmux pane without attaching:

tmux capture-pane -p -t myserver

For a temporary development session, redirect standard output and errors through tee:

cd ~/myserver
node server.js 2>&1 | tee -a server.log

The same pattern can be used with python app.py. Logs can contain request paths, application errors, submitted values, or other sensitive material, so store them in the private project directory, review their contents before sharing, and remove them when no longer required. Python's simple HTTP server writes basic request information to its terminal output.

Recover after Android stops an application

If Android terminates Termux, the tmux server ends with it. Reopen Termux, run tmux ls, and do not assume the session survived. If no session exists, create a new one, change to the correct project directory, and restart the application using the original command. Verify the loopback endpoint again before relying on the public URL.

If Android terminates the Localtonet client, reopen it and confirm that the device reconnects. Then check the saved tunnel. Depending on its current state, you may need to press Start again. A connected device and a running local server are both required, but neither alone proves that the tunnel is running.

Network transitions can also interrupt connectivity. When moving between Wi-Fi and mobile data, allow the Android client to reconnect, confirm the tunnel state, and repeat both the local and public tests. Do not diagnose DNS or rewrite application code until you have checked those states.

tmux is not an Android uptime guarantee

tmux preserves a shell session only while the Termux application process remains alive. Battery management, memory pressure, a reboot, a force-stop action, or manufacturer-specific background restrictions can terminate it. This guide does not depend on wake-lock commands because those require additional Termux components and still cannot guarantee that Android will preserve the process.

If the device provides per-application battery controls, review them for both Termux and Localtonet while the service is needed. Labels and behavior vary by Android release and manufacturer. Avoid force-stopping either application, and test the actual device instead of assuming that a battery setting guarantees continuous operation.

Update dependencies deliberately

Stop the server before a maintenance update. For Termux packages, review and apply available updates:

pkg update
pkg upgrade

For the Express project, inspect outdated packages and the audit report before deciding what to change:

cd ~/myserver
npm outdated
npm audit

Apply compatible updates deliberately, test the application locally, and retain the lock file. Do not apply an automatic breaking upgrade immediately before a public demonstration.

For Flask, inspect the environment with:

python -m pip list --outdated
python -m pip check

Update packages only after reviewing compatibility with the application. Restart the service and repeat the local response tests after every dependency change.

Remove public access when finished

Cleanup should happen in this order: press Stop for the Localtonet tunnel, confirm that the public address no longer serves the application, stop the local server with Ctrl+C, and delete the saved tunnel if it will not be reused. Deleting a tunnel is different from stopping it. Stop preserves the configuration for later use, while deletion removes that saved tunnel from the account.

Use a custom subdomain or custom domain carefully

Random Sub Domain, Custom Sub Domain, and Custom Domain Process Types all deliver the selected local HTTP service through a public HTTPS address. A generated subdomain is usually the simplest choice for temporary testing. A custom subdomain provides a more recognizable Localtonet-hosted name where supported. A custom domain connects a hostname you control.

Custom-domain configuration requires DNS changes. Select Custom Domain in the current workflow and use the exact DNS instructions displayed by our dashboard or current documentation. Do not copy DNS records, nameservers, or certificate instructions from an old tutorial. Wait for the required DNS changes to propagate before treating a hostname failure as an Android application problem.

Availability can vary by account, plan, client version, and current product configuration. Check the dashboard before designing a workflow around a particular hostname option. Do not assume that a custom subdomain or custom domain will be available for every account.

Secure the service before public exposure

Security boundaries limiting public HTTPS traffic to the intended Android web service.
Public access should be restricted to the intended web application while other device resources remain isolated.

A public tunnel changes who can send requests to the application. Treat every public request as untrusted internet traffic, even when the URL was shared with only one person. URLs can be copied, logged, forwarded, stored in browser history, or discovered through an unintended disclosure.

๐Ÿ” Use documented edge controls Localtonet supports Basic Authentication and IP whitelisting for restricting access. Configure the controls shown for the tunnel and verify them before sharing the URL.
๐Ÿ›ก๏ธ Keep application authorization Edge restrictions supplement application login, route permissions, session security, and object-level authorization. They do not replace them.
๐Ÿ“‚ Expose the minimum content Serve a dedicated directory or narrowly scoped API. Never expose the Termux home directory, shared-storage root, credentials, backups, or private media.
๐Ÿงฉ Maintain dependencies Review package updates and known dependency issues, then test locally before restoring public access.
๐Ÿ“ Control logs and errors Avoid returning stack traces, environment variables, filesystem paths, tokens, or internal configuration to public clients.
๐Ÿ›‘ Stop unused tunnels Remove public reachability as soon as testing, demonstration, or sharing is complete.

Basic Authentication and IP whitelisting

The current Localtonet Android application listing documents Basic Authentication and IP whitelisting as access-control capabilities. Basic Authentication can place a username and password check in front of the public endpoint. IP whitelisting can restrict requests to approved source IP addresses. Use the current controls shown for your tunnel because option placement and availability can vary by account or product version.

Test restrictions from both an allowed and a disallowed client before relying on them. An IP allowlist can be inconvenient when an approved user's public address changes, especially on mobile or residential networks. Basic Authentication credentials must be strong, private, and transmitted only through the HTTPS endpoint.

Edge authentication does not replace application authorization

A tunnel-level credential can restrict entry to the endpoint, but the application must still decide which authenticated user can read, create, modify, or delete each resource. Keep route-level authorization, input validation, secure session handling, upload controls, and database permissions inside the application.

Protect secrets and user input

Keep API keys, Localtonet AuthTokens, database credentials, and private endpoints outside publicly served files. Do not embed secrets in JavaScript delivered to the browser. Never put a Localtonet AuthToken in index.html, application responses, screenshots, or a public source repository.

Validate request bodies, parameters, file names, and content types. Limit uploads and request sizes where the framework supports it. Avoid constructing shell commands, paths, database queries, or template expressions directly from user-supplied values. Return controlled error messages rather than stack traces or environment details.

Python's simple HTTP server and Flask's development server remain development tools even when the public endpoint uses HTTPS and access controls. HTTPS protects traffic to the public endpoint, but it does not add missing authorization, harden a development server, remove vulnerable dependencies, or prevent the application from serving the wrong files.

Troubleshooting Android server and tunnel failures

Problem Likely cause Safe diagnostic or fix
Both local and public requests fail The server stopped, crashed, or never opened the configured port Check the Termux output, run ss -ltn, restart the application, and verify the loopback URL before testing the tunnel.
Local response works but the public URL fails The Android client is disconnected, the tunnel is stopped, the wrong AuthToken was selected, or an access rule blocks the request Confirm the client state, tunnel state, selected token, relay, and current Basic Authentication or IP whitelist configuration.
Public endpoint returns the wrong application The tunnel points to another local port Compare the configured target with the exact local address that produced the expected response.
Connection refused No process is listening on the configured port Start the selected server and match the tunnel port to 8080, 3000, or 5000.
Port already in use Another process or an earlier server instance already owns the port Find the listener with ss -ltnp where available, stop the previous server cleanly, or select another unprivileged port and update both the server and tunnel.
The server returns a 404 response The request reached the application but used an undefined route Test / and the documented /api/status path. A route-level 404 is different from a network connection failure.
Python shows a directory listing No index.html exists in the active document root Stop the server if unintended files are visible, create the expected index file, and restart from ~/android-site.
Files in shared storage are unavailable Termux lacks Android shared-storage permission Prefer a Termux-owned project directory. If shared storage is required, run termux-setup-storage and grant only the access needed.
The service disappears in the background Android suspended or terminated Termux or the Localtonet client Reopen the affected application, restart the server or tunnel as needed, review battery settings, and repeat local and public checks.
No tmux session exists after reopening Termux The entire Termux process ended Create a new tmux session and restart the server. tmux cannot survive termination of the Termux application process.
The custom domain does not resolve DNS records are missing, incorrect, or still propagating Compare the live DNS configuration with the current instructions in the dashboard. Do not change the local server if its loopback and assigned tunnel address work.
Access works on one network but not another An IP whitelist, source-address change, or network policy is affecting the request Review the allowlist and test with an authorized source address. Do not disable application authorization merely to simplify testing.

Distinguish application failures from tunnel failures

An application failure appears at the loopback address. Examples include a refused connection, Python serving the wrong directory, an Express exception, or a Flask route returning an error. Read the local process output and fix that condition before investigating Localtonet.

A tunnel-side failure occurs when the expected local request works but the same path does not work through the public HTTPS endpoint. Check the connected AuthToken, Android client state, tunnel state, selected relay, target IP and port, Process Type, and access controls. If the phone recently changed networks, allow the outbound connection to recover and retest.

Frequently asked questions

Can I host a web server on Android without root?

Yes. Termux can run Python, Node.js, Flask, and other user-space tools without root. Use an unprivileged port such as 3000, 5000, or 8080. Localtonet can publish that local HTTP service through a public HTTPS address without requiring the server to bind directly to port 80 or 443.

Why should the server bind to 127.0.0.1?

Binding to 127.0.0.1 limits direct connections to applications on the same phone. This reduces accidental exposure to other devices on local Wi-Fi. Our Android client can still forward requests to that address because it runs on the same device.

Does creating a Localtonet tunnel make it active immediately?

No. Creating the tunnel saves its configuration. You must press Start and confirm that the tunnel is running. The selected Android client must also remain connected, and the Termux server must remain active on the configured local port.

Does an HTTPS tunnel secure the entire application?

No. HTTPS protects traffic to the public endpoint, but it does not add missing application authorization, validate input, remove vulnerable dependencies, prevent unsafe file exposure, or make a development server production-ready. Configure tunnel access controls where appropriate and secure the application itself.

Can I protect the public endpoint with Basic Authentication or an IP whitelist?

Localtonet supports Basic Authentication and IP whitelisting. Configure the controls currently shown for your tunnel and account, then test them from allowed and disallowed clients. These controls supplement application authorization rather than replacing it.

Can tmux guarantee that the Android server stays online?

No. tmux preserves a terminal session while the Termux process remains alive. Android can still terminate that process because of battery management, memory pressure, a reboot, a force-stop action, or manufacturer-specific restrictions. Reopen Termux, restart the service, and verify it whenever the session disappears.

Can I use my own domain for the Android server?

HTTP tunnels offer a Custom Domain Process Type where it is available for the account and configuration. Select it in the current dashboard and follow the DNS instructions shown there. Do not rely on DNS values copied from older tutorials.

Is Python's http.server suitable for a permanent public website?

It is best limited to temporary development and controlled sharing. It lacks many controls expected from a hardened production server and can expose directory listings. Use a production-oriented deployment and an appropriate hosting environment when reliability, authentication, auditing, or security guarantees are required.

What should I restart after the phone changes networks?

First verify that the local Termux server still responds. Then confirm that the Localtonet Android client has reconnected and that the HTTP tunnel is running. Restart only the failed component, and repeat the public test from another network.

Publish your Android development server carefully

Build and verify the service on 127.0.0.1, authenticate the official Localtonet Android client, configure the matching HTTP target, and start the public tunnel only for as long as access is needed.

Get Started Free โ†’

Corrections & updates

Substantive changes approved by the Localtonet editorial team are listed transparently below.

Add the mandatory clickable guide navigation card and matching IDs to all linked primary sections. Verify and rewrite the Localtonet HTTP tunnel procedure in the exact current documented order, including device authentication, relay selection, local target configuration, Process Type behavior, creation, Start, verification, Stop, and deletion. Expand the Termux prerequisite and installation guidance with official sources and current compatibility requirements. Add explicit expected-result checks for Python, Express, Flask, and the pub

Removed unsupported Localtonet Termux installation commands, unverified VPN limitations, comparative ngrok claims, the technically incorrect cross-device SSH reverse tunnel, hardcoded custom-domain nameservers, and the unsafe Android phantom-process ADB workaround. Corrected the explanation of tmux and wake locks so they are not presented as guarantees against Android process termination. Bound all sample servers to 127.0.0.1, strengthened warnings for Python's simple HTTP server and Flask's development server, preserved the documente

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support