| @@ -0,0 +1,1275 @@ |
| 1 | #+title: How to Install NextDNS on the Unifi Dream Machine |
| 2 | #+date: 2023-12-03 |
| 3 | |
| 4 | * Overview |
| 5 | :PROPERTIES: |
| 6 | :ID: 711309AE-955D-4B2D-B716-CFD700079157 |
| 7 | :PUBDATE: 2023-12-03 Sun 22:32 |
| 8 | :END: |
| 9 | |
| 10 | I recently installed NextDNS on my Unifi Dream Machine router using the |
| 11 | [[https://github.com/nextdns/nextdns/wiki/UnifiOS][UnifiOS]] wiki page on |
| 12 | NextDNS's GitHub repository. |
| 13 | |
| 14 | As a result of this, I wanted to write down the process in case the wiki or |
| 15 | installer ever gets lost. |
| 16 | |
| 17 | * Wiki |
| 18 | :PROPERTIES: |
| 19 | :ID: 8457B7A9-AE62-448D-B092-C04759F8D468 |
| 20 | :PUBDATE: 2023-12-03 Sun 22:32 |
| 21 | :END: |
| 22 | |
| 23 | The following is copied from the wiki page linked above, with one difference in |
| 24 | the =ssh= command. |
| 25 | |
| 26 | Install instructions for Unifi Dream Machine (UDM) standard and pro routers. |
| 27 | |
| 28 | ** Install |
| 29 | :PROPERTIES: |
| 30 | :ID: 907F595C-6D53-409D-AB97-2B830D09B62E |
| 31 | :END: |
| 32 | |
| 33 | Enable SSH: |
| 34 | |
| 35 | - Go to your unifi admin interface and select your device (not the controller |
| 36 | settings, but the Dream Machine settings) |
| 37 | - Click on "Settings" at the bottom of the page |
| 38 | - Go to the "Advanced" section on the left pan |
| 39 | - Enable SSH |
| 40 | - Set a SSH password |
| 41 | |
| 42 | Connect to your router using =ssh root@xxx.xxx.xxx.xxx= with the password you |
| 43 | configured. |
| 44 | |
| 45 | Run the following command and follow the instructions: |
| 46 | |
| 47 | #+begin_src sh |
| 48 | sh -c 'sh -c "$(curl -sL https://nextdns.io/install)"' |
| 49 | #+end_src |
| 50 | |
| 51 | Note: Queries from the UDM itself won’t be routed to NextDNS nor encrypted due |
| 52 | to current system limitation. All traffic from other devices on then network |
| 53 | will. |
| 54 | |
| 55 | ** Upgrade |
| 56 | :PROPERTIES: |
| 57 | :ID: 3836C070-2C7C-456D-AB3B-15DDE60D2F99 |
| 58 | :END: |
| 59 | |
| 60 | To upgrade to the last version, simply re-run the installer above. If a new |
| 61 | version is available, the upgrade action will added to the list of possible |
| 62 | actions. |
| 63 | |
| 64 | ** Uninstall |
| 65 | :PROPERTIES: |
| 66 | :ID: DFD1BA2F-EC4E-4B5C-9CEA-098DFF0AD62F |
| 67 | :END: |
| 68 | |
| 69 | To uninstall, re-run the installer above and select "Remove" in the menu. |
| 70 | |
| 71 | ** Troubleshooting |
| 72 | :PROPERTIES: |
| 73 | :ID: 0B0F4E70-FACC-4C7C-8EB9-55398AA8476F |
| 74 | :END: |
| 75 | |
| 76 | If the installation fail, please the installer in debug mode and contact us at |
| 77 | team@nextdns.io with the transcript of the installation: |
| 78 | |
| 79 | #+begin_src sh |
| 80 | sh -c 'DEBUG=1 sh -c "$(curl -sL https://nextdns.io/install)"' |
| 81 | #+end_Ssrc |
| 82 | |
| 83 | *** Content Filtering Conflict |
| 84 | :PROPERTIES: |
| 85 | :ID: BCDD3267-4C04-45AC-BAAD-9D15F414ED4D |
| 86 | :END: |
| 87 | |
| 88 | NextDNS CLI and the UDM Content Filtering or the Ad Blocking features are |
| 89 | incompatible. If you want to use NextDNS CLI, please make sure they are |
| 90 | disabled. |
| 91 | |
| 92 | To disable Content Filtering, go to Settings > Network, then for each network, |
| 93 | set the Content Filtering feature to None |
| 94 | |
| 95 | To disable Ad Blocking, go to Settings > Application Firewall. In the General |
| 96 | tab, uncheck the Ad Blocking checkbox. |
| 97 | |
| 98 | *** APT Error |
| 99 | :PROPERTIES: |
| 100 | :ID: 83244A13-7154-475A-8193-064A1B81D3AE |
| 101 | :END: |
| 102 | |
| 103 | If you get an apt error as follow: |
| 104 | |
| 105 | #+begin_src sh |
| 106 | E: Failed to fetch http://security.debian.org/dists/stretch/updates/main/binary-arm64/Packages 404 Not Found [IP: 151.101.70.132 80] |
| 107 | #+end_src |
| 108 | |
| 109 | You may try to following: |
| 110 | |
| 111 | #+begin_src sh |
| 112 | sed -i -e 's/deb.debian.org/archive.debian.org/g' \ |
| 113 | -e 's|security.debian.org|archive.debian.org/|g' \ |
| 114 | -e '/stretch-updates/d' /etc/apt/sources.list |
| 115 | #+end_src |
| 116 | |
| 117 | * install.sh |
| 118 | :PROPERTIES: |
| 119 | :ID: 91DE0DD0-8177-4594-B067-373ABF99C343 |
| 120 | :PUBDATE: 2023-12-03 Sun 22:34 |
| 121 | :END: |
| 122 | |
| 123 | Here are the contents of the =install.sh= file used above, as of 2023-12-03: |
| 124 | |
| 125 | #+begin_src sh |
| 126 | #!/bin/sh |
| 127 | |
| 128 | main() { |
| 129 | OS=$(detect_os) |
| 130 | GOARCH=$(detect_goarch) |
| 131 | GOOS=$(detect_goos) |
| 132 | NEXTDNS_BIN=$(bin_location) |
| 133 | INSTALL_RELEASE=$(get_release) |
| 134 | |
| 135 | export NEXTDNS_INSTALLER=1 |
| 136 | |
| 137 | log_info "OS: $OS" |
| 138 | log_info "GOARCH: $GOARCH" |
| 139 | log_info "GOOS: $GOOS" |
| 140 | log_info "NEXTDNS_BIN: $NEXTDNS_BIN" |
| 141 | log_info "INSTALL_RELEASE: $INSTALL_RELEASE" |
| 142 | |
| 143 | if [ -z "$OS" ] || [ -z "$GOARCH" ] || [ -z "$GOOS" ] || [ -z "$NEXTDNS_BIN" ] || [ -z "$INSTALL_RELEASE" ]; then |
| 144 | log_error "Cannot detect running environment." |
| 145 | exit 1 |
| 146 | fi |
| 147 | |
| 148 | case "$RUN_COMMAND" in |
| 149 | install|upgrade|uninstall|configure) "$RUN_COMMAND"; exit ;; |
| 150 | esac |
| 151 | |
| 152 | while true; do |
| 153 | CURRENT_RELEASE=$(get_current_release) |
| 154 | log_debug "Start install loop with CURRENT_RELEASE=$CURRENT_RELEASE" |
| 155 | |
| 156 | if [ "$CURRENT_RELEASE" ]; then |
| 157 | if ! is_version_current; then |
| 158 | log_debug "NextDNS is out of date ($CURRENT_RELEASE != $INSTALL_RELEASE)" |
| 159 | menu \ |
| 160 | u "Upgrade NextDNS from $CURRENT_RELEASE to $INSTALL_RELEASE" upgrade \ |
| 161 | c "Configure NextDNS" configure \ |
| 162 | r "Remove NextDNS" uninstall \ |
| 163 | e "Exit" exit |
| 164 | else |
| 165 | log_debug "NextDNS is up to date ($CURRENT_RELEASE)" |
| 166 | menu \ |
| 167 | c "Configure NextDNS" configure \ |
| 168 | r "Remove NextDNS" uninstall \ |
| 169 | e "Exit" exit |
| 170 | fi |
| 171 | else |
| 172 | log_debug "NextDNS is not installed" |
| 173 | menu \ |
| 174 | i "Install NextDNS" install \ |
| 175 | e "Exit" exit |
| 176 | fi |
| 177 | done |
| 178 | } |
| 179 | |
| 180 | install() { |
| 181 | if [ "$(get_current_release)" ]; then |
| 182 | log_info "Already installed" |
| 183 | return |
| 184 | fi |
| 185 | if type=$(install_type); then |
| 186 | log_info "Installing NextDNS..." |
| 187 | log_debug "Using $type install type" |
| 188 | if "install_$type"; then |
| 189 | if [ ! -x "$NEXTDNS_BIN" ]; then |
| 190 | log_error "Installation failed: binary not installed in $NEXTDNS_BIN" |
| 191 | return 1 |
| 192 | fi |
| 193 | configure |
| 194 | post_install |
| 195 | exit 0 |
| 196 | fi |
| 197 | else |
| 198 | return $? |
| 199 | fi |
| 200 | } |
| 201 | |
| 202 | upgrade() { |
| 203 | if [ "$(get_current_release)" = "$INSTALL_RELEASE" ]; then |
| 204 | log_info "Already on the latest version" |
| 205 | return |
| 206 | fi |
| 207 | if type=$(install_type); then |
| 208 | log_info "Upgrading NextDNS..." |
| 209 | log_debug "Using $type install type" |
| 210 | "upgrade_$type" |
| 211 | else |
| 212 | return $? |
| 213 | fi |
| 214 | } |
| 215 | |
| 216 | uninstall() { |
| 217 | if type=$(install_type); then |
| 218 | log_info "Uninstalling NextDNS..." |
| 219 | log_debug "Using $type uninstall type" |
| 220 | "uninstall_$type" |
| 221 | else |
| 222 | return $? |
| 223 | fi |
| 224 | } |
| 225 | |
| 226 | precheck() { |
| 227 | if [ -e "/data/unifi" ] && [ -f "/run/dnsfilter/dnsfilter" ]; then |
| 228 | log_warn "UDM Content Filtering and/or Ad Blocking feature is enabled." |
| 229 | log_warn "Please disable it to use NextDNS." |
| 230 | log_warn "" |
| 231 | log_warn " To disable Content Filtering, go to Settings > Network." |
| 232 | log_warn " For each network, set the Content Filtering feature to None." |
| 233 | log_warn "" |
| 234 | log_warn " To disable Ad Blocking, go to Settings > Application Firewall" |
| 235 | log_warn " In the General tab, uncheck the Ad Blocking checkbox." |
| 236 | log_warn "" |
| 237 | while [ -f "/run/dnsfilter/dnsfilter" ]; do |
| 238 | sleep 1 |
| 239 | done |
| 240 | log_info "Content Filtering feature successfuly disabled." |
| 241 | fi |
| 242 | } |
| 243 | |
| 244 | configure() { |
| 245 | log_debug "Start configure" |
| 246 | precheck |
| 247 | args="" |
| 248 | add_arg() { |
| 249 | for value in $2; do |
| 250 | log_debug "Add arg -$1=$value" |
| 251 | args="$args -$1=$value" |
| 252 | done |
| 253 | } |
| 254 | add_arg_bool_ask() { |
| 255 | arg=$1 |
| 256 | msg=$2 |
| 257 | default=$3 |
| 258 | if [ -z "$default" ]; then |
| 259 | default=$(get_config_bool "$arg") |
| 260 | fi |
| 261 | # shellcheck disable=SC2046 |
| 262 | add_arg "$arg" $(ask_bool "$msg" "$default") |
| 263 | } |
| 264 | # Use profile from now on |
| 265 | add_arg profile "$(get_profile_id)" |
| 266 | |
| 267 | doc "Sending your devices name lets you filter analytics and logs by device." |
| 268 | add_arg_bool_ask report-client-info 'Report device name?' true |
| 269 | |
| 270 | case $(guess_host_type) in |
| 271 | router) |
| 272 | add_arg setup-router true |
| 273 | ;; |
| 274 | unsure) |
| 275 | doc "Accept DNS request from other network hosts." |
| 276 | if [ "$(get_config_bool setup-router)" = "true" ]; then |
| 277 | router_default=true |
| 278 | fi |
| 279 | if [ "$(ask_bool 'Setup as a router?' $router_default)" = "true" ]; then |
| 280 | add_arg setup-router true |
| 281 | fi |
| 282 | ;; |
| 283 | esac |
| 284 | |
| 285 | doc "Make NextDNS CLI cache responses. This improves latency and reduces the amount" |
| 286 | doc "of queries sent to NextDNS." |
| 287 | if [ "$(guess_host_type)" = "router" ]; then |
| 288 | doc "Note that enabling this feature will disable dnsmasq for DNS to avoid double" |
| 289 | doc "caching." |
| 290 | fi |
| 291 | if [ "$(get_config cache-size)" != "0" ]; then |
| 292 | cache_default=true |
| 293 | fi |
| 294 | if [ "$(ask_bool 'Enable caching?' $cache_default)" = "true" ]; then |
| 295 | add_arg cache-size "10MB" |
| 296 | |
| 297 | doc "Instant refresh will force low TTL on responses sent to clients so they rely" |
| 298 | doc "on CLI DNS cache. This will allow changes on your NextDNS config to be applied" |
| 299 | doc "on your LAN hosts without having to wait for their cache to expire." |
| 300 | if [ "$(get_config max-ttl)" = "5s" ]; then |
| 301 | instant_refresh_default=true |
| 302 | fi |
| 303 | if [ "$(ask_bool 'Enable instant refresh?' $instant_refresh_default)" = "true" ]; then |
| 304 | add_arg max-ttl "5s" |
| 305 | fi |
| 306 | fi |
| 307 | |
| 308 | if [ "$(guess_host_type)" != "router" ]; then |
| 309 | doc "Changes DNS settings of the host automatically when NextDNS is started." |
| 310 | doc "If you say no here, you will have to manually configure DNS to 127.0.0.1." |
| 311 | add_arg_bool_ask auto-activate 'Automatically setup local host DNS?' true |
| 312 | fi |
| 313 | # shellcheck disable=SC2086 |
| 314 | asroot "$NEXTDNS_BIN" install $args |
| 315 | } |
| 316 | |
| 317 | post_install() { |
| 318 | println |
| 319 | println "Congratulations! NextDNS is now installed." |
| 320 | println |
| 321 | println "To upgrade/uninstall, run this command again and select the appropriate option." |
| 322 | println |
| 323 | println "You can use the NextDNS command to control the daemon." |
| 324 | println "Here are a few important commands to know:" |
| 325 | println |
| 326 | println "# Start, stop, restart the daemon:" |
| 327 | println "nextdns start" |
| 328 | println "nextdns stop" |
| 329 | println "nextdns restart" |
| 330 | println |
| 331 | println "# Configure the local host to point to NextDNS or not:" |
| 332 | println "nextdns activate" |
| 333 | println "nextdns deactivate" |
| 334 | println |
| 335 | println "# Explore daemon logs:" |
| 336 | println "nextdns log" |
| 337 | println |
| 338 | println "# For more commands, use:" |
| 339 | println "nextdns help" |
| 340 | println |
| 341 | } |
| 342 | |
| 343 | install_bin() { |
| 344 | bin_path=$NEXTDNS_BIN |
| 345 | if [ "$1" ]; then |
| 346 | bin_path=$1 |
| 347 | fi |
| 348 | log_debug "Installing $INSTALL_RELEASE binary for $GOOS/$GOARCH to $bin_path" |
| 349 | case "$INSTALL_RELEASE" in |
| 350 | */*) |
| 351 | # Snapshot |
| 352 | branch=${INSTALL_RELEASE%/*} |
| 353 | hash=${INSTALL_RELEASE#*/} |
| 354 | url="https://snapshot.nextdns.io/${branch}/nextdns-${hash}_${GOOS}_${GOARCH}.tar.gz" |
| 355 | ;; |
| 356 | *) |
| 357 | url="https://github.com/nextdns/nextdns/releases/download/v${INSTALL_RELEASE}/nextdns_${INSTALL_RELEASE}_${GOOS}_${GOARCH}.tar.gz" |
| 358 | ;; |
| 359 | esac |
| 360 | log_debug "Downloading $url" |
| 361 | asroot mkdir -p "$(dirname "$bin_path")" && |
| 362 | curl -sL "$url" | asroot sh -c "tar Ozxf - nextdns > \"$bin_path\"" && |
| 363 | asroot chmod 755 "$bin_path" |
| 364 | } |
| 365 | |
| 366 | upgrade_bin() { |
| 367 | tmp=$NEXTDNS_BIN.tmp |
| 368 | if install_bin "$tmp"; then |
| 369 | asroot "$NEXTDNS_BIN" uninstall |
| 370 | asroot mv "$tmp" "$NEXTDNS_BIN" |
| 371 | asroot "$NEXTDNS_BIN" install |
| 372 | fi |
| 373 | log_debug "Removing spurious temporary install file" |
| 374 | asroot rm -rf "$tmp" |
| 375 | } |
| 376 | |
| 377 | uninstall_bin() { |
| 378 | asroot "$NEXTDNS_BIN" uninstall |
| 379 | asroot rm -f "$NEXTDNS_BIN" |
| 380 | } |
| 381 | |
| 382 | install_rpm() { |
| 383 | asroot curl -Ls https://repo.nextdns.io/nextdns.repo -o /etc/yum.repos.d/nextdns.repo && |
| 384 | asroot yum install -y nextdns |
| 385 | } |
| 386 | |
| 387 | upgrade_rpm() { |
| 388 | asroot yum update -y nextdns |
| 389 | } |
| 390 | |
| 391 | uninstall_rpm() { |
| 392 | asroot yum remove -y nextdns |
| 393 | } |
| 394 | |
| 395 | install_zypper() { |
| 396 | if asroot zypper repos | grep -q nextdns >/dev/null; then |
| 397 | echo "Repository nextdns already exists. Skipping adding repository..." |
| 398 | else |
| 399 | asroot zypper ar -f -r https://repo.nextdns.io/nextdns.repo nextdns |
| 400 | fi |
| 401 | asroot zypper refresh && asroot zypper in -y nextdns |
| 402 | } |
| 403 | |
| 404 | upgrade_zypper() { |
| 405 | asroot zypper up nextdns |
| 406 | } |
| 407 | |
| 408 | uninstall_zypper() { |
| 409 | asroot zypper remove -y nextdns |
| 410 | case $(ask_bool 'Do you want to remove the repository from the repositories list?' true) in |
| 411 | true) |
| 412 | asroot zypper removerepo nextdns |
| 413 | ;; |
| 414 | esac |
| 415 | } |
| 416 | |
| 417 | install_deb() { |
| 418 | if [ -f /etc/default/ubnt-dpkg-cache ]; then |
| 419 | # On UnifiOS 2, make sure the package is persisted over upgrades |
| 420 | sed -e '/^DPKG_CACHE_UBNT_PKGS+=" nextdns"/{:a;n;ba;q}' \ |
| 421 | -e '$aDPKG_CACHE_UBNT_PKGS+=" nextdns"' \ |
| 422 | -i /etc/default/ubnt-dpkg-cache |
| 423 | fi |
| 424 | |
| 425 | install_deb_keyring && |
| 426 | asroot sh -c 'echo "deb [signed-by=/etc/apt/keyrings/nextdns.gpg] https://repo.nextdns.io/deb stable main" > /etc/apt/sources.list.d/nextdns.list' && |
| 427 | (dpkg --compare-versions $(dpkg-query --showformat='${Version}' --show apt) ge 1.1 || |
| 428 | asroot ln -s /etc/apt/keyrings/nextdns.gpg /etc/apt/trusted.gpg.d/.) && |
| 429 | (test "$OS" = "debian" && asroot apt-get -y install apt-transport-https || true) && |
| 430 | asroot apt-get update && |
| 431 | asroot apt-get install -y nextdns |
| 432 | } |
| 433 | |
| 434 | install_deb_keyring() { |
| 435 | # Fallback on curl, some debian based distrib don't have wget while debian |
| 436 | # doesn't have curl by default. |
| 437 | asroot mkdir -p /etc/apt/keyrings |
| 438 | ( asroot wget -qO /etc/apt/keyrings/nextdns.gpg https://repo.nextdns.io/nextdns.gpg || |
| 439 | asroot curl -sfL https://repo.nextdns.io/nextdns.gpg -o /etc/apt/keyrings/nextdns.gpg ) && |
| 440 | asroot chmod 0644 /etc/apt/keyrings/nextdns.gpg |
| 441 | } |
| 442 | |
| 443 | upgrade_deb() { |
| 444 | install_deb_keyring && |
| 445 | asroot apt-get update && |
| 446 | asroot apt-get install -y nextdns |
| 447 | } |
| 448 | |
| 449 | uninstall_deb() { |
| 450 | asroot apt-get remove -y nextdns |
| 451 | } |
| 452 | |
| 453 | install_apk() { |
| 454 | repo=https://repo.nextdns.io/apk |
| 455 | asroot wget -O /etc/apk/keys/nextdns.pub https://repo.nextdns.io/nextdns.pub && |
| 456 | (grep -v $repo /etc/apk/repositories; echo $repo) | asroot tee /etc/apk/repositories >/dev/null && |
| 457 | asroot apk update && |
| 458 | asroot apk add nextdns |
| 459 | } |
| 460 | |
| 461 | upgrade_apk() { |
| 462 | asroot apk update && asroot apk upgrade nextdns |
| 463 | } |
| 464 | |
| 465 | uninstall_apk() { |
| 466 | asroot apk del nextdns |
| 467 | } |
| 468 | |
| 469 | install_arch() { |
| 470 | asroot pacman -Sy yay && |
| 471 | yay -Sy nextdns |
| 472 | } |
| 473 | |
| 474 | upgrade_arch() { |
| 475 | yay -Suy nextdns |
| 476 | } |
| 477 | |
| 478 | uninstall_arch() { |
| 479 | asroot pacman -R nextdns |
| 480 | } |
| 481 | |
| 482 | install_merlin_path() { |
| 483 | # Add next to Merlin's path |
| 484 | mkdir -p /tmp/opt/sbin |
| 485 | ln -sf "$NEXTDNS_BIN" /tmp/opt/sbin/nextdns |
| 486 | } |
| 487 | |
| 488 | install_merlin() { |
| 489 | if install_bin; then |
| 490 | install_merlin_path |
| 491 | fi |
| 492 | } |
| 493 | |
| 494 | uninstall_merlin() { |
| 495 | uninstall_bin |
| 496 | rm -f /tmp/opt/sbin/nextdns |
| 497 | } |
| 498 | |
| 499 | upgrade_merlin() { |
| 500 | if upgrade_bin; then |
| 501 | install_merlin_path |
| 502 | fi |
| 503 | } |
| 504 | |
| 505 | install_openwrt() { |
| 506 | opkg update && |
| 507 | opkg install nextdns |
| 508 | rt=$? |
| 509 | if [ $rt -eq 0 ]; then |
| 510 | case $(ask_bool 'Install the GUI?' true) in |
| 511 | true) |
| 512 | opkg install luci-app-nextdns |
| 513 | rt=$? |
| 514 | ;; |
| 515 | esac |
| 516 | fi |
| 517 | return $rt |
| 518 | } |
| 519 | |
| 520 | upgrade_openwrt() { |
| 521 | opkg update && |
| 522 | opkg upgrade nextdns |
| 523 | } |
| 524 | |
| 525 | uninstall_openwrt() { |
| 526 | opkg remove nextdns |
| 527 | } |
| 528 | |
| 529 | install_ddwrt() { |
| 530 | if [ "$(nvram get enable_jffs2)" = "0" ]; then |
| 531 | log_error "JFFS support not enabled" |
| 532 | log_info "To enabled JFFS:" |
| 533 | log_info " 1. On the router web page click on Administration." |
| 534 | log_info " 2. Scroll down until you see JFFS2 Support section." |
| 535 | log_info " 3. Click Enable JFFS." |
| 536 | log_info " 4. Click Save." |
| 537 | log_info " 5. Wait couple seconds, then click Apply." |
| 538 | log_info " 6. Wait again. Go back to the Enable JFFS section, and enable Clean JFFS." |
| 539 | log_info " 7. Do not click Save. Click Apply instead." |
| 540 | log_info " 8. Wait till you get the web-GUI back, then disable Clean JFFS again." |
| 541 | log_info " 9. Click Save." |
| 542 | log_info "10. Relaunch this installer." |
| 543 | exit 1 |
| 544 | fi |
| 545 | mkdir -p /jffs/nextdns && |
| 546 | openssl_get https://curl.haxx.se/ca/cacert.pem | http_body > /jffs/nextdns/ca.pem && |
| 547 | install_bin |
| 548 | } |
| 549 | |
| 550 | upgrade_ddwrt() { |
| 551 | upgrade_bin |
| 552 | } |
| 553 | |
| 554 | uninstall_ddwrt() { |
| 555 | uninstall_bin |
| 556 | rm -rf /jffs/nextdns |
| 557 | } |
| 558 | |
| 559 | install_brew() { |
| 560 | silent_exec brew install nextdns/tap/nextdns |
| 561 | } |
| 562 | |
| 563 | upgrade_brew() { |
| 564 | silent_exec brew upgrade nextdns/tap/nextdns |
| 565 | asroot "$NEXTDNS_BIN" install |
| 566 | } |
| 567 | |
| 568 | uninstall_brew() { |
| 569 | silent_exec brew uninstall nextdns/tap/nextdns |
| 570 | } |
| 571 | |
| 572 | install_freebsd() { |
| 573 | # TODO: port install |
| 574 | install_bin |
| 575 | } |
| 576 | |
| 577 | upgrade_freebsd() { |
| 578 | # TODO: port upgrade |
| 579 | upgrade_bin |
| 580 | } |
| 581 | |
| 582 | uninstall_freebsd() { |
| 583 | # TODO: port uninstall |
| 584 | uninstall_bin |
| 585 | } |
| 586 | |
| 587 | install_pfsense() { |
| 588 | # TODO: port install + UI |
| 589 | install_bin |
| 590 | } |
| 591 | |
| 592 | upgrade_pfsense() { |
| 593 | # TODO: port upgrade |
| 594 | upgrade_bin |
| 595 | } |
| 596 | |
| 597 | uninstall_pfsense() { |
| 598 | # TODO: port uninstall |
| 599 | uninstall_bin |
| 600 | } |
| 601 | |
| 602 | install_opnsense() { |
| 603 | # TODO: port install + UI |
| 604 | install_bin |
| 605 | } |
| 606 | |
| 607 | upgrade_opnsense() { |
| 608 | # TODO: port upgrade |
| 609 | upgrade_bin |
| 610 | } |
| 611 | |
| 612 | uninstall_opnsense() { |
| 613 | # TODO: port uninstall |
| 614 | uninstall_bin |
| 615 | } |
| 616 | |
| 617 | ubios_install_source() { |
| 618 | echo "deb [signed-by=/etc/apt/keyrings/nextdns.gpg] https://repo.nextdns.io/deb stable main" > /data/nextdns.list |
| 619 | podman exec unifi-os mv /data/nextdns.list /etc/apt/sources.list.d/nextdns.list |
| 620 | rm -f /tmp/nextdns.list |
| 621 | podman exec unifi-os apt-get install -y gnupg1 curl |
| 622 | podman exec unifi-os mkdir -p /etc/apt/keyrings/ |
| 623 | podman exec unifi-os curl -sfL https://repo.nextdns.io/nextdns.gpg -o /etc/apt/keyrings/nextdns.gpg |
| 624 | podman exec unifi-os apt-get update -o Dir::Etc::sourcelist="sources.list.d/nextdns.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" |
| 625 | } |
| 626 | |
| 627 | install_ubios() { |
| 628 | ubios_install_source |
| 629 | podman exec unifi-os apt-get install -y nextdns |
| 630 | } |
| 631 | |
| 632 | upgrade_ubios() { |
| 633 | ubios_install_source |
| 634 | podman exec unifi-os apt-get install --only-upgrade -y nextdns |
| 635 | } |
| 636 | |
| 637 | uninstall_ubios() { |
| 638 | podman exec unifi-os apt-get remove -y nextdns |
| 639 | } |
| 640 | |
| 641 | install_ubios_snapshot() { |
| 642 | branch=${INSTALL_RELEASE%/*} |
| 643 | hash=${INSTALL_RELEASE#*/} |
| 644 | url="https://snapshot.nextdns.io/${branch}/nextdns-${hash}_${GOOS}_${GOARCH}.tar.gz" |
| 645 | podman exec unifi-os sh -c "curl -o- $url | tar Ozxf - nextdns > /usr/bin/nextdns; /usr/bin/nextdns install" |
| 646 | } |
| 647 | |
| 648 | upgrade_ubios_snapshot() { |
| 649 | /data/nextdns uninstall |
| 650 | install_ubios_snapshot |
| 651 | } |
| 652 | |
| 653 | install_type() { |
| 654 | if [ "$FORCE_INSTALL_TYPE" ]; then |
| 655 | echo "$FORCE_INSTALL_TYPE"; return 0 |
| 656 | fi |
| 657 | case "$INSTALL_RELEASE" in |
| 658 | */*) |
| 659 | case $OS in |
| 660 | ubios) |
| 661 | echo "ubios_snapshot"; return 0 |
| 662 | ;; |
| 663 | *) |
| 664 | # Snapshot mode always use binary install |
| 665 | echo "bin"; return 0 |
| 666 | ;; |
| 667 | esac |
| 668 | esac |
| 669 | case $OS in |
| 670 | centos|fedora|rhel) |
| 671 | echo "rpm" |
| 672 | ;; |
| 673 | opensuse-tumbleweed|opensuse-leap|opensuse) |
| 674 | echo "zypper" |
| 675 | ;; |
| 676 | debian|ubuntu|elementary|raspbian|linuxmint|pop|neon|sparky|vyos|Deepin) |
| 677 | echo "deb" |
| 678 | ;; |
| 679 | alpine) |
| 680 | echo "apk" |
| 681 | ;; |
| 682 | arch|manjaro|steamos) |
| 683 | #echo "arch" # TODO: fix AUR install |
| 684 | echo "bin" |
| 685 | ;; |
| 686 | openwrt) |
| 687 | # shellcheck disable=SC1091 |
| 688 | . /etc/os-release |
| 689 | major=$(echo "$VERSION_ID" | cut -d. -f1) |
| 690 | case $major in |
| 691 | *[!0-9]*) |
| 692 | if [ "$VERSION_ID" = "19.07.0-rc1" ]; then |
| 693 | # No opkg support before 19.07.0-rc2 |
| 694 | echo "bin" |
| 695 | else |
| 696 | # Likely 'snapshot' build in this case, but still > major version 19 |
| 697 | echo "openwrt" |
| 698 | fi |
| 699 | ;; |
| 700 | *) |
| 701 | if [ "$major" -lt 19 ]; then |
| 702 | # No opkg support before 19.07.0-rc2 |
| 703 | echo "bin" |
| 704 | else |
| 705 | echo "openwrt" |
| 706 | fi |
| 707 | ;; |
| 708 | esac |
| 709 | ;; |
| 710 | asuswrt-merlin) |
| 711 | echo "merlin" |
| 712 | ;; |
| 713 | edgeos|synology|clear-linux-os|solus|openbsd|netbsd|overthebox) |
| 714 | echo "bin" |
| 715 | ;; |
| 716 | ddwrt) |
| 717 | echo "ddwrt" |
| 718 | ;; |
| 719 | darwin) |
| 720 | if [ -x /usr/local/bin/brew ] || [ -x /opt/homebrew/bin/brew ]; then |
| 721 | echo "brew" |
| 722 | else |
| 723 | log_debug "Homebrew not installed, fallback on binary install" |
| 724 | echo "bin" |
| 725 | fi |
| 726 | ;; |
| 727 | freebsd) |
| 728 | echo "freebsd" |
| 729 | ;; |
| 730 | pfsense) |
| 731 | echo "pfsense" |
| 732 | ;; |
| 733 | opnsense) |
| 734 | echo "opnsense" |
| 735 | ;; |
| 736 | ubios) |
| 737 | echo "ubios" |
| 738 | ;; |
| 739 | gentoo) |
| 740 | echo "bin" |
| 741 | ;; |
| 742 | void) |
| 743 | # TODO: pkg for xbps |
| 744 | echo "bin" |
| 745 | ;; |
| 746 | *) |
| 747 | log_error "Unsupported installation for $(detect_os)" |
| 748 | return 1 |
| 749 | ;; |
| 750 | esac |
| 751 | } |
| 752 | |
| 753 | get_config() { |
| 754 | "$NEXTDNS_BIN" config | grep -E "^$1 " | cut -d' ' -f 2 |
| 755 | } |
| 756 | |
| 757 | get_config_bool() { |
| 758 | val=$(get_config "$1") |
| 759 | case $val in |
| 760 | true|false) |
| 761 | echo "$val" |
| 762 | ;; |
| 763 | esac |
| 764 | echo "$2" |
| 765 | } |
| 766 | |
| 767 | get_profile_id() { |
| 768 | log_debug "Get profile ID" |
| 769 | if [ "$CONFIG_ID" ]; then |
| 770 | # backward compat |
| 771 | PROFILE_ID="$CONFIG_ID" |
| 772 | fi |
| 773 | while [ -z "$PROFILE_ID" ]; do |
| 774 | default= |
| 775 | prev_id=$(get_config profile) |
| 776 | if [ -z "$prev_id" ]; then |
| 777 | # backward compat |
| 778 | prev_id=$(get_config config) |
| 779 | fi |
| 780 | if [ "$prev_id" ]; then |
| 781 | log_debug "Previous profile ID: $prev_id" |
| 782 | default=" (default=$prev_id)" |
| 783 | fi |
| 784 | print "NextDNS Profile ID%s: " "$default" |
| 785 | read -r id |
| 786 | if [ -z "$id" ]; then |
| 787 | id=$prev_id |
| 788 | fi |
| 789 | if echo "$id" | grep -qE '^[0-9a-f]{6}$'; then |
| 790 | PROFILE_ID=$id |
| 791 | break |
| 792 | else |
| 793 | log_error "Invalid profile ID." |
| 794 | println |
| 795 | println "ID format is 6 alphanumerical lowercase characters (example: 123abc)." |
| 796 | println "Your ID can be found on the Setup tab of https://my.nextdns.io." |
| 797 | println |
| 798 | fi |
| 799 | done |
| 800 | echo "$PROFILE_ID" |
| 801 | } |
| 802 | |
| 803 | log_debug() { |
| 804 | if [ "$DEBUG" = "1" ]; then |
| 805 | printf "\033[30;1mDEBUG: %s\033[0m\n" "$*" >&2 |
| 806 | fi |
| 807 | } |
| 808 | |
| 809 | log_info() { |
| 810 | printf "INFO: %s\n" "$*" >&2 |
| 811 | } |
| 812 | |
| 813 | log_warn() { |
| 814 | printf "\033[33mWARN: %s\033[0m\n" "$*" >&2 |
| 815 | } |
| 816 | |
| 817 | log_error() { |
| 818 | printf "\033[31mERROR: %s\033[0m\n" "$*" >&2 |
| 819 | } |
| 820 | |
| 821 | print() { |
| 822 | format=$1 |
| 823 | if [ $# -gt 0 ]; then |
| 824 | shift |
| 825 | fi |
| 826 | # shellcheck disable=SC2059 |
| 827 | printf "$format" "$@" >&2 |
| 828 | } |
| 829 | |
| 830 | println() { |
| 831 | format=$1 |
| 832 | if [ $# -gt 0 ]; then |
| 833 | shift |
| 834 | fi |
| 835 | # shellcheck disable=SC2059 |
| 836 | printf "$format\n" "$@" >&2 |
| 837 | } |
| 838 | |
| 839 | doc() { |
| 840 | # shellcheck disable=SC2059 |
| 841 | printf "\033[30;1m%s\033[0m\n" "$*" >&2 |
| 842 | } |
| 843 | |
| 844 | menu() { |
| 845 | while true; do |
| 846 | n=0 |
| 847 | default= |
| 848 | for item in "$@"; do |
| 849 | case $((n%3)) in |
| 850 | 0) |
| 851 | key=$item |
| 852 | if [ -z "$default" ]; then |
| 853 | default=$key |
| 854 | fi |
| 855 | ;; |
| 856 | 1) |
| 857 | echo "$key) $item" |
| 858 | ;; |
| 859 | esac |
| 860 | n=$((n+1)) |
| 861 | done |
| 862 | print "Choice (default=%s): " "$default" |
| 863 | read -r choice |
| 864 | if [ -z "$choice" ]; then |
| 865 | choice=$default |
| 866 | fi |
| 867 | n=0 |
| 868 | for item in "$@"; do |
| 869 | case $((n%3)) in |
| 870 | 0) |
| 871 | key=$item |
| 872 | ;; |
| 873 | 2) |
| 874 | if [ "$key" = "$choice" ]; then |
| 875 | if ! "$item"; then |
| 876 | log_error "$item: exit $?" |
| 877 | fi |
| 878 | break 2 |
| 879 | fi |
| 880 | ;; |
| 881 | esac |
| 882 | n=$((n+1)) |
| 883 | done |
| 884 | echo "Invalid choice" |
| 885 | done |
| 886 | } |
| 887 | |
| 888 | ask_bool() { |
| 889 | msg=$1 |
| 890 | default=$2 |
| 891 | case $default in |
| 892 | true) |
| 893 | msg="$msg [Y|n]: " |
| 894 | ;; |
| 895 | false) |
| 896 | msg="$msg [y|N]: " |
| 897 | ;; |
| 898 | *) |
| 899 | msg="$msg (y/n): " |
| 900 | esac |
| 901 | while true; do |
| 902 | print "%s" "$msg" |
| 903 | read -r answer |
| 904 | if [ -z "$answer" ]; then |
| 905 | answer=$default |
| 906 | fi |
| 907 | case $answer in |
| 908 | y|Y|yes|YES|true) |
| 909 | echo "true" |
| 910 | return 0 |
| 911 | ;; |
| 912 | n|N|no|NO|false) |
| 913 | echo "false" |
| 914 | return 0 |
| 915 | ;; |
| 916 | *) |
| 917 | echo "Invalid input, use yes or no" |
| 918 | ;; |
| 919 | esac |
| 920 | done |
| 921 | } |
| 922 | |
| 923 | detect_endiannes() { |
| 924 | if ! hexdump /dev/null 2>/dev/null; then |
| 925 | # Some firmwares do not contain hexdump, for those, try to detect endianness |
| 926 | # differently. |
| 927 | case $(cat /proc/cpuinfo) in |
| 928 | *BCM5300*) |
| 929 | # RT-AC66U does not support Merlin version over 380.70 which |
| 930 | # lacks hexdump command. |
| 931 | echo "le" |
| 932 | ;; |
| 933 | *) |
| 934 | log_error "Cannot determine endianness" |
| 935 | return 1 |
| 936 | ;; |
| 937 | esac |
| 938 | return 0 |
| 939 | fi |
| 940 | case $(hexdump -s 5 -n 1 -e '"%x"' /bin/sh | head -c1) in |
| 941 | 1) |
| 942 | echo "le" |
| 943 | ;; |
| 944 | 2) |
| 945 | echo "" |
| 946 | ;; |
| 947 | esac |
| 948 | } |
| 949 | |
| 950 | detect_goarch() { |
| 951 | if [ "$FORCE_GOARCH" ]; then |
| 952 | echo "$FORCE_GOARCH"; return 0 |
| 953 | fi |
| 954 | case $(uname -m) in |
| 955 | x86_64|amd64) |
| 956 | echo "amd64" |
| 957 | ;; |
| 958 | i386|i686) |
| 959 | echo "386" |
| 960 | ;; |
| 961 | arm) |
| 962 | # FreeBSD does not include arm version |
| 963 | case "$(sysctl -b hw.model 2>/dev/null)" in |
| 964 | *A9*) |
| 965 | echo "armv7" |
| 966 | ;; |
| 967 | *) |
| 968 | # Unknown version, fallback to the lowest |
| 969 | echo "armv5" |
| 970 | ;; |
| 971 | esac |
| 972 | ;; |
| 973 | armv5*) |
| 974 | echo "armv5" |
| 975 | ;; |
| 976 | armv6*|armv7*) |
| 977 | if grep -q vfp /proc/cpuinfo 2>/dev/null; then |
| 978 | echo "armv$(uname -m | sed -e 's/[[:alpha:]]//g')" |
| 979 | else |
| 980 | # Soft floating point |
| 981 | echo "armv5" |
| 982 | fi |
| 983 | ;; |
| 984 | aarch64) |
| 985 | case "$(uname -o 2>/dev/null)" in |
| 986 | ASUSWRT-Merlin*) |
| 987 | # XXX when using arm64 build on ASUS AC66U and ACG86U, we get Go error: |
| 988 | # "out of memory allocating heap arena metadata". |
| 989 | echo "armv7" |
| 990 | ;; |
| 991 | *) |
| 992 | echo "arm64" |
| 993 | ;; |
| 994 | esac |
| 995 | ;; |
| 996 | armv8*|arm64) |
| 997 | echo "arm64" |
| 998 | ;; |
| 999 | mips*) |
| 1000 | # TODO: detect hardfloat |
| 1001 | echo "$(uname -m)$(detect_endiannes)_softfloat" |
| 1002 | ;; |
| 1003 | *) |
| 1004 | log_error "Unsupported GOARCH: $(uname -m)" |
| 1005 | return 1 |
| 1006 | ;; |
| 1007 | esac |
| 1008 | } |
| 1009 | |
| 1010 | detect_goos() { |
| 1011 | if [ "$FORCE_GOOS" ]; then |
| 1012 | echo "$FORCE_GOOS"; return 0 |
| 1013 | fi |
| 1014 | case $(uname -s) in |
| 1015 | Linux) |
| 1016 | echo "linux" |
| 1017 | ;; |
| 1018 | Darwin) |
| 1019 | echo "darwin" |
| 1020 | ;; |
| 1021 | FreeBSD) |
| 1022 | echo "freebsd" |
| 1023 | ;; |
| 1024 | NetBSD) |
| 1025 | echo "netbsd" |
| 1026 | ;; |
| 1027 | OpenBSD) |
| 1028 | echo "openbsd" |
| 1029 | ;; |
| 1030 | *) |
| 1031 | log_error "Unsupported GOOS: $(uname -s)" |
| 1032 | return 1 |
| 1033 | esac |
| 1034 | } |
| 1035 | |
| 1036 | detect_os() { |
| 1037 | if [ "$FORCE_OS" ]; then |
| 1038 | echo "$FORCE_OS"; return 0 |
| 1039 | fi |
| 1040 | case $(uname -s) in |
| 1041 | Linux) |
| 1042 | case $(uname -o) in |
| 1043 | GNU/Linux|Linux) |
| 1044 | if grep -q -e '^EdgeRouter' -e '^UniFiSecurityGateway' /etc/version 2> /dev/null; then |
| 1045 | echo "edgeos"; return 0 |
| 1046 | fi |
| 1047 | if uname -u 2>/dev/null | grep -q '^synology'; then |
| 1048 | echo "synology"; return 0 |
| 1049 | fi |
| 1050 | # shellcheck disable=SC1091 |
| 1051 | dist=$(. /etc/os-release; echo "$ID") |
| 1052 | case $dist in |
| 1053 | ubios) |
| 1054 | if [ -z "$(command -v podman)" ]; then |
| 1055 | log_error "This version of UnifiOS is not supported. Make sure you run version 1.7.0 or above." |
| 1056 | return 1 |
| 1057 | fi |
| 1058 | echo "$dist"; return 0 |
| 1059 | ;; |
| 1060 | debian|ubuntu|elementary|raspbian|centos|fedora|rhel|arch|manjaro|openwrt|clear-linux-os|linuxmint|opensuse-tumbleweed|opensuse-leap|opensuse|solus|pop|neon|overthebox|sparky|vyos|void|alpine|Deepin|gentoo|steamos) |
| 1061 | echo "$dist"; return 0 |
| 1062 | ;; |
| 1063 | esac |
| 1064 | # shellcheck disable=SC1091 |
| 1065 | for dist in $(. /etc/os-release; echo "$ID_LIKE"); do |
| 1066 | case $dist in |
| 1067 | debian|ubuntu|rhel|fedora|openwrt) |
| 1068 | log_debug "Using ID_LIKE" |
| 1069 | echo "$dist"; return 0 |
| 1070 | ;; |
| 1071 | esac |
| 1072 | done |
| 1073 | ;; |
| 1074 | ASUSWRT-Merlin*) |
| 1075 | echo "asuswrt-merlin"; return 0 |
| 1076 | ;; |
| 1077 | DD-WRT) |
| 1078 | echo "ddwrt"; return 0 |
| 1079 | esac |
| 1080 | ;; |
| 1081 | Darwin) |
| 1082 | echo "darwin"; return 0 |
| 1083 | ;; |
| 1084 | FreeBSD) |
| 1085 | if [ -f /etc/platform ]; then |
| 1086 | case $(cat /etc/platform) in |
| 1087 | pfSense) |
| 1088 | echo "pfsense"; return 0 |
| 1089 | ;; |
| 1090 | esac |
| 1091 | fi |
| 1092 | if [ -x /usr/local/sbin/opnsense-version ]; then |
| 1093 | case $(/usr/local/sbin/opnsense-version -N) in |
| 1094 | OPNsense) |
| 1095 | echo "opnsense"; return 0 |
| 1096 | ;; |
| 1097 | esac |
| 1098 | fi |
| 1099 | echo "freebsd"; return 0 |
| 1100 | ;; |
| 1101 | NetBSD) |
| 1102 | echo "netbsd"; return 0 |
| 1103 | ;; |
| 1104 | OpenBSD) |
| 1105 | echo "openbsd"; return 0 |
| 1106 | ;; |
| 1107 | *) |
| 1108 | esac |
| 1109 | log_error "Unsupported OS: $(uname -o) $(grep ID "/etc/os-release" 2>/dev/null | xargs)" |
| 1110 | return 1 |
| 1111 | } |
| 1112 | |
| 1113 | guess_host_type() { |
| 1114 | if [ -d /data/unifi ]; then |
| 1115 | # Special case when installer is run from inside the ubios podman |
| 1116 | echo "router"; return 0 |
| 1117 | fi |
| 1118 | |
| 1119 | case $OS in |
| 1120 | pfsense|opnsense|openwrt|asuswrt-merlin|edgeos|ddwrt|synology|overthebox|ubios) |
| 1121 | echo "router" |
| 1122 | ;; |
| 1123 | darwin|steamos) |
| 1124 | echo "workstation" |
| 1125 | ;; |
| 1126 | *) |
| 1127 | echo "unsure" |
| 1128 | ;; |
| 1129 | esac |
| 1130 | } |
| 1131 | |
| 1132 | asroot() { |
| 1133 | # Some platform (Merlin) do not have the "id" command and $USER report a non root username with uid 0. |
| 1134 | if [ "$(grep '^Uid:' /proc/$$/status 2>/dev/null|cut -f2)" = "0" ] || [ "$USER" = "root" ] || [ "$(id -u 2>/dev/null)" = "0" ]; then |
| 1135 | "$@" |
| 1136 | elif [ "$(command -v sudo 2>/dev/null)" ]; then |
| 1137 | sudo "$@" |
| 1138 | else |
| 1139 | echo "Root required" |
| 1140 | su -m root -c "$*" |
| 1141 | fi |
| 1142 | } |
| 1143 | |
| 1144 | silent_exec() { |
| 1145 | if [ "$DEBUG" = 1 ]; then |
| 1146 | "$@" |
| 1147 | else |
| 1148 | if ! out=$("$@" 2>&1); then |
| 1149 | rt=$? |
| 1150 | println "\033[30;1m%s\033[0m" "$out" |
| 1151 | return $rt |
| 1152 | fi |
| 1153 | fi |
| 1154 | } |
| 1155 | |
| 1156 | bin_location() { |
| 1157 | case $OS in |
| 1158 | centos|fedora|rhel|debian|ubuntu|elementary|raspbian|arch|manjaro|clear-linux-os|linuxmint|opensuse-tumbleweed|opensuse-leap|opensuse|solus|pop|neon|sparky|vyos|void|alpine|Deepin|gentoo) |
| 1159 | echo "/usr/bin/nextdns" |
| 1160 | ;; |
| 1161 | openwrt|overthebox) |
| 1162 | echo "/usr/sbin/nextdns" |
| 1163 | ;; |
| 1164 | synology) |
| 1165 | echo "/usr/local/bin/nextdns" |
| 1166 | ;; |
| 1167 | darwin) |
| 1168 | echo "$(brew --prefix 2>/dev/null || echo /usr/local)/bin/nextdns" |
| 1169 | ;; |
| 1170 | asuswrt-merlin|ddwrt) |
| 1171 | echo "/jffs/nextdns/nextdns" |
| 1172 | ;; |
| 1173 | freebsd|pfsense|opnsense|netbsd|openbsd) |
| 1174 | echo "/usr/local/sbin/nextdns" |
| 1175 | ;; |
| 1176 | edgeos) |
| 1177 | echo "/config/nextdns/nextdns" |
| 1178 | ;; |
| 1179 | ubios) |
| 1180 | echo "/data/nextdns" |
| 1181 | ;; |
| 1182 | steamos) |
| 1183 | echo "$HOME/.local/bin/nextdns" |
| 1184 | ;; |
| 1185 | *) |
| 1186 | log_error "Unknown bin location for $OS" |
| 1187 | ;; |
| 1188 | esac |
| 1189 | } |
| 1190 | |
| 1191 | is_version_current() { |
| 1192 | case "$INSTALL_RELEASE" in |
| 1193 | */*) |
| 1194 | # Snapshot |
| 1195 | hash=${INSTALL_RELEASE#*/} |
| 1196 | test "0.0.0-$hash" = "$CURRENT_RELEASE" |
| 1197 | ;; |
| 1198 | *) |
| 1199 | test "$INSTALL_RELEASE" = "$CURRENT_RELEASE" |
| 1200 | ;; |
| 1201 | esac |
| 1202 | } |
| 1203 | |
| 1204 | get_current_release() { |
| 1205 | if [ -x "$NEXTDNS_BIN" ]; then |
| 1206 | $NEXTDNS_BIN version|cut -d' ' -f 3 |
| 1207 | fi |
| 1208 | } |
| 1209 | |
| 1210 | get_release() { |
| 1211 | if [ "$NEXTDNS_VERSION" ]; then |
| 1212 | echo "$NEXTDNS_VERSION" |
| 1213 | else |
| 1214 | for cmd in curl wget openssl true; do |
| 1215 | # command is the "right" way but may be compiled out of busybox shell |
| 1216 | ! command -v $cmd > /dev/null 2>&1 || break |
| 1217 | ! which $cmd > /dev/null 2>&1 || break |
| 1218 | done |
| 1219 | case "$cmd" in |
| 1220 | curl) cmd="curl -A curl -s" ;; |
| 1221 | wget) cmd="wget -qO- -U curl" ;; |
| 1222 | openssl) cmd="openssl_get" ;; |
| 1223 | *) |
| 1224 | log_error "Cannot retrieve latest version" |
| 1225 | return |
| 1226 | ;; |
| 1227 | esac |
| 1228 | v=$($cmd "https://api.github.com/repos/nextdns/nextdns/releases/latest" | \ |
| 1229 | grep '"tag_name":' | esed 's/.*"([^"]+)".*/\1/' | sed -e 's/^v//') |
| 1230 | if [ -z "$v" ]; then |
| 1231 | log_error "Cannot get latest version: $out" |
| 1232 | fi |
| 1233 | echo "$v" |
| 1234 | fi |
| 1235 | } |
| 1236 | |
| 1237 | esed() { |
| 1238 | if (echo | sed -E '' >/dev/null 2>&1); then |
| 1239 | sed -E "$@" |
| 1240 | else |
| 1241 | sed -r "$@" |
| 1242 | fi |
| 1243 | } |
| 1244 | |
| 1245 | http_redirect() { |
| 1246 | while read -r header; do |
| 1247 | case $header in |
| 1248 | Location:*) |
| 1249 | echo "${header#Location: }" |
| 1250 | return |
| 1251 | ;; |
| 1252 | esac |
| 1253 | if [ "$header" = "" ]; then |
| 1254 | break |
| 1255 | fi |
| 1256 | done |
| 1257 | cat > /dev/null |
| 1258 | return 1 |
| 1259 | } |
| 1260 | |
| 1261 | http_body() { |
| 1262 | sed -n '/^\r/,$p' | sed 1d |
| 1263 | } |
| 1264 | |
| 1265 | openssl_get() { |
| 1266 | host=${1#https://*} # https://dom.com/path -> dom.com/path |
| 1267 | path=/${host#*/} # dom.com/path -> /path |
| 1268 | host=${host%$path} # dom.com/path -> dom.com |
| 1269 | printf "GET %s HTTP/1.0\nHost: %s\nUser-Agent: curl\n\n" "$path" "$host" | |
| 1270 | openssl s_client -quiet -connect "$host:443" 2>/dev/null |
| 1271 | } |
| 1272 | |
| 1273 | umask 0022 |
| 1274 | main |
| 1275 | #+end_src |