Last active
July 3, 2025 09:18
-
-
Save gengue/2336a4f207e9c5a13926c5f965ad6ce0 to your computer and use it in GitHub Desktop.
Add local domains in MacOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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