diff --git a/configuration.nix b/configuration.nix index 3d259ac..fd171c5 100644 --- a/configuration.nix +++ b/configuration.nix @@ -12,6 +12,7 @@ ./redstring.nix ./catacomb.nix ./gitea.nix + ./inquisitor.nix ]; # Use the GRUB 2 boot loader. diff --git a/inquisitor.nix b/inquisitor.nix new file mode 100644 index 0000000..a266c4f --- /dev/null +++ b/inquisitor.nix @@ -0,0 +1,138 @@ +{pkgs, ...}: + +let + # Import the inquisitor package and build it + inquisitorSource = pkgs.fetchFromGitHub { + owner = "Jaculabilis"; + repo = "Inquisitor"; + rev = "a6d961aba948d3a682dbde12dbaa8805eadbbd84"; + sha256 = "10n6c5zvi27f92b7am0rrdizxz0mlp3rw1y1jyd44b57ykk7x6fr"; + }; + inquisitor = pkgs.callPackage inquisitorSource {}; + + # Define the inquisitor data directory + inquisiDir = "/var/lib/inquisitor"; + + # Define an scp helper for executing in cron jobs + scp-helper = pkgs.writeShellScriptBin "scp-helper" '' + ${pkgs.openssh}/bin/scp -i ${inquisiDir}/inquisitor.key -oStrictHostKeyChecking=no "$@" + ''; + + # Define the inquisitor service user + inquisitorUser = { + name = "inquisitor"; + group = "inquisitor"; + description = "Inquisitor service user"; + isSystemUser = true; + shell = pkgs.bashInteractive; + packages = [ inquisitor pkgs.cron ]; + }; + + # Create the inquisitor config file in the nix store, pointing to /var/lib/ + inquisitorConfig = pkgs.writeTextFile { + name = "inquisitor.conf"; + text = '' + DataPath = ${inquisiDir}/data/ + SourcePath = ${inquisiDir}/sources/ + CachePath = ${inquisiDir}/cache/ + Verbose = false + LogFile = ${inquisiDir}/inquisitor.log + ''; + }; + + # Create a setup script to ensure the service directory state + inquisitorSetup = pkgs.writeShellScriptBin "inquisitor-setup.sh" '' + # Ensure the service directory and the default source directory + ${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/data/inquisitor/ + ${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/sources/ + ${pkgs.coreutils}/bin/mkdir -p ${inquisiDir}/cache/ + if [ ! -f ${inquisiDir}/data/inquisitor/state ]; then + ${pkgs.coreutils}/bin/echo "{}" > ${inquisiDir}/data/inquisitor/state + fi + + # Ensure the service owns the folders + chown -R ${inquisitorUser.name} ${inquisiDir} + + # Ensure the scp helper is present + if [ -f ${inquisiDir}/scp-helper ]; then + rm ${inquisiDir}/scp-helper + fi + ln -s -t ${inquisiDir} ${scp-helper}/bin/scp-helper + ''; + + # Create a run script for the server + inquisitorRun = pkgs.writeShellScriptBin "inquisitor-run.sh" '' + cd ${inquisiDir} + ${inquisitor}/bin/gunicorn \ + --bind=localhost:24133 \ + --workers=4 \ + --timeout 120 \ + --log-level debug \ + "inquisitor.app:wsgi()" + ''; + + # Create a wrapper to execute the cli as the service user + inquisitorWrapper = pkgs.writeShellScriptBin "inq" '' + sudo --user=inquisitor ${inquisitor}/bin/inquisitor "$@" + ''; +in +{ + users.users.inquisitor = inquisitorUser; + users.groups.inquisitor = {}; + + # Link the config in /etc to avoid envvar shenanigans + environment.etc."inquisitor.conf".source = "${inquisitorConfig}"; + + # Give all users the inq wrapper + environment.systemPackages = [ inquisitorWrapper ]; + + # Allow the sudo in the cli wrapper without password + security.sudo.extraRules = [{ + commands = [{ + command = "${inquisitor}/bin/inquisitor"; + options = [ "NOPASSWD" ]; + }]; + runAs = "${inquisitorUser.name}"; + groups = [ "users" ]; + }]; + + # Run the setup script on activation + system.activationScripts.inquisitorSetup = "${inquisitorSetup}/bin/inquisitor-setup.sh"; + + # Set up the inquisitor service + systemd.services.inquisitor = + { + description = "Inquisitor server"; + script = "${inquisitorRun}/bin/inquisitor-run.sh"; + serviceConfig = { + User = "${inquisitorUser.name}"; + Type = "simple"; + }; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + enable = true; + }; + + # Set up nginx to reverse proxy from the beatific url to the inq server + services.nginx.enable = true; + services.nginx.virtualHosts.inquisitorHost = { + listen = [ { addr = "10.7.3.1"; port = 80; } ]; + locations."/".extraConfig = '' + access_log /var/log/nginx/access.inquisitor.log; + proxy_buffering off; + proxy_pass http://localhost:24133/; + ''; + }; + + # Allow nginx through the firewall + networking.firewall = { + allowedTCPPorts = [ + 80 # http + 443 # https + ]; + }; + + # Enable cron, but don't set up any system cron jobs + # Inquisitor updates will be managed manually + services.cron.enable = true; +}