added stuff

This commit is contained in:
vali 2024-04-09 23:11:33 +02:00
commit 7d4f626b7d
907 changed files with 70990 additions and 0 deletions

View file

@ -0,0 +1,31 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib) mkOption mkEnableOption types literalExpression;
cfg = config.programs.comma;
in {
options.programs.comma = {
enable = mkEnableOption "comma, a wrapper to run software without installing it";
package = mkOption {
type = types.package;
default = pkgs.comma.override {nix-index-unwrapped = config.programs.nix-index.package;};
defaultText = literalExpression "pkgs.comma.override { nix-index-unwrapped = config.programs.nix-index.package; }";
description = "Package providing the `comma` tool.";
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [cfg.package];
programs = {
command-not-found.enable = lib.mkForce false;
nix-index.enable = true;
};
};
}

View file

@ -0,0 +1,7 @@
{
imports = [
./comma
./wakapi
./reposilite
];
}

View file

@ -0,0 +1,242 @@
{
config,
lib,
...
}: let
inherit (lib) mkEnableOption mkOption types mkIf getExe;
writeServiceConfig = config:
lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name}: ${
(
if (lib.isBool value)
then (lib.boolToString value)
else (toString value)
)
}")
config);
cfg = config.services.reposilite;
in {
options.services.reposilite = {
enable = mkEnableOption "reposilite - maven repository manager";
package = mkOption {
type = with types; nullOr package;
default = null; # reposilite is not in nixpkgs
description = "Package to install";
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/reposilite";
description = "Working directory";
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Open firewall for reposilite";
};
user = mkOption {
type = types.str;
default = "reposilite";
description = "User to run reposilite as";
};
group = mkOption {
type = types.str;
default = "reposilite";
description = "Group to run reposilite as";
};
settings = mkOption {
default = {};
description = "Settings to pass to reposilite";
type = with types;
submodule {
freeformType = attrs;
options = {
hostname = mkOption {
type = types.str;
default = "0.0.0.0";
description = "Hostname to listen on";
};
port = mkOption {
type = types.int;
default = 8080;
description = "Port to listen on";
};
database = mkOption {
type = types.str;
default = "sqlite reposilite.db";
description = ''
Database configuration. Supported storage providers:
- mysql localhost:3306 database user password
- sqlite reposilite.db
- sqlite --temporary
Experimental providers (not covered with tests):
- postgresql localhost:5432 database user password
- h2 reposilite
'';
};
sslEnabled = mkOption {
type = types.bool;
default = false;
example = true;
description = "Support encrypted connections";
};
sslPort = mkOption {
type = types.int;
default = 443;
description = "Port to listen on for SSL connections";
};
keyPath = mkOption {
type = with types; nullOr str;
default = "$${WORKING_DIRECTORY}/cert.pem $${WORKING_DIRECTORY}/key.pem";
example = "${cfg.dataDir}/cert.pem ${cfg.dataDir}/key.pem";
description = ''
Key file to use. You can specify absolute path to the given file or use {option}`services.reposilite.dataDir` variable.
If you want to use .pem certificate you need to specify its path next to the key path.
'';
};
keyPassword = mkOption {
type = with types; nullOr str;
default = "";
example = "reposilite";
description = "Key password to use";
};
enforceSsl = mkOption {
type = types.bool;
default = false;
description = "Redirect http traffic to https";
};
webThreadPoolSize = mkOption {
type = types.addCheck types.int (x: x >= 5);
default = 16;
description = "Max amount of threads used by core thread pool (min: 5)";
};
ioThreadPool = mkOption {
type = types.addCheck types.int (x: x >= 2);
default = 8;
description = "IO thread pool handles all tasks that may benefit from non-blocking IO (min: 2)";
};
databaseThreadPool = mkOption {
type = types.addCheck types.int (x: x >= 1);
default = 8;
description = "Database thread pool manages open connections to database (min: 1)";
};
compressionStrategy = mkOption {
type = types.enum ["none" "gzip"];
default = "none";
description = ''
Select compression strategy used by this instance.
Using 'none' reduces usage of CPU & memory, but ends up with higher transfer usage.
GZIP is better option if you're not limiting resources that much to increase overall request times.
'';
};
idleTimeout = mkOption {
type = types.int;
default = 30000;
description = "Default idle timeout used by Jetty";
};
bypassExternalCache = mkOption {
type = types.bool;
default = true;
description = ''
Bypass external cache and use internal one.
Adds cache bypass headers to each request from `/api/*` scope served by this instance
'';
};
cachedLogSize = mkOption {
type = types.int;
default = 50;
description = "Amount of messages stored in cached logger";
};
defaultFrontend = mkOption {
type = types.bool;
default = true;
description = "Enable default frontend with dashboard";
};
basePath = mkOption {
type = types.str;
default = "/";
description = ''
Set custom base path for Reposilite instance.
It's not recommended to mount Reposilite under custom base path
and you should always prioritize subdomain over this option.
'';
};
debugEnabled = mkOption {
type = types.bool;
default = false;
description = "Debug mode";
};
};
};
};
};
config = mkIf cfg.enable {
environment = {
systemPackages = [cfg.package];
etc."reposilite/configuration.cdn" = mkIf (cfg.settings != {}) {
text = writeServiceConfig cfg.settings;
};
};
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.settings.port];
users = {
groups.reposilite = {
name = cfg.group;
};
users.reposilite = {
group = cfg.user;
home = cfg.dataDir;
isSystemUser = true;
createHome = true;
};
};
systemd.services."reposilite" = {
description = "Reposilite - Maven repository";
wantedBy = ["multi-user.target"];
script = let
inherit (cfg) dataDir;
staticConfig = ''--local-config "/etc/reposilite/configuration.cdn" --local-configuration-mode none'';
in ''
${getExe cfg.package} --working-directory "${dataDir}" ${staticConfig}
'';
serviceConfig = {
inherit (cfg) user group;
WorkingDirectory = cfg.dataDir;
SuccessExitStatus = 0;
TimeoutStopSec = 10;
Restart = "on-failure";
RestartSec = 5;
};
};
};
}

View file

@ -0,0 +1,147 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib) concatStrings mapAttrsToList concatMapAttrs optionalAttrs optionalString foldl' stringLength elem substring head lowerChars toUpper isBool isList boolToString types mkIf optional mkOption mkEnableOption;
cfg = config.services.wakapi;
user = config.users.users.wakapi.name;
group = config.users.groups.wakapi.name;
configFile = pkgs.writeText "wakapi.env" (concatStrings (mapAttrsToList (name: value: "${name}=${value}\n") configEnv));
# Convert name from camel case (e.g. disable2FARemember) to upper case snake case (e.g. DISABLE_2FA_REMEMBER).
nameToEnvVar = name: let
parts = builtins.split "([A-Z0-9]+)" name;
partsToEnvVar = parts:
foldl' (key: x: let
last = stringLength key - 1;
in
if isList x
then key + optionalString (key != "" && substring last 1 key != "_") "_" + head x
else if key != "" && elem (substring 0 1 x) lowerChars
then # to handle e.g. [ "disable" [ "2FAR" ] "emember" ]
substring 0 last key + optionalString (substring (last - 1) 1 key != "_") "_" + substring last 1 key + toUpper x
else key + toUpper x) ""
parts;
in
if builtins.match "[A-Z0-9_]+" name != null
then name
else partsToEnvVar parts;
# Due to the different naming schemes allowed for config keys,
# we can only check for values consistently after converting them to their corresponding environment variable name.
configEnv = let
configEnv = concatMapAttrs (name: value:
optionalAttrs (value != null) {
${nameToEnvVar name} =
if isBool value
then boolToString value
else toString value;
})
cfg.config;
in
configEnv;
in {
options.services.wakapi = with types; {
enable = mkEnableOption "wakapi";
package = mkOption {
type = package;
default = pkgs.wakapi;
defaultText = literalExpression "pkgs.wakapi";
description = "wakapi package to use.";
};
stateDirectory = mkOption {
type = str;
default = "wakapi";
defaultText = literalExpression "wakapi";
description = "The state directory for the systemd service. Will be located in /var/lib";
};
config = mkOption {
type = attrsOf (nullOr (oneOf [bool int str]));
default = {
config = {};
};
example = literalExpression ''
{
WAKAPI_LISTEN_IPV4=127.0.0.1
WAKAPI_LISTEN_IPV6=::1
WAKAPI_PORT=3000
}
'';
description = ''
The configuration of wakatime is done through environment variables,
therefore it is recommended to use upper snake case (e.g. {env}`WAKAPI_DATA_CLEANUP_TIME`).
However, camel case (e.g. `wakapiDataCleanupTime`) is also supported:
The NixOS module will convert it automatically to
upper case snake case (e.g. {env}`WAKAPI_DATA_CLEANUP_TIME`).
In this conversion digits (0-9) are handled just like upper case characters,
so `foo2` would be converted to {env}`FOO_2`.
Names already in this format remain unchanged, so `FOO2` remains `FOO2` if passed as such,
even though `foo2` would have been converted to {env}`FOO_2`.
This allows working around any potential future conflicting naming conventions.
Based on the attributes passed to this config option an environment file will be generated
that is passed to wakapi's systemd service.
The available configuration options can be found in
[self-hostiing guide](https://github.com/muety/wakapi#-configuration-options) to
find about the environment variables you can use.
'';
};
environmentFile = mkOption {
type = with types; nullOr path;
default = null;
example = "/etc/wakapi.env";
description = ''
Additional environment file as defined in {manpage}`systemd.exec(5)`.
Sensitive secrets such as {env}`WAKAPI_PASSWORD_SALT` and {env}`WAKAPI_DB_PASSWORD`
may be passed to the service while avoiding potentially making them world-readable in the nix store or
to convert an existing non-nix installation with minimum hassle.
Note that this file needs to be available on the host on which
`wakapi` is running.
'';
};
};
config = mkIf cfg.enable {
users.users.wakapi = {
inherit group;
isSystemUser = true;
};
users.groups.wakapi = {};
systemd.services.wakapi = {
after = ["network.target"];
#path = with pkgs; [openssl];
serviceConfig = {
User = user;
Group = group;
EnvironmentFile = [configFile] ++ optional (cfg.environmentFile != null) cfg.environmentFile;
ExecStart = "${cfg.package}/bin/wakapi";
LimitNOFILE = "1048576";
PrivateTmp = "true";
PrivateDevices = "true";
ProtectHome = "true";
ProtectSystem = "strict";
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
StateDirectory = "${cfg.stateDirectory}";
WorkingDirectory = "/var/lib/${cfg.stateDirectory}";
StateDirectoryMode = "0700";
Restart = "always";
};
wantedBy = ["multi-user.target"];
};
systemd.tmpfiles.rules = [
"D /var/lib/${cfg.stateDirectory}/data 755 ${user} ${group} - -"
];
};
}