2 inputs.flake-utils.url = "github:numtide/flake-utils";
3 inputs.nixpkgs.url = "github:NixOS/nixpkgs";
5 description = "Pastebin-like service";
7 outputs = { self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem (system:
9 pkgs = import nixpkgs { inherit system; overlays = []; };
12 checks = pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) {
14 let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; };
17 server = { pkgs, ... }: {
18 imports = [ self.nixosModule ];
20 environment.systemPackages = [ pkgs.curl ];
23 adminAddr = "foo@example.org";
25 ProxyPass / unix:///run/paste/gunicorn.sock|http://localhost/
26 ProxyPassReverse / unix:///run/paste/gunicorn.sock|http://localhost/
29 services.paste.enable = true;
35 server.wait_for_unit("httpd.service")
36 server.wait_for_unit("paste.service")
37 server.wait_until_succeeds("[ -S /run/paste/gunicorn.sock ]", 10)
38 server.succeed("curl -f http://localhost/")
39 server.succeed("curl -f http://localhost/ | grep -q 'Get the source'")
44 nixosModule = { config, lib, pkgs, ... }:
46 cfg = config.services.paste;
48 # Necessary for situations where flake gets included multiple times
49 key = builtins.hashString "sha256" (builtins.path { path = self.sourceInfo.outPath; name = "source"; });
52 enable = lib.mkOption {
53 type = lib.types.bool;
55 description = "Whether to enable the pastebin service";
58 dataDir = lib.mkOption {
59 type = lib.types.path;
60 default = "/var/lib/paste";
62 The directory where Paste stores its data.
66 socketsDir = lib.mkOption {
68 default = "/run/paste";
69 description = "Socket which is used for communication with Paste.";
72 webDirectory = lib.mkOption {
73 type = lib.types.nullOr lib.types.str;
75 description = "Subdirectory url to which the app will be served";
79 systemdStateDirectory = lib.mkOption {
81 # Use ReadWritePaths= instead if varDir is outside of /var/lib
82 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
83 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
85 Adjusted paste data directory for systemd
89 systemdRuntimeDirectory = lib.mkOption {
91 # Use ReadWritePaths= instead if socketsDir is outside of /run
92 default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
93 lib.strings.removePrefix "/run/" cfg.socketsDir;
95 Adjusted paste sockets directory for systemd
99 sockets = lib.mkOption {
100 type = lib.types.attrsOf lib.types.path;
102 pid = "${cfg.socketsDir}/gunicorn.pid";
103 gunicorn = "${cfg.socketsDir}/gunicorn.sock";
113 config = lib.mkIf cfg.enable {
114 systemd.services.paste = {
115 description = "Pastebin like service";
116 after = [ "network.target" ];
117 wantedBy = [ "multi-user.target" ];
120 Environment = pkgs.lib.optionals (cfg.webDirectory != null) [ "SCRIPT_NAME=${cfg.webDirectory}" ];
122 User = config.services.httpd.user;
124 python = pkgs.python3.withPackages (p: [p.gunicorn p.flask p.pygments p.python_magic ]);
126 "${python}/bin/gunicorn -w4 -p ${cfg.sockets.pid} -e PASTE_DIRECTORY=${cfg.dataDir} --bind unix:${cfg.sockets.gunicorn} --chdir ${./paste} paste:app";
129 PIDFile = cfg.sockets.pid;
130 RuntimeDirectory = cfg.systemdRuntimeDirectory;
131 StateDirectory = cfg.systemdStateDirectory;
132 StandardOutput = "journal";
133 StandardError = "inherit";