# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).
{
  config,
  pkgs,
  lib,
  mms,
  ...
}: {
  imports = [
    ./hardware-configuration-void.nix
    ./common.nix
    mms.module
  ];

  networking.hostName = "void"; # Define your hostname.

  services.samba = {
    enable = false;
    openFirewall = true;
    securityType = "user";
    settings.global = {
      workgroup = "WORKGROUP";
      "server string" = "void";
      "netbios name" = "void";
      security = "user";
      "hosts allow" = "0.0.0.0/0";
      "guest account" = "nobody";
      "map to guest" = "bad user";
      "log level" = 4;
      #"smb encrypt" = "mandatory";
    };
    shares."Music" = {
      path = "/pile/Music";
      browsable = "yes";
      "read only" = "yes";
      "guest ok" = "no";
      "read list" = "@music";
    };
  };

  users.users.music = {
    group = "music";
    isNormalUser = true;
  };

  # enqble i2c-dev kernel module for control of backlight in external monitor
  # https://discourse.nixos.org/t/how-to-enable-ddc-brightness-control-i2c-permissions/20800/3
  boot.extraModulePackages = [
    config.boot.kernelPackages.ddcci-driver
  ];
  boot.kernelModules = ["i2c-dev" "ddcci_backlight"];
  hardware.i2c.enable = true;

  # package for controlling brightness on external monitor
  environment.systemPackages = [
    pkgs.ddcutil
  ];

  # mount external drive
  fileSystems."/external".label = "external";
  fileSystems."/external".options = ["nofail" "x-systemd.automount"];

  # backup
  services.borgbackup.jobs."external" = {
    paths = [
      "/home"
      "/var"
      "/pile"
    ];
    exclude = [
      "/home/*/.local/share/Steam"
      "**/*cache"
      "**/*Cache"
      "**/*trash"
      "**/*Trash"
      "/home/*/.mozilla/firefox"
      "/home/*/GOG Games"
      "**/target"
      "**/result"
      "/var/log"
    ];
    repo = "/external/voidbackup";
    encryption = {
      mode = "repokey-blake2";
      passCommand = "cat /root/borgbackup/passphrase";
    };
    compression = "auto,lzma";
    startAt = "daily";
    persistentTimer = true;
    extraCreateArgs = ["--stats" "--info" "--list" "--filter" "AMEC"];
    extraPruneArgs = ["--stats" "--info" "--list"];
    removableDevice = true;
    prune.keep = {
      within = "1d";
      daily = 7;
      weekly = 4;
      monthly = 12;
    };
  };
  systemd.services."borgbackup-job-external" = {
    unitConfig = {
      RequiresMountsFor = "/external";
      Requires = "external.mount";
    };
  };
  services.borgbackup.jobs."hetzner" = {
    paths = [
      "/home"
      "/var"
      "/pile"
    ];
    exclude = [
      "/home/*/.local/share/Steam"
      "**/*cache"
      "**/*Cache"
      "**/*trash"
      "**/*Trash"
      "/home/*/.mozilla/firefox"
      "/home/*/GOG Games"
      "**/target"
      "**/result"
      "/var/log"
      "/pile/void2backup"
    ];
    repo = "ssh://u480566-sub1@u480566-sub1.your-storagebox.de:23/./repo";
    encryption = {
      mode = "repokey-blake2";
      passCommand = "cat /root/borgbackup/hetzner_passphrase";
    };
    environment.BORG_RSH = "ssh -i /root/borgbackup/hetzner_ssh_key";
    compression = "auto,lzma";
    startAt = "daily";
    persistentTimer = true;
    extraCreateArgs = ["--stats" "--info" "--list" "--filter" "AMEC"];
    extraPruneArgs = ["--stats" "--info" "--list"];
    prune.keep = {
      within = "1d";
      daily = 7;
      weekly = 4;
      monthly = 12;
    };
    preHook = ''
      /bin/sh -c 'while ! /run/current-system/sw/bin/ping -c1 google.com; do sleep 1; done'
    '';
  };

  # postgresql backup
  services.postgresqlBackup = {
    enable = true;
    backupAll = true;
    location = "/var/backup/postgresql";
  };
  systemd.timers."postgresqlBackup".unitConfig.Persistent = true;

  # minecraft TerraFirmaGreg server
  services.modded-minecraft-servers = let
    # "Borrowed" from AllTheMods Discord
    jvmOpts = builtins.concatStringsSep " " [
      "-XX:+UseG1GC"
      "-XX:+ParallelRefProcEnabled"
      "-XX:MaxGCPauseMillis=200"
      "-XX:+UnlockExperimentalVMOptions"
      "-XX:+DisableExplicitGC"
      "-XX:+AlwaysPreTouch"
      "-XX:G1NewSizePercent=40"
      "-XX:G1MaxNewSizePercent=50"
      "-XX:G1HeapRegionSize=16M"
      "-XX:G1ReservePercent=15"
      "-XX:G1HeapWastePercent=5"
      "-XX:G1MixedGCCountTarget=4"
      "-XX:InitiatingHeapOccupancyPercent=20"
      "-XX:G1MixedGCLiveThresholdPercent=90"
      "-XX:G1RSetUpdatingPauseTimePercent=5"
      "-XX:SurvivorRatio=32"
      "-XX:+PerfDisableSharedMem"
      "-XX:MaxTenuringThreshold=1"
    ];
  in {
    eula = true;
    instances.terrafirmagreg = {
      enable = true;
      rsyncSSHKeys = [""];
      serverConfig = {
        server-port = 25565;
        motd = "Welcome to logistic-bot's TerraFirmaGreg server (v0.9.11)";
        allow-flight = true;
        allow-nether = false;
        difficulty = 0;
        enable-rcon = false;
        level-type = "tfc\:overworld";
        view-distance = 24;
      };

      inherit jvmOpts;
      jvmPackage = pkgs.jdk17;
      jvmMaxAllocation = "8196M";
      jvmInitialAllocation = "2048M";
    };
    instances.terrafirmagreg-stable = {
      enable = false;
      rsyncSSHKeys = [""];
      serverConfig = {
        server-port = 25566;
        motd = "Welcome to logistic-bot's TerraFirmaGreg server (v0.7.19 stable)";
        allow-flight = true;
        allow-nether = false;
        difficulty = 0;
        enable-rcon = false;
        level-type = "tfc\:overworld";
        view-distance = 24;
      };

      jvmPackage = pkgs.jdk17;
      jvmMaxAllocation = "8196M";
      jvmInitialAllocation = "2048M";

      # "Borrowed" from AllTheMods Discord
      inherit jvmOpts;
    };
  };
  systemd.services."mc-terrafirmagreg" = {
    requires = ["NetworkManager-wait-online.service"];
    after = ["NetworkManager-wait-online.service"];
  };

  services.miniflux = {
    enable = true;
    config = {
      LISTEN_ADDR = "localhost:8700";
      BASE_URL = "http://miniflux.005540.xyz";
      CREATE_ADMIN = 1;
    };
    adminCredentialsFile = "/home/khais/.miniflux.password";
  };

  services.jellyfin = {
    enable = true;
    openFirewall = true;
    user = "khais";
  };

  services.forgejo = {
    enable = true;
    database.type = "postgres";
    # Enable support for Git Large File Storage
    lfs.enable = true;
    settings = {
      server = {
        DOMAIN = "forgejo.005540.xyz";
        # You need to specify this to remove the port from URLs in the web UI.
        ROOT_URL = "https://forgejo.005540.xyz/";
        HTTP_PORT = 3000;
      };
      # You can temporarily allow registration to create an admin user.
      service.DISABLE_REGISTRATION = false;
      service.REGISTER_MANUAL_CONFIRM = true;
      # Add support for actions, based on act: https://github.com/nektos/act
      actions = {
        ENABLED = true;
        DEFAULT_ACTIONS_URL = "github";
      };
    };
  };

  services.paperless = {
    enable = true;
    address = "127.0.0.1";
    port = 28981;
    passwordFile = "/etc/nixos/secrets/paperless-password";
    consumptionDir = "/var/lib/paperless-upload";
    settings = {
      PAPERLESS_DBHOST = "/run/postgresql";
      PAPERLESS_DBNAME = "paperless";
      PAPERLESS_DBUSER = "paperless";
      PAPERLESS_DBPASS = "paperless";
      PAPERLESS_OCR_LANGUAGE = "fra+eng+deu";
      PAPERLESS_FILENAME_FORMAT = "{created_year}/{correspondent}/{title}";
      PAPERLESS_OCR_USER_ARGS = {
        optimize = 1;
        pdfa_image_compression = "lossless";
        # do not fail to import documents that have a digital signature
        # https://github.com/paperless-ngx/paperless-ngx/discussions/4047#discussioncomment-7019544
        invalidate_digital_signatures = true;
      };
      PAPERLESS_TIME_ZONE = "Europe/Paris";
      PAPERLESS_CONSUMER_ENABLE_BARCODES = "true";
      PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE = "true";
      PAPERLESS_CONSUMER_BARCODE_SCANNER = "ZXING";
      PAPERLESS_TASK_WORKERS = "4";
      PAPERLESS_THREADS_PER_WORKER = "1";
      PAPERLESS_WORKER_TIMEOUT = "18000";
      PAPERLESS_URL = "https://paperless.005540.xyz";
    };
  };
  users.groups.paperless-upload = {};
  users.users.paperless = {
    extraGroups = ["paperless-upload"];
  };
  users.users.paperless-upload = {
    isNormalUser = true;
    homeMode = "770";
    extraGroups = ["paperless"];
  };
  system.activationScripts.makePaperlessUploadDir = lib.stringAfter ["var"] ''
    mkdir -m 775 -p /var/lib/paperless-upload
    chown paperless:paperless /var/lib/paperless-upload/
  '';

  # immich
  services.immich = {
    enable = true;
    port = 2283;
    mediaLocation = "/pile/Photos/immich";
    settings.server.externalDomain = "http://immich.005540.xyz";
  };
  system.activationScripts.makeImmichMediaDir = lib.stringAfter ["var"] ''
    mkdir -m 775 -p /pile/Photos/immich
    chown immich:immich /pile/Photos/immich
  '';
  users.users.immich.extraGroups = ["video" "render"];

  services.nextcloud = {
    enable = true;
    package = pkgs.nextcloud31;
    hostName = "nextcloud.005540.xyz";
    https = true;
    secretFile = "/etc/nixos/secrets/nextcloud/secrets.json";
    config.adminpassFile = "/etc/nixos/secrets/nextcloud/adminpass";
    config.dbtype = "pgsql";
    settings.default_locale = "fr";
    settings.default_phone_region = "+33";
    database.createLocally = true;
    configureRedis = true;
    maxUploadSize = "64G";
  };

  # dynamic dns
  services.ddclient = {
    enable = true;
    protocol = "namecheap";
    passwordFile = "/etc/nixos/secrets/ddclient/password";
    server = "dynamicdns.park-your-domain.com";
    username = "005540.xyz";
    domains = ["@" "*"];
    use = "web";
    extraConfig = ''
      web=dynamicdns.park-your-domain.com/getip
    '';
  };

  # static ipv6
  networking.interfaces.wlo1.ipv6.addresses = [
    {
      address = "2a01:cb06:101:e100:e052:b96a:4ea7:5fa0";
      prefixLength = 64;
    }
  ];

  security.acme = {
    acceptTerms = true;
    defaults = {
      email = "khais.colin+letsencrypt@gmail.com";
      dnsProvider = "namecheap";
    };
  };

  services.victorialogs = {
    enable = true;
    extraOptions = ["-memory.allowedBytes=100MB"];
  };

  services.journald.upload = {
    enable = true;
    settings.Upload.URL = "http://localhost:9428/insert/journald";
  };

  networking.firewall.allowedTCPPorts = [
    80
    443
  ];
  networking.firewall.allowedUDPPorts = [
    80
    443
  ];

  # reverse proxy
  services.nginx = {
    enable = true;
    recommendedTlsSettings = true;
    recommendedOptimisation = true;
    recommendedGzipSettings = true;
    recommendedProxySettings = true;
    logError = "stderr info";
    appendHttpConfig = ''
      access_log syslog:server=unix:/dev/log combined;
    '';
    virtualHosts = {
      "void.hummingbird-stork.ts.net" = {
        locations."/".proxyPass = "http://localhost:8096";
      };
      "jellyfin.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:8096";
        enableACME = true;
        forceSSL = true;
      };
      "forgejo.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:3000";
        enableACME = true;
        forceSSL = true;
      };
      "miniflux.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:8700";
        enableACME = true;
        forceSSL = true;
      };
      "paperless.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:28981";
        enableACME = true;
        forceSSL = true;
      };
      "immich.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:2283";
        locations."/".proxyWebsockets = true;
        extraConfig = ''
          client_max_body_size 50000M;
          proxy_read_timeout   600s;
          proxy_send_timeout   600s;
          send_timeout         600s;
        '';
        enableACME = true;
        forceSSL = true;
      };
      "audiobookshelf.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:8000";
        locations."/".proxyWebsockets = true;
        enableACME = true;
        forceSSL = true;
      };
      "victorialogs.005540.xyz" = {
        locations."/".proxyPass = "http://localhost:9428";
        locations."/".basicAuthFile = "/etc/nixos/secrets/victorialogs/basicauth";
        enableACME = true;
        forceSSL = true;
      };
      "nextcloud.005540.xyz" = {
        locations."/".proxyWebsockets = true;
        enableACME = true;
        forceSSL = true;
      };
    };
  };
}
