aboutsummaryrefslogblamecommitdiff
path: root/flakes/paste/flake.nix
blob: 97e31c84fcb3b4aed647020d8c24e8c000c0dbac (plain) (tree)














































                                                                                               

                                                                                                                  


























































































                                                                                                                                                                        
{
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs";

  description = "Pastebin-like service";

  outputs = { self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem (system:
    let
      pkgs = import nixpkgs { inherit system; overlays = []; };
    in rec {
      hydraJobs = checks;
      checks = pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) {
        test =
          let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; };
          in testing.makeTest {
            nodes = {
              server = { pkgs, ... }: {
                imports = [ self.nixosModule ];
                config = {
                  environment.systemPackages = [ pkgs.curl ];
                  services.httpd = {
                    enable = true;
                    adminAddr = "foo@example.org";
                    extraConfig = ''
                      ProxyPass        / unix:///run/paste/gunicorn.sock|http://localhost/
                      ProxyPassReverse / unix:///run/paste/gunicorn.sock|http://localhost/
                    '';
                  };
                  services.paste.enable = true;
                };
              };
            };
            testScript = ''
              start_all()
              server.wait_for_unit("httpd.service")
              server.wait_for_unit("paste.service")
              server.wait_until_succeeds("[ -S /run/paste/gunicorn.sock ]", 10)
              server.succeed("curl -f http://localhost/")
              server.succeed("curl -f http://localhost/ | grep -q 'Get the source'")
            '';
          };
        };
    }) // rec {
      nixosModule = { config, lib, pkgs, ... }:
        let
          cfg = config.services.paste;
        in {
          # Necessary for situations where flake gets included multiple times
          key = builtins.hashString "sha256" (builtins.path { path = self.sourceInfo.outPath; name = "source"; });
          options = {
            services.paste = {
              enable = lib.mkOption {
                type = lib.types.bool;
                default = false;
                description = "Whether to enable the pastebin service";
              };

              dataDir = lib.mkOption {
                type = lib.types.path;
                default = "/var/lib/paste";
                description = ''
                  The directory where Paste stores its data.
                '';
              };

              socketsDir = lib.mkOption {
                type = lib.types.str;
                default = "/run/paste";
                description = "Socket which is used for communication with Paste.";
              };

              webDirectory = lib.mkOption {
                type = lib.types.nullOr lib.types.str;
                default = null;
                description = "Subdirectory url to which the app will be served";
              };

              # Output variables
              systemdStateDirectory = lib.mkOption {
                type = lib.types.str;
                # Use ReadWritePaths= instead if varDir is outside of /var/lib
                default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
                              lib.strings.removePrefix "/var/lib/" cfg.dataDir;
                description = ''
                  Adjusted paste data directory for systemd
                '';
                readOnly = true;
              };
              systemdRuntimeDirectory = lib.mkOption {
                type = lib.types.str;
                # Use ReadWritePaths= instead if socketsDir is outside of /run
                default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
                  lib.strings.removePrefix "/run/" cfg.socketsDir;
                description = ''
                Adjusted paste sockets directory for systemd
                '';
                readOnly = true;
              };
              sockets = lib.mkOption {
                type = lib.types.attrsOf lib.types.path;
                default = {
                  pid      = "${cfg.socketsDir}/gunicorn.pid";
                  gunicorn = "${cfg.socketsDir}/gunicorn.sock";
                };
                readOnly = true;
                description = ''
                  Paste sockets
                  '';
              };
            };
          };

          config = lib.mkIf cfg.enable {
            systemd.services.paste = {
              description = "Pastebin like service";
              after = [ "network.target" ];
              wantedBy = [ "multi-user.target" ];

              serviceConfig = {
                Environment = pkgs.lib.optionals (cfg.webDirectory != null) [ "SCRIPT_NAME=${cfg.webDirectory}" ];
                Type = "simple";
                User = config.services.httpd.user;
                ExecStart = let
                  python = pkgs.python3.withPackages (p: [p.gunicorn p.flask p.pygments p.python_magic ]);
                in
                  "${python}/bin/gunicorn -w4 -p ${cfg.sockets.pid} -e PASTE_DIRECTORY=${cfg.dataDir} --bind unix:${cfg.sockets.gunicorn} --chdir ${./paste} paste:app";
                Restart = "always";
                RestartSec = "5s";
                PIDFile = cfg.sockets.pid;
                RuntimeDirectory = cfg.systemdRuntimeDirectory;
                StateDirectory = cfg.systemdStateDirectory;
                StandardOutput = "journal";
                StandardError = "inherit";
              };

            };
          };
        };
    };
}