DEV Community

Locahl
Locahl

Posted on

How to switch local and staging domains with the hosts file

You want shop.test on localhost during the day, then the real client domain pointed at staging, then maybe the same domain pointed at a new server before DNS moves.

You do not need dnsmasq for that. You need a clean way to switch mappings without leaving three conflicting lines in /etc/hosts.

Why one big hosts file fails

After a few months it often looks like this:

127.0.0.1   shop.test
127.0.0.1   api.shop.test
# 203.0.113.10  www.client.com
10.0.0.5    www.client.com
127.0.0.1   www.client.com
Enter fullscreen mode Exit fullscreen mode

Same hostname, several intentions. The browser will not tell you which line won. It just resolves something.

Comments help for a day. They do not help when you are tired and switching contexts.

Use profiles instead of comments

Keep separate files. Only one is active at a time for a given hostname.

Example layout:

~/dev/hosts-profiles/
  local
  staging
  cutover
Enter fullscreen mode Exit fullscreen mode

local

127.0.0.1   shop.test
127.0.0.1   api.shop.test
127.0.0.1   admin.shop.test
Enter fullscreen mode Exit fullscreen mode

staging

203.0.113.40   www.client.com
203.0.113.40   api.client.com
Enter fullscreen mode Exit fullscreen mode

cutover (pre-DNS migration test)

198.51.100.20   www.client.com
198.51.100.20   api.client.com
Enter fullscreen mode Exit fullscreen mode

Apply a profile

macOS / Linux:

PROFILE=staging
sudo cp /etc/hosts "/etc/hosts.bak.$(date +%Y%m%d-%H%M%S)"
sudo cp ~/dev/hosts-profiles/$PROFILE /etc/hosts
Enter fullscreen mode Exit fullscreen mode

Then flush DNS for your OS.

Windows: same idea. Keep profile files, back up the live hosts file, copy the profile over:

C:\Windows\System32\drivers\etc\hosts
Enter fullscreen mode Exit fullscreen mode

Then:

ipconfig /flushdns
Enter fullscreen mode Exit fullscreen mode

Small bash helper

#!/usr/bin/env bash
set -euo pipefail
PROFILE="${1:?usage: hosts-use <profile>}"
SRC="$HOME/dev/hosts-profiles/$PROFILE"
[[ -f "$SRC" ]] || { echo "missing $SRC"; exit 1; }

sudo cp /etc/hosts "/etc/hosts.bak.$(date +%Y%m%d-%H%M%S)"
sudo cp "$SRC" /etc/hosts

# macOS. Swap this block on Windows/Linux.
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
echo "Active hosts profile: $PROFILE"
Enter fullscreen mode Exit fullscreen mode

Usage:

./hosts-use local
./hosts-use staging
Enter fullscreen mode Exit fullscreen mode

Optional: base file + project overlay

If you want personal localhost names plus project-specific domains:

~/dev/hosts-profiles/
  _base
  project-shop-local
  project-shop-staging
Enter fullscreen mode Exit fullscreen mode

Apply with:

cat ~/dev/hosts-profiles/_base \
    ~/dev/hosts-profiles/project-shop-staging \
  | sudo tee /etc/hosts >/dev/null
Enter fullscreen mode Exit fullscreen mode

Keep _base small. Put production hostnames only in the project overlay so they are easy to turn off.

Pre-DNS cutover checklist

This is one of the best uses of hosts:

  1. Put the production hostnames on the new server IP in a cutover profile
  2. Apply the profile and flush DNS
  3. Test login, cookies, HTTPS, redirects, anything that depends on the Host header
  4. Switch back when you are done

Write the rollback next to the migration checklist. You will want it on cutover night.

Docker caveat

Hosts on your laptop affect the browser on your laptop.

Processes inside containers usually use Docker DNS, not your host /etc/hosts.

  • Browser to shop.test on the host: host hosts file
  • Container to another container: Compose service names or extra_hosts

Do not debug the wrong layer.

After every switch

# What does the OS resolve?
getent hosts www.client.com
# macOS alternative:
# dscacheutil -q host -a name www.client.com

# What is in the file?
grep -n "www.client.com" /etc/hosts
Enter fullscreen mode Exit fullscreen mode

If the terminal IP is wrong, fix hosts first. Do not dig into the app yet.

When hosts profiles stop being enough

Move to dnsmasq, CoreDNS, or company DNS when you need:

  • lots of wildcards
  • many services added every week
  • one shared dynamic map for a whole team

Until then, separate profile files beat a single commented hosts file.

Start with three files

  1. local for your .test domains
  2. staging for client staging IPs
  3. cutover left empty until migration week

Switch the whole file, flush DNS, verify in the terminal. That is the whole method.

Top comments (0)