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";
};
};
};
};
};
}
|