feat: Add crowdsec module
This commit is contained in:
parent
09198a416c
commit
b90af26085
modules
237
modules/crowdsec.nix
Normal file
237
modules/crowdsec.nix
Normal file
|
@ -0,0 +1,237 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.crowdsec;
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
|
||||
# TODO(tlater): Upstream properly installing the service file
|
||||
crowdsec = pkgs.symlinkJoin {
|
||||
name = "crowdsec-with-unit";
|
||||
paths = [
|
||||
pkgs.crowdsec
|
||||
(pkgs.runCommandLocal "crowdsec.service" { } ''
|
||||
mkdir -p $out/lib/systemd/system/
|
||||
|
||||
substitute ${pkgs.crowdsec}/share/crowdsec/config/crowdsec.service $out/lib/systemd/system/crowdsec.service \
|
||||
--replace-fail /usr/local ${pkgs.crowdsec}
|
||||
'')
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.crowdsec =
|
||||
let
|
||||
inherit (lib.types) nullOr package path;
|
||||
in
|
||||
{
|
||||
enable = lib.mkEnableOption "crowdsec";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = package;
|
||||
default = crowdsec;
|
||||
};
|
||||
|
||||
stateDirectory = lib.mkOption {
|
||||
type = path;
|
||||
readOnly = true;
|
||||
|
||||
description = ''
|
||||
The state directory of the crowdsec instance. Cannot be
|
||||
changed, but is exposed for downstream use.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
default = { };
|
||||
|
||||
description = ''
|
||||
The crowdsec configuration. Refer to
|
||||
<https://docs.crowdsec.net/docs/next/configuration/crowdsec_configuration/>
|
||||
for details on supported values.
|
||||
'';
|
||||
};
|
||||
|
||||
# clientCredentials = lib.mkOption {
|
||||
# type = path;
|
||||
|
||||
# description = ''
|
||||
# The API client credentials to configure; Required to access
|
||||
# the service at all.
|
||||
# '';
|
||||
# };
|
||||
|
||||
centralApiCredentials = lib.mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
|
||||
description = ''
|
||||
The API key to access crowdsec's central API - this is
|
||||
required to access any of the shared blocklists.
|
||||
|
||||
Use of this feature is optional, entering no API key (the
|
||||
default) turns all sharing or receiving of blocked IPs off.
|
||||
|
||||
Note that adding the API key by itself does not enable
|
||||
sharing of blocked IPs with the central API. This limits the
|
||||
types of blocklists this instance can access.
|
||||
|
||||
To also turn sharing blocked IPs on, set
|
||||
`api.server.online_client.sharing = true;`.
|
||||
'';
|
||||
};
|
||||
|
||||
ctiApiKey = lib.mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
|
||||
description = ''
|
||||
The API key for crowdsec's CTI offering.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Set up default settings; anything that *shouldn't* be changed is
|
||||
# set to the default priority so that users need to use
|
||||
# `lib.mkForce`.
|
||||
services.crowdsec = {
|
||||
stateDirectory = "/var/lib/crowdsec";
|
||||
|
||||
settings = {
|
||||
common = {
|
||||
# Default config daemonizes, but the service is set to
|
||||
# `notify`; presumably the daemonization isn't really intended
|
||||
daemonize = false;
|
||||
# The default logs to files, which isn't the preferred way
|
||||
# on NixOS
|
||||
log_media = "stdout";
|
||||
};
|
||||
|
||||
config_paths = {
|
||||
config_dir = "/etc/crowdsec/";
|
||||
data_dir = "${cfg.stateDirectory}/data/";
|
||||
# This "config" file is intended to be written to using the
|
||||
# cscli tool, so you can temporarily make it so rules don't
|
||||
# do anything but log what they *would* do for
|
||||
# experimentation.
|
||||
simulation_path = "${cfg.stateDirectory}/config/simulation.yaml";
|
||||
|
||||
pattern_dir = "${cfg.package}/share/crowdsec/config/patterns";
|
||||
|
||||
# We don't want to actually download anything; Any rules
|
||||
# will be properly packaged.
|
||||
hub_dir = lib.mkDefault "/var/empty/";
|
||||
index_path = lib.mkDefault "/var/empty/.index.json";
|
||||
|
||||
# Integrations aren't supported for now
|
||||
notification_dir = lib.mkDefault "/var/empty/";
|
||||
plugin_dir = lib.mkDefault "/var/empty/";
|
||||
};
|
||||
|
||||
crowdsec_service.acquisition_path = lib.mkDefault "${cfg.package}/share/crowdsec/config/acquis.yaml";
|
||||
|
||||
cscli = {
|
||||
prometheus_uri = lib.mkDefault "127.0.0.1:6060";
|
||||
};
|
||||
|
||||
api = {
|
||||
cti = {
|
||||
enabled = cfg.ctiApiKey != null;
|
||||
key = cfg.ctiApiKey;
|
||||
};
|
||||
# client.credentials_path = cfg.clientCredentials;
|
||||
client.credentials_path = "${cfg.stateDirectory}/local_credentials.yaml";
|
||||
server = {
|
||||
listen_uri = lib.mkDefault "127.0.0.1:8080";
|
||||
profiles_path = lib.mkDefault "${cfg.package}/share/crowdsec/config/profiles.yaml";
|
||||
console_path = lib.mkDefault "${cfg.package}/share/crowdsec/config/console.yaml";
|
||||
|
||||
online_client = {
|
||||
# By default, we don't let crowdsec phone home, since
|
||||
# this is usually within NixOS users' concerns.
|
||||
#
|
||||
# TODO: Enable when this option becomes available
|
||||
# (1.6.4, current nixpkgs-unstable)
|
||||
# sharing = lib.mkDefault false;
|
||||
credentials_path = cfg.centralApiCredentials;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# We enable prometheus by default, since cscli relies on it
|
||||
# for metrics
|
||||
prometheus = {
|
||||
enabled = lib.mkDefault true;
|
||||
level = lib.mkDefault "full";
|
||||
listen_addr = lib.mkDefault "127.0.0.1";
|
||||
listen_port = lib.mkDefault 6060;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.packages = [
|
||||
cfg.package
|
||||
];
|
||||
|
||||
environment.etc."crowdsec/config.yaml".source =
|
||||
settingsFormat.generate "crowdsec-settings.yaml" cfg.settings;
|
||||
|
||||
# Note that the service basics are already defined upstream
|
||||
systemd.services.crowdsec.serviceConfig = {
|
||||
|
||||
# TODO: ExecStartPre to make `/var/lib/crowdsec/config`
|
||||
|
||||
User = "crowdsec";
|
||||
Group = "crowdsec";
|
||||
SupplementaryGroups = [ "systemd-journal" ];
|
||||
|
||||
StateDirectory = "crowdsec";
|
||||
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHome = true;
|
||||
CapabilityBoundingSet = [ ];
|
||||
LockPersonality = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
|
||||
NoNewPrivileges = true;
|
||||
RestrictSUIDSGID = true;
|
||||
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid"; # Needed for journal access
|
||||
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"@network-io"
|
||||
];
|
||||
SystemCallArchitectures = [ "native" ];
|
||||
SystemCallErrorNumber = "EPERM";
|
||||
|
||||
ExecPaths = [ "/nix/store" ];
|
||||
NoExecPaths = [ "/" ];
|
||||
};
|
||||
|
||||
users = {
|
||||
users.crowdsec = {
|
||||
isSystemUser = true;
|
||||
home = cfg.stateDirectory;
|
||||
group = "crowdsec";
|
||||
};
|
||||
groups = {
|
||||
crowdsec = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1 +1,6 @@
|
|||
{ imports = [ ./nginxExtensions.nix ]; }
|
||||
{
|
||||
imports = [
|
||||
./crowdsec.nix
|
||||
./nginxExtensions.nix
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue