Test development site over LAN

7 minute read  

You’re developing a website/webapp and everything is working perfectly from your machine locally on the browser. You want to now test it from another machine or mobile device over LAN (Local Area Network). What are your options and when would you want to choose one over another?

It depends on the complexity of your website/webapp:

  • The site/app is a pure frontend (HTML/CSS/JS)
  • The site/app has a backend component (PHP, Ruby, Python, Node, etc.) and a database
  • The site/app has multiple components and services

In all cases, you first need to make sure your machine Firewall setting allow incoming requests from other devices. And then choose 1 of the 3 options for hosting your development site.

Firewall setting to allow incoming requests to the machine

If your machine doesn’t have Firewall or has Firewall setting to OFF, then you’re already accepting all incoming requests. However most consumer machines with Windows or Mac typically have Firewall setting that restricts incoming requests by default. You need to allow the machine to accept incoming request to your Web Server process.

How? Normally you have 2 options:

  • Manually: add the process to your Firewall setting and allow it to accept incoming connections. A process in general is an executable on your machine: either an application or a binary, e.g. the Dropbox app or the node binary. For our purpose of Web Server process in development platforms, they typically are the node.js, ruby, python, php binaries on your machine.

  • By prompt (on Mac): an easier way is to develop your site/app normally, and when you first start the Web Server process that listens on all IPs with --host=0.0.0.0 (see section below), your machine Firewall will prompt and ask if you want to allow the process to accept incoming requests. You should choose Allow. If you happened to choose Deny, you can always go to your Firewall setting and manually change it.

Below is an example of a Mac Firewall setting that allows node and ruby processes to accept incoming connections. Note that there are 2 node processes in the list because we have 2 different binaries of node on our system.

Firewall is now configured. Let’s walk over the simplest case where your site/app is a pure frontend HTML/CSS/JS files. We then have 3 options for how to test it over LAN:

OPTION 1: DIRECTLY HOST THE SITE/APP FROM YOUR MACHINE

We typically have 3 choices here.

  1. OS built-in Web Server: traditionally developers have been using the built-in Web Server that came with their OS (e.g. Internet Information Services - IIS in Windows, or Web Sharing in Mac which is a repackaged Apache). This works, but it’s very OS specific.

  2. Apache or XAMPP: install the official Apache Web Server on their machine or employ a bundle like WAMP or XAMPP. Even though installation may be different among OSes, the config and usage of Apache or XAMPP should be the same across Windows, Mac, and Linux. This is a better choice compared to #1 since it allows for better reproducible result.

  3. Dev platform Web Server: or if you’re developing a frontend app with emerging technologies like AngularJS / Angular2, or a static site with generators like Jekyll or Hexo, there almost always a Web Server process included in the platform.

#1 and #2 are more cumbersome than convenient.

#3 is the best choice here since it’s already a part of the platform that you’re using to develop your site/app. There is no need for extra installation, however you need to make sure that the Web Server will respond through the LAN IP.

The Web Server process should listen on all IPs

Most of the time, the default Web Server setup in those development platforms only allow the process to listen on localhost. localhost refers to the internal IP address of a machine itself, called the loopback IP 127.0.0.1. This means, to reach your development site/app you have to type in the browser http://localhost or http://127.0.0.1. This works just fine on your development machine because the local browser can reach localhost and your Web Server process is listening for traffic there.

However, from another device like a mobile phone, if you type in http://localhost the mobile browser won’t go anywhere because localhost refers to the mobile phone itself and there is no Web Server process running on it. From the mobile phone, you will need to reach the development machine through its LAN IP.

Look at your machine’s Networking info to find the LAN IP of the machine, say it’s 192.168.1.100. You’d type in your mobile phone browser http://192.168.1.100. Wa-lah, it should work, right? Maybe, but not all the time.

You need to make sure that the process serving your site/app not only listens on the default localhost/127.0.0.1 but also listens on your machine LAN IP 192.168.1.100.

All popular Web Server processes that comes with development platforms have a command line parameter named --host or something similar that allows you to specify which IP the process will listen on. You can start your process with --host=192.168.1.100 and it will listen on that particular IP and respond to incoming requests.

0.0.0.0 is a special IP address that if you start your Web Server process with --host=0.0.0.0 (another form is --host 0.0.0.0), it will listen on all IPs. This is the most preferred way to start your process since you don’t need to stop and restart to adjust the --host=IP every time your machine LAN IP changes.

Examples of --host usage in a few different development platforms

Example: AngularJS that uses http-server

The setting to start the http-server is most likely in the package.json. Find the relevant script line.

{
  "scripts": {
    "start": "http-server -a localhost -p 8000"
  }
}

And add the --host parameter

{
  "scripts": {
    "start": "http-server -a localhost -p 8000 --host 0.0.0.0"
  }
}

Example: AngularJS that uses webpack-dev-server

Similarly, the setting to start the webpack-dev-server is most likely in the package.json. Find the relevant script line, and add the --host parameter.

{
  "scripts": {
    "start": "webpack-dev-server --config config/webpack.dev.js --watch --content-base src/ --host 0.0.0.0"
  }
}

Example: Jekyll serve

Start the command with --host parameter

jekyll serve --config _config.yml,_config.dev.yml --host 0.0.0.0

Other devices can now reach your development site/app at http://192.168.1.100:port where port is the port that your Web Server process chose to use.

OPTION 2: RUN APACHE/NGINX ON A VIRTUAL MACHINE

Instead of installing Apache directly on your machine OS, use a Virtual Machine for it. This approach is better than the direct Apache/XAMPP installation on host approach mentioned earlier because not only it’s OS independent, but it’s also portable and can be automated.

You can use either VMWare or VirtualBox for this. There are 2 ways to configure a Virtual Machine:

  • Manually: install a Linux distro (Ubuntu by popular choice) and configure Apache on it
  • Use Vagrant: get an Ubuntu box up and provision Apache through Vagrant

At CODEandPROCESS, we’re against doing things manually, especially tedious tasks like installation and configuration. Vagrant is a tool to manage and configure Virtual Machines. It runs on top of Virtual Machine engines like VMWare and VirtualBox. We’ll use Vagrant with VirtualBox in our walkthrough.

Create a Vagrantfile that uses an Ubuntu box

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
end

Add in Apache provisioning with inline script

# Create a variable to hold our script content
$script = <<SCRIPT
sudo apt-get update
sudo apt-get install -y apache2
SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"

  ### Provision Apache
  # set up port 8080 on host machine that we can reach Apache
  config.vm.network "forwarded_port", guest: 80, host: 8080
  # run the script inside the VM
  config.vm.provision "shell", inline: $script
end

Finally, link our site/app code on the host machine to the VM

# Create a variable to hold our script content
$script = <<SCRIPT
sudo apt-get update
sudo apt-get install -y apache2
SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"

  ### Provision Apache
  # set up the port that Apache will use
  config.vm.network "forwarded_port", guest: 80, host: 8080
  # run the script inside the VM
  config.vm.provision "shell", inline: $script
  
  ### Link host files to VM
  config.vm.synced_folder "/path/to/site-app/built/dist", "/var/www/html"
end

/var/www/html is the Apache document-root directory inside the VM.

/path/to/site-app/built/dist is a folder on your host machine. Don’t point it at your development source code folder. This should be where you have built distribution files from your site/app.

The distribution version of your development site/app is now accessible at http://localhost:8080 from the local host machine, or at http://192.168.1.100:8080 (or whatever the LAN IP of your machine is) from other devices.

OPTION 3: RUN APACHE/NGINX ON DOCKER

To be continued.

Leave a Comment