From d277b15c23d7a9e8702e3debaa4a30c19a189867 Mon Sep 17 00:00:00 2001 From: Ewan Croft Date: Sat, 14 Jun 2025 12:26:53 +0100 Subject: [PATCH] feat(duckdns): enhance setup script with manual macOS option and improved logging --- scripts/setup_duckdns.sh | 157 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 3 deletions(-) diff --git a/scripts/setup_duckdns.sh b/scripts/setup_duckdns.sh index 699ae16..7bae5c9 100755 --- a/scripts/setup_duckdns.sh +++ b/scripts/setup_duckdns.sh @@ -115,7 +115,42 @@ setup_linux_cron() { cat > "$script_path" << EOF #!/bin/bash -echo url=\" https://www.duckdns.org/update?domains=$DOMAIN&token=$TOKEN&ip=\" | curl -k -o $log_path -K - + +# DuckDNS Update Script +# Auto-generated by DuckDNS setup script + +DOMAIN="$DOMAIN" +TOKEN="$TOKEN" +LOG_FILE="$log_path" + +# Function to log messages +log_message() { + echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE" +} + +# Function to get IP address +get_ip_address() { + # Auto-detect public IP + curl -s https://ipv4.icanhazip.com/ || curl -s https://api.ipify.org || curl -s https://checkip.amazonaws.com/ +} + +# Get current IP +CURRENT_IP=\$(get_ip_address) + +if [[ -z "\$CURRENT_IP" ]]; then + log_message "ERROR: Failed to determine IP address" + exit 1 +fi + +# Update DuckDNS +RESPONSE=\$(curl -s "https://www.duckdns.org/update?domains=\$DOMAIN&token=\$TOKEN&ip=\$CURRENT_IP") + +if [[ "\$RESPONSE" == "OK" ]]; then + log_message "SUCCESS: Updated \$DOMAIN.duckdns.org to \$CURRENT_IP" +else + log_message "ERROR: Failed to update DuckDNS. Response: \$RESPONSE" + exit 1 +fi EOF print_info "Making duck.sh executable..." @@ -128,7 +163,7 @@ EOF if bash "$script_path"; then print_success "DuckDNS update test successful!" print_info "Log content:" - cat "$log_path" + cat "$log_path" 2>/dev/null || print_info "Log file will be created on first run." else print_error "DuckDNS update test failed. Check $log_path for details." fi @@ -136,6 +171,106 @@ EOF print_success "DuckDNS setup for Linux using Cron completed successfully!" } +# Function for macOS manual setup (alternative to Homebrew) +setup_macos_manual() { + print_info "Setting up DuckDNS for macOS using manual script and launchd..." + echo + + if ! command -v curl &> /dev/null; then + print_error "Curl is not installed. Please install curl first." + exit 1 + fi + + print_info "Creating .duckdns directory and script..." + mkdir -p "$HOME/.duckdns" + + local script_path="$HOME/.duckdns/duck.sh" + local log_path="$HOME/.duckdns/duck.log" + + cat > "$script_path" << EOF +#!/bin/bash + +# DuckDNS Update Script +# Auto-generated by DuckDNS setup script + +DOMAIN="$DOMAIN" +TOKEN="$TOKEN" +LOG_FILE="$log_path" + +# Function to log messages +log_message() { + echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE" +} + +# Function to get IP address +get_ip_address() { + # Auto-detect public IP + curl -s https://ipv4.icanhazip.com/ || curl -s https://api.ipify.org || curl -s https://checkip.amazonaws.com/ +} + +# Get current IP +CURRENT_IP=\$(get_ip_address) + +if [[ -z "\$CURRENT_IP" ]]; then + log_message "ERROR: Failed to determine IP address" + exit 1 +fi + +# Update DuckDNS +RESPONSE=\$(curl -s "https://www.duckdns.org/update?domains=\$DOMAIN&token=\$TOKEN&ip=\$CURRENT_IP") + +if [[ "\$RESPONSE" == "OK" ]]; then + log_message "SUCCESS: Updated \$DOMAIN.duckdns.org to \$CURRENT_IP" +else + log_message "ERROR: Failed to update DuckDNS. Response: \$RESPONSE" + exit 1 +fi +EOF + + print_info "Making duck.sh executable..." + chmod 700 "$script_path" || { print_error "Failed to make duck.sh executable."; exit 1; } + + print_info "Creating launchd plist..." + local plist_path="$HOME/Library/LaunchAgents/com.duckdns.updater.plist" + cat > "$plist_path" << EOF + + + + + Label + com.duckdns.updater + ProgramArguments + + $script_path + + StartInterval + 300 + RunAtLoad + + StandardOutPath + /dev/null + StandardErrorPath + /dev/null + + +EOF + + print_info "Loading launchd service..." + launchctl load "$plist_path" || { print_error "Failed to load launchd service."; exit 1; } + + print_info "Testing the script..." + if bash "$script_path"; then + print_success "DuckDNS update test successful!" + print_info "Log content:" + cat "$log_path" 2>/dev/null || print_info "Log file will be created on first run." + else + print_error "DuckDNS update test failed. Check $log_path for details." + fi + + print_success "DuckDNS setup for macOS using manual script completed successfully!" + print_info "The service will run every 5 minutes automatically." +} + # Main function main() { print_info "DuckDNS Setup Script" @@ -151,7 +286,23 @@ main() { case "$OS" in "macOS") - setup_macos_homebrew + echo + print_info "Choose setup method for macOS:" + echo "1. Homebrew (recommended)" + echo "2. Manual script with launchd" + read -p "Enter your choice (1 or 2): " choice + case "$choice" in + 1) + setup_macos_homebrew + ;; + 2) + setup_macos_manual + ;; + *) + print_error "Invalid choice. Please run the script again." + exit 1 + ;; + esac ;; "Linux") setup_linux_cron -- 2.51.2