Skip to content

Instantly share code, notes, and snippets.

@gengue
Last active July 3, 2025 09:18
Show Gist options
  • Save gengue/2336a4f207e9c5a13926c5f965ad6ce0 to your computer and use it in GitHub Desktop.
Save gengue/2336a4f207e9c5a13926c5f965ad6ce0 to your computer and use it in GitHub Desktop.
Add local domains in MacOS
#!/bin/bash
# A script to add or remove local domains from the /etc/hosts file and
# optionally manage locally-trusted SSL certificates using mkcert.
# --- Configuration ---
HOSTS_FILE="/etc/hosts"
IP_ADDRESS="127.0.0.1"
# --- Help Function ---
show_help() {
echo "Usage: sudo ./local-domain <command> [options] <domain>"
echo ""
echo "Commands:"
echo " add (default) Adds a domain to your /etc/hosts file."
echo " remove Removes a domain from your /etc/hosts file."
echo " help, -h, --help Show this help message."
echo ""
echo "Options for 'add':"
echo " --https Generate a locally-trusted SSL certificate for the domain."
echo " Certs are saved in 'certs/<domain>/'."
echo ""
echo "Options for 'remove':"
echo " --with-certs Also remove the associated SSL certificate directory."
echo ""
echo "Examples:"
echo " # Add a domain (add command is optional)"
echo " sudo ./local-domain my-app.local"
echo " sudo ./local-domain add my-app.local"
echo ""
echo " # Add a domain and generate an SSL certificate"
echo " sudo ./local-domain add --https my-app.local"
echo ""
echo " # Remove a domain"
echo " sudo ./local-domain remove my-app.local"
echo ""
echo " # Remove a domain and its certificates"
echo " sudo ./local-domain remove --with-certs my-app.local"
}
# --- Command and Argument Parsing ---
COMMAND="add" # Default command
if [[ "$1" == "add" || "$1" == "remove" || "$1" == "help" || "$1" == "-h" || "$1" == "--help" ]]; then
COMMAND=$1
shift
fi
if [[ "$COMMAND" == "help" || "$COMMAND" == "-h" || "$COMMAND" == "--help" ]]; then
show_help
exit 0
fi
HTTPS_ENABLED=false
WITH_CERTS=false
DOMAIN=""
while (( "$#" )); do
case "$1" in
--https)
HTTPS_ENABLED=true
shift
;;
--with-certs)
WITH_CERTS=true
shift
;;
-*)
echo "Error: Unsupported flag $1" >&2
show_help
exit 1
;;
*)
if [ -n "$DOMAIN" ]; then
echo "Error: Please specify only one domain." >&2
show_help
exit 1
fi
DOMAIN=$1
shift
;;
esac
done
# --- Script Logic ---
# 1. Check for root privileges
if [ "$EUID" -ne 0 ]; then
echo "❌ This script must be run with sudo."
echo " Run './local-domain --help' for usage instructions."
exit 1
fi
# 2. Check for domain argument
if [ -z "$DOMAIN" ]; then
echo "❌ No domain provided for command '$COMMAND'."
show_help
exit 1
fi
# --- Function Definitions ---
add_domain() {
# Handle HTTPS setup if requested
if [ "$HTTPS_ENABLED" = true ]; then
if ! command -v mkcert &> /dev/null; then
echo "❌ 'mkcert' is not installed. Please install it first (e.g., 'brew install mkcert')."
exit 1
fi
ORIGINAL_USER=$SUDO_USER
if [ -z "$ORIGINAL_USER" ]; then
echo "❌ Could not determine the original user from \$SUDO_USER. Cannot run mkcert."
exit 1
fi
echo "🚀 HTTPS option enabled. Generating certificate for '$DOMAIN'..."
echo " Ensuring local CA is installed for user '$ORIGINAL_USER'..."
sudo -u "$ORIGINAL_USER" mkcert -install
CERT_DIR="certs/$DOMAIN"
echo " Creating certificate directory: $CERT_DIR"
sudo -u "$ORIGINAL_USER" mkdir -p "$CERT_DIR"
echo " Generating certificate and key..."
sudo -u "$ORIGINAL_USER" mkcert -key-file "$CERT_DIR/key.pem" -cert-file "$CERT_DIR/cert.pem" "$DOMAIN"
echo "✅ Certificate and key created in '$CERT_DIR'."
fi
# Add domain to hosts file
if grep -q -E "^\s*$IP_ADDRESS\s+.*\b$DOMAIN\b" "$HOSTS_FILE"; then
echo "✅ Domain '$DOMAIN' already exists in $HOSTS_FILE."
else
echo "Editing $HOSTS_FILE to add '$DOMAIN'..."
echo "$IP_ADDRESS $DOMAIN" >> "$HOSTS_FILE"
echo "✅ Domain '$DOMAIN' added to $HOSTS_FILE."
fi
}
remove_domain() {
# Remove domain from hosts file
if grep -q -E "^\s*$IP_ADDRESS\s+.*\b$DOMAIN\b" "$HOSTS_FILE"; then
echo "Editing $HOSTS_FILE to remove '$DOMAIN'..."
# Use sed to delete the line containing the domain. Creates a backup file.
sed -i.bak "/\b$DOMAIN\b/d" "$HOSTS_FILE"
echo "✅ Domain '$DOMAIN' removed from $HOSTS_FILE."
else
echo "ℹ️ Domain '$DOMAIN' not found in $HOSTS_FILE."
fi
# Handle certificate removal if requested
if [ "$WITH_CERTS" = true ]; then
CERT_DIR="certs/$DOMAIN"
if [ -d "$CERT_DIR" ]; then
echo "Removing certificate directory: $CERT_DIR"
rm -rf "$CERT_DIR"
echo "✅ Certificate directory removed."
else
echo "ℹ️ Certificate directory '$CERT_DIR' not found."
fi
fi
}
# --- Main Execution ---
case "$COMMAND" in
add)
add_domain
;;
remove)
remove_domain
;;
esac
# Flush DNS cache
echo "Flushing DNS cache..."
dscacheutil -flushcache >/dev/null 2>&1
killall -HUP mDNSResponder >/dev/null 2>&1
echo "✅ Successfully processed domain '$DOMAIN'."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment