Compare commits
14 Commits
master
...
nginx-add-
Author | SHA1 | Date |
---|---|---|
Izorkin | 412d1a9851 | |
Izorkin | 9700b9c08d | |
Izorkin | f775c42454 | |
Izorkin | ced421eff4 | |
Izorkin | 36e7cb8c5e | |
Izorkin | 8a341bf253 | |
Izorkin | b557482517 | |
Izorkin | b2659618aa | |
Izorkin | ac9860453b | |
Izorkin | 8b10998cae | |
Izorkin | 4dcbc6cd4e | |
Inex Code | 1b8bdb013a | |
Inex Code | 3f42ad5c68 | |
Inex Code | 63aaeec08c |
|
@ -1,3 +1,7 @@
|
||||||
|
outputs
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
source
|
||||||
userdata/userdata.json
|
userdata/userdata.json
|
||||||
hardware-configuration.nix
|
hardware-configuration.nix
|
||||||
networking.nix
|
networking.nix
|
||||||
|
|
|
@ -6,27 +6,28 @@ in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
|
./generic/api/api.nix
|
||||||
./variables-module.nix
|
./generic/modules/api.nix
|
||||||
./variables.nix
|
./generic/modules/userdata.nix
|
||||||
./files.nix
|
./generic/overlays/default.nix
|
||||||
./users.nix
|
./generic/services/backup/restic.nix
|
||||||
./mailserver/system/mailserver.nix
|
./generic/services/cloud/nextcloud.nix
|
||||||
./mailserver/system/alps.nix
|
./generic/services/git/gitea.nix
|
||||||
./vpn/ocserv.nix
|
./generic/services/letsencrypt/acme.nix
|
||||||
./api/api.nix
|
./generic/services/letsencrypt/resolve.nix
|
||||||
./api/api-module.nix
|
./generic/services/mail/alps.nix
|
||||||
./social/pleroma.nix
|
./generic/services/mail/mailserver.nix
|
||||||
./letsencrypt/acme.nix
|
./generic/services/passmgr/bitwarden.nix
|
||||||
./letsencrypt/resolve.nix
|
./generic/services/social/pleroma.nix
|
||||||
./backup/restic.nix
|
./generic/services/videomeet/jitsi.nix
|
||||||
./passmgr/bitwarden.nix
|
./generic/services/vpn/ocserv.nix
|
||||||
./webserver/nginx.nix
|
./generic/services/webserver/modsecurity/default.nix
|
||||||
./webserver/memcached.nix
|
./generic/services/webserver/memcached.nix
|
||||||
./nextcloud/nextcloud.nix
|
./generic/services/webserver/nginx.nix
|
||||||
./resources/limits.nix
|
./generic/system/limits.nix
|
||||||
./videomeet/jitsi.nix
|
./generic/system/tmpfiles.nix
|
||||||
./git/gitea.nix
|
./generic/system/userdata.nix
|
||||||
|
./generic/system/users.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.overlays = [ (nix-overlay) ];
|
nixpkgs.overlays = [ (nix-overlay) ];
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{ lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
nixpkgs.config.packageOverrides = pkgs: rec {
|
||||||
|
spdev = import ./../pkgs { inherit pkgs; };
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.overlays = [
|
||||||
|
(self: super: {
|
||||||
|
nginx = super.nginxMainline.override {
|
||||||
|
withDebug = false;
|
||||||
|
withStream = false;
|
||||||
|
modules = [
|
||||||
|
pkgs.nginxModules.rtmp
|
||||||
|
pkgs.nginxModules.dav
|
||||||
|
pkgs.nginxModules.moreheaders
|
||||||
|
pkgs.nginxModules.modsecurity-nginx
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{ pkgs ? import <nixpkgs> { } }:
|
||||||
|
rec {
|
||||||
|
libmodsecurity = pkgs.callPackage ./libmodsecurity { };
|
||||||
|
modsecurity-crs = pkgs.callPackage ./modsecurity-crs { };
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
{ lib, stdenv, fetchFromGitHub
|
||||||
|
, autoreconfHook, bison, flex, pkg-config
|
||||||
|
, curl, geoip, libmaxminddb, libxml2, lmdb, lua, pcre
|
||||||
|
, ssdeep, valgrind, yajl
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "libmodsecurity";
|
||||||
|
version = "3.0.6";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "SpiderLabs";
|
||||||
|
repo = "ModSecurity";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-V+NBT2YN8qO3Px8zEzSA2ZsjSf1pv8+VlLxYlrpqfGg=";
|
||||||
|
fetchSubmodules = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ autoreconfHook bison flex pkg-config ];
|
||||||
|
buildInputs = [ curl geoip libmaxminddb libxml2 lmdb lua pcre ssdeep valgrind yajl ];
|
||||||
|
|
||||||
|
outputs = [ "out" "dev" ];
|
||||||
|
|
||||||
|
configureFlags = [
|
||||||
|
"--enable-parser-generation"
|
||||||
|
"--with-curl=${curl.dev}"
|
||||||
|
"--with-libxml=${libxml2.dev}"
|
||||||
|
"--with-lmdb=${lmdb.out}"
|
||||||
|
"--with-maxmind=${libmaxminddb}"
|
||||||
|
"--with-pcre=${pcre.dev}"
|
||||||
|
"--with-ssdeep=${ssdeep}"
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace build/lmdb.m4 \
|
||||||
|
--replace "\''${path}/include/lmdb.h" "${lmdb.dev}/include/lmdb.h" \
|
||||||
|
--replace "lmdb_inc_path=\"\''${path}/include\"" "lmdb_inc_path=\"${lmdb.dev}/include\""
|
||||||
|
substituteInPlace build/ssdeep.m4 \
|
||||||
|
--replace "/usr/local/libfuzzy" "${ssdeep}/lib" \
|
||||||
|
--replace "\''${path}/include/fuzzy.h" "${ssdeep}/include/fuzzy.h" \
|
||||||
|
--replace "ssdeep_inc_path=\"\''${path}/include\"" "ssdeep_inc_path=\"${ssdeep}/include\""
|
||||||
|
substituteInPlace modsecurity.conf-recommended \
|
||||||
|
--replace "SecUnicodeMapFile unicode.mapping 20127" "SecUnicodeMapFile $out/share/modsecurity/unicode.mapping 20127"
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
mkdir -p $out/share/modsecurity
|
||||||
|
cp ${src}/{AUTHORS,CHANGES,LICENSE,README.md,modsecurity.conf-recommended,unicode.mapping} $out/share/modsecurity
|
||||||
|
'';
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://github.com/SpiderLabs/ModSecurity";
|
||||||
|
description = ''
|
||||||
|
ModSecurity v3 library component.
|
||||||
|
'';
|
||||||
|
longDescription = ''
|
||||||
|
Libmodsecurity is one component of the ModSecurity v3 project. The
|
||||||
|
library codebase serves as an interface to ModSecurity Connectors taking
|
||||||
|
in web traffic and applying traditional ModSecurity processing. In
|
||||||
|
general, it provides the capability to load/interpret rules written in
|
||||||
|
the ModSecurity SecRules format and apply them to HTTP content provided
|
||||||
|
by your application via Connectors.
|
||||||
|
'';
|
||||||
|
license = licenses.asl20;
|
||||||
|
platforms = platforms.all;
|
||||||
|
maintainers = with maintainers; [ izorkin ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
{ lib, stdenv, fetchFromGitHub }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
version = "3.3.2";
|
||||||
|
pname = "modsecurity-crs";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "coreruleset";
|
||||||
|
repo = "coreruleset";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-m/iVLhk2y5BpYu8EwC2adrrDnbaVCQ0SE25ltvMokCw=";
|
||||||
|
};
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
install -D -m444 -t $out/rules ${src}/rules/*.conf
|
||||||
|
install -D -m444 -t $out/rules ${src}/rules/*.data
|
||||||
|
install -D -m444 -t $out/share/doc/modsecurity-crs ${src}/*.md
|
||||||
|
install -D -m444 -t $out/share/doc/modsecurity-crs ${src}/{CHANGES,INSTALL,LICENSE}
|
||||||
|
install -D -m444 -t $out/share/modsecurity-crs ${src}/rules/*.example
|
||||||
|
install -D -m444 -t $out/share/modsecurity-crs ${src}/crs-setup.conf.example
|
||||||
|
cat > $out/share/modsecurity-crs/modsecurity-crs.load.example <<EOF
|
||||||
|
##
|
||||||
|
## This is a sample file for loading OWASP CRS's rules.
|
||||||
|
##
|
||||||
|
Include /etc/modsecurity/crs/crs-setup.conf
|
||||||
|
IncludeOptional /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
|
||||||
|
Include $out/rules/*.conf
|
||||||
|
IncludeOptional /etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://coreruleset.org";
|
||||||
|
description = ''
|
||||||
|
The OWASP ModSecurity Core Rule Set is a set of generic attack detection
|
||||||
|
rules for use with ModSecurity or compatible web application firewalls.
|
||||||
|
'';
|
||||||
|
license = licenses.asl20;
|
||||||
|
platforms = platforms.all;
|
||||||
|
maintainers = with maintainers; [ izorkin ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,11 +13,6 @@ in
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
services.dovecot2 = {
|
|
||||||
enablePAM = lib.mkForce true;
|
|
||||||
showPAMFailure = lib.mkForce true;
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users = {
|
users.users = {
|
||||||
virtualMail = {
|
virtualMail = {
|
||||||
isNormalUser = false;
|
isNormalUser = false;
|
||||||
|
@ -34,7 +29,6 @@ in
|
||||||
loginAccounts = {
|
loginAccounts = {
|
||||||
"${cfg.username}@${cfg.domain}" = {
|
"${cfg.username}@${cfg.domain}" = {
|
||||||
hashedPassword = cfg.hashedMasterPassword;
|
hashedPassword = cfg.hashedMasterPassword;
|
||||||
catchAll = [ cfg.domain ];
|
|
||||||
sieveScript = ''
|
sieveScript = ''
|
||||||
require ["fileinto", "mailbox"];
|
require ["fileinto", "mailbox"];
|
||||||
if header :contains "Chat-Version" "1.0"
|
if header :contains "Chat-Version" "1.0"
|
||||||
|
@ -49,7 +43,6 @@ in
|
||||||
name = "${user.username}@${cfg.domain}";
|
name = "${user.username}@${cfg.domain}";
|
||||||
value = {
|
value = {
|
||||||
hashedPassword = user.hashedPassword;
|
hashedPassword = user.hashedPassword;
|
||||||
catchAll = [ cfg.domain ];
|
|
||||||
sieveScript = ''
|
sieveScript = ''
|
||||||
require ["fileinto", "mailbox"];
|
require ["fileinto", "mailbox"];
|
||||||
if header :contains "Chat-Version" "1.0"
|
if header :contains "Chat-Version" "1.0"
|
|
@ -0,0 +1,74 @@
|
||||||
|
{config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
environment.etc."modsecurity/modsecurity_includes.conf".text = ''
|
||||||
|
Include /etc/modsecurity/modsecurity.conf
|
||||||
|
Include /etc/modsecurity/crs-setup.conf
|
||||||
|
Include ${pkgs.spdev.modsecurity-crs}/rules/*.conf
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."modsecurity/modsecurity.conf".text = ''
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
|
||||||
|
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
|
||||||
|
SecRule REQUEST_HEADERS:Content-Type "application/json" \
|
||||||
|
"id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
|
||||||
|
SecRequestBodyLimit 13107200
|
||||||
|
SecRequestBodyNoFilesLimit 131072
|
||||||
|
SecRequestBodyLimitAction Reject
|
||||||
|
SecRule REQBODY_ERROR "!@eq 0" \
|
||||||
|
"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
|
||||||
|
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
|
||||||
|
"id:'200003',phase:2,t:none,log,deny,status:400, \
|
||||||
|
msg:'Multipart request body failed strict validation: \
|
||||||
|
PE %{REQBODY_PROCESSOR_ERROR}, \
|
||||||
|
BQ %{MULTIPART_BOUNDARY_QUOTED}, \
|
||||||
|
BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
|
||||||
|
DB %{MULTIPART_DATA_BEFORE}, \
|
||||||
|
DA %{MULTIPART_DATA_AFTER}, \
|
||||||
|
HF %{MULTIPART_HEADER_FOLDING}, \
|
||||||
|
LF %{MULTIPART_LF_LINE}, \
|
||||||
|
SM %{MULTIPART_MISSING_SEMICOLON}, \
|
||||||
|
IQ %{MULTIPART_INVALID_QUOTING}, \
|
||||||
|
IP %{MULTIPART_INVALID_PART}, \
|
||||||
|
IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
|
||||||
|
FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
|
||||||
|
SecRule MULTIPART_UNMATCHED_BOUNDARY "@eq 1" \
|
||||||
|
"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
|
||||||
|
SecPcreMatchLimit 1000
|
||||||
|
SecPcreMatchLimitRecursion 1000
|
||||||
|
SecRule TX:/^MSC_/ "!@streq 0" \
|
||||||
|
"id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
|
||||||
|
SecResponseBodyAccess On
|
||||||
|
SecResponseBodyMimeType text/plain text/html text/xml
|
||||||
|
SecResponseBodyLimit 524288
|
||||||
|
SecResponseBodyLimitAction ProcessPartial
|
||||||
|
SecTmpDir /tmp/
|
||||||
|
SecDataDir /tmp/
|
||||||
|
SecDebugLog /var/log/nginx/modsec_debug.log
|
||||||
|
SecDebugLogLevel 3
|
||||||
|
SecAuditEngine RelevantOnly
|
||||||
|
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
|
||||||
|
SecAuditLogParts ABIJDEFHZ
|
||||||
|
SecAuditLogType Serial
|
||||||
|
SecAuditLog /var/log/nginx/modsec_audit.log
|
||||||
|
SecAuditLogFormat Json
|
||||||
|
SecArgumentSeparator &
|
||||||
|
SecCookieFormat 0
|
||||||
|
SecUnicodeMapFile ${pkgs.spdev.libmodsecurity}/share/modsecurity/unicode.mapping 20127
|
||||||
|
SecStatusEngine On
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."modsecurity/crs-setup.conf".text = ''
|
||||||
|
SecDefaultAction "phase:1,log,auditlog,pass"
|
||||||
|
SecDefaultAction "phase:2,log,auditlog,pass"
|
||||||
|
SecCollectionTimeout 600
|
||||||
|
SecAction \
|
||||||
|
"id:900990,\
|
||||||
|
phase:1,\
|
||||||
|
nolog,\
|
||||||
|
pass,\
|
||||||
|
t:none,\
|
||||||
|
setvar:tx.crs_setup_version=332"
|
||||||
|
'';
|
||||||
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
{ pkgs, config, ... }:
|
{ lib, pkgs, config, ... }:
|
||||||
let
|
let
|
||||||
domain = config.services.userdata.domain;
|
domain = config.services.userdata.domain;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
systemd.services.nginx.serviceConfig.SystemCallFilter = lib.mkForce "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid";
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableReload = true;
|
enableReload = true;
|
||||||
|
package = pkgs.nginx;
|
||||||
recommendedGzipSettings = true;
|
recommendedGzipSettings = true;
|
||||||
recommendedOptimisation = true;
|
recommendedOptimisation = true;
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
|
@ -37,6 +40,10 @@ in
|
||||||
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
|
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
|
||||||
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
|
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
extraConfig = ''
|
||||||
|
modsecurity on;
|
||||||
|
modsecurity_rules_file /etc/modsecurity/modsecurity_includes.conf;
|
||||||
|
'';
|
||||||
locations = {
|
locations = {
|
||||||
"/" = {
|
"/" = {
|
||||||
proxyPass = "http://127.0.0.1:80/";
|
proxyPass = "http://127.0.0.1:80/";
|
|
@ -24,11 +24,11 @@ in
|
||||||
[
|
[
|
||||||
(if cfg.bitwarden.enable then "d /var/lib/bitwarden 0777 bitwarden_rs bitwarden_rs -" else "")
|
(if cfg.bitwarden.enable then "d /var/lib/bitwarden 0777 bitwarden_rs bitwarden_rs -" else "")
|
||||||
(if cfg.bitwarden.enable then "d /var/lib/bitwarden/backup 0777 bitwarden_rs bitwarden_rs -" else "")
|
(if cfg.bitwarden.enable then "d /var/lib/bitwarden/backup 0777 bitwarden_rs bitwarden_rs -" else "")
|
||||||
(if cfg.pleroma.enable then "d /var/lib/pleroma 0600 pleroma pleroma - -" else "")
|
(if cfg.pleroma.enable then "d /var/lib/pleroma 0700 pleroma pleroma - -" else "")
|
||||||
"d /var/lib/restic 0600 restic - - -"
|
"d /var/lib/restic 0600 restic - - -"
|
||||||
"f+ /var/lib/restic/pass 0400 restic - - ${resticPass}"
|
"f+ /var/lib/restic/pass 0400 restic - - ${resticPass}"
|
||||||
"f+ /root/.config/rclone/rclone.conf 0400 root root - ${rcloneConfig}"
|
"f+ /root/.config/rclone/rclone.conf 0400 root root - ${rcloneConfig}"
|
||||||
(if cfg.pleroma.enable then "f+ /var/lib/pleroma/secrets.exs 0755 pleroma pleroma - -" else "")
|
(if cfg.pleroma.enable then "f /var/lib/pleroma/secrets.exs 0755 pleroma pleroma - -" else "")
|
||||||
"f+ /var/domain 0444 selfprivacy-api selfprivacy-api - ${domain}"
|
"f+ /var/domain 0444 selfprivacy-api selfprivacy-api - ${domain}"
|
||||||
(if cfg.nextcloud.enable then "f+ /var/lib/nextcloud/db-pass 0440 nextcloud nextcloud - ${nextcloudDBPass}" else "")
|
(if cfg.nextcloud.enable then "f+ /var/lib/nextcloud/db-pass 0440 nextcloud nextcloud - ${nextcloudDBPass}" else "")
|
||||||
(if cfg.nextcloud.enable then "f+ /var/lib/nextcloud/admin-pass 0440 nextcloud nextcloud - ${nextcloudAdminPass}" else "")
|
(if cfg.nextcloud.enable then "f+ /var/lib/nextcloud/admin-pass 0440 nextcloud nextcloud - ${nextcloudAdminPass}" else "")
|
|
@ -0,0 +1,6 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
services = {
|
||||||
|
userdata = builtins.fromJSON (builtins.readFile ./../../userdata/userdata.json);
|
||||||
|
};
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ in
|
||||||
value = {
|
value = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
hashedPassword = user.hashedPassword;
|
hashedPassword = user.hashedPassword;
|
||||||
openssh.authorizedKeys.keys = user.sshKeys;
|
openssh.authorizedKeys.keys = (if user ? sshKeys then user.sshKeys else []);
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
cfg.users);
|
cfg.users);
|
|
@ -1,6 +0,0 @@
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
services = {
|
|
||||||
userdata = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in New Issue