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,6 @@
{
imports = [
./nixos
./home-manager
];
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,101 @@
{
config,
lib,
pkgs,
...
}:
with builtins; let
cfg = config.programs.gtklock;
inherit (lib) types mkIf mkOption mkEnableOption mkPackageOptionMD literalExpression optionals optionalString;
inherit (lib.generators) toINI;
# the main config includes two very niche options: style (which takes a path) and modules, which takes a list of module paths
# concatted by ";"
# for type checking purposes, I prefer templating the main section of the config and let the user safely choose options
# extraConfig takes an attrset, and converts it to the correct INI format - it's mostly just strings and integers, so that's fine
baseConfig = ''
[main]
${optionalString (cfg.config.gtk-theme != "") "gtk-theme=${cfg.config.gtk-theme}"}
${optionalString (cfg.config.style != "") "style=${cfg.config.style}"}
${optionalString (cfg.config.modules != []) "modules=${concatStringsSep ";" cfg.config.modules}"}
'';
finalConfig = baseConfig + optionals (cfg.extraConfig != null) (toINI {} cfg.extraConfig);
in {
meta.maintainers = [maintainers.NotAShelf];
options.programs.gtklock = {
enable = mkEnableOption "GTK-based lockscreen for Wayland";
package = mkPackageOptionMD pkgs "gtklock" {};
config = {
gtk-theme = mkOption {
type = types.str;
default = "";
description = ''
GTK theme to use for gtklock.
'';
example = "Adwaita-dark";
};
style = mkOption {
type = with types; oneOf [str path];
default = "";
description = ''
The css file to be used for gtklock.
'';
example = literalExpression ''
pkgs.writeText "gtklock-style.css" '''
window {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
'''
'';
};
modules = mkOption {
type = with types; listOf (either package str);
default = [];
description = ''
A list of gtklock modulesto use. Can either be packages, absolute paths, or strings.
'';
example = literalExpression ''
[
"${pkgs.gtklock-powerbar-module.outPath}/lib/gtklock/powerbar-module.so"
"${pkgs.gtklock-playerctl-module.outPath}/lib/gtklock/playerctl-module.so"
];
'';
};
};
extraConfig = mkOption {
type = with types; nullOr attrs;
default = {
countdown = {
countdown-position = "top-right";
justify = "right";
countdown = 20;
};
};
description = ''
Extra configuration to append to gtklock configuration file.
Mostly used for appending module configurations.
'';
example = literalExpression ''
countdown = {
countdown-position = "top-right";
justify = "right";
countdown = 20;
}
'';
};
};
config = mkIf cfg.enable {
home.packages = [cfg.package];
xdg.configFile."gtklock/config.ini".source = pkgs.writeText "gtklock-config.ini" finalConfig;
};
}

View file

@ -0,0 +1,76 @@
{
config,
pkgs,
lib,
...
}: let
inherit (lib) mkOption mkEnableOption types;
cfg = config.services.transience;
in {
meta.maintainers = [lib.maintainers.NotAShelf];
options.services.transience = {
enable = mkEnableOption "transience";
user = mkOption {
type = with types; nullOr string;
default = null;
description = "The user that the directories will be relative to";
};
days = mkOption {
type = types.int;
default = 30;
description = "Number of days after which files are deleted";
};
directories = mkOption {
type = with types; listOf path;
default = [];
description = ''
A list of directories that will be cleaned.
Must be relative to the user's home directory.
'';
};
};
config = {
assertions = [
{
assertion = cfg.enable -> cfg.user == null;
message = ''
You have enabled services.transience, but have not specified your user. You must specify a "main user"
for your system for Transience to work properly.
'';
}
{
assertion = cfg.directories == [];
message = ''
You have enabled services.transience, but have not specified any directories to clean up. Please specify
at least one folder. This option defaults to an empty list, but you must specify a list of directories for
Transience to work properly.
'';
}
];
systemd.user.services.transience = let
dirs =
map (
x:
config.home-manager.users.${cfg.user}.home.homeDirectory + "/" + x
)
cfg.directories;
in {
Install.wantedBy = ["default.target"];
Service.ExecStart = ''
${builtins.concatStringsSep "\n" (map (x: "find ${
lib.escapeShellArg x
} -mtime +${cfg.days} -exec rm -rv {} + -depth;")
dirs)}
'';
Unit.Description = "Clean up transient directories";
};
};
}

View file

@ -0,0 +1,50 @@
{
config,
lib,
pkgs,
...
}:
with builtins; let
inherit (lib) types mkIf mkOption mkEnableOption mkPackageOptionMD literalExpression;
cfg = config.programs.vifm;
in {
meta.maintainers = [maintainers.NotAShelf];
options.programs.vifm = {
enable = mkEnableOption "vifm, file manager with curses interface, which provides Vim-like environment for managing objects within file systems";
package = mkPackageOptionMD pkgs "vifm" {};
config = mkOption {
type = types.lines;
default = "";
description = "Vifm configuration to be written in vifmrc";
example = literalExpression ''
" vim:ft=vifm
set vicmd="nvim"
set runexec
'';
};
extraConfigFiles = mkOption {
type = with types; listOf str;
default = [];
example = ["~/.config/vifm/vifmrc.local"];
description = ''
Extra vifm configuration files to be sourced in vifmrc
Can be an absolute path, or a path relative to `$XDG_CONFIG_HOME/vifm`
'';
};
};
config = mkIf cfg.enable {
home.packages = [cfg.package];
xdg.configFile."vifm/vifmrc".source = pkgs.writeText "vifmrc" (
(lib.concatLines (lib.forEach cfg.extraConfigFiles (x: "source ${x}")))
+ cfg.config
);
};
}

View file

@ -0,0 +1,61 @@
{
config,
lib,
pkgs,
...
}:
with builtins; let
inherit (lib) types mkIf mkOption mkEnableOption mkPackageOptionMD literalExpression;
cfg = config.programs.xplr;
initialConfig = ''
version = '${cfg.package.version}'
'';
# we provide a default version line within the configuration file, which is obtained from the package's attributes
# merge the initial configFile, a mapped list of plugins and then the user defined configuration to obtain the final configuration
pluginPath =
if cfg.plugins != []
then ("package.path=\n" + (concatStringsSep " ..\n" (map (p: ''"${p}/init.lua;"'') cfg.plugins)) + " ..\npackage.path\n")
else "\n";
configFile = initialConfig + pluginPath + cfg.config;
in {
meta.maintainers = [maintainers.NotAShelf];
options.programs.xplr = {
enable = mkEnableOption "xplr, terminal UI based file explorer" // {default = true;};
package = mkPackageOptionMD pkgs "xplr" {};
plugins = mkOption {
type = with types; nullOr (listOf (either package str));
default = [];
defaultText = literalExpression "[]";
description = ''
Plugins to be added to your configuration file. Must be a package, an absolute plugin path, or string
to be recognized by xplr. Paths will be relative to $XDG_CONFIG_HOME/xplr/init.lua unless they are absolute.
'';
};
# TODO: rename, this is the main configuration
config = mkOption {
type = types.lines;
default = "";
description = ''
Extra xplr configuration.
'';
example = literalExpression ''
require("wl-clipboard").setup {
copy_command = "wl-copy -t text/uri-list",
paste_command = "wl-paste",
keep_selection = true,
}
'';
};
};
config = mkIf cfg.enable {
home.packages = [cfg.package];
xdg.configFile."xplr/init.lua".source = pkgs.writeText "init.lua" configFile;
};
}

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