Skip to content

Instantly share code, notes, and snippets.

@Igloczek
Last active December 1, 2025 15:23
Show Gist options
  • Select an option

  • Save Igloczek/85ec5914dd56265554672b04dd2bc7ee to your computer and use it in GitHub Desktop.

Select an option

Save Igloczek/85ec5914dd56265554672b04dd2bc7ee to your computer and use it in GitHub Desktop.
local reverse proxy setup guide

Local Dev Proxy

Automated local development proxy using Caddy. Handles HTTPS (.test domains) and HMR automatically.

Setup (New Device)

1. Install Caddy

brew install caddy

2. Install & Configure DNSmasq (Optional but Recommended)

This enables wildcard DNS so all .test domains point to localhost automatically (no manual /etc/hosts editing).

# Install DNSmasq
brew install dnsmasq

# Configure it to route .test to 127.0.0.1
echo 'address=/.test/127.0.0.1' > $(brew --prefix)/etc/dnsmasq.conf

# Start the service
sudo brew services start dnsmasq

# Register the resolver with macOS
sudo mkdir -p /etc/resolver
sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'

3. Install the Caddy Service (Auto-Reloading)

Run the following commands to set up the launchd agent that watches for config changes:

# Create log directory first
mkdir -p "$(brew --prefix)/var/log"

# Generate plist with expanded paths
cat <<EOF > ~/Library/LaunchAgents/com.caddy.local-proxy.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.caddy.local-proxy</string>
    <key>ProgramArguments</key>
    <array>
        <string>$(which caddy)</string>
        <string>run</string>
        <string>--config</string>
        <string>$(brew --prefix)/etc/Caddyfile</string>
        <string>--watch</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>$(brew --prefix)/var/log/caddy.log</string>
    <key>StandardOutPath</key>
    <string>$(brew --prefix)/var/log/caddy.log</string>
</dict>
</plist>
EOF

# Create the central config
echo -e "{\n    local_certs\n}\nimport ${HOME}/Sites/*/Caddyfile" > $(brew --prefix)/etc/Caddyfile

# Load the service
launchctl load ~/Library/LaunchAgents/com.caddy.local-proxy.plist

4. Trust the Root CA

Caddy needs to be running first to generate the CA, then you trust it:

caddy start --config $(brew --prefix)/etc/Caddyfile
sudo caddy trust
caddy stop

Note: If you see permission errors in logs, fix ownership of Caddy's data folder:

sudo chown -R $(whoami) ~/Library/Application\ Support/Caddy

Adding a New Project

  1. Create ~/Sites/my-project/Caddyfile:

    my-project.test {
      reverse_proxy localhost:3000
    }
  2. That's it. Caddy automatically detects the new file, and DNSmasq routes the domain. (Visit https://my-project.test)

Troubleshooting

  • Check Logs: tail -f /usr/local/var/log/caddy.log
  • Restart Service: launchctl kickstart -k gui/$(id -u)/com.caddy.local-proxy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment