├── README.md └── localhost /README.md: -------------------------------------------------------------------------------- 1 | ### localhost subdomains 2 | 3 | Map subdomains of localhost to ports. 4 | 5 | ``` 6 | hello.localhost → localhost:1234 7 | db.localhost → localhost:5432 8 | printer.localhost → localhost:9100 9 | ``` 10 | 11 | This is a direct continuation of Charles' process: 12 | https://inclouds.space/localhost-domains 13 | 14 | For this to work, we'll need to do two things: 15 | 1. redirect `*.localhost` to `127.0.0.1` 16 | 2. have a server on `127.0.0.1` that reverse proxies to the right port 17 | 18 | This was tested on Ubuntu 22. Your mileage may vary. 19 | 20 | #### redirect with `dnsmasq` 21 | 22 | _NB: You might not actually need this, `systemd-resolved` might already be doing 23 | the redirecting! See [hacker news](https://news.ycombinator.com/item?id=43644434)_. 24 | 25 | To get `dnsmasq` to redirect all subdomains (*.localhost) to 127.0.0.1, install 26 | it (via brew or apt) and then configure it as follows: 27 | 28 | ``` 29 | echo 'port=5353' | sudo tee -a /etc/dnsmasq.conf 30 | echo 'address=/localhost/127.0.0.1' | sudo tee -a /etc/dnsmasq.conf 31 | sudo systemctl restart dnsmasq 32 | ``` 33 | 34 | NB: we use port 5353 to avoid conflicts with the `systemd-resolved` 35 | 36 | Next, to further avoid conflicts with `systemd-resolved` add `nameserver 37 | 127.0.0.1` to the top of `/etc/resolv.conf` so that `dnsmasq` becomes the 38 | primary DNS resolver. 39 | 40 | #### serve with `caddy` + `localhost` 41 | 42 | Then, we use `caddy` to direct subdomains to particular ports. 43 | 44 | You can do this by writing a Caddyfile by hand. I've written a little bash 45 | script with Claude's help to do this for me. You can add the bash script 46 | `localhost` to your `PATH`. In my case, I added the following line to my 47 | `.zshrc`. 48 | 49 | ``` 50 | export PATH="$PATH:$HOME/dev/localhost" 51 | ``` 52 | 53 | Now you can `localhost add hello 8000` or `localhost remove`. 54 | 55 | #### testing it out 56 | 57 | Run a local server! 58 | ``` 59 | echo 'hello.localhost!' > index.html 60 | python3 -m http.server 1234 61 | ``` 62 | 63 | Name the port! 64 | ``` 65 | localhost add hello 1234 66 | ``` 67 | 68 | Now open `hello.localhost` in your browser! 69 | -------------------------------------------------------------------------------- /localhost: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | CADDYFILE="$SCRIPT_DIR/Caddyfile" 5 | 6 | add_subdomain() { 7 | local subdomain=$1 8 | local port=$2 9 | 10 | cat >> $CADDYFILE << EOF 11 | 12 | $subdomain.localhost { 13 | reverse_proxy localhost:$port 14 | tls internal 15 | encode gzip zstd 16 | } 17 | 18 | EOF 19 | echo "Added configuration for $subdomain.localhost pointing to localhost:$port" 20 | } 21 | 22 | remove_by_name() { 23 | local subdomain=$1 24 | 25 | sed -i "/^$subdomain\.localhost {/,/^}/d" $CADDYFILE 26 | echo "Removed configuration for $subdomain.localhost" 27 | } 28 | 29 | remove_by_port() { 30 | local port=$1 31 | local subdomain 32 | 33 | # Find subdomain matching this port 34 | subdomain=$(grep -B1 "reverse_proxy localhost:$port" $CADDYFILE | grep -o '[^ ]*\.localhost' | sed 's/\.localhost//') 35 | 36 | if [ -n "$subdomain" ]; then 37 | remove_by_name "$subdomain" 38 | else 39 | echo "No configuration found for port $port" 40 | fi 41 | } 42 | 43 | reload_caddy() { 44 | if pgrep -x "caddy" > /dev/null; then 45 | echo "Reloading Caddy configuration..." 46 | caddy reload --config "$CADDYFILE" 47 | else 48 | echo "Starting Caddy..." 49 | caddy start --config "$CADDYFILE" 50 | fi 51 | } 52 | 53 | case "$1" in 54 | add) 55 | if [ $# -ne 3 ]; then 56 | echo "Usage: $(basename $0) add " 57 | exit 1 58 | fi 59 | add_subdomain "$2" "$3" 60 | reload_caddy 61 | ;; 62 | remove) 63 | if [ $# -ne 2 ]; then 64 | echo "Usage: $(basename $0) remove " 65 | exit 1 66 | fi 67 | # Check if the argument is a number (port) or string (subdomain) 68 | if [[ "$2" =~ ^[0-9]+$ ]]; then 69 | remove_by_port "$2" 70 | else 71 | remove_by_name "$2" 72 | fi 73 | reload_caddy 74 | ;; 75 | list) 76 | cat $CADDYFILE 77 | ;; 78 | *) 79 | echo "Usage: $(basename $0) add " 80 | echo " $(basename $0) remove " 81 | echo " $(basename $0) list" 82 | exit 1 83 | ;; 84 | esac 85 | --------------------------------------------------------------------------------