From cca51699eee9d4fc3391bfb296b397df26a895d9 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Wed, 18 Dec 2024 15:40:15 +0300 Subject: [PATCH] feat: Dynamic templating --- README.md | 116 ++++++++++++++++++ configuration.nix | 24 ++++ flake.lock | 10 +- flake.nix | 10 ++ lib/meta.nix | 21 ++++ sp-modules/bitwarden/flake.nix | 24 ++++ sp-modules/bitwarden/icon.svg | 3 + sp-modules/bitwarden/module.nix | 48 +++++++- sp-modules/gitea/flake.nix | 22 ++++ sp-modules/gitea/icon.svg | 3 + sp-modules/gitea/module.nix | 83 +++++++++++-- sp-modules/jitsi-meet/flake.nix | 24 ++++ sp-modules/jitsi-meet/icon.svg | 3 + sp-modules/jitsi-meet/module.nix | 25 +++- sp-modules/monitoring/flake.nix | 27 ++++ sp-modules/monitoring/icon.svg | 3 + sp-modules/monitoring/module.nix | 14 ++- sp-modules/mumble/config-paths-needed.json | 5 + sp-modules/mumble/flake.nix | 35 ++++++ sp-modules/mumble/icon.svg | 9 ++ sp-modules/mumble/module.nix | 87 +++++++++++++ sp-modules/nextcloud/flake.nix | 23 ++++ sp-modules/nextcloud/icon.svg | 10 ++ sp-modules/nextcloud/module.nix | 36 +++++- sp-modules/ocserv/flake.nix | 20 +++ sp-modules/ocserv/icon.svg | 3 + sp-modules/ocserv/module.nix | 17 ++- sp-modules/pleroma/flake.nix | 26 ++++ sp-modules/pleroma/icon.svg | 10 ++ sp-modules/pleroma/module.nix | 24 +++- sp-modules/roundcube/flake.nix | 20 +++ sp-modules/roundcube/icon.svg | 5 + sp-modules/roundcube/module.nix | 17 ++- sp-modules/simple-nixos-mailserver/flake.nix | 21 ++++ sp-modules/simple-nixos-mailserver/icon.svg | 3 + .../simple-nixos-mailserver/options.nix | 14 ++- 36 files changed, 802 insertions(+), 43 deletions(-) create mode 100644 lib/meta.nix create mode 100644 sp-modules/bitwarden/icon.svg create mode 100644 sp-modules/gitea/icon.svg create mode 100644 sp-modules/jitsi-meet/icon.svg create mode 100644 sp-modules/monitoring/icon.svg create mode 100644 sp-modules/mumble/config-paths-needed.json create mode 100644 sp-modules/mumble/flake.nix create mode 100644 sp-modules/mumble/icon.svg create mode 100644 sp-modules/mumble/module.nix create mode 100644 sp-modules/nextcloud/icon.svg create mode 100644 sp-modules/ocserv/icon.svg create mode 100644 sp-modules/pleroma/icon.svg create mode 100644 sp-modules/roundcube/icon.svg create mode 100644 sp-modules/simple-nixos-mailserver/icon.svg diff --git a/README.md b/README.md index 3625aaf..a1b72c2 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,119 @@ If you added a new SelfPrivacy module, you have to also edit a `genUserdata` fun ``` Substitute `PACKAGE_NAME` and `NIXPKGS_COMMIT_SHA1` with affected package name and nixpkgs commit SHA1 (found at step 1), respectively. 3. Commit the [`overlay.nix`](overlay.nix) changes. Configuration is ready to be built. + +## SelfPrivacy Module schema + +### Flake.nix metadata + +```nix +{ + description = "Flake description"; + + outputs = { self }: { + nixosModules.default = import ./module.nix; + configPathsNeeded = + builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = {lib, ...}: { + # Schema version + spModuleVersion = 1; + # Must be the same name as flake and Systemd slice + id = "jitsi-meet"; + # Service name displayed to a user + name = "JitsiMeet"; + # Description displayed to a user + description = "Jitsi Meet is a free and open-source video conferencing solution."; + # Icon of the service + svgIcon = builtins.readFile ./icon.svg; + # Do we need to show URL in the UI? True by default + showUrl = true; + # If there are several subdomain options, which one to use to generate the URL? + primarySubdomain = "subdomain"; + # Can be moved to another volume? + isMovable = false; + # Is required for SelfPrivacy operation? + isRequired = false; + # Can be backed up by API? + # Implied to be TRUE by default + canBeBackedUp = true; + # Description of the backup + backupDescription = "Secrets that are used to encrypt the communication."; + # Systemd services that API checks and manipulates + systemdServices = [ + "prosody.service" + "jitsi-videobridge2.service" + "jicofo.service" + ]; + # A unix user used by this service + # By default implied to be the same as the service ID + user = "jitsi-meet"; + # A unix group used by this group + # By default implied to be the same as the user + group = "jitsi-meet"; + # Folders that have to be moved or backed up + # Ownership is implied by the user/group defined above + folders = [ + "/var/lib/jitsi-meet" + ]; + # Same as above, but if you need to overwrite ownership + ownedFolders = [ + { + path = "/var/lib/prometheus"; + owner = "prometheus"; + group = "prometheus"; + } + ]; + # PostgreSQL databases to back up + postgreDatabases = []; + # Licenses of this service + license = [ + lib.licenses.asl20 + ]; + # Homepage for this service + homepage = "https://jitsi.org/meet"; + # Git repository with the sources of this service + sourcePage = "https://github.com/jitsi/jitsi-meet"; + # What is our support level for this service? + # Supported values: + # - normal + # - deprecated + # - experimental + supportLevel = "normal"; + }; + }; +} +``` + +### Flake options + +```nix +enable = (lib.mkOption { + default = false; + type = lib.types.bool; + description = "Enable"; +}) // { + meta = { + type = "enable"; + }; +}; +location = (lib.mkOption { + type = lib.types.str; + description = "Location"; +}) // { + meta = { + type = "location"; + }; +}; +subdomain = (lib.mkOption { + default = ""; + type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; +}) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; +}; +``` diff --git a/configuration.nix b/configuration.nix index eeb02a7..4ee7959 100644 --- a/configuration.nix +++ b/configuration.nix @@ -14,6 +14,20 @@ let echo "$token" ''; }; + # TODO: We need this in the API's environmet, not here. + sp-fetch-remote-module = pkgs.writeShellApplication { + name = "sp-fetch-remote-module"; + runtimeInputs = [ config.nix.package.out ]; + text = '' + if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 + fi + + URL="$1" + nix eval --file /etc/nixos/sp-fetch-remote-module.nix --raw --apply "f: f { flakeURL = \"$URL\"; }" | jq . + ''; + }; in { imports = [ @@ -27,6 +41,15 @@ in # ./resources/limits.nix ]; + environment.etc."sp-fetch-remote-module.nix" = { + text = '' + { flakeURL }: let + sp-module = builtins.getFlake flakeURL; + pkgs = import ${pkgs.path} {}; + in (import ${./lib/meta.nix}) { inherit pkgs sp-module; } + ''; + }; + fileSystems."/".options = [ "noatime" ]; services.selfprivacy-api.enable = true; @@ -90,6 +113,7 @@ in git jq sp-print-api-token + sp-fetch-remote-module ]; # consider environment.defaultPackages = lib.mkForce []; documentation.enable = false; # no {man,info}-pages & docs, etc to save space diff --git a/flake.lock b/flake.lock index de7563d..7f0f7e4 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ ] }, "locked": { - "lastModified": 1734269435, - "narHash": "sha256-KimSmykCfcGPKGUMgOxlC+s9nw7sNO5B8vW74Fj76Uc=", - "ref": "master", - "rev": "7d9150a77ab86f5624f726be1d03da23fd124334", - "revCount": 1473, + "lastModified": 1734807830, + "narHash": "sha256-nzkcvZjMo5bE2ZML404+9Hzhq7UmMx8+V+LclrCYZRA=", + "ref": "inex/dynamic-templating", + "rev": "fcc167fb33b4154f0685ac94f3def3a9dbcd26e6", + "revCount": 1487, "type": "git", "url": "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git" }, diff --git a/flake.nix b/flake.nix index f74bce0..27c0444 100644 --- a/flake.nix +++ b/flake.nix @@ -25,6 +25,16 @@ deployment ./configuration.nix selfprivacy-api.nixosModules.default + ({ pkgs, lib, ... }: { + environment.etc = (lib.attrsets.mapAttrs' + (name: sp-module: { + name = "sp-modules/${name}"; + value.text = import ./lib/meta.nix { inherit pkgs sp-module; }; + }) + sp-modules) // { + suggested-sp-modules.text = builtins.toJSON (builtins.attrNames (builtins.readDir ./sp-modules)); + }; + }) ( let deepFilter = ref: attrset: diff --git a/lib/meta.nix b/lib/meta.nix new file mode 100644 index 0000000..35f9bc1 --- /dev/null +++ b/lib/meta.nix @@ -0,0 +1,21 @@ +{ sp-module, pkgs }: +let + lib = pkgs.lib; + # sp-module = builtins.getFlake "git+file:.?dir=sp-modules/jitsi-meet"; + # sp-module = builtins.getFlake flakeURL; + options = (pkgs.lib.evalModules { modules = [{ _module.check = false; } sp-module.nixosModules.default]; }).options; + # Transform a Nix option to a JSON structure with metadata + optionToMeta = (name: option: { + name = name; + description = if builtins.hasAttr "description" option then option.description else null; + loc = option.loc; + meta = if builtins.hasAttr "meta" option then option.meta else null; + # value = if builtins.hasAttr "value" option then option.value else null; + default = if builtins.hasAttr "default" option then option.default else null; + }); +in +builtins.toJSON ({ + meta = if builtins.hasAttr "meta" sp-module then sp-module.meta { inherit lib; } else null; + configPathsNeeded = sp-module.configPathsNeeded; + options = pkgs.lib.mapAttrs optionToMeta (builtins.head (lib.mapAttrsToList (name: value: value) options.selfprivacy.modules)); +}) diff --git a/sp-modules/bitwarden/flake.nix b/sp-modules/bitwarden/flake.nix index d01d6b9..dfea84c 100644 --- a/sp-modules/bitwarden/flake.nix +++ b/sp-modules/bitwarden/flake.nix @@ -6,5 +6,29 @@ { imports = [ ./module.nix ./cleanup-module.nix ]; }; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "bitwarden"; + name = "Bitwarden"; + description = "Bitwarden is a password manager."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = true; + isRequired = false; + backupDescription = "Password database, encryption certificate and attachments."; + systemdServices = [ + "vaultwarden.service" + ]; + user = "vaultwarden"; + folders = [ + "/var/lib/bitwarden" + "/var/lib/bitwarden_rs" + ]; + license = [ + lib.licenses.agpl3Only + ]; + homepage = "https://github.com/dani-garcia/vaultwarden"; + sourcePage = "https://github.com/dani-garcia/vaultwarden"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/bitwarden/icon.svg b/sp-modules/bitwarden/icon.svg new file mode 100644 index 0000000..ced270c --- /dev/null +++ b/sp-modules/bitwarden/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/bitwarden/module.nix b/sp-modules/bitwarden/module.nix index ad4ab09..5fa12ca 100644 --- a/sp-modules/bitwarden/module.nix +++ b/sp-modules/bitwarden/module.nix @@ -7,28 +7,64 @@ let in { options.selfprivacy.modules.bitwarden = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable Vaultwarden"; + }) // { + meta = { + type = "enable"; + }; }; - location = lib.mkOption { + location = (lib.mkOption { type = lib.types.str; + description = "Vaultwarden location"; + }) // { + meta = { + type = "location"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "password"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; - signupsAllowed = lib.mkOption { + signupsAllowed = (lib.mkOption { default = true; type = lib.types.bool; + description = "Allow new user signups"; + }) // { + meta = { + type = "bool"; + weight = 1; + }; }; - sendsAllowed = lib.mkOption { + sendsAllowed = (lib.mkOption { default = true; type = lib.types.bool; + description = "Allow users to use Bitwarden Send"; + }) // { + meta = { + type = "bool"; + weight = 2; + }; }; - emergencyAccessAllowed = lib.mkOption { + emergencyAccessAllowed = (lib.mkOption { default = true; type = lib.types.bool; + description = "Allow users to enable Emergency Access"; + }) // { + meta = { + type = "bool"; + weight = 3; + }; }; }; diff --git a/sp-modules/gitea/flake.nix b/sp-modules/gitea/flake.nix index dd9857d..35f444a 100644 --- a/sp-modules/gitea/flake.nix +++ b/sp-modules/gitea/flake.nix @@ -5,5 +5,27 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "gitea"; + name = "Forgejo"; + description = "Forgejo is a Git forge."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = true; + isRequired = false; + backupDescription = "Git repositories, database and user data."; + systemdServices = [ + "forgejo.service" + ]; + folders = [ + "/var/lib/gitea" + ]; + license = [ + lib.licenses.gpl3Plus + ]; + homepage = "https://forgejo.org"; + sourcePage = "https://codeberg.org/forgejo/forgejo"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/gitea/icon.svg b/sp-modules/gitea/icon.svg new file mode 100644 index 0000000..9ba8a76 --- /dev/null +++ b/sp-modules/gitea/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/gitea/module.nix b/sp-modules/gitea/module.nix index d854127..8fc063c 100644 --- a/sp-modules/gitea/module.nix +++ b/sp-modules/gitea/module.nix @@ -6,47 +6,106 @@ let then "/volumes/${cfg.location}/gitea" else "/var/lib/gitea"; cfg = sp.modules.gitea; + themes = [ + "forgejo-auto" + "forgejo-light" + "forgejo-dark" + "gitea-auto" + "gitea-light" + "gitea-dark" + ]; in { options.selfprivacy.modules.gitea = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable Forgejo"; + }) // { + meta = { + type = "enable"; + }; }; - location = lib.mkOption { + location = (lib.mkOption { type = lib.types.str; + description = "Forgejo location"; + }) // { + meta = { + type = "location"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "git"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; - appName = lib.mkOption { + appName = (lib.mkOption { default = "SelfPrivacy git Service"; type = lib.types.str; + description = "The name displayed in the web interface"; + }) // { + meta = { + type = "string"; + weight = 1; + }; }; - enableLfs = lib.mkOption { + enableLfs = (lib.mkOption { default = true; type = lib.types.bool; + description = "Enable Git LFS"; + }) // { + meta = { + type = "bool"; + weight = 2; + }; }; - forcePrivate = lib.mkOption { + forcePrivate = (lib.mkOption { default = false; type = lib.types.bool; description = "Force all new repositories to be private"; + }) // { + meta = { + type = "bool"; + weight = 3; + }; }; - disableRegistration = lib.mkOption { + disableRegistration = (lib.mkOption { default = false; type = lib.types.bool; description = "Disable registration of new users"; + }) // { + meta = { + type = "bool"; + weight = 4; + }; }; - requireSigninView = lib.mkOption { + requireSigninView = (lib.mkOption { default = false; type = lib.types.bool; - description = "Require signin to view any page"; + description = "Force users to log in to view any page"; + }) // { + meta = { + type = "bool"; + weight = 5; + }; }; - defaultTheme = lib.mkOption { + defaultTheme = (lib.mkOption { default = "forgejo-auto"; - type = lib.types.enum [ "forgejo-auto" "forgejo-light" "forgejo-dark" "auto" "gitea" "arc-green" ]; - description = "The default theme for the gitea instance"; + type = lib.types.enum themes; + description = "Default theme"; + }) // { + meta = { + type = "enum"; + options = themes; + weight = 6; + }; }; }; diff --git a/sp-modules/jitsi-meet/flake.nix b/sp-modules/jitsi-meet/flake.nix index e93ae96..1e923d9 100644 --- a/sp-modules/jitsi-meet/flake.nix +++ b/sp-modules/jitsi-meet/flake.nix @@ -5,5 +5,29 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "jitsi-meet"; + name = "JitsiMeet"; + description = "Jitsi Meet is a free and open-source video conferencing solution."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = false; + isRequired = false; + backupDescription = "Secrets that are used to encrypt the communication."; + systemdServices = [ + "prosody.service" + "jitsi-videobridge2.service" + "jicofo.service" + ]; + folders = [ + "/var/lib/jitsi-meet" + ]; + license = [ + lib.licenses.asl20 + ]; + homepage = "https://jitsi.org/meet"; + sourcePage = "https://github.com/jitsi/jitsi-meet"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/jitsi-meet/icon.svg b/sp-modules/jitsi-meet/icon.svg new file mode 100644 index 0000000..e3a6eaa --- /dev/null +++ b/sp-modules/jitsi-meet/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/jitsi-meet/module.nix b/sp-modules/jitsi-meet/module.nix index f394ab4..87cf429 100644 --- a/sp-modules/jitsi-meet/module.nix +++ b/sp-modules/jitsi-meet/module.nix @@ -5,17 +5,36 @@ let in { options.selfprivacy.modules.jitsi-meet = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable JitsiMeet"; + }) // { + meta = { + type = "enable"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "meet"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; - appName = lib.mkOption { + appName = (lib.mkOption { default = "Jitsi Meet"; type = lib.types.str; + description = "The name displayed in the web interface"; + }) // { + meta = { + type = "string"; + weight = 1; + }; }; }; diff --git a/sp-modules/monitoring/flake.nix b/sp-modules/monitoring/flake.nix index b6b3f77..76d9fdb 100644 --- a/sp-modules/monitoring/flake.nix +++ b/sp-modules/monitoring/flake.nix @@ -5,5 +5,32 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "monitoring"; + name = "Prometheus"; + description = "Prometheus is used for resource monitoring and alerts."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = false; + isRequired = true; + canBeBackedUp = false; + backupDescription = "Backups are not available for Prometheus."; + systemdServices = [ + "prometheus.service" + ]; + ownedFolders = [ + { + path = "/var/lib/prometheus"; + owner = "prometheus"; + group = "prometheus"; + } + ]; + license = [ + lib.licenses.asl20 + ]; + homepage = "https://prometheus.io/"; + sourcePage = "https://prometheus.io/"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/monitoring/icon.svg b/sp-modules/monitoring/icon.svg new file mode 100644 index 0000000..db5daf0 --- /dev/null +++ b/sp-modules/monitoring/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/monitoring/module.nix b/sp-modules/monitoring/module.nix index 5981af7..9b2f92c 100644 --- a/sp-modules/monitoring/module.nix +++ b/sp-modules/monitoring/module.nix @@ -4,12 +4,22 @@ let in { options.selfprivacy.modules.monitoring = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable monitoring service"; + }) // { + meta = { + type = "enable"; + }; }; - location = lib.mkOption { + location = (lib.mkOption { type = lib.types.str; + description = "Monitoring data location"; + }) // { + meta = { + type = "location"; + }; }; }; config = lib.mkIf cfg.enable { diff --git a/sp-modules/mumble/config-paths-needed.json b/sp-modules/mumble/config-paths-needed.json new file mode 100644 index 0000000..a08720f --- /dev/null +++ b/sp-modules/mumble/config-paths-needed.json @@ -0,0 +1,5 @@ +[ + [ "selfprivacy", "domain" ], + [ "selfprivacy", "useBinds" ], + [ "selfprivacy", "modules", "mumble" ] +] diff --git a/sp-modules/mumble/flake.nix b/sp-modules/mumble/flake.nix new file mode 100644 index 0000000..0d04808 --- /dev/null +++ b/sp-modules/mumble/flake.nix @@ -0,0 +1,35 @@ +{ + description = "PoC SP module for Mumble conferences server"; + + outputs = { self }: { + nixosModules.default = import ./module.nix; + configPathsNeeded = + builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "mumble"; + name = "Mumble"; + description = "Open Source, Low Latency, High Quality Voice Chat."; + svgIcon = builtins.readFile ./icon.svg; + showUrl = false; + isMovable = true; + isRequired = false; + canBeBackedUp = true; + backupDescription = "Mumble server data."; + systemdServices = [ + "murmur.service" + ]; + user = "murmur"; + group = "murmur"; + folders = [ + "/var/lib/murmur" + ]; + license = [ + lib.licenses.bsd3 + ]; + homepage = "https://www.mumble.info"; + sourcePage = "https://github.com/mumble-voip/mumble"; + supportLevel = "normal"; + }; + }; +} diff --git a/sp-modules/mumble/icon.svg b/sp-modules/mumble/icon.svg new file mode 100644 index 0000000..4289864 --- /dev/null +++ b/sp-modules/mumble/icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sp-modules/mumble/module.nix b/sp-modules/mumble/module.nix new file mode 100644 index 0000000..d477e29 --- /dev/null +++ b/sp-modules/mumble/module.nix @@ -0,0 +1,87 @@ +{ config, lib, ... }: +let + domain = config.selfprivacy.domain; + sp = config.selfprivacy; + cfg = sp.modules.mumble; +in +{ + options.selfprivacy.modules.mumble = { + enable = (lib.mkOption { + default = false; + type = lib.types.bool; + description = "Enable Mumble"; + }) // { + meta = { + type = "enable"; + }; + }; + subdomain = (lib.mkOption { + default = "mumble"; + type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; + }; + location = (lib.mkOption { + type = lib.types.str; + description = "Location"; + }) // { + meta = { + type = "location"; + }; + }; + appName = (lib.mkOption { + default = "SelfPrivacy Mumble Service"; + type = lib.types.str; + description = "The name of your Mumble server"; + }) // { + meta = { + type = "string"; + weight = 1; + }; + }; + welcomeText = (lib.mkOption { + default = "Welcome to my Mumble server!"; + type = lib.types.str; + description = "Welcome message"; + }) // { + meta = { + type = "string"; + weight = 2; + }; + }; + }; + + config = lib.mkIf cfg.enable { + fileSystems = lib.mkIf sp.useBinds { + "/var/lib/murmur" = { + device = "/volumes/${cfg.location}/murmur"; + options = [ + "bind" + "x-systemd.required-by=murmur.service" + "x-systemd.before=murmur.service" + ]; + }; + }; + services.murmur = { + enable = true; + openFirewall = true; + registerHostname = "${cfg.subdomain}.${domain}"; + hostName = "${cfg.subdomain}.${domain}"; + registerName = cfg.appName; + }; + systemd = { + services = { + murmur.serviceConfig.Slice = "mumble.slice"; + }; + slices.mumble = { + description = "Mumble service slice"; + }; + }; + }; +} diff --git a/sp-modules/nextcloud/flake.nix b/sp-modules/nextcloud/flake.nix index 2cf384e..65031a2 100644 --- a/sp-modules/nextcloud/flake.nix +++ b/sp-modules/nextcloud/flake.nix @@ -6,5 +6,28 @@ { imports = [ ./module.nix ./cleanup-module.nix ]; }; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "nextcloud"; + name = "Nextcloud"; + description = "Nextcloud is a cloud storage service that offers a web interface and a desktop client."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = true; + isRequired = false; + canBeBackedUp = true; + backupDescription = "All the files and other data stored in Nextcloud."; + systemdServices = [ + "phpfpm-nextcloud.service" + ]; + folders = [ + "/var/lib/nextcloud" + ]; + license = [ + lib.licenses.agpl3Plus + ]; + homepage = "https://nextcloud.com/"; + sourcePage = "https://github.com/nextcloud"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/nextcloud/icon.svg b/sp-modules/nextcloud/icon.svg new file mode 100644 index 0000000..d7dbcb5 --- /dev/null +++ b/sp-modules/nextcloud/icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sp-modules/nextcloud/module.nix b/sp-modules/nextcloud/module.nix index f4b7d08..12ad007 100644 --- a/sp-modules/nextcloud/module.nix +++ b/sp-modules/nextcloud/module.nix @@ -1,20 +1,44 @@ { config, lib, pkgs, ... }: { options.selfprivacy.modules.nextcloud = with lib; { - enable = mkOption { - type = types.bool; + enable = (lib.mkOption { default = false; + type = lib.types.bool; + description = "Enable Nextcloud"; + }) // { + meta = { + type = "enable"; + }; }; - location = mkOption { - type = types.str; + location = (lib.mkOption { + type = lib.types.str; + description = "Nextcloud location"; + }) // { + meta = { + type = "location"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "cloud"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; - enableImagemagick = lib.mkOption { + enableImagemagick = (lib.mkOption { type = types.bool; default = true; + description = "Enable ImageMagick"; + }) // { + meta = { + type = "bool"; + weight = 1; + }; }; }; diff --git a/sp-modules/ocserv/flake.nix b/sp-modules/ocserv/flake.nix index d08ad70..9f09338 100644 --- a/sp-modules/ocserv/flake.nix +++ b/sp-modules/ocserv/flake.nix @@ -5,5 +5,25 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "ocserv"; + name = "OpenConnect VPN"; + description = "OpenConnect VPN to connect your devices and access the internet."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = false; + isRequired = false; + canBeBackedUp = false; + backupDescription = "Backups are not available for OpenConnect VPN."; + systemdServices = [ + "ocserv.service" + ]; + license = [ + lib.licenses.gpl2Plus + ]; + homepage = "https://gitlab.com/openconnect/ocserv"; + sourcePage = "https://gitlab.com/openconnect/ocserv"; + supportLevel = "deprecated"; + }; }; } diff --git a/sp-modules/ocserv/icon.svg b/sp-modules/ocserv/icon.svg new file mode 100644 index 0000000..288f743 --- /dev/null +++ b/sp-modules/ocserv/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/ocserv/module.nix b/sp-modules/ocserv/module.nix index f4d2dc0..a332a17 100644 --- a/sp-modules/ocserv/module.nix +++ b/sp-modules/ocserv/module.nix @@ -7,13 +7,26 @@ let in { options.selfprivacy.modules.ocserv = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable"; + }) // { + meta = { + type = "enable"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "vpn"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; }; diff --git a/sp-modules/pleroma/flake.nix b/sp-modules/pleroma/flake.nix index a524458..2887c93 100644 --- a/sp-modules/pleroma/flake.nix +++ b/sp-modules/pleroma/flake.nix @@ -5,5 +5,31 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "pleroma"; + name = "Pleroma"; + description = "Pleroma is a microblogging service that offers a web interface and a desktop client."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = true; + isRequired = false; + canBeBackedUp = true; + backupDescription = "Your Pleroma accounts, posts and media."; + systemdServices = [ + "pleroma.service" + ]; + folders = [ + "/var/lib/pleroma" + ]; + postgreDatabases = [ + "pleroma" + ]; + license = [ + lib.licenses.agpl3Only + ]; + homepage = "https://pleroma.social/"; + sourcePage = "https://git.pleroma.social/pleroma/pleroma"; + supportLevel = "deprecated"; + }; }; } diff --git a/sp-modules/pleroma/icon.svg b/sp-modules/pleroma/icon.svg new file mode 100644 index 0000000..f87c438 --- /dev/null +++ b/sp-modules/pleroma/icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/sp-modules/pleroma/module.nix b/sp-modules/pleroma/module.nix index f345e5d..14c10a5 100644 --- a/sp-modules/pleroma/module.nix +++ b/sp-modules/pleroma/module.nix @@ -6,16 +6,34 @@ let in { options.selfprivacy.modules.pleroma = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable"; + }) // { + meta = { + type = "enable"; + }; }; - location = lib.mkOption { + location = (lib.mkOption { type = lib.types.str; + description = "Location"; + }) // { + meta = { + type = "location"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "social"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; }; config = lib.mkIf cfg.enable { diff --git a/sp-modules/roundcube/flake.nix b/sp-modules/roundcube/flake.nix index d335522..12035e8 100644 --- a/sp-modules/roundcube/flake.nix +++ b/sp-modules/roundcube/flake.nix @@ -5,5 +5,25 @@ nixosModules.default = import ./module.nix; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "roundcube"; + name = "Roundcube"; + description = "Roundcube is an open source webmail software."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = false; + isRequired = false; + canBeBackedUp = false; + backupDescription = "Nothing to backup."; + systemdServices = [ + "phpfpm-roundcube.service" + ]; + license = [ + lib.licenses.gpl3 + ]; + homepage = "https://roundcube.net/"; + sourcePage = "https://github.com/roundcube/roundcubemail"; + supportLevel = "normal"; + }; }; } diff --git a/sp-modules/roundcube/icon.svg b/sp-modules/roundcube/icon.svg new file mode 100644 index 0000000..35918e1 --- /dev/null +++ b/sp-modules/roundcube/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/sp-modules/roundcube/module.nix b/sp-modules/roundcube/module.nix index a279ff1..8067289 100644 --- a/sp-modules/roundcube/module.nix +++ b/sp-modules/roundcube/module.nix @@ -5,13 +5,26 @@ let in { options.selfprivacy.modules.roundcube = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable"; + }) // { + meta = { + type = "enable"; + }; }; - subdomain = lib.mkOption { + subdomain = (lib.mkOption { default = "roundcube"; type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + description = "Subdomain"; + }) // { + meta = { + widget = "subdomain"; + type = "string"; + regex = "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]"; + weight = 0; + }; }; }; diff --git a/sp-modules/simple-nixos-mailserver/flake.nix b/sp-modules/simple-nixos-mailserver/flake.nix index a19d2da..cce75bb 100644 --- a/sp-modules/simple-nixos-mailserver/flake.nix +++ b/sp-modules/simple-nixos-mailserver/flake.nix @@ -14,6 +14,27 @@ }; configPathsNeeded = builtins.fromJSON (builtins.readFile ./config-paths-needed.json); + meta = { lib, ... }: { + spModuleVersion = 1; + id = "simple-nixos-mailserver"; + name = "Mail Server"; + description = "E-Mail for company and family."; + svgIcon = builtins.readFile ./icon.svg; + isMovable = true; + isRequired = true; + canBeBackedUp = true; + backupDescription = "Mail boxes and filters."; + systemdServices = [ + "dovecot2.service" + "postfix.service" + ]; + user = "virtualMail"; + folders = [ + "/var/vmail" + "/var/sieve" + ]; + supportLevel = "normal"; + }; # TODO generate json docs from module? something like: # nix eval --impure --expr 'let flake = builtins.getFlake (builtins.toPath ./.); pkgs = flake.inputs.mailserver.inputs.nixpkgs.legacyPackages.x86_64-linux; in (pkgs.nixosOptionsDoc { inherit (pkgs.lib.evalModules { modules = [ flake.nixosModules.default ]; }) options; }).optionsJSON' diff --git a/sp-modules/simple-nixos-mailserver/icon.svg b/sp-modules/simple-nixos-mailserver/icon.svg new file mode 100644 index 0000000..b6d877d --- /dev/null +++ b/sp-modules/simple-nixos-mailserver/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/sp-modules/simple-nixos-mailserver/options.nix b/sp-modules/simple-nixos-mailserver/options.nix index c6f6d3a..b8a5782 100644 --- a/sp-modules/simple-nixos-mailserver/options.nix +++ b/sp-modules/simple-nixos-mailserver/options.nix @@ -1,12 +1,22 @@ { lib, ... }: { options.selfprivacy.modules.simple-nixos-mailserver = { - enable = lib.mkOption { + enable = (lib.mkOption { default = false; type = lib.types.bool; + description = "Enable mail server"; + }) // { + meta = { + type = "enable"; + }; }; - location = lib.mkOption { + location = (lib.mkOption { type = lib.types.str; + description = "Location"; + }) // { + meta = { + type = "location"; + }; }; }; }