diff --git a/flake.lock b/flake.lock index a7a3210..e930223 100644 --- a/flake.lock +++ b/flake.lock @@ -1,6 +1,207 @@ { "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": "nixpkgs", + "systems": "systems" + }, + "locked": { + "lastModified": 1761656077, + "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", + "owner": "ryantm", + "repo": "agenix", + "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "blobs": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1744478979, + "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "nixos-mailserver", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "nixos-mailserver", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "nixos-mailserver", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixos-mailserver": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-25_05": "nixpkgs-25_05" + }, + "locked": { + "lastModified": 1755110674, + "narHash": "sha256-PigqTAGkdBYXVFWsJnqcirrLeFqRFN4PFigLA8FzxeI=", + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "rev": "f5936247dbdb8501221978562ab0b302dd75456c", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "ref": "nixos-25.05", + "repo": "nixos-mailserver", + "type": "gitlab" + } + }, "nixpkgs": { + "locked": { + "lastModified": 1754028485, + "narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "59e69648d345d6e8fef86158c555730fa12af9de", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-25_05": { + "locked": { + "lastModified": 1747610100, + "narHash": "sha256-rpR5ZPMkWzcnCcYYo3lScqfuzEw5Uyfh+R0EKZfroAc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ca49c4304acf0973078db0a9d200fd2bae75676d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { "locked": { "lastModified": 1761597516, "narHash": "sha256-wxX7u6D2rpkJLWkZ2E932SIvDJW8+ON/0Yy8+a5vsDU=", @@ -17,7 +218,24 @@ }, "root": { "inputs": { - "nixpkgs": "nixpkgs" + "agenix": "agenix", + "nixos-mailserver": "nixos-mailserver", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index d614834..2128c0c 100644 --- a/flake.nix +++ b/flake.nix @@ -3,11 +3,22 @@ inputs = { nixpkgs.url = "nixpkgs/nixos-25.05"; + nixos-mailserver = { + url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-25.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.agenix.inputs.nixpkgs.follows = "nixpkgs"; + inputs.agenix.inputs.darwin.follows = ""; + }; }; outputs = { self, nixpkgs, + nixos-mailserver, + agenix, ... }: let lib = nixpkgs.lib; @@ -15,7 +26,7 @@ nixosConfigurations = { distrust = lib.nixosSystem { system = "x86_64-linux"; - modules = [./system ./services]; + modules = [./system ./services nixos-mailserver.nixosModules.default agenix.nixosModules.default]; }; }; }; diff --git a/secrets/bind_pw b/secrets/bind_pw new file mode 100644 index 0000000..d3c4258 --- /dev/null +++ b/secrets/bind_pw @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 OPPxWw Slc68CGLIV6b8991IWvlIPpkdBxDG6hH3ytF+eWlZS0 +CZFb1fdZ67vbZHwhQUokWwHL7NOapVfOgx1sk+Z8rp4 +-> ssh-ed25519 aO1l/A R8fGdM3+lIABd5s8uPQUibKm3zhqYvvn4w4mEZuy9B4 +J/YMkcSa76rhuq64UCYc8Q4GVRh/jdYVKWU8V7LQ+i4 +--- tD1M4bRODHpYr9AnDocT8hN+TZUB11QMq9KytykLb5k +ڷ +Nͳy^AgY02pLD=*ktDo \ No newline at end of file diff --git a/secrets/nextcloud-admin-pass b/secrets/nextcloud-admin-pass new file mode 100644 index 0000000..9a46ce1 Binary files /dev/null and b/secrets/nextcloud-admin-pass differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix new file mode 100644 index 0000000..60cf7f6 --- /dev/null +++ b/secrets/secrets.nix @@ -0,0 +1,14 @@ +let + user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxah5pnxmk+P7HtwRsryDoAHZsDs5RcGP9IPCNg1KFe cardno:16_179_196"; + users = [ user ]; + + system = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMKxw1fDsIUUh3vWCD90LDgDMAG/NSVRg7QamUbknz5A root@distrust"; + systems = [ system ]; + + all = users ++ systems; +in +{ + "bind_pw".publicKeys = all; + "nextcloud-admin-pass".publicKeys = all; + "vaultwarden.env".publicKeys = all; +} diff --git a/secrets/vaultwarden.env b/secrets/vaultwarden.env new file mode 100644 index 0000000..cab01a4 Binary files /dev/null and b/secrets/vaultwarden.env differ diff --git a/services/akkoma.nix b/services/akkoma.nix index 8314a27..3bc99d8 100644 --- a/services/akkoma.nix +++ b/services/akkoma.nix @@ -5,6 +5,7 @@ ... }: let fediPort = 8083; + onionUrl = "http://n5j5sq55iem2hzbgvkba5vwd5gx5qj2pkb7nxyginbtmnkah74rtulad.onion"; inherit ((pkgs.formats.elixirConf {}).lib) mkAtom; in { services.akkoma = { @@ -39,14 +40,11 @@ in { }; }; - services.caddy.virtualHosts."social.distrust.network".extraConfig = '' + services.caddy.virtualHosts."http://social.distrust.network ${onionUrl}".extraConfig = '' reverse_proxy localhost:${toString fediPort} ''; services.tor.relay.onionServices."akkoma".map = [ - { - port = 80; - target = {port = fediPort;}; - } + 80 ]; } diff --git a/services/dante.nix b/services/dante.nix new file mode 100644 index 0000000..9193a64 --- /dev/null +++ b/services/dante.nix @@ -0,0 +1,14 @@ +{ + services.dante = { + enable = true; + config = '' + internal: 0.0.0.0 port=1080 + external: eth0 + clientmethod: none + socksmethod: none + ''; + }; + + networking.firewall.allowedTCPPorts = [ 1080 ]; + networking.firewall.allowedUDPPorts = [ 1080 ]; +} diff --git a/services/default.nix b/services/default.nix index f83aa83..49cc03e 100644 --- a/services/default.nix +++ b/services/default.nix @@ -1,12 +1,14 @@ { imports = [ ./caddy.nix - ./tor.nix ./site.nix ./nextcloud.nix ./forgejo.nix ./akkoma.nix ./prosody.nix ./lldap.nix + ./dante.nix + ./vaultwarden.nix + ./mailserver.nix ]; } diff --git a/services/forgejo.nix b/services/forgejo.nix index 942676d..ff3c826 100644 --- a/services/forgejo.nix +++ b/services/forgejo.nix @@ -1,5 +1,6 @@ let forgejoPort = 8082; + onionUrl = "http://cr27k6asjs7skvjxs6smhqfam3wlvmft2f3iins44k6p6rmmfyolobqd.onion"; in { services.forgejo = { enable = true; @@ -8,17 +9,15 @@ in { DOMAIN = "git.distrust.network"; HTTP_PORT = forgejoPort; ROOT_URL = "https://git.distrust.network/"; + SSH_PORT = 292; }; }; - services.caddy.virtualHosts."git.distrust.network".extraConfig = '' + services.caddy.virtualHosts."https://git.distrust.network ${onionUrl}".extraConfig = '' reverse_proxy localhost:${toString forgejoPort} ''; services.tor.relay.onionServices."forgejo".map = [ - { - port = 80; - target = {port = forgejoPort;}; - } + 80 ]; } diff --git a/services/mailserver.nix b/services/mailserver.nix new file mode 100644 index 0000000..393da6f --- /dev/null +++ b/services/mailserver.nix @@ -0,0 +1,16 @@ +{ config, ... }: +{ + mailserver = { + enable = true; + fqdn = "distrust.network"; + domains = [ "distrust.network" ]; + certificateScheme = "acme"; + ldap = { + enable = true; + bind.dn = "cn=bind,ou=people,dc=distrust,dc=network"; + bind.passwordFile = config.age.secrets."bind_pw".path; + searchBase = "ou=people,dc=distrust,dc=network"; + uris = [ "ldap://localhost:3890" ]; + }; + }; +} diff --git a/services/nextcloud.nix b/services/nextcloud.nix index 8b3c31f..fcc914c 100644 --- a/services/nextcloud.nix +++ b/services/nextcloud.nix @@ -1,17 +1,23 @@ { pkgs, config, + lib, ... }: let - nextcloudPort = 8081; + onionUrl = "http://znfdxs4e3rqvzxtkksiidomupgm2x44wtrzyxtpomczto3xg5qxpcbqd.onion"; in { - environment.etc."nextcloud-admin-pass".text = "PWD"; + age.secrets."nextcloud-admin-pass".file = ../secrets/nextcloud-admin-pass; + services.nextcloud = { enable = true; hostName = "cloud.distrust.network"; - settings.trusted_domains = ["znfdxs4e3rqvzxtkksiidomupgm2x44wtrzyxtpomczto3xg5qxpcbqd.onion"]; + settings = { + trusted_domains = ["znfdxs4e3rqvzxtkksiidomupgm2x44wtrzyxtpomczto3xg5qxpcbqd.onion"]; + trusted_proxies = ["127.0.0.1"]; + maintenance_window_start = 1; + }; config = { - adminpassFile = "/etc/nextcloud-admin-pass"; + adminpassFile = config.age.secrets."nextcloud-admin-pass".path; dbtype = "pgsql"; }; package = pkgs.nextcloud32; @@ -21,14 +27,77 @@ in { database.createLocally = true; }; - services.nginx.virtualHosts."${config.services.nextcloud.hostName}".listen = [ - { - addr = "127.0.0.1"; - port = nextcloudPort; - } - ]; + users.groups.nextcloud.members = [ "nextcloud" "caddy" ]; + services.nginx.enable = lib.mkForce false; + services.phpfpm.pools.nextcloud.settings = { + "listen.owner" = "caddy"; + "listen.group" = "caddy"; + }; + services.caddy.virtualHosts."https://cloud.distrust.network ${onionUrl}".extraConfig = '' + # encode zstd gzip + + root * ${config.services.nginx.virtualHosts."cloud.distrust.network".root} - services.caddy.virtualHosts."https://cloud.distrust.network".extraConfig = '' - reverse_proxy localhost:${toString nextcloudPort} + redir /.well-known/carddav /remote.php/dav 301 + redir /.well-known/caldav /remote.php/dav 301 + redir /.well-known/* /index.php{uri} 301 + redir /remote/* /remote.php{uri} 301 + + + header { + Strict-Transport-Security max-age=31536000 + Permissions-Policy interest-cohort=() + X-Content-Type-Options nosniff + X-Frame-Options SAMEORIGIN + Referrer-Policy no-referrer + X-XSS-Protection "1; mode=block" + X-Permitted-Cross-Domain-Policies none + X-Robots-Tag "noindex, nofollow" + -X-Powered-By + Host {host} + X-Real-IP {remote_host} + X-Forwarded-For {remote_host} + X-Forwarded-Proto {scheme} + X-Forwarded-Host {host} + } + + + php_fastcgi unix/${config.services.phpfpm.pools.nextcloud.socket} { + root ${config.services.nginx.virtualHosts."cloud.distrust.network".root} + env front_controller_active true + env modHeadersAvailable true + } + + @forbidden { + path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/* + path /.* /autotest* /occ* /issue* /indie* /db_* /console* + not path /.well-known/* + } + error @forbidden 404 + + @immutable { + path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite + query v=* + } + header @immutable Cache-Control "max-age=15778463, immutable" + + @static { + path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite + not query v=* + } + header @static Cache-Control "max-age=15778463" + + @woff2 path *.woff2 + header @woff2 Cache-Control "max-age=604800" + + file_server ''; + + services.nextcloud.phpOptions = { + "opcache.interned_strings_buffer" = 64; + }; + + services.tor.relay.onionServices."nextcloud".map = [ + 80 + ]; } diff --git a/services/prosody.nix b/services/prosody.nix index 35212f7..aa33eba 100644 --- a/services/prosody.nix +++ b/services/prosody.nix @@ -1,8 +1,11 @@ { pkgs, lib, + config, ... }: { + age.secrets."bind_pw".file = ../secrets/bind_pw; + services.prosody = { package = pkgs.prosody.override { withExtraLuaPackages = pkgs: with pkgs.luaPackages; [lualdap]; @@ -27,7 +30,7 @@ ldap_base = "ou=people,dc=distrust,dc=network" ldap_server = "localhost:3890" ldap_rootdn = "uid=bind,ou=people,dc=distrust,dc=network" - ldap_password = "bindpassword" + ldap_password = "${builtins.readFile config.age.secrets."bind_pw".path}" ''; }; diff --git a/services/site.nix b/services/site.nix index 7392f54..de36ade 100644 --- a/services/site.nix +++ b/services/site.nix @@ -4,29 +4,16 @@ ... }: let sitePort = 8080; + onionUrl = "http://nzmkihvxjazbb3fgu7drbklpt6ibg4suff4glxpadhrd4pf5wd2od5yd.onion"; in { - systemd.services.python-http-server = { - description = "Simple Python HTTP Server"; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; - serviceConfig = { - ExecStart = "${pkgs.python3}/bin/python3 -m http.server ${toString sitePort} --directory /var/www/distrust.network"; - Restart = "on-failure"; - User = "nobody"; - WorkingDirectory = "/var/www/distrust.network"; - }; - }; - - services.caddy.virtualHosts."distrust.network" = { - extraConfig = '' - reverse_proxy localhost:${toString sitePort} + services.caddy.virtualHosts = { + "https://distrust.network ${onionUrl}".extraConfig = '' + root * /etc/nixos/site + file_server ''; }; services.tor.relay.onionServices."site".map = [ - { - port = 80; - target = {port = sitePort;}; - } + 80 ]; } diff --git a/services/tor.nix b/services/tor.nix deleted file mode 100644 index 6464ec6..0000000 --- a/services/tor.nix +++ /dev/null @@ -1,9 +0,0 @@ -{lib, ...}: { - services.tor = { - settings.HiddenServiceNonAnonymousMode = false; - client = { - enable = true; - dns.enable = true; - }; - }; -} diff --git a/services/vaultwarden.nix b/services/vaultwarden.nix new file mode 100644 index 0000000..834ddb1 --- /dev/null +++ b/services/vaultwarden.nix @@ -0,0 +1,25 @@ +{ config, ... }: +let + vaultPort = 8222; + onionUrl = "http://gfoqwlo4nmhcywzzyhfanhkf7hz64lkjayngfyrpbd7ohaucu3q4znqd.onion"; +in +{ + age.secrets."vaultwarden.env".file = ../secrets/vaultwarden.env; + + services.vaultwarden = { + enable = true; + config = { + DOMAIN = "https://vault.distrust.network"; + ROCKET_PORT = vaultPort; + }; + environmentFile = config.age.secrets."vaultwarden.env".path; + }; + + services.caddy.virtualHosts."https://vault.distrust.network ${onionUrl}".extraConfig = '' + reverse_proxy localhost:${toString vaultPort} + ''; + + services.tor.relay.onionServices."vaultwarden".map = [ + 80 + ]; +} diff --git a/site/index.html b/site/index.html new file mode 100755 index 0000000..660cd00 --- /dev/null +++ b/site/index.html @@ -0,0 +1,63 @@ + +
+"The mask of self-deception was no longer a mask for me, it was a part of me." Robert W. Chambers
+distrust.network works off one simple principle:
Pricing starts at $1 per month (or however you'd like to pay, any extra being a tip), and upgrades to lifetime access as soon as you have paid $100 total. Payment is in BTC only.
+We provide a plethora of services, available through either TOR or the clearnet. These include (and are limited to):
+All services have a strict no-logs and no-metrics policy. Where it is difficult to configure this in a service, logs are directly piped and/or symlinked to /dev/null.
The server runs a hardened NixOS config, and is updated when appropriate for any security/hardening tweaks.
+If you are interested, email me with your desired username.
+