diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index a020a52cf7cd..db0f14b2bf46 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -128,6 +128,13 @@
services.teleport.
+
+
+ BaGet,
+ a lightweight NuGet and symbol server. Available at
+ services.baget.
+
+
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index 768766ad249f..7fbc342b74fd 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -39,6 +39,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [teleport](https://goteleport.com), allows engineers and security professionals to unify access for SSH servers, Kubernetes clusters, web applications, and databases across all environments. Available at [services.teleport](#opt-services.teleport.enable).
+- [BaGet](https://loic-sharma.github.io/BaGet/), a lightweight NuGet and symbol server. Available at [services.baget](#opt-services.baget.enable).
+
## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
- `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 4e0bff076794..b4a0bcb01dca 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -992,6 +992,7 @@
./services/web-apps/bookstack.nix
./services/web-apps/calibre-web.nix
./services/web-apps/code-server.nix
+ ./services/web-apps/baget.nix
./services/web-apps/convos.nix
./services/web-apps/cryptpad.nix
./services/web-apps/dex.nix
diff --git a/nixos/modules/services/web-apps/baget.nix b/nixos/modules/services/web-apps/baget.nix
new file mode 100644
index 000000000000..3007dd4fbb26
--- /dev/null
+++ b/nixos/modules/services/web-apps/baget.nix
@@ -0,0 +1,170 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.baget;
+
+ defaultConfig = {
+ "PackageDeletionBehavior" = "Unlist";
+ "AllowPackageOverwrites" = false;
+
+ "Database" = {
+ "Type" = "Sqlite";
+ "ConnectionString" = "Data Source=baget.db";
+ };
+
+ "Storage" = {
+ "Type" = "FileSystem";
+ "Path" = "";
+ };
+
+ "Search" = {
+ "Type" = "Database";
+ };
+
+ "Mirror" = {
+ "Enabled" = false;
+ "PackageSource" = "https://api.nuget.org/v3/index.json";
+ };
+
+ "Logging" = {
+ "IncludeScopes" = false;
+ "Debug" = {
+ "LogLevel" = {
+ "Default" = "Warning";
+ };
+ };
+ "Console" = {
+ "LogLevel" = {
+ "Microsoft.Hosting.Lifetime" = "Information";
+ "Default" = "Warning";
+ };
+ };
+ };
+ };
+
+ configAttrs = recursiveUpdate defaultConfig cfg.extraConfig;
+
+ configFormat = pkgs.formats.json {};
+ configFile = configFormat.generate "appsettings.json" configAttrs;
+
+in
+{
+ options.services.baget = {
+ enable = mkEnableOption "BaGet NuGet-compatible server";
+
+ apiKeyFile = mkOption {
+ type = types.path;
+ example = "/root/baget.key";
+ description = ''
+ Private API key for BaGet.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = configFormat.type;
+ default = {};
+ example = {
+ "Database" = {
+ "Type" = "PostgreSql";
+ "ConnectionString" = "Server=/run/postgresql;Port=5432;";
+ };
+ };
+ defaultText = literalExpression ''
+ {
+ "PackageDeletionBehavior" = "Unlist";
+ "AllowPackageOverwrites" = false;
+
+ "Database" = {
+ "Type" = "Sqlite";
+ "ConnectionString" = "Data Source=baget.db";
+ };
+
+ "Storage" = {
+ "Type" = "FileSystem";
+ "Path" = "";
+ };
+
+ "Search" = {
+ "Type" = "Database";
+ };
+
+ "Mirror" = {
+ "Enabled" = false;
+ "PackageSource" = "https://api.nuget.org/v3/index.json";
+ };
+
+ "Logging" = {
+ "IncludeScopes" = false;
+ "Debug" = {
+ "LogLevel" = {
+ "Default" = "Warning";
+ };
+ };
+ "Console" = {
+ "LogLevel" = {
+ "Microsoft.Hosting.Lifetime" = "Information";
+ "Default" = "Warning";
+ };
+ };
+ };
+ }
+ '';
+ description = ''
+ Extra configuration options for BaGet. Refer to for details.
+ Default value is merged with values from here.
+ '';
+ };
+ };
+
+ # implementation
+
+ config = mkIf cfg.enable {
+
+ systemd.services.baget = {
+ description = "BaGet server";
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "network-online.target" ];
+ after = [ "network.target" "network-online.target" ];
+ path = [ pkgs.jq ];
+ serviceConfig = {
+ WorkingDirectory = "/var/lib/baget";
+ DynamicUser = true;
+ StateDirectory = "baget";
+ StateDirectoryMode = "0700";
+ LoadCredential = "api_key:${cfg.apiKeyFile}";
+
+ CapabilityBoundingSet = "";
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateTmp = true;
+ PrivateUsers = true;
+ PrivateMounts = true;
+ ProtectHome = true;
+ ProtectClock = true;
+ ProtectProc = "noaccess";
+ ProcSubset = "pid";
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectControlGroups = true;
+ ProtectHostname = true;
+ RestrictSUIDSGID = true;
+ RestrictRealtime = true;
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ RemoveIPC = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ SystemCallFilter = [ "@system-service" "~@privileged" ];
+ };
+ script = ''
+ jq --slurpfile apiKeys <(jq -R . "$CREDENTIALS_DIRECTORY/api_key") '.ApiKey = $apiKeys[0]' ${configFile} > appsettings.json
+ ln -snf ${pkgs.baget}/lib/BaGet/wwwroot wwwroot
+ exec ${pkgs.baget}/bin/BaGet
+ '';
+ };
+
+ };
+}