This repository has been archived on 2024-07-08. You can view files and clone it, but cannot push or open issues or pull requests.
nix-config-tn/nixos/lib/default.nix

121 lines
5.5 KiB
Nix
Raw Normal View History

{ inputs, lib, ... }:
with lib;
rec {
2024-04-29 18:10:40 -05:00
firstOrDefault = first: default: if first != null then first else default;
existsOrDefault = x: set: default: if builtins.hasAttr x set then builtins.getAttr x set else default;
# Will be v. useful when i grok
# https://github.com/ahbk/my-nixos/blob/5fe1521b11422c66fd823b442393b3b044a5a5b8/nix#L5
# pick a list of attributes from an attrSet
# mySystem.pick = attrNames: attrSet: filterAttrs (name: value: elem name attrNames) attrSet;
# create an env-file (package) that can be sourced to set environment variables
# mySystem.mkEnv = name: value: pkgs.writeText "${name}-env" (concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") value));
# loop over an attrSet and merge the attrSets returned from f into one (latter override the former in case of conflict)
# mySystem.mergeAttrs = f: attrs: builtins.foldlAttrs (acc: name: value: (recursiveUpdate acc (f name value))) { } attrs;
# main service builder
mkService = options: (
let
user = existsOrDefault "user" options "568";
group = existsOrDefault "group" options "568";
addTraefikLabels = if (builtins.hasAttr "container" options) && (builtins.hasAttr "addTraefikLabels" options.container) then options.container.addTraefikLabels else true;
addToHomepage = lib.attrsets.attrByPath [ "homepage" "enable" ] true options;
homepageIcon = if (builtins.hasAttr "homepage" options) && (builtins.hasAttr "icon" options.homepage) then options.homepage.icon else "${options.app}.svg";
subdomain = existsOrDefault "subdomainOverride" options options.app;
host = existsOrDefault "host" options "${subdomain}.${options.domain}";
enableBackups = (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options)
&& (lib.attrsets.attrByPath [ "persistence" "enable" ] true options);
# nix doesnt have an exhausive list of options for oci
# so here i try to get a robust list of security options for containers
# because everyone needs more tinfoild hat right? RIGHT?
2024-04-29 18:10:40 -05:00
containerExtraOptions = lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "privileged" ] false options) [ "--privileged" ]
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "readOnly" ] false options) [ "--read-only" ]
2024-04-24 18:23:29 -05:00
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "tmpfs" ] false options) [ (map (folders: "--tmpfs=${folders}") tmpfsFolders) ]
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "noNewPrivileges" ] false options) [ "--security-opt=no-new-privileges" ]
++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "dropAll" ] false options) [ "--cap-drop=ALL" ]
;
in
{
virtualisation.oci-containers.containers.${options.app} = mkIf options.container.enable {
image = "${options.container.image}";
user = "${user}:${group}";
environment = {
TZ = options.timeZone;
} // options.container.env;
2024-04-29 18:10:40 -05:00
environmentFiles = lib.attrsets.attrByPath [ "container" "envFiles" ] [ ] options;
volumes = [ "/etc/localtime:/etc/localtime:ro" ]
++ lib.optionals (lib.attrsets.hasAttrByPath [ "container" "persistentFolderMount" ] options) [
"${options.persistence.folder}:${options.container.persistentFolderMount}:rw"
]
++ lib.attrsets.attrByPath [ "container" "volumes" ] [ ] options;
labels = mkIf addTraefikLabels (mkTraefikLabels {
name = subdomain;
2024-04-29 18:10:40 -05:00
inherit (options) port;
inherit (options) domain;
url = host;
});
extraOptions = containerExtraOptions;
};
2024-04-29 18:10:40 -05:00
systemd.tmpfiles.rules = lib.optionals (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options) [ "d ${options.persistence.folder} 0755 ${user} ${group} -" ]
;
# built a entry for homepage
mySystem.services.homepage.${options.homepage.category} = mkIf addToHomepage [
{
${options.app} = {
icon = homepageIcon;
href = "https://${ host }";
2024-04-29 18:10:40 -05:00
inherit host;
inherit (options) description;
};
}
];
}
);
# build up traefik docker labels
mkTraefikLabels = options: (
let
inherit (options) name;
subdomain = if builtins.hasAttr "subdomain" options then options.subdomain else options.name;
host = existsOrDefault "host" options "${options.name}.${options.domain}";
# created if port is specified
service = if builtins.hasAttr "service" options then options.service else options.name;
middleware = if builtins.hasAttr "middleware" options then options.middleware else "local-ip-only@file";
in
{
"traefik.enable" = "true";
"traefik.http.routers.${name}.rule" = "Host(`${host}`)";
"traefik.http.routers.${name}.entrypoints" = "websecure";
"traefik.http.routers.${name}.middlewares" = "${middleware}";
} // attrsets.optionalAttrs (builtins.hasAttr "port" options) {
"traefik.http.routers.${name}.service" = service;
"traefik.http.services.${service}.loadbalancer.server.port" = "${builtins.toString options.port}";
} // attrsets.optionalAttrs (builtins.hasAttr "scheme" options) {
"traefik.http.routers.${name}.service" = service;
"traefik.http.services.${service}.loadbalancer.server.scheme" = "${options.scheme}";
} // attrsets.optionalAttrs (builtins.hasAttr "service" options) {
"traefik.http.routers.${name}.service" = service;
}
);
}