{"id":2174,"date":"2024-04-27T23:29:00","date_gmt":"2024-04-27T15:29:00","guid":{"rendered":"https:\/\/pjq.me\/?p=2174"},"modified":"2024-04-27T23:29:01","modified_gmt":"2024-04-27T15:29:01","slug":"cloudflare-ddns-update-shell-script","status":"publish","type":"post","link":"https:\/\/pjq.me\/?p=2174","title":{"rendered":"Cloudflare ddns update shell script"},"content":{"rendered":"\n<p>I am running my NAS at home, and it has the public IP, but the IP will be changed randomly, so I need to bind it to the subdomain in the Cloudflare, so I can visit it even the IP changed. So this shell script is using to update the A Record in the DNS Recording.<\/p>\n\n\n\n<p>The script is post to the github as well<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>https:\/\/gist.github.com\/pjq\/80fb9444a623b9540b0a48a14f202a41<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\n# CHANGE THESE\nauth_email=\"xxxxx@gmail.com\"\nauth_key=\"xxxxxxxx\" # found in cloudflare account settings\nzone_name=\"xxxxx\"\nsub_domains=(\"sub1\" \"sub2\")\nzone_id=\"your_zone_id\"\n\n# MAYBE CHANGE THESE\nexport HTTP_PROXY=\"\"\nexport HTTPS_PROXY=\"\"\n\nip_file=\"ip.txt\"\nlog_file=\"cloudflare.log\"\n\n# Fetch IP Address\nget_ip() {\n    curl --noproxy '*' -s http:\/\/ipv4.icanhazip.com\n}\n\n# Log function for output and date\nlog() {\n    if &#91; \"$1\" ]; then\n        echo -e \"&#91;$(date)] - $1\" >> $log_file\n    fi\n}\n\n# Check for changes in IP\ncheck_ip() {\n    local ip=$1\n    if &#91; ${ip} == \"165.227.51.176\" ];then\n        log \"It's the proxied IP address, exit.\"\n        exit 0\n    fi\n\n    if &#91; -f $ip_file ]; then\n        old_ip=$(cat $ip_file)\n        if &#91; $ip == $old_ip ]; then\n            log \"IP has not changed.\"\n            exit 0\n        fi\n    fi\n}\n\n# Modified get_identifiers function to handle separate identifier files for each subdomain\nget_identifiers() {\n    local sub_domain=$1\n    local id_file=\"${sub_domain}_cloudflare.ids\"  # Separate file for each subdomain\n    local record_name=\"${sub_domain}.${zone_name}\"\n    local zone_identifier=\n    local record_identifier=\n\n    if &#91; -f $id_file ] &amp;&amp; &#91; $(wc -l $id_file | cut -d \" \" -f 1) == 2 ]; then\n        zone_identifier=$(head -1 $id_file)\n        record_identifier=$(tail -1 $id_file)\n    else\n        zone_identifier=$(curl -s -X GET \"https:\/\/api.cloudflare.com\/client\/v4\/zones?name=$zone_name\" -H \"X-Auth-Email: $auth_email\" -H \"Authorization: Bearer $auth_key\" -H \"Content-Type: application\/json\" | grep -Po '(?&lt;=\"id\":\")&#91;^\"]*' | head -1 )\n        record_identifier=$(curl -s -X GET \"https:\/\/api.cloudflare.com\/client\/v4\/zones\/$zone_identifier\/dns_records?name=$record_name\" -H \"X-Auth-Email: $auth_email\" -H \"Authorization: Bearer $auth_key\" -H \"Content-Type: application\/json\"  | grep -Po '(?&lt;=\"id\":\")&#91;^\"]*')\n        echo \"$zone_identifier\" > $id_file\n        echo \"$record_identifier\" >> $id_file\n    fi\n\n    log \"Fetched identifiers for $sub_domain - Zone ID: $zone_identifier, Record ID: $record_identifier\"\n    echo $zone_identifier $record_identifier\n}\n\n# Update Cloudflare record\nupdate_record() {\n    local zone_identifier=$1\n    local record_identifier=$2\n    local ip=$3\n    local sub_domain=$4\n    local record_name=\"${sub_domain}.${zone_name}\"\n\n    update=$(curl -s -X PUT \"https:\/\/api.cloudflare.com\/client\/v4\/zones\/$zone_identifier\/dns_records\/$record_identifier\" -H \"X-Auth-Email: $auth_email\" -H \"Authorization: Bearer $auth_key\" -H \"Content-Type: application\/json\" --data \"{\\\"id\\\":\\\"$zone_identifier\\\",\\\"type\\\":\\\"A\\\",\\\"name\\\":\\\"$record_name\\\",\\\"content\\\":\\\"$ip\\\"}\")\n\n    if &#91;&#91; $update == *\"\\\"success\\\":false\"* ]]; then\n        message=\"API UPDATE FAILED for $sub_domain. DUMPING RESULTS:\\n$update\"\n        log \"$message\"\n        echo -e \"$message\"\n        exit 1\n    else\n        message=\"IP changed to: $ip for $sub_domain\"\n        echo \"$ip\" > $ip_file\n        log \"$message\"\n        echo \"$message\"\n    fi\n}\n\n# Script execution starts here\nlog \"Check Initiated\"\nip=$(get_ip)\n\ncheck_ip $ip\n\nfor sub_domain in \"${sub_domains&#91;@]}\"; do\n    log \"Processing $sub_domain\"\n    identifiers=($(get_identifiers $sub_domain))\n    update_record ${identifiers&#91;0]} ${identifiers&#91;1]} $ip $sub_domain\ndone<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I am running my NAS at home, and it has the public IP, but the IP will be changed randomly, so I need to bind it to the subdomain in the Cloudflare, so I can visit it even the IP<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2174","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cloudflare ddns update shell script - Jianqing&#039;s Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/pjq.me\/?p=2174\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cloudflare ddns update shell script - Jianqing&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"I am running my NAS at home, and it has the public IP, but the IP will be changed randomly, so I need to bind it to the subdomain in the Cloudflare, so I can visit it even the IP\" \/>\n<meta property=\"og:url\" content=\"https:\/\/pjq.me\/?p=2174\" \/>\n<meta property=\"og:site_name\" content=\"Jianqing&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-04-27T15:29:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-27T15:29:01+00:00\" \/>\n<meta name=\"author\" content=\"pengjianqing\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"pengjianqing\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/pjq.me\/?p=2174#article\",\"isPartOf\":{\"@id\":\"https:\/\/pjq.me\/?p=2174\"},\"author\":{\"name\":\"pengjianqing\",\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60\"},\"headline\":\"Cloudflare ddns update shell script\",\"datePublished\":\"2024-04-27T15:29:00+00:00\",\"dateModified\":\"2024-04-27T15:29:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/pjq.me\/?p=2174\"},\"wordCount\":83,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/pjq.me\/?p=2174#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/pjq.me\/?p=2174\",\"url\":\"https:\/\/pjq.me\/?p=2174\",\"name\":\"Cloudflare ddns update shell script - Jianqing&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\/\/pjq.me\/#website\"},\"datePublished\":\"2024-04-27T15:29:00+00:00\",\"dateModified\":\"2024-04-27T15:29:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/pjq.me\/?p=2174#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/pjq.me\/?p=2174\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/pjq.me\/?p=2174#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/pjq.me\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cloudflare ddns update shell script\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/pjq.me\/#website\",\"url\":\"https:\/\/pjq.me\/\",\"name\":\"Jianqing&#039;s Blog\",\"description\":\"Thoughts and Future\",\"publisher\":{\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/pjq.me\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60\",\"name\":\"pengjianqing\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/pjq.me\/wp-content\/uploads\/2021\/12\/Screen-Shot-2021-12-02-at-6.10.58-PM.png\",\"contentUrl\":\"https:\/\/pjq.me\/wp-content\/uploads\/2021\/12\/Screen-Shot-2021-12-02-at-6.10.58-PM.png\",\"width\":460,\"height\":752,\"caption\":\"pengjianqing\"},\"logo\":{\"@id\":\"https:\/\/pjq.me\/#\/schema\/person\/image\/\"},\"url\":\"https:\/\/pjq.me\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cloudflare ddns update shell script - Jianqing&#039;s Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/pjq.me\/?p=2174","og_locale":"en_US","og_type":"article","og_title":"Cloudflare ddns update shell script - Jianqing&#039;s Blog","og_description":"I am running my NAS at home, and it has the public IP, but the IP will be changed randomly, so I need to bind it to the subdomain in the Cloudflare, so I can visit it even the IP","og_url":"https:\/\/pjq.me\/?p=2174","og_site_name":"Jianqing&#039;s Blog","article_published_time":"2024-04-27T15:29:00+00:00","article_modified_time":"2024-04-27T15:29:01+00:00","author":"pengjianqing","twitter_card":"summary_large_image","twitter_misc":{"Written by":"pengjianqing","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/pjq.me\/?p=2174#article","isPartOf":{"@id":"https:\/\/pjq.me\/?p=2174"},"author":{"name":"pengjianqing","@id":"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60"},"headline":"Cloudflare ddns update shell script","datePublished":"2024-04-27T15:29:00+00:00","dateModified":"2024-04-27T15:29:01+00:00","mainEntityOfPage":{"@id":"https:\/\/pjq.me\/?p=2174"},"wordCount":83,"commentCount":0,"publisher":{"@id":"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/pjq.me\/?p=2174#respond"]}]},{"@type":"WebPage","@id":"https:\/\/pjq.me\/?p=2174","url":"https:\/\/pjq.me\/?p=2174","name":"Cloudflare ddns update shell script - Jianqing&#039;s Blog","isPartOf":{"@id":"https:\/\/pjq.me\/#website"},"datePublished":"2024-04-27T15:29:00+00:00","dateModified":"2024-04-27T15:29:01+00:00","breadcrumb":{"@id":"https:\/\/pjq.me\/?p=2174#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/pjq.me\/?p=2174"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/pjq.me\/?p=2174#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/pjq.me\/"},{"@type":"ListItem","position":2,"name":"Cloudflare ddns update shell script"}]},{"@type":"WebSite","@id":"https:\/\/pjq.me\/#website","url":"https:\/\/pjq.me\/","name":"Jianqing&#039;s Blog","description":"Thoughts and Future","publisher":{"@id":"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pjq.me\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/pjq.me\/#\/schema\/person\/0eb1e72d1e69fbbd9b5c0bfd8e2aae60","name":"pengjianqing","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/pjq.me\/#\/schema\/person\/image\/","url":"https:\/\/pjq.me\/wp-content\/uploads\/2021\/12\/Screen-Shot-2021-12-02-at-6.10.58-PM.png","contentUrl":"https:\/\/pjq.me\/wp-content\/uploads\/2021\/12\/Screen-Shot-2021-12-02-at-6.10.58-PM.png","width":460,"height":752,"caption":"pengjianqing"},"logo":{"@id":"https:\/\/pjq.me\/#\/schema\/person\/image\/"},"url":"https:\/\/pjq.me\/?author=1"}]}},"views":1403,"_links":{"self":[{"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/posts\/2174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pjq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2174"}],"version-history":[{"count":2,"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/posts\/2174\/revisions"}],"predecessor-version":[{"id":2176,"href":"https:\/\/pjq.me\/index.php?rest_route=\/wp\/v2\/posts\/2174\/revisions\/2176"}],"wp:attachment":[{"href":"https:\/\/pjq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pjq.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pjq.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}