← Back to Articles

How to Open Your Local Dev App on Your Phone

Featured Image

When developing locally, it’s common to set up a custom domain like dave.dev to replicate a production environment. However, accessing this local site from another device, like your phone, can be challenging. The issue is that your phone can’t resolve dave.dev unless you have configured the router DNS to forward traffic to your PC or you have custom DNS configured on your phone. A simple way around this would be if web browsers allowed you to set the Host header in the request, but unfortunately, this feature is not available in popular browsers.

The challenge arises because most local servers are configured to respond only to specific Host headers, such as dave.dev. Simply using your PC’s IP (192.168.1.x) from another device won’t work unless the Host header matches. If you don’t need the host header to be present and you don’t need TLS certificate termination then you don’t need to do any extra steps to open your app from your phone, you could simply hit http://192.168.1.x/ directly. The following solutions are meant to target the case where you either need to have the host header or you want to test your app on “HTTPS”.

Fortunately, several methods can help, ranging from quick external tools to more advanced local network setups depending on if you need to access it only locally or expose it to the internet. Here are some ways to access your local site on your phone:

Ngrok or Cloudflare (simplest solution)

Ngrok and Cloudflare are popular tools for exposing local servers to the internet. They create a public URL that forwards requests to your local server, allowing you to access your site remotely while preserving the Host header. This has the drawback of routing traffic through the internet, but it’s a quick and easy solution and doesn’t require any router or DNS configuration.

Cloudflare has a much generous free solution while also being easier to use than ngrok in most cases. You can set up your own custom domain name with cloudflare which is not something you can do with ngrok’s free version.

Pros

  • Fast and easy setup.
  • Works even if your phone is on a different network.
  • Others can access your app via internet.

Cons

  • Routes traffic through the internet.
  • Might hit bandwidth limits.
  • May not be a free solution or have limits depending on the service.

Local Proxy: a fully local solution

If you didn’t want to route the traffic through the internet (which might be an overkill or unfeasible for local development server serving lots of native esm modules) or use a third party tool like ngrok or cloudflare, you could instead set up a simple local proxy server on your PC. You would hit this proxy server on a specific port, and it would forward the request to your local server while adding the correct Host header behind the scenes. You could easily start this proxy server and pass it the source port, destination port and host header to make it flexible.

This works well if you don’t need your app to be accessible from the internet.

$ node my-proxy.js --source-port=3914 --destination-port=80 --host=dave.dev

Now if you hit http://192.168.1.x:3914 from your phone, it will forward the request to your local server on your PC running on port 80 and add the correct Host header.

import http from 'http'
import httpProxy from 'http-proxy'
import yargs from 'yargs'

const argv = yargs(process.argv.slice(2))
    .options({
        'source-port': { type: 'number', demandOption: true, alias: 's', describe: 'Source port to listen on' },
        'destination-port': { type: 'number', demandOption: true, alias: 'd', describe: 'Destination port to forward requests to' },
        'host': { type: 'string', demandOption: true, alias: 'h', describe: 'Host header to set for proxied requests' }
    })
    .check((args) => {
        if (isNaN(args['source-port']) || isNaN(args['destination-port'])) {
            throw new Error('Source and destination ports must be valid numbers')
        }
        if (!args.host) {
            throw new Error('Host must be provided')
        }
        return true
    })
    .argv

const proxy = httpProxy.createProxyServer()

const server = http.createServer((req, res) => {
    req.headers.host = argv.host
    proxy.web(req, res, { target: `http://localhost:${argv['destination-port']}` })
})

server.listen(argv['source-port'], () => {
    console.log(`Proxy running on http://localhost:${argv['source-port']}, forwarding to http://localhost:${argv['destination-port']} with host header: ${argv.host}`)
})

Pros

  • Fully local; no internet dependency.
  • Low latency and easy setup.

Cons

  • Requires running a separate proxy alongside your server.
  • Need to be on the same network as the proxy and the server.
  • No external / internet access support.

Public proxy and VPN

If you need to access your local server but you don't want to use a tunnel and you are not able to open ports on your router then as long as you have a VPN access to your network, you could use a public-facing proxy server that connects to your VPN and forwards the traffic to your local server.

  1. Add a new domain in your Cloudflare settings, e.g. my-app.example.com
  2. Point this domain to your public proxy server IP address.
  3. Establish a VPN connection from your public proxy server.
  4. Have the public proxy server forward the traffic to your local server, adding the correct Host header.

Cloudflare --> Proxy (+VPN) --> Local Server

server {
    listen 80;
    server_name my-app.example.com;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host my-app.local;
        proxy_pass http://192.168.8.236;
    }
}

Pros

  • Works even if your phone is on a different network.
  • Others can access your app via internet.
  • No need to open ports on your router.
  • Get a truly native public URL / CDN support without a tunnel.

Cons

  • Requires a public proxy server.
  • Requires owning a domain name.
  • Optionally requires a VPN connection.

Modify /etc/hosts file on your phone

If you have a rooted Android phone or a jailbroken iPhone, you can modify the /etc/hosts file to resolve dave.dev to your PC’s IP address. This is a quick and easy way to access your local site on your phone.

Pros

  • Quick and easy setup.
  • Fully local and private.

Cons

  • Requires a rooted Android phone or jailbroken iPhone.
  • Not a permanent solution.

Local DNS with dnsmasq

You can set up a local DNS resolver on your PC to resolve dave.dev. Then go to your phone’s settings and specify that you want to use your own custom DNS server (the one running on your PC). This way, your phone will resolve dave.dev to your local PC IP address.

Steps:

  1. Install dnsmasq:
  2. Configure dnsmasq: Edit /etc/dnsmasq.conf and add address=/dave.dev/192.168.1.x
  3. Restart dnsmasq.
  4. Set Your PC as the DNS Server on Your Phone

Pros

  • Seamless use of dave.dev across devices.
  • Fully local and private.

Cons

  • Requires DNS configuration on your phone.
  • Slightly more complex setup.

Update Router DNS settings

If you have access to your router’s settings, you can configure the DNS on the router to route dave.dev to your local PC. Simply add a DNS entry dave.dev > 192.168.1.x

Pros

  • Seamless use of dave.dev across devices.
  • Fully local and private.

Cons

  • Requires access to router settings.
  • Not portable across networks.
  • Need to change router settings every time.

Port Forwarding (no host header support)

If you don’t need the host header to be present and you have access to your router settings, you can set up port forwarding to your PC. This way, you can access your local server from your phone using your PC’s IP address and a specific port.

This means that on your phone you would hit http://PUBLIC_IP:3914 directly and it would forward the request to your local server running on port 80.

Pros

  • Fully local and private.
  • Easy setup.

Cons

  • No host header support.
  • Requires access to router settings.

Listen to Deep Dive

Download