summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/networking/pihole-ftl-setup-script.nix
blob: 966fc82a8b1fb3b4dae30062372b00633ea685b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{
  cfg,
  config,
  lib,
  pkgs,
}:

let
  pihole = cfg.piholePackage;
  makePayload =
    list:
    builtins.toJSON {
      inherit (list) type enabled;
      address = list.url;
      comment = list.description;
    };
  payloads = map makePayload cfg.lists;
  macvendorURL = lib.strings.escapeShellArg cfg.macvendorURL;
in
''
  # Can't use -u (unset) because api.sh uses API_URL before it is set
  set +u
  set -eo pipefail
  pihole="${lib.getExe pihole}"
  jq="${lib.getExe pkgs.jq}"

  ${lib.getExe pkgs.curl} --retry 3 --retry-delay 5 "${macvendorURL}" -o "${cfg.settings.files.macvendor}" || echo "Failed to download MAC database from ${macvendorURL}"

  # If the database doesn't exist, it needs to be created with gravity.sh
  if [ ! -f '${cfg.settings.files.gravity}' ]; then
    $pihole -g
    # Send SIGRTMIN to FTL, which makes it reload the database, opening the newly created one
    ${lib.getExe' pkgs.procps "kill"} -s SIGRTMIN "$(systemctl show --property MainPID --value ${config.systemd.services.pihole-ftl.name})"
  fi

  # shellcheck disable=SC1091
  source ${pihole}/share/pihole/advanced/Scripts/api.sh
  # shellcheck disable=SC1091
  source ${pihole}/share/pihole/advanced/Scripts/utils.sh

  any_failed=0

  addList() {
    local payload="$1" result type id error

    echo "Adding list: $payload"
    type=$($jq -r '.type' <<< "$payload")
    result=$(PostFTLData "lists?type=$type" "$payload")

    error="$($jq '.error' <<< "$result")"
    if [[ "$error" != "null" ]]; then
      if $jq -e '
        .error.key == "database_error"
        and .error.hint == "The item is already present"
      ' <<< "$result" > /dev/null; then
        echo "List already present"
        return
      fi

      echo "Error: $error"
      any_failed=1
      return
    fi

    id="$($jq '.lists.[].id?' <<< "$result")"
    if [[ "$id" == "null" ]]; then
      any_failed=1
      error="$($jq '.processed.errors.[].error' <<< "$result")"
      echo "Error: $error"
      return
    fi

    echo "Added list ID $id: $result"
  }

  for _ in 1 2 3; do
    (TestAPIAvailability) && break
    echo "Retrying API shortly..."
    ${lib.getExe' pkgs.coreutils "sleep"} .5s
  done;

  LoginAPI

  ${builtins.concatStringsSep "\n" (
    map (
      payload:
      lib.pipe payload [
        lib.strings.escapeShellArg
        (payload: "addList ${payload}")
      ]
    ) payloads
  )}

  # Run gravity.sh to load any new lists
  $pihole -g
  exit $any_failed
''