diff options
| author | tv <tv@krebsco.de> | 2018-04-24 19:28:09 +0200 | 
|---|---|---|
| committer | tv <tv@krebsco.de> | 2018-04-24 19:28:09 +0200 | 
| commit | 21053de317e838c06a20425bdb3e81b7ac132d83 (patch) | |
| tree | d722f9c2a525d6d66310da5e86dbcff73c79672a | |
| parent | 0fe9b28302c905523f2ecefadfd167e1547785f9 (diff) | |
| parent | c99e8256b223761eb50cf5d6841ab64f989851c3 (diff) | |
Merge remote-tracking branch 'prism/master'
31 files changed, 650 insertions, 87 deletions
| diff --git a/krebs/1systems/onebutton/config.nix b/krebs/1systems/onebutton/config.nix new file mode 100644 index 000000000..c634d73ce --- /dev/null +++ b/krebs/1systems/onebutton/config.nix @@ -0,0 +1,44 @@ +{ config, pkgs, lib, ... }: +{ +  imports = [ +    <stockholm/krebs> +    <stockholm/krebs/2configs> +    { # minimal disk usage +      environment.noXlibs = true; +      nix.gc.automatic = true; +      nix.gc.dates = "03:10"; +      programs.info.enable = false; +      programs.man.enable = false; +      services.journald.extraConfig = "SystemMaxUse=50M"; +      services.nixosManual.enable = false; +    } +  ]; +  krebs.build.host = config.krebs.hosts.onebutton; +  # NixOS wants to enable GRUB by default +  boot.loader.grub.enable = false; +  # Enables the generation of /boot/extlinux/extlinux.conf +  boot.loader.generic-extlinux-compatible.enable = true; + +  # !!! If your board is a Raspberry Pi 1, select this: +  boot.kernelPackages = pkgs.linuxPackages_rpi; + +  nix.binaryCaches = [ "http://nixos-arm.dezgeg.me/channel" ]; +  nix.binaryCachePublicKeys = [ "nixos-arm.dezgeg.me-1:xBaUKS3n17BZPKeyxL4JfbTqECsT+ysbDJz29kLFRW0=%" ]; + +  # !!! Needed for the virtual console to work on the RPi 3, as the default of 16M doesn't seem to be enough. +  # boot.kernelParams = ["cma=32M"]; + +  fileSystems = { +    "/boot" = { +      device = "/dev/disk/by-label/NIXOS_BOOT"; +      fsType = "vfat"; +    }; +    "/" = { +      device = "/dev/disk/by-label/NIXOS_SD"; +      fsType = "ext4"; +    }; +  }; + +  swapDevices = [ { device = "/swapfile"; size = 1024; } ]; +  services.openssh.enable = true; +} diff --git a/krebs/1systems/onebutton/source.nix b/krebs/1systems/onebutton/source.nix new file mode 100644 index 000000000..8f25881c9 --- /dev/null +++ b/krebs/1systems/onebutton/source.nix @@ -0,0 +1,16 @@ +with import <stockholm/lib>; +let +  pkgs = import <nixpkgs> {}; +  nixpkgs = pkgs.fetchFromGitHub { +    owner = "nixos"; +    repo = "nixpkgs-channels"; +    rev = "6c064e6b"; # only binary cache for unstable arm6 +    sha256 = "1rqzh475xn43phagrr30lb0fd292c1s8as53irihsnd5wcksnbyd"; +  }; +in import <stockholm/krebs/source.nix> { +  name = "onebutton"; +  override.nixpkgs = mkForce { +    file = toString nixpkgs; +  }; + +} diff --git a/krebs/3modules/krebs/default.nix b/krebs/3modules/krebs/default.nix index 1e626f0a0..a916c1873 100644 --- a/krebs/3modules/krebs/default.nix +++ b/krebs/3modules/krebs/default.nix @@ -91,6 +91,37 @@ in {        ssh.privkey.path = <secrets/ssh.id_ed25519>;        ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICxFkBln23wUxt4RhIHE3GvdKeBpJbjn++6maupHqUHp";      }; +    onebutton = { +      cores = 1; +      owner = config.krebs.users.krebs; +      nets = { +        retiolum = { +          ip4.addr = "10.243.0.101"; +          ip6.addr = "42:0:0:0:0:0:0:101"; +          aliases = [ +            "onebutton.r" +          ]; +          tinc.pubkey = '' +            -----BEGIN PUBLIC KEY----- +            MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA11w6votRExwE0ZEiQmPa +            9WGNsMfNAZEd14iHaHCZH7UPQEH+cH/T6isGPpaysindroMnqFe9mUf/cdYChb6N +            aaFreApwGBQaJPUcdy4cfphrFpzmOClpOFuFbnV7ZvAk/wefBad3kUzsq/lK4HvB +            7nPKeOB9kljphLrkzuLL/h2yOenMpO2ZdvwxyWN8HKmUNgvpBQjIr+Hka6cgy7Gp +            pBVFHfSnad/eHeEvq91O/bHxrAxzH5N5DVagPDpkbiWYGl+0XVGP/h0CApr15Ael +            +j2pJYc0ZlaXIp4KmNRqbd/fLe52JLrWbnFX4rRuY/DhoMqK8kjECEZ7gLiNSpCC +            KlnlJ2LXX9c+d79ubzl5yLAJ3d6T4IJqkbAWJDuCrj821M9ZDk/qZwerayhrrvkF +            tMYkQoGSe8MvSOU0rTEoH5iSRwDC7M0XzUe4l8/yZLFyD4Prz/dq6coqANfk/tlE +            DnH3vDu9lmFvYrLcd6yDWzFfI3mWDJoUa6AKKoScCOaCkRfIM4Aew0i73+h1nJLO +            59AAbZIkDYyWs53QniIG4EQteI9y/9j/628nPAVj68V5oIN76RDXfFHWDWq4DxmU +            PpGVmoIKcKZmnl7RrDomRVpuGMdyQ+kCzIGH3XYe12v8Y5beHZBrd3OajgHZ/Tfp +            jP873cT6h0hsGm9glgOYho8CAwEAAQ== +            -----END PUBLIC KEY----- +          ''; +        }; +      }; +      ssh.privkey.path = <secrets/ssh.id_ed25519>; +      ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAcZg+iLaPZ0SpLM+nANxIjZC/RIsansjyutK0+gPhIe "; +    };      puyak = {        ci = true;        owner = config.krebs.users.krebs; diff --git a/krebs/5pkgs/simple/Reaktor/plugins.nix b/krebs/5pkgs/simple/Reaktor/plugins.nix index bcfcbf76b..f3b771190 100644 --- a/krebs/5pkgs/simple/Reaktor/plugins.nix +++ b/krebs/5pkgs/simple/Reaktor/plugins.nix @@ -120,11 +120,24 @@ rec {    url-title = (buildSimpleReaktorPlugin "url-title" {      pattern = "^.*(?P<args>http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+).*$$";      path = with pkgs; [ curl perl ]; -    script = pkgs.writeDash "lambda-pl" '' -      if [ "$#" -gt 0 ]; then -        curl -SsL --max-time 5 "$1" | -          perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si' -      fi +    script = pkgs.writePython3 [ "beautifulsoup4" "lxml" ] "url-title" '' +      import sys +      import urllib.request +      from bs4 import BeautifulSoup + +      try: +          soup = BeautifulSoup(urllib.request.urlopen(sys.argv[1]), "lxml") +          title = soup.find('title').string + +          if title: +              if len(title) > 512: +                  print('message to long, skipped') +              elif len(title.split('\n')) > 5: +                  print('to many lines, skipped') +              else: +                  print(title) +      except:  # noqa: E722 +          pass      '';    }); diff --git a/krebs/5pkgs/simple/generate-secrets/default.nix b/krebs/5pkgs/simple/generate-secrets/default.nix new file mode 100644 index 000000000..a800ff543 --- /dev/null +++ b/krebs/5pkgs/simple/generate-secrets/default.nix @@ -0,0 +1,46 @@ +{ pkgs }: +pkgs.writeDashBin "generate-secrets" '' +  HOSTNAME="$1" +  TMPDIR=$(${pkgs.coreutils}/bin/mktemp -d) +  PASSWORD=$(${pkgs.pwgen}/bin/pwgen 25 1) +  HASHED_PASSWORD=$(echo $PASSWORD | ${pkgs.hashPassword}/bin/hashPassword -s) > /dev/null + +  ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f $TMPDIR/ssh.id_ed25519 -P "" -C "" >/dev/null +  ${pkgs.openssl}/bin/openssl genrsa -out $TMPDIR/retiolum.rsa_key.priv 4096 2>/dev/null > /dev/null +  ${pkgs.openssl}/bin/openssl rsa -in $TMPDIR/retiolum.rsa_key.priv -pubout -out $TMPDIR/retiolum.rsa_key.pub 2>/dev/null > /dev/null +  cat <<EOF > $TMPDIR/hashedPasswords.nix +  { +    root = "$HASHED_PASSWORD"; +  } +  EOF + +  cd $TMPDIR +  for x in *; do +    ${pkgs.coreutils}/bin/cat $x | ${pkgs.brain}/bin/brain insert -m krebs-secrets/$HOSTNAME/$x > /dev/null +  done +  echo $PASSWORD | ${pkgs.brain}/bin/brain insert -m hosts/$HOSTNAME/root > /dev/null + +  cat <<EOF +    $HOSTNAME = { +      cores = 1; +      owner = config.krebs.users.krebs; +      nets = { +        retiolum = { +          ip4.addr = "10.243.0.changeme"; +          ip6.addr = "42:0:0:0:0:0:0:changeme"; +          aliases = [ +            "$HOSTNAME.r" +          ]; +          tinc.pubkey = ${"''"} +  $(cat $TMPDIR/retiolum.rsa_key.pub) +          ${"''"}; +        }; +      }; +      ssh.privkey.path = <secrets/ssh.id_ed25519>; +      ssh.pubkey = "$(cat $TMPDIR/ssh.id_ed25519.pub)"; +    }; +  EOF + +  rm -rf $TMPDIR +'' + diff --git a/lass/1systems/mors/config.nix b/lass/1systems/mors/config.nix index cd259d0fe..c59494e4d 100644 --- a/lass/1systems/mors/config.nix +++ b/lass/1systems/mors/config.nix @@ -141,6 +141,15 @@ with import <stockholm/lib>;      dnsutils      generate-secrets +    (pkgs.writeDashBin "btc-coinbase" '' +      ${pkgs.curl}/bin/curl -Ss 'https://api.coinbase.com/v2/prices/spot?currency=EUR' | ${pkgs.jq}/bin/jq '.data.amount' +    '') +    (pkgs.writeDashBin "btc-wex" '' +      ${pkgs.curl}/bin/curl -Ss 'https://wex.nz/api/3/ticker/btc_eur' | ${pkgs.jq}/bin/jq '.btc_eur.avg' +    '') +    (pkgs.writeDashBin "btc-kraken" '' +      ${pkgs.curl}/bin/curl -Ss  'https://api.kraken.com/0/public/Ticker?pair=BTCEUR' | ${pkgs.jq}/bin/jq '.result.XXBTZEUR.a[0]' +    '')    ];    #TODO: fix this shit @@ -177,4 +186,34 @@ with import <stockholm/lib>;    programs.adb.enable = true;    users.users.mainUser.extraGroups = [ "adbusers" "docker" ];    virtualisation.docker.enable = true; + +  lass.restic = genAttrs [ +    "daedalus" +    "icarus" +    "littleT" +    "prism" +    "shodan" +    "skynet" +  ] (dest: { +    dirs = [ +      "/home/lass/src" +      "/home/lass/work" +      "/home/lass/.gnupg" +      "/home/lass/Maildir" +      "/home/lass/stockholm" +      "/home/lass/.password-store" +      "/home/bitcoin" +      "/home/bch" +    ]; +    passwordFile = (toString <secrets>) + "/restic/${dest}"; +    repo = "sftp:backup@${dest}.r:/backups/mors"; +    #sshPrivateKey = config.krebs.build.host.ssh.privkey.path; +    extraArguments = [ +      "sftp.command='ssh backup@${dest}.r -i ${config.krebs.build.host.ssh.privkey.path} -s sftp'" +    ]; +    timerConfig = { +      OnCalendar = "00:05"; +      RandomizedDelaySec = "5h"; +    }; +  });  } diff --git a/lass/1systems/prism/config.nix b/lass/1systems/prism/config.nix index c0e4620cc..983604f8e 100644 --- a/lass/1systems/prism/config.nix +++ b/lass/1systems/prism/config.nix @@ -8,11 +8,15 @@ in {    imports = [      <stockholm/lass>      { -      networking.interfaces.et0.ip4 = [ +      networking.interfaces.et0.ipv4.addresses = [          {            address = ip;            prefixLength = 27;          } +        { +          address = "46.4.114.243"; +          prefixLength = 27; +        }        ];        networking.defaultGateway = "46.4.114.225";        networking.nameservers = [ @@ -110,29 +114,13 @@ in {        };        # TODO write function for proxy_pass (ssl/nonssl) -      services.nginx.virtualHosts."hackerfleet.de" = { -        serverAliases = [ -          "*.hackerfleet.de" -        ]; -        locations."/".extraConfig = '' -          proxy_pass http://192.168.122.92:80; -        ''; -      }; -      services.nginx.virtualHosts."hackerfleet.de-s" = { -        serverName = "hackerfleet.de"; -        listen = [ -          { -            addr = "0.0.0.0"; -            port = 443; -          } -        ]; -        serverAliases = [ -          "*.hackerfleet.de" -        ]; -        locations."/".extraConfig = '' -          proxy_pass http://192.168.122.92:443; -        ''; -      }; + +      krebs.iptables.tables.filter.FORWARD.rules = [ +        { v6 = false; precedence = 1000; predicate = "-d 192.168.122.92"; target = "ACCEPT"; } +      ]; +      krebs.iptables.tables.nat.PREROUTING.rules = [ +        { v6 = false; precedence = 1000; predicate = "-d 46.4.114.243"; target = "DNAT --to-destination 192.168.122.92"; } +      ];      }      {        users.users.tv = { diff --git a/lass/2configs/monitoring/node-exporter.nix b/lass/2configs/monitoring/node-exporter.nix new file mode 100644 index 000000000..8c27e90d4 --- /dev/null +++ b/lass/2configs/monitoring/node-exporter.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: +{ +  networking.firewall.allowedTCPPorts = [ 9100 ]; + +  services.prometheus.exporters = { +    node = { +      enable = true; +      enabledCollectors = [ +        "systemd" +      ]; +    }; +  }; +} diff --git a/lass/2configs/monitoring/prometheus-server.nix b/lass/2configs/monitoring/prometheus-server.nix new file mode 100644 index 000000000..d56d7e552 --- /dev/null +++ b/lass/2configs/monitoring/prometheus-server.nix @@ -0,0 +1,179 @@ +{ pkgs, lib, config, ... }: +{ +  #networking = { +  #  firewall.allowedTCPPorts = [ +  #    3000  # grafana +  #    9090  # prometheus +  #    9093  # alertmanager +  #  ]; +  #  useDHCP = true; +  #}; + +  services = { +    prometheus = { +      enable = true; +      extraFlags = [ +        "-storage.local.retention 8760h" +        "-storage.local.series-file-shrink-ratio 0.3" +        "-storage.local.memory-chunks 2097152" +        "-storage.local.max-chunks-to-persist 1048576" +        "-storage.local.index-cache-size.fingerprint-to-metric 2097152" +        "-storage.local.index-cache-size.fingerprint-to-timerange 1048576" +        "-storage.local.index-cache-size.label-name-to-label-values 2097152" +        "-storage.local.index-cache-size.label-pair-to-fingerprints 41943040" +      ]; +      alertmanagerURL = [ "http://localhost:9093" ]; +      rules = [ +        '' +          ALERT node_down +          IF up == 0 +          FOR 5m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: Node is down.", +            description = "{{$labels.alias}} has been down for more than 5 minutes." +          } +          ALERT node_systemd_service_failed +          IF node_systemd_unit_state{state="failed"} == 1 +          FOR 4m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: Service {{$labels.name}} failed to start.", +            description = "{{$labels.alias}} failed to (re)start service {{$labels.name}}." +          } +          ALERT node_filesystem_full_90percent +          IF sort(node_filesystem_free{device!="ramfs"} < node_filesystem_size{device!="ramfs"} * 0.1) / 1024^3 +          FOR 5m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: Filesystem is running out of space soon.", +            description = "{{$labels.alias}} device {{$labels.device}} on {{$labels.mountpoint}} got less than 10% space left on its filesystem." +          } +          ALERT node_filesystem_full_in_4h +          IF predict_linear(node_filesystem_free{device!="ramfs"}[1h], 4*3600) <= 0 +          FOR 5m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: Filesystem is running out of space in 4 hours.", +            description = "{{$labels.alias}} device {{$labels.device}} on {{$labels.mountpoint}} is running out of space of in approx. 4 hours" +          } +          ALERT node_filedescriptors_full_in_3h +          IF predict_linear(node_filefd_allocated[1h], 3*3600) >= node_filefd_maximum +          FOR 20m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}} is running out of available file descriptors in 3 hours.", +            description = "{{$labels.alias}} is running out of available file descriptors in approx. 3 hours" +          } +          ALERT node_load1_90percent +          IF node_load1 / on(alias) count(node_cpu{mode="system"}) by (alias) >= 0.9 +          FOR 1h +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: Running on high load.", +            description = "{{$labels.alias}} is running with > 90% total load for at least 1h." +          } +          ALERT node_cpu_util_90percent +          IF 100 - (avg by (alias) (irate(node_cpu{mode="idle"}[5m])) * 100) >= 90 +          FOR 1h +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary = "{{$labels.alias}}: High CPU utilization.", +            description = "{{$labels.alias}} has total CPU utilization over 90% for at least 1h." +          } +          ALERT node_ram_using_90percent +          IF node_memory_MemFree + node_memory_Buffers + node_memory_Cached < node_memory_MemTotal * 0.1 +          FOR 30m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary="{{$labels.alias}}: Using lots of RAM.", +            description="{{$labels.alias}} is using at least 90% of its RAM for at least 30 minutes now.", +          } +          ALERT node_swap_using_80percent +          IF node_memory_SwapTotal - (node_memory_SwapFree + node_memory_SwapCached) > node_memory_SwapTotal * 0.8 +          FOR 10m +          LABELS { +            severity="page" +          } +          ANNOTATIONS { +            summary="{{$labels.alias}}: Running out of swap soon.", +            description="{{$labels.alias}} is using 80% of its swap space for at least 10 minutes now." +          } +        '' +      ]; +      scrapeConfigs = [ +        { +          job_name = "node"; +          scrape_interval = "10s"; +          static_configs = [ +            { +              targets = [ +                "localhost:9100" +              ]; +              labels = { +                alias = "prometheus.example.com"; +              }; +            } +          ]; +        } +      ]; +      alertmanager = { +        enable = true; +        listenAddress = "0.0.0.0"; +        configuration = { +          "global" = { +            "smtp_smarthost" = "smtp.example.com:587"; +            "smtp_from" = "alertmanager@example.com"; +          }; +          "route" = { +            "group_by" = [ "alertname" "alias" ]; +            "group_wait" = "30s"; +            "group_interval" = "2m"; +            "repeat_interval" = "4h"; +            "receiver" = "team-admins"; +          }; +          "receivers" = [ +            { +              "name" = "team-admins"; +              "email_configs" = [ +                { +                  "to" = "devnull@example.com"; +                  "send_resolved" = true; +                } +              ]; +              "webhook_configs" = [ +                { +                  "url" = "https://example.com/prometheus-alerts"; +                  "send_resolved" = true; +                } +              ]; +            } +          ]; +        }; +      }; +    }; +    grafana = { +      enable = true; +      addr = "0.0.0.0"; +      domain = "grafana.example.com"; +      rootUrl = "https://grafana.example.com/"; +      security = import <secrets/grafana_security.nix>; # { AdminUser = ""; adminPassword = ""} +    }; +  }; +} diff --git a/lass/2configs/reaktor-coders.nix b/lass/2configs/reaktor-coders.nix index 5fa1611ae..5a39f7115 100644 --- a/lass/2configs/reaktor-coders.nix +++ b/lass/2configs/reaktor-coders.nix @@ -4,7 +4,7 @@ with import <stockholm/lib>;  {    krebs.Reaktor.coders = {      nickname = "Reaktor|lass"; -    channels = [ "#coders" "#germany" ]; +    channels = [ "#coders" "#germany" "#panthermoderns" ];      extraEnviron = {        REAKTOR_HOST = "irc.hackint.org";      }; @@ -87,6 +87,19 @@ with import <stockholm/lib>;            exec /run/wrappers/bin/ping -q -c1 "$1" 2>&1 | tail -1          '';        }) +      (buildSimpleReaktorPlugin "google" { +        pattern = "^!g (?P<args>.*)$$"; +        script = pkgs.writeDash "google" '' +          exec ${pkgs.ddgr}/bin/ddgr -C -n1 --json "$@" | \ +            ${pkgs.jq}/bin/jq '@text "\(.[0].abstract) \(.[0].url)"' +        ''; +      }) +      (buildSimpleReaktorPlugin "blockchain" { +        pattern = ".*[Bb]lockchain.*$$"; +        script = pkgs.writeDash "blockchain" '' +          exec echo 'DID SOMEBODY SAY BLOCKCHAIN? https://paste.krebsco.de/r99pMoQq/+inline' +        ''; +      })      ];    };  } diff --git a/lass/2configs/syncthing.nix b/lass/2configs/syncthing.nix index cef43d1e6..17debf822 100644 --- a/lass/2configs/syncthing.nix +++ b/lass/2configs/syncthing.nix @@ -3,7 +3,6 @@ with import <stockholm/lib>;  {    services.syncthing = {      enable = true; -    useInotify = true;    };    krebs.iptables.tables.filter.INPUT.rules = [      { predicate = "-p tcp --dport 22000"; target = "ACCEPT";} diff --git a/lass/2configs/websites/util.nix b/lass/2configs/websites/util.nix index 62055d0fd..441b7af90 100644 --- a/lass/2configs/websites/util.nix +++ b/lass/2configs/websites/util.nix @@ -16,7 +16,7 @@ rec {      in {        services.nginx.virtualHosts.${domain} = {          enableACME = true; -        enableSSL = true; +        onlySSL = true;          extraConfig = ''            listen 80;            listen [::]:80; @@ -34,7 +34,7 @@ rec {      in {        services.nginx.virtualHosts."${domain}" = {          enableACME = true; -        enableSSL = true; +        onlySSL = true;          serverAliases = domains;          extraConfig = ''            listen 80; @@ -148,7 +148,7 @@ rec {      in {        services.nginx.virtualHosts."${domain}" = {          enableACME = true; -        enableSSL = true; +        onlySSL = true;          serverAliases = domains;          extraConfig = ''            listen 80; diff --git a/lass/3modules/default.nix b/lass/3modules/default.nix index 0c10e1ec2..5e7e6dff3 100644 --- a/lass/3modules/default.nix +++ b/lass/3modules/default.nix @@ -8,6 +8,7 @@ _:      ./mysql-backup.nix      ./news.nix      ./pyload.nix +    ./restic.nix      ./screenlock.nix      ./umts.nix      ./usershadow.nix diff --git a/lass/3modules/restic.nix b/lass/3modules/restic.nix new file mode 100644 index 000000000..c720793b1 --- /dev/null +++ b/lass/3modules/restic.nix @@ -0,0 +1,119 @@ +{ config, lib, pkgs, ... }: + +with import <stockholm/lib>; + +{ +  options.lass.restic = mkOption { +    type = types.attrsOf (types.submodule ({ config, ... }: { +      options = { +        name = mkOption { +          type = types.str; +          default = config._module.args.name; +        }; +        passwordFile = mkOption { +          type = types.str; +          default = toString <secrets/restic-password>; +          description = '' +            read the repository password from a file. +          ''; +          example = "/etc/nixos/restic-password"; + +        }; +        repo = mkOption { +          type = types.str; +          default = "sftp:backup@prism.r:/backups/${config.name}"; +          description = '' +            repository to backup to. +          ''; +          example = "sftp:backup@192.168.1.100:/backups/${config.name}"; +        }; +        dirs = mkOption { +          type = types.listOf types.str; +          default = []; +          description = '' +            which directories to backup. +          ''; +          example = [ +            "/var/lib/postgresql" +            "/home/user/backup" +          ]; +        }; +        timerConfig = mkOption { +          type = types.attrsOf types.str; +          default = { +            OnCalendar = "daily"; +          }; +          description = '' +            When to run the backup. See man systemd.timer for details. +          ''; +          example = { +            OnCalendar = "00:05"; +            RandomizedDelaySec = "5h"; +          }; +        }; +        user = mkOption { +          type = types.str; +          default = "root"; +          description = '' +            As which user the backup should run. +          ''; +          example = "postgresql"; +        }; +        extraArguments = mkOption { +          type = types.listOf types.str; +          default = []; +          description = '' +            Extra arguments to append to the restic command. +          ''; +          example = [ +            "sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp" +          ]; +        }; +        initialize = mkOption { +          type = types.bool; +          default = false; +          description = '' +            Create the repository if it doesn't exist. +          ''; +        }; +      }; +    })); +    default = {}; +  }; + +  config = { +    systemd.services = +      mapAttrs' (_: plan: +        let +          extraArguments = concatMapStringsSep " " (arg: "-o ${arg}") plan.extraArguments; +          connectTo = elemAt (splitString ":" plan.repo) 1; +          resticCmd = "${pkgs.restic}/bin/restic ${extraArguments}"; +        in nameValuePair "backup.${plan.name}" { +          environment = { +            RESTIC_PASSWORD_FILE = plan.passwordFile; +            RESTIC_REPOSITORY = plan.repo; +          }; +          path = with pkgs; [ +            openssh +          ]; +          restartIfChanged = false; +          serviceConfig = { +            ExecStartPre = mkIf plan.initialize (pkgs.writeScript "rustic-${plan.name}-init" '' +              #! ${pkgs.bash}/bin/bash +              ${resticCmd} snapshots || ${resticCmd} init +            ''); +            ExecStart = pkgs.writeDash "rustic-${plan.name}" ( +              "#! ${pkgs.bash}/bin/bash\n" + +              concatMapStringsSep "\n" (dir: "${resticCmd} backup ${dir}") plan.dirs +            ); +            User = plan.user; +          }; +        } +      ) config.lass.restic; +    systemd.timers = +      mapAttrs' (_: plan: nameValuePair "backup.${plan.name}" { +        wantedBy = [ "timers.target" ]; +        timerConfig = plan.timerConfig; +      }) config.lass.restic; +  }; +} diff --git a/lass/5pkgs/generate-secrets/default.nix b/lass/5pkgs/l-gen-secrets/default.nix index 5a4afe7c5..4b25fbd4c 100644 --- a/lass/5pkgs/generate-secrets/default.nix +++ b/lass/5pkgs/l-gen-secrets/default.nix @@ -1,5 +1,5 @@  { pkgs }: -pkgs.writeDashBin "generate-secrets" '' +pkgs.writeDashBin "l-gen-secrets" ''    HOSTNAME="$1"    TMPDIR=$(${pkgs.coreutils}/bin/mktemp -d)    PASSWORD=$(${pkgs.pwgen}/bin/pwgen 25 1) @@ -17,9 +17,9 @@ pkgs.writeDashBin "generate-secrets" ''    cd $TMPDIR    for x in *; do -    ${pkgs.coreutils}/bin/cat $x | ${pkgs.pass}/bin/pass insert -m hosts/$HOSTNAME/$x > /dev/null +    ${pkgs.coreutils}/bin/cat $x | ${pkgs.pass}/bin/pass insert -m krebs-secrets/$HOSTNAME/$x > /dev/null    done -  echo $PASSWORD | ${pkgs.pass}/bin/pass insert -m admin/hosts/$HOSTNAME/pass > /dev/null +  echo $PASSWORD | ${pkgs.pass}/bin/pass insert -m hosts/$HOSTNAME/pass > /dev | 
