{ description = "Skynet Discord Bot"; inputs = { nixpkgs.url = "nixpkgs/nixos-23.05"; naersk.url = "github:nix-community/naersk"; utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, utils, naersk }: utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages."${system}"; naersk-lib = naersk.lib."${system}"; package_name = "skynet_discord_bot"; desc = "Skynet Discord Bot"; in rec { # `nix build` packages."${package_name}" = naersk-lib.buildPackage { pname = "${package_name}"; root = ./.; buildInputs = [ pkgs.openssl pkgs.pkg-config ]; }; defaultPackage = packages."${package_name}"; # `nix run` apps."${package_name}" = utils.lib.mkApp { drv = packages."${package_name}"; }; defaultApp = apps."${package_name}"; # `nix develop` devShell = pkgs.mkShell { nativeBuildInputs = with pkgs; [ rustc cargo pkg-config openssl]; }; nixosModule = { lib, pkgs, config, ... }: with lib; let cfg = config.services."${package_name}"; # secret options are in the env file(s) loaded separately environment_config = { LDAP_API = cfg.ldap; SKYNET_SERVER = cfg.discord.server; HOME = cfg.home; DATABASE = "database.db"; CSV = "wolves.csv"; }; service_name = script: lib.strings.sanitizeDerivationName("${cfg.user}@${script}"); # oneshot scripts to run serviceGenerator = mapAttrs' (script: time: nameValuePair (service_name script) { description = "Service for ${desc} ${script}"; wantedBy = [ ]; after = [ "network-online.target" ]; environment = environment_config; serviceConfig = { Type = "oneshot"; User = "${cfg.user}"; Group = "${cfg.user}"; ExecStart = "${self.defaultPackage."${system}"}/bin/${script}"; EnvironmentFile = [ "${cfg.env.ldap}" "${cfg.env.discord}" "${cfg.env.mail}" ]; }; }); # each timer will run the above service timerGenerator = mapAttrs' (script: time: nameValuePair (service_name script) { description = "Timer for ${desc} ${script}"; wantedBy = [ "timers.target" ]; partOf = [ "${service_name script}.service" ]; timerConfig = { OnCalendar = time; Unit = "${service_name script}.service"; Persistent = true; }; }); # modify these scripts = { # every 20 min "update_data" = "*:0,20,40"; # groups are updated every 8 hours, offset from teh ldap "update_users" = "01,09,17:00:00"; }; in { options.services."${package_name}" = { enable = mkEnableOption "enable ${package_name}"; env = { ldap = mkOption rec { type = types.str; description = "ENV file with LDAP_DISCORD_AUTH"; }; discord = mkOption rec { type = types.str; description = "ENV file with DISCORD_TOKEN"; }; mail = mkOption rec { type = types.str; description = "ENV file with EMAIL_SMTP, EMAIL_USER, EMAIL_PASS"; }; }; discord = { server = mkOption rec { type = types.str; description = "ID of the server the bot runs on"; }; }; ldap = mkOption rec { type = types.str; default = "https://api.account.skynet.ie"; description = "Location of the ldap api"; }; user = mkOption rec { type = types.str; default = "${package_name}"; description = "The user to run the service"; }; home = mkOption rec { type = types.str; default = "/etc/${cfg.prefix}${package_name}"; description = "The home for the user"; }; prefix = mkOption rec { type = types.str; default = "skynet_"; example = default; description = "The prefix used to name service/folders"; }; }; config = mkIf cfg.enable { users.groups."${cfg.user}" = { }; users.users."${cfg.user}" = { createHome = true; isSystemUser = true; home = "${cfg.home}"; group = "${cfg.user}"; }; systemd.services = { # main service "${package_name}" = { description = desc; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ ]; environment = environment_config; serviceConfig = { User = "${cfg.user}"; Group = "${cfg.user}"; Restart = "always"; ExecStart = "${self.defaultPackage."${system}"}/bin/${package_name}"; # can have multiple env files EnvironmentFile = [ "${cfg.env.ldap}" "${cfg.env.discord}" "${cfg.env.mail}" ]; }; }; } // serviceGenerator scripts; # timers to run the above services systemd.timers = timerGenerator scripts; }; }; } ); }