From 75bac814d421f4d30e6881c7cf61c2b9938d1011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Sat, 14 Feb 2026 17:01:31 +0100 Subject: [PATCH] feat: add NixOS module for declarative deployment Adds nixos-module.nix with services.oubliette options (enable, package, settings, configFile) and a hardened systemd service. Exposes the module as nixosModules.default in flake.nix. Co-Authored-By: Claude Opus 4.6 --- README.md | 22 +++++++++++++++++ flake.nix | 2 ++ nixos-module.nix | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 nixos-module.nix diff --git a/README.md b/README.md index cd939a3..c289b17 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,25 @@ Test with: ```sh ssh -o StrictHostKeyChecking=no -p 2222 root@localhost ``` + +### NixOS Module + +Add the flake as an input and enable the service: + +```nix +{ + services.oubliette = { + enable = true; + package = inputs.oubliette.packages.${system}.default; + settings = { + ssh.listen_addr = ":2222"; + auth.accept_after = 10; + auth.static_credentials = [ + { username = "root"; password = "toor"; } + ]; + }; + }; +} +``` + +Alternatively, use `configFile` to pass a pre-written TOML file instead of `settings`. diff --git a/flake.nix b/flake.nix index 5f2982b..490cefb 100644 --- a/flake.nix +++ b/flake.nix @@ -11,6 +11,8 @@ forAllSystems = nixpkgs.lib.genAttrs supportedSystems; in { + nixosModules.default = import ./nixos-module.nix; + packages = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; diff --git a/nixos-module.nix b/nixos-module.nix new file mode 100644 index 0000000..e422418 --- /dev/null +++ b/nixos-module.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.oubliette; + tomlFormat = pkgs.formats.toml { }; + + configFile = + if cfg.configFile != null + then cfg.configFile + else tomlFormat.generate "oubliette.toml" cfg.settings; +in +{ + options.services.oubliette = { + enable = lib.mkEnableOption "Oubliette SSH honeypot"; + + package = lib.mkPackageOption pkgs "oubliette" { }; + + configFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = '' + Path to a pre-written TOML configuration file. + Mutually exclusive with {option}`settings`. + ''; + }; + + settings = lib.mkOption { + type = tomlFormat.type; + default = { }; + description = '' + Configuration for Oubliette as a Nix attribute set. + Will be converted to TOML. Mutually exclusive with {option}`configFile`. + See oubliette.toml.example for available options. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = !(cfg.configFile != null && cfg.settings != { }); + message = "services.oubliette: `configFile` and `settings` are mutually exclusive."; + } + ]; + + services.oubliette.settings.ssh.host_key_path = lib.mkDefault "/var/lib/oubliette/host_key"; + + systemd.services.oubliette = { + description = "Oubliette SSH Honeypot"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} -config ${configFile}"; + DynamicUser = true; + StateDirectory = "oubliette"; + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ReadWritePaths = [ "/var/lib/oubliette" ]; + }; + }; + }; +}