Compare commits

...

224 Commits

Author SHA1 Message Date
Inex Code ce3231774e chore: update nixpkgs 2024-05-02 22:34:36 +03:00
Inex Code f8223192e5 fix: Add DeSEC to dnsPropagationCheckExceptions
Probably a temp fix to #59
2024-05-02 22:31:30 +03:00
Alexander 4c183d5b40 fix deSEC: DESEC_POLLING_INTERVAL=30, propagation timeout and TTL 2024-03-12 19:58:37 +04:00
Inex Code 5e005dc436 chore: update API 3.1.0 2024-03-07 23:52:30 +03:00
Inex Code 6619760f47 Revert "try fix"
This reverts commit 3b4466b49d.
2024-02-23 20:46:24 +03:00
Inex Code 3b4466b49d try fix 2024-02-23 20:45:38 +03:00
Inex Code 5d9c385d08 Revert "chore: update API 3.0.1"
This reverts commit 3a7876aeb4.
2024-02-23 20:40:26 +03:00
Inex Code 3a7876aeb4 chore: update API 3.0.1 2024-02-23 20:22:35 +03:00
Inex Code c7583bf501 Merge pull request 'modules: parameterize all subdomains' (#54) from subdomains into flakes
Reviewed-on: #54
2024-02-20 17:51:47 +02:00
Alexander ad43d31c0c modules: parameterize all subdomains 2024-02-20 14:42:37 +04:00
Inex Code 2159c4cc6e Merge pull request 'Bitwarden: Fix webauthn login' (#55) from fix-bitwarden into flakes
Reviewed-on: #55
2024-02-19 14:29:27 +02:00
Inex Code 3d6f47e0e7 chore: update nixpkgs 2024-02-19 15:23:38 +03:00
Inex Code f103f708da fix(bitwarden): Webauthn login didn't work 2024-02-19 15:23:25 +03:00
Alexander Tomokhov 2d4e7e89a1 configure NixOS to allow configuration without password nor ssh key 2024-01-23 16:37:35 +04:00
Alexander d389b6785f Merge branch 'flakes-test' into flakes 2024-01-19 09:59:09 +04:00
Inex Code a8aca42762 feat(ssh): Allow ecdsa-sha2-nistp256 keys 2024-01-19 03:01:20 +04:00
Alexander f9b86f403d default timezone is "Etc/UTC" 2024-01-19 02:59:29 +04:00
Alexander 643f7716ae remove DOMAIN environment variable 2024-01-19 02:48:27 +04:00
Alexander c96e6fe099 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=refs/heads/master&rev=0ccb85d5cc24a20ecc8647035c93bc08e3e31b78' (2024-01-10)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=refs/heads/master&rev=e3761a200c1ce244b285772a0c731a10e6169ef3' (2024-01-15)
2024-01-18 15:18:32 +04:00
Alexander 842d5a0dd1 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=remove-rest-flaked&rev=fb5a8142da48436cd7a30f267d156d50f47829f6' (2024-01-09)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=refs/heads/master&rev=0ccb85d5cc24a20ecc8647035c93bc08e3e31b78' (2024-01-10)
2024-01-11 00:13:44 +04:00
Alexander 3311c5ff50 readme: small additions 2024-01-11 00:03:01 +04:00
Alexander 6b66513870 readme: how to update inputs of this flake 2024-01-10 07:13:17 +04:00
Alexander c08d56ae1c flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f' (2023-12-17)
  → 'github:nixos/nixpkgs/c1be43e8e837b8dbee2b3665a007e761680f0c3d' (2024-01-05)
2024-01-10 06:57:58 +04:00
Alexander e8842e455b Merge branch 'flakes' into flakes-test 2024-01-10 03:35:26 +04:00
Alexander 1a677f273b fix nextcloud auth page redirection 2024-01-10 01:49:51 +04:00
Inex Code 94456c8bd8 upd 2024-01-09 22:33:24 +03:00
Inex Code 3e0eae6d7d Test SP API 3.0.0 2024-01-09 22:04:53 +03:00
Inex Code c0af154421 Update SP API version 2023-12-31 19:22:33 +03:00
Inex Code f287e68f2b fix setuptools version 2023-12-28 22:26:53 +03:00
Inex Code f1e789c7af Update SP API version 2023-12-28 22:25:16 +03:00
Alexander 3d8de64da0 selfprivacy-api git branch: userdata => flakes 2023-12-28 20:52:51 +04:00
Alexander 1e73c88547 uppercase config.selfprivacy.server.provider 2023-12-28 20:05:33 +04:00
Alexander 51f3f12640 system.autoUpgrade: no verbosity of nixos-rebuild 2023-12-28 13:28:46 +04:00
Alexander 013bd9b8e2 sp-nixos: split script into ExecStartPre && ExecStart 2023-12-28 13:20:49 +04:00
Alexander 15f5d6096d sp-modules: refactor options types 2023-12-28 13:19:47 +04:00
Alexander a32613ece4 nixos-upgrade.serviceConfig.ExecCondition on /etc/nixos changes 2023-12-28 13:19:47 +04:00
Alexander 0c895e4015 module: set to false: restartIfChanged and unitConfig.X-StopOnRemoval 2023-12-28 11:07:18 +04:00
Alexander 08aa0b9ffc systemd.services.nixos-upgrade.serviceConfig.WorkingDirectory 2023-12-28 10:57:45 +04:00
Alexander be45d3ed52 systemd.services.nixos-upgrade.serviceConfig.ExecStartPre 2023-12-28 10:42:58 +04:00
Alexander efc703bf0c system services lock path:./sp-modules without flake.lock; cd /etc/nixos 2023-12-28 04:38:24 +04:00
Alexander cc78c2915f remove channel option value from syustem.autoUpgrade 2023-12-28 02:07:46 +04:00
Alexander fe44ba6fd8 fix nextcloud: fail if secrets are missing 2023-12-27 15:05:23 +04:00
Alexander 77619456d7 /etc/nixos#sp-nixos => /etc/nixos#default 2023-12-27 14:02:27 +04:00
Alexander f94d0aef03 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=400be88738fd6c8d18bcc439a81ee208b49bc749' (2023-12-22)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=7883063dca4d946c0955faafd78642224d4a9be8' (2023-12-27)
2023-12-27 13:37:55 +04:00
Alexander 23332cda46 add TODO about environment.variables.DOMAIN 2023-12-27 12:54:10 +04:00
Alexander 85f85239a3 do not set nix.package 2023-12-27 11:37:59 +04:00
Alexander 33ba5c41ac API systemd service Type is simple 2023-12-22 23:52:03 +04:00
Alexander 5bd15a768a system.stateVersion: default or config.selfprivacy.stateVersion 2023-12-22 23:04:03 +04:00
Alexander a185dd1e3e selfprivacy-api: add debug for nixos-rebuild 2023-12-22 21:18:05 +04:00
Alexander e6496b95a4 useACMEHost for all services 2023-12-22 21:18:05 +04:00
Alexander 5aba990f95 move system.stateVersion back to userdata 2023-12-22 19:33:24 +04:00
Alexander 05fe40ac21 fix ACME for DigitalOcean: add DNS propagation check exceptions 2023-12-22 19:08:53 +04:00
Alexander 19f30daf80 sp-modules: x-systemd.before=... for all mountpoints 2023-12-22 18:07:14 +04:00
Alexander 5f8cc727e0 ACME: CLOUDFLARE_POLLING_INTERVAL=30
As said in https://github.com/go-acme/lego/issues/2068.
2023-12-22 14:06:55 +04:00
Alexander 64fc2ae57e mailserver: localDnsResolver = false 2023-12-21 15:13:21 +04:00
Alexander 66c0184a93 ACME: dnsPropagationCheck = true 2023-12-21 13:38:28 +04:00
Alexander 4c3072ade8 ACME: CLOUDFLARE_POLLING_INTERVAL=10 2023-12-21 13:08:34 +04:00
Alexander 0e62c9292b dnsPropagationCheck = false explicitly for certs.${domain} 2023-12-21 12:15:28 +04:00
Alexander 5760a753af ACME dnsPropagationCheck = false 2023-12-20 18:29:39 +04:00
Alexander f2a951a71e API module: systemd service Type = "oneshot" 2023-12-20 18:21:51 +04:00
Alexander fd6e49a21a ACME: do not disable DNS propagation check 2023-12-20 17:43:47 +04:00
Alexander dcaf96c773 Revert "Revert "Revert "add wildcard ACME certificate"""
This reverts commit 4faf8e7dda.
2023-12-20 17:43:47 +04:00
Alexander 3a66da49e1 do not `lib.mkForce` acme.certs 2023-12-20 17:43:47 +04:00
Alexander 5cd12848cc `nix.channel.enable = false` since we're on flakes 2023-12-20 17:43:46 +04:00
Alexander 4faf8e7dda Revert "Revert "add wildcard ACME certificate""
This reverts commit 0c4d57c33d.
2023-12-20 16:59:57 +04:00
Alexander c18f332f5f Revert "use enableACME for all virtualHosts"
This reverts commit 46366702bc.
2023-12-19 23:46:42 +04:00
Alexander 46366702bc use enableACME for all virtualHosts 2023-12-19 17:22:32 +04:00
Alexander 0c4d57c33d Revert "add wildcard ACME certificate"
This reverts commit b37cadff68
(except pleroma virtualHosts).
2023-12-19 17:22:32 +04:00
Alexander 426e6f72c5 gitea: bind mount /var/lib/gitea 2023-12-19 17:22:32 +04:00
Alexander eb59d33e1f nginx: / location with root = "/var/www/root" 2023-12-19 17:22:31 +04:00
Alexander b37cadff68 add wildcard ACME certificate 2023-12-19 01:52:27 +04:00
Inex Code 312077240a fix(acme): add dns propagation check exceptions 2023-12-19 01:19:03 +04:00
Alexander 69f84cdc2b bitwarden: "ConditionPathExists" instead of "after" 2023-12-19 01:19:03 +04:00
Alexander 0ad2ffc30e api module: avoid simultaneous runs 2023-12-19 00:20:18 +04:00
Alexander 83a17063ac explicit dependency between backup-vaultwarden and vaultwarden 2023-12-18 23:40:15 +04:00
Alexander 257b0c08e8 sp-modules: some startup fixes 2023-12-18 22:42:13 +04:00
Alexander da5dac6877 sp-nixos-upgrade: update sp-modules/ own flake.lock 2023-12-18 22:30:24 +04:00
Alexander 3d7aa5e6de fix selfprivacy-api build with new nixpkgs 2023-12-18 21:44:32 +04:00
Alexander 365f027326 move nginx exclusive virtualHosts to SP modules 2023-12-18 19:02:54 +04:00
Alexander d881cc8ce5 upgrade nixpkgs to NixOS 23.11 2023-12-18 18:44:18 +04:00
Alexander b7045a8198 upgrade nixpkgs to NixOS 23.05 2023-12-18 17:56:15 +04:00
Alexander 67c2b12c44 sp-modules: get rid of systemd.tmpfiles
Because it causes troubles when using bind-mounts for /var/lib/*.
2023-12-18 16:30:40 +04:00
Alexander 83e8f6e8a1 get rid of files.nix; ACME/credentialsFile and other cleanup 2023-12-18 07:49:27 +04:00
Alexander 7f6c48f978 gitea: RequiresMountsFor and ConditionPathIsMountPoint @ /var/lib/gitea 2023-12-12 20:50:09 +04:00
Alexander a797b856fc flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=dc230e2e898a510bfdc52e57d829996df02f26b5' (2023-12-12)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=2bdb73d348d1a8b85a71aa480ab1c08fafb2c9ba' (2023-12-12)
2023-12-12 16:30:22 +04:00
Alexander d1711ea9c3 selfprivacy-api: sp-nixos-rebuild with sp-modules relocking 2023-12-12 14:15:06 +04:00
Alexander defaca8793 clean configuration; simple-nixos-mailserver is an ordinary SP module 2023-12-12 08:25:10 +04:00
Alexander 25bd151ef3 use lower case for config.selfprivacy.server.provider 2023-12-11 21:58:12 +04:00
Alexander 519ebbcb69 get rid of system argument; do not set nixpkgs.hostPlatform 2023-12-05 07:36:26 +04:00
Alexander 4c4aef5363 get system.stateVersion from "deployment" argument 2023-12-05 04:51:37 +04:00
Alexander 9dde55159b update selfprivacy-api 2023-12-05 01:56:49 +04:00
Alexander 6cd002ae1d remove restic SP module 2023-12-05 01:56:13 +04:00
Alexander c052f9172a move gitea to SP module 2023-12-04 15:59:22 +04:00
Alexander 054d6d9182 move jitsi-meet to SP module 2023-12-04 15:50:00 +04:00
Alexander 3f573e3dc3 activationScripts: rewrite /etc/nixos with configuration source 2023-12-04 15:25:01 +04:00
Alexander c63b6b808c acme: RestartSec = 15 * 60 2023-12-04 14:33:43 +04:00
Alexander Tomokhov c0aa73ca1b move bitwarden to SP module 2023-12-04 14:33:43 +04:00
Alexander Tomokhov ade4dc08b1 sp-modules: use jq exit status code 2023-12-03 10:37:37 +04:00
Alexander Tomokhov 4716b9bf19 move restic to SP module 2023-12-03 10:05:51 +04:00
Alexander Tomokhov c7419b3255 move pleroma to SP module 2023-12-03 09:46:36 +04:00
Alexander Tomokhov b458458c30 move ocserv to SP module 2023-12-03 09:46:36 +04:00
Alexander Tomokhov 4cbe63ac64 flake: abort on missing configPathsNeeded with message 2023-12-01 08:32:31 +04:00
Alexander Tomokhov 600d8f427d mailserver: set users.groups.acmereceivers.members 2023-11-29 08:28:19 +04:00
Alexander Tomokhov b6cd5846f2 users.groups: acmerecievers => acmereceivers 2023-11-29 08:25:24 +04:00
Alexander Tomokhov 1a5a4be306 nextcloud: fix secrets extraction 2023-11-29 08:19:04 +04:00
Alexander Tomokhov 364a5c8076 mailserver: adapt to deprecated and new types of certificateScheme 2023-11-26 09:39:47 +04:00
Alexander Tomokhov a224731dcf nextcloud: write passwords using `install` 2023-11-26 09:39:47 +04:00
Alexander Tomokhov e814157437 fix config attributes contrain for function imports 2023-11-26 08:56:48 +04:00
Alexander Tomokhov 0db1c4a6ce downgrade simple-nixos-mailserver to 6d0d9fb9 2023-11-26 04:28:36 +04:00
Alexander Tomokhov a98dafc98c fix nextcloud (case when enabled)
Previously, second mkIf for cleanup case took precedence when merge with
`//`. Now it's 2 modules: one for selfprivacy.modules.nextcloud.enable
== true, another for selfprivacy.modules.nextcloud.enable == false.
2023-11-26 03:11:29 +04:00
Alexander Tomokhov 3138260605 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=8791462f87c4a134f5ccb7099a814892c110d43b' (2023-11-23)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=75f4e8d40eff59debcd5eb96e64e2e7c3db75e7f' (2023-11-23)
2023-11-23 21:33:35 +04:00
Alexander Tomokhov 1bf7190388 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=8ccec537401b51583d89f59790953ad32534563a' (2023-11-23)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=8791462f87c4a134f5ccb7099a814892c110d43b' (2023-11-23)
2023-11-23 21:20:35 +04:00
Alexander Tomokhov cc26a5e150 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=9c18ab285cd2221a50950c796456929019f5fb2a' (2023-11-22)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=8ccec537401b51583d89f59790953ad32534563a' (2023-11-23)
2023-11-23 11:36:20 +04:00
Alexander Tomokhov 6ebcc35882 systemd.enableEmergencyMode = false; systemd.coredump.enable = false; 2023-11-23 11:09:49 +04:00
Alexander Tomokhov 985aff90d3 disable ssh passwordAuthentication by default 2023-11-23 11:08:59 +04:00
Alexander Tomokhov bd6b8a5e75 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=2bbc2be6b57f05a159db1f175e8fa84d67eac8da' (2023-11-22)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=9c18ab285cd2221a50950c796456929019f5fb2a' (2023-11-22)
2023-11-23 03:00:25 +04:00
Alexander Tomokhov 6d96b4aa8f flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=aa4e5a9251b440c161b79590fef7d2707cdce9b4' (2023-11-22)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=2bbc2be6b57f05a159db1f175e8fa84d67eac8da' (2023-11-22)
2023-11-22 23:09:42 +04:00
Alexander Tomokhov 8067559207 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=22f9d2e9df2db29493003d436c6b75fe58b5c5f0' (2023-11-21)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=aa4e5a9251b440c161b79590fef7d2707cdce9b4' (2023-11-22)
2023-11-22 22:17:00 +04:00
Alexander Tomokhov 252ed72154 remove autoUpgrade from userdata-variables.nix 2023-11-22 06:45:23 +04:00
Alexander Tomokhov e53eb8d65d flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=e1847e1ce8327d8d36e80b84cd55d7b38baaa40c' (2023-11-20)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=22f9d2e9df2db29493003d436c6b75fe58b5c5f0' (2023-11-21)
2023-11-22 01:58:44 +04:00
Alexander Tomokhov e59d86fcdc flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=nixos-module&rev=e28aa8d60d824133fc3e170d2ed144bf0ec342a3' (2023-11-18)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=userdata&rev=e1847e1ce8327d8d36e80b84cd55d7b38baaa40c' (2023-11-20)
2023-11-21 03:49:45 +04:00
Alexander Tomokhov 7c5bc70fec rm -rf /old-root on every boot
NixOS stage 1 init moves all remnants of previous OS to /old-root.
2023-11-21 03:01:28 +04:00
Alexander Tomokhov 308a70fe20 selfprivacy/current-config-source => selfprivacy/nixos-config-source 2023-11-21 01:24:36 +04:00
Alexander Tomokhov a3063ec732 fileSystems./.options = [ noatime ]; 2023-11-21 01:23:28 +04:00
Alexander Tomokhov e45224d67f fix resources/limits.txt but do not use them for now 2023-11-18 19:26:52 +04:00
Alexander Tomokhov 391e41e8a4 disable documentation.enable = false alltogether 2023-11-18 18:54:55 +04:00
Alexander Tomokhov 0704d18b1a do not install {man,info}-pages and docs to save space 2023-11-18 17:39:14 +04:00
Alexander Tomokhov 6a3a83e270 files.nix: /etc/nixos/userdata.json => /etc/selfprivacy/secrets.json 2023-11-18 09:11:54 +04:00
Alexander Tomokhov b64be4e34f /etc/nixos/userdata/userdata.json => /etc/nixos/userdata.json 2023-11-18 08:54:29 +04:00
Alexander Tomokhov 65e58666fd nixpkgs.hostPlatform = system 2023-11-18 08:28:04 +04:00
Alexander Tomokhov 43abd2ca45 flake.lock: Update
Flake lock file updates:

• Updated input 'selfprivacy-api':
    'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=nixos-module&rev=e6e9d0677e51e5b1f2f5ee60809d190ab18a9f3e' (2023-11-16)
  → 'git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=nixos-module&rev=e28aa8d60d824133fc3e170d2ed144bf0ec342a3' (2023-11-18)
2023-11-18 06:39:10 +04:00
Alexander Tomokhov e6e2f1fd84 configuration.nix: a few nix.* tweaks 2023-11-18 06:37:45 +04:00
Alexander Tomokhov 72d73b6297 autoUpgrade.enable = false by default 2023-11-18 05:40:57 +04:00
Alexander Tomokhov 0f54898cb8 sp-modules: fix nextcloud secrets json path 2023-11-18 05:40:02 +04:00
Alexander Tomokhov d5b04699c1 sp-module: refactor simple-nixos-mailserver flake 2023-11-16 06:36:39 +04:00
Alexander Tomokhov d69a8cd662 migrate selfprivacy-api NixOS module to selfprivacy API repository
But do not treat it as a SP module.
2023-11-16 06:36:39 +04:00
Alexander Tomokhov 80447abb2e selfprivacy.userdata -> selfprivacy; SP modules -> selfprivacy.modules 2023-11-16 04:00:15 +04:00
Alexander Tomokhov f4fb0a9ce8 move nextcloud nginx configuration part to SP module 2023-11-15 23:43:59 +04:00
Alexander Tomokhov 41c3a0fc00 add PoC SP module for nextcloud 2023-11-15 22:36:19 +04:00
Alexander Tomokhov d281f51775 TODO notes: flake: config contrain algorithm 2023-11-15 20:18:49 +04:00
Alexander Tomokhov b0bb84138b delete garbage sp-modules-options.json file 2023-11-15 20:12:33 +04:00
Alexander Tomokhov 4419a1323a fix config attributes contrain mechanism for SP modules
Now it should work for all nested imports too. `imports` are traversed
recursively to redefine each imported module function with altered one,
constraining its config attribute (respecting config-paths-needed.json).
2023-11-15 04:31:20 +04:00
Alexander Tomokhov 26b3071929 system.configurationRevision = self.rev or "@${self.lastModifiedDate}" 2023-11-14 06:22:39 +04:00
Alexander Tomokhov f33fb9e9bf just-nixos => sp-nixos; selfprivacy/current-config-source; add formatter 2023-11-14 02:47:08 +04:00
Alexander Tomokhov e656719ebd remove userdata folder 2023-11-13 19:53:15 +04:00
Alexander Tomokhov f440006806 remove erroneous system attribute from nixosConfigurations 2023-11-13 19:52:34 +04:00
Alexander Tomokhov 80ba7d0bda PoC working SP module system
+ simple-nixos-mailserver as an SP module
2023-11-13 00:37:50 +04:00
Alexander Tomokhov d9e2311f3c system.configurationRevision = self.rev; 2023-11-12 01:39:52 +04:00
Alexander Tomokhov 6c849e2628 embed top-level flake source folder into the build 2023-11-10 07:05:38 +04:00
Alexander Tomokhov 7378329891 pass top-level-flake to set system.configurationRevision 2023-11-10 06:53:21 +04:00
Alexander Tomokhov b4b37f42f2 get rid of overlay for selfprivacy-graphql-api 2023-11-06 13:04:03 +04:00
Alexander Tomokhov 7cee132d8e nixosConfiguration-fun takes a set as an argument
This set must contain:
- hardware-configuration
- userdata (parsed)
2023-11-06 12:50:46 +04:00
Alexander Tomokhov 4afa777e7c Revert "add hardware-configuration.nix for testing purposes"
This reverts commit 659ca147fd.
2023-11-06 11:24:38 +04:00
Alexander Tomokhov 57412e328d .gitignore: /result 2023-11-06 11:11:34 +04:00
Alexander Tomokhov a822f97699 pin dependencies in flake 2023-07-17 05:05:29 +04:00
Alexander Tomokhov 82dd9ad2d4 now it's a function, requiring userdata argument 2023-07-17 04:37:04 +04:00
Alexander Tomokhov d4af9f4459 attempt to readFile userdsata.json 2023-07-17 04:19:57 +04:00
Alexander Tomokhov ee2a895c61 test 2023-07-17 04:15:03 +04:00
Alexander Tomokhov 659ca147fd add hardware-configuration.nix for testing purposes 2023-07-15 16:52:30 +04:00
Inex Code 65b5a19777 Merge pull request 'fix: Reloading nginx after ACME' (#34) from nginx-reload-fix into master
Reviewed-on: #34
2023-06-14 19:19:56 +03:00
Inex Code 60dd766846 fix: Reloading nginx after ACME 2023-06-14 19:19:49 +03:00
Inex Code 8006f83257 Merge pull request 'refactor(jitsi): Use the common TLS cert for Jitsi' (#33) from jitsi-tls-fix into master
Reviewed-on: #33
2023-06-09 16:01:09 +03:00
Inex Code 74d35b16f2 fix(jitsi): disable gettings tls certs 2023-06-09 15:59:15 +03:00
Inex Code dd020c3a7d fix(acme): Disable DNS propagation check 2023-06-09 15:57:19 +03:00
Inex Code ba1695c642 fix(jitsi): Use the common TLS cert 2023-06-09 14:06:22 +03:00
Inex Code bc5778fdea feat(dns): Add support for DigitalOcean DNS and DeSEC DNS (#31)
Co-authored-by: inexcode <inex.code@selfprivacy.org>
Co-authored-by: NaiJi  <naiji@udongein.xyz>
Reviewed-on: #31
2023-06-05 15:45:07 +03:00
Inex Code 8d99d1c78a fix: Make bitwarden read the env file 2023-05-14 17:22:09 +03:00
Inex Code 5e64b08381 feat(bitwarden): Add admin token support 2023-05-03 10:48:57 +03:00
Inex Code 7e590ae60c revert(gitea): Nix deprecations x2 2023-03-20 18:39:41 +03:00
Inex Code eb36e9b265 revert(gitea): Nix deprecations 2023-03-20 18:36:32 +03:00
Inex Code 3626506e3a fix: Conflicting Gitea log level 2023-03-20 18:31:39 +03:00
Inex Code c8c69957b5 Merge pull request 'nixos-22.11' (#25) from nixos-22.11 into master
Reviewed-on: #25
2023-03-20 17:23:02 +02:00
Inex Code 9a8af62e0b fix: State Version type 2023-03-17 15:10:47 +03:00
Inex Code a5b965f08f fix(api): Python version 2023-03-17 15:09:13 +03:00
Inex Code d7edf5a95d chore(mailserver): Bump Mailserver to 22.11 release 2023-03-17 15:05:21 +03:00
Inex Code bdaf88208f fix: Huey version 2023-03-17 14:54:14 +03:00
Inex Code 2e175f8c10 feat: Add state version 2023-03-17 14:50:54 +03:00
Inex Code 497cf28ecc fix: Change Gitea settings due to Nix deprecations 2023-03-17 14:50:40 +03:00
Inex Code 9c662d9629 chore: Change channel of overlay for testing 2023-03-17 14:38:48 +03:00
Inex Code 0500315ae0 chore(nextcloud): Upgrade Nextcloud to v25 2023-03-17 14:38:11 +03:00
Inex Code d8f0922b8a fix(gitea): incorrect root URL 2023-01-08 10:29:08 +02:00
Inex Code ab0c3e113c Merge pull request 'API 2.1.0 support' (#24) from api-redis into master
Reviewed-on: #24
2022-12-30 20:35:45 +02:00
Inex Code b4827e6e26 Merge branch 'master' into api-redis 2022-12-30 20:35:16 +02:00
Inex Code bfe0d18090 chore: Switch to API 2.1.0 2022-12-30 21:34:23 +03:00
Inex Code 426d84f636 Merge pull request 'feat: opt-in to displaying gitea email on profile' (#23) from sova/selfprivacy-nixos-config:master into master
Reviewed-on: #23
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
2022-12-29 19:41:38 +02:00
sоvд[сова] 41edc9f26f Merge pull request 'feat: set default gitea email display to false' (#1) from sova/gitea-default-email-display into master
Reviewed-on: sova/selfprivacy-nixos-config#1
2022-12-28 16:49:00 +02:00
sоvд[сова] 5d3395648a feat: set default gitea email display to false 2022-12-28 14:46:51 +00:00
Inex Code 1944739d28 chore(nextcloud): Upgrade Nextcloud to v24 2022-12-01 18:06:57 +03:00
Inex Code 08d8407a86 Merge pull request 'chore(mailserver): Update the simple-nixos-mailserver to the 22.05 version' (#21) from mailserver-22.05 into master
Reviewed-on: #21
2022-12-01 17:02:30 +02:00
Inex Code 0d3e8c890c Switch API branch to develop 2022-11-20 17:12:20 +03:00
Inex Code 3dd8ff1821 feat: add dns.useStagingACME option
Used for testing environments, so we don't stumble upon ACME rate limits.
2022-11-16 11:02:20 +03:00
Inex Code 895a816ef5 fix: one more path to backups data 2022-11-08 02:55:26 +03:00
Inex Code 5210e610df fix: path to backup backet 2022-11-08 02:49:12 +03:00
Inex Code eab3d1e761 fix: path of the provider info 2022-11-08 02:41:18 +03:00
Inex Code a59fbef22a feat: Enable Digital Ocean agent when on DO 2022-11-08 01:44:28 +03:00
Inex Code 7a6f57def8 feat(userdata): Support for newer JSON schema of provider 2022-11-08 01:44:09 +03:00
Inex Code e4ba827d5a Merge branch '3rd-party-bumps/nextcloud-24' into api-redis 2022-11-04 11:57:09 +03:00
Inex Code aeeffe42b1 feat: a redis database for SelfPrivacy API 2022-11-04 11:57:00 +03:00
Inex Code 399790e202 chore(nextcloud): Upgrade Nextcloud to v24 2022-10-28 11:52:47 +03:00
Inex Code 5f2ab0495b chore(mailserver): Update the simple-nixos-mailserver to the 22.05 version 2022-10-20 23:19:04 +03:00
Inex Code 53c9655b7b Switched to binds, volume management, new API 2022-08-26 14:21:05 +04:00
Inex Code 52b896da45 Fix Nextcloud initialization 2022-08-10 15:09:44 +04:00
Inex Code 8c81f24fa7 Add util-linux and e2fsprogs to SP API path
This is required for disk space analysis and file system extension by the API
2022-07-27 16:14:38 +03:00
Inex Code c1ed3a522c Move secrets out of Nix Store (#19)
Nix store is world-readable, and while nix repl fails to get the secret due to file permissions, we should still set up secrets without getting them in Nix store.

In the past tmpfiles.d was used, but its entire contents get to the nix store.

Now, all files with secrets are generated in activation scripts, with the help of jq and sed.

Also dead Pleroma code was deleted, but CAPTCHA is still broken.

Co-authored-by: inexcode <inex.code@selfprivacy.org>
Reviewed-on: #19
Co-authored-by: Inex Code <inex.code@selfprivacy.org>
Co-committed-by: Inex Code <inex.code@selfprivacy.org>
2022-07-19 15:18:46 +03:00
NaiJi ✨ dbb6757d77 Merge pull request 'Remove alps from server configurtaion' (#18) from remove-alps into master
Reviewed-on: #18
2022-06-24 18:55:47 +03:00
NaiJi ✨ 0c41badf3b Remove alps from server configurtaion 2022-06-24 18:51:29 +03:00
NaiJi ✨ 23e424b841 Update alp repository url 2022-06-22 13:45:30 +03:00
Inex Code 67851c7bee Fix tmpfiles.d escaping 2022-06-09 22:52:54 +03:00
Inex Code 5b4128c010 Renamed bitwarden user to vaultwaden 2022-05-02 11:04:02 +03:00
Inex Code f6b3c26900 Add tokens.json to gitignore 2022-04-29 16:40:59 +03:00
Inex Code 9d1249d10e Remove channel definiton from autoUpgrade 2022-04-29 15:56:16 +03:00
Inex Code ea7572c4e9 Prevent sending SIGKILL to rebuild service 2022-04-29 15:48:08 +03:00
Inex Code a5b57d378d Fix kill mode for rebuild services 2022-04-29 15:19:38 +03:00
Inex Code 289b715873 Merge pull request 'Add groups to users' (#17) from nixos-21.11-migration into master
Reviewed-on: #17
2022-04-26 10:54:43 +03:00
Inex Code 1a31e32424 Add groups to users 2022-04-20 13:22:16 +03:00
Inex Code cb6378a970 Merge pull request 'Added fixes for VPN networking' (#16) from vpn-fix into master
Reviewed-on: #16
2022-02-28 13:09:24 +02:00
Inex Code 4bf80d7a2d Added fixes for VPN networking
(cherry picked from commit d1620a9680)
2022-02-28 13:59:24 +03:00
Inex Code a0a6c99fe8 roll back the roll back 2022-02-16 11:06:51 +03:00
Inex Code 8cb55168eb Merge pull request 'jitsi-fixes' (#15) from jitsi-fixes into master
Reviewed-on: #15
2022-02-16 08:30:24 +02:00
Illia Chub 896600bf52 Added missing dependencies 2022-02-16 07:01:12 +02:00
Illia Chub c03fd25959 Resolved build issues with DNS-01 nad webroot enabled 2022-02-16 06:59:59 +02:00
Inex Code b583340e1d Revert "Merge pull request 'Fixed Jitsi functionality and Jitsi certificate resolution' (#14) from jitsi-fixes into master"
This reverts commit dc767677d8, reversing
changes made to d4bb381693.
2022-02-15 15:48:42 +03:00
Inex Code dc767677d8 Merge pull request 'Fixed Jitsi functionality and Jitsi certificate resolution' (#14) from jitsi-fixes into master
Reviewed-on: #14
2022-02-15 14:09:45 +02:00
Illia Chub 163afde7cf Fixed Jitsi functionality and Jitsi certificate resolution 2022-02-08 08:44:54 +02:00
59 changed files with 1481 additions and 1416 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
userdata/userdata.json
userdata/tokens.json
hardware-configuration.nix
networking.nix
networking.nix
/result

125
README.md
View File

@ -1,67 +1,70 @@
# SelfPrivacy NixOS configuration
This is a NixOS config which builds a SelfPrivacy server distribution
based on data provided in `userdata/userdata.json`.
This configuration is not self-contained, as it needs to be plugged as an input of a top-level NixOS configuration flake (i.e. https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-template/). This flake outputs the following function:
```nix
nixosConfigurations-fun =
{ hardware-configuration # hardware-configuration.nix file
, deployment # deployment.nix file
, userdata # nix attrset, obtained by fromJSON from userdata.json
, top-level-flake # `self`-reference of the top-level flake
, sp-modules # flake inputs of sp-modules flake
}:
```
which returns one or more attributes, containing NixOS configurations (created with `nixpkgs.lib.nixosSystem`). (As of 2024-01-10 there is only a single configuration named `default`.)
JSON schema is provided in `userdata/schema.json` for reference.
## updating flake inputs
**hardware-configuration.nix is not included.**
We have 2 flake inputs:
- nixpkgs
- selfprivacy-api
Example JSON config:
Both get updated the same ways.
```json
{
"backblaze": {
"accountId": "BACKBLAZE_KEY_ID",
"accountKey": "BACKBLAZE_ACCOUNT_KEY",
"bucket": "BACKBLAZE_BUCKET_NAME"
},
"api": {
"token": "API_TOKEN",
"enableSwagger": false
},
"bitwarden": {
"enable": true
},
"cloudflare": {
"apiKey": "CF_TOKEN"
},
"databasePassword": "DB_PASSWORD",
"domain": "DOMAIN",
"hashedMasterPassword": "HASHED_PASSWORD",
"hostname": "DOMAIN",
"nextcloud": {
"enable": true,
"adminPassword": "PASSWORD",
"databasePassword": "PASSWORD"
},
"gitea": {
"enable": true
},
"jitsi": {
"enable": true
},
"ocserv": {
"enable": true
},
"pleroma": {
"enable": true
},
"timezone": "Europe/Moscow",
"resticPassword": "PASSWORD",
"ssh": {
"enable": true,
"rootSshKeys": [
"ssh-ed25519 KEY user@host"
],
"passwordAuthentication": true
},
"username": "LUSER",
"users": [
{
"hashedPassword": "OTHER_USER_HASHED_PASSWORD",
"username": "OTHER_USER"
}
]
}
```
There are 2 methods:
1. specify input name only in a command, relying on URL inside `flake.nix`
2. specify input name and URL in a command, **overriding** whatever URL is inside `flake.nix` for the input to update (override)
In any case a Nix flake input is specified using some special _references_ syntax, including URLs, revisions, etc, described in manual: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#examples. Such reference can be used inside `flake.nix` or as an argument to `nix flake` commands. When a new reference is encountered Nix downloads and extracts it to /nix/store.
Before and after running `nix flake lock` (or `nix flake update`) commands you would most likely want to list current inputs using `nix flake metadata`, which are read from `flake.lock` file. Although, Nix should also print a diff between changed references once changed.
`--commit-lock-file` option tells Nix commands to do `git commit flake.lock` automatically, creating a new commit for you.
### method 1: update specific input
Example:
```console
$ nix flake lock --update-input nixpkgs
$ nix flake lock --update-input selfprivacy-api
```
Depending on how "precise" the URL was speficied in `flake.nix`, with _unmodified_ `flake.nix` the result might be:
* URL with `rev` (sha1) parameter => nothing will update (as we're already at exact commit)
* URL with `ref` (branch) parameter => input will update to the latest commit of the specified branch
* URL without `rev` nor `ref` => input will update to the latest commit of a default branch!
---
Once Nix 2.19 stabilizes, a different command _must_ be used for updating a single input (recursively), like this:
```console
$ nix flake update nixpkgs
```
### method 2: override specific input
Overriding is more powerful (for non-nested flakes) as it allows to change a flake input reference to anything just in one command (not only update in the bounds of a branch or a repository).
Example:
```console
$ nix flake lock --override-input nixpkgs github:nixos/nixpkgs?ref=nixos-23.11
$ nix flake lock --override-input selfprivacy-api git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git?ref=flakes
```
Similarly to update mechanism (described above), depending on the "precision" of an URL, its update scope varies accordingly.
Note, that subsequent calls of `nix flake lock --update-input <INPUT>` or `nix flake update` (or `nix flake update INPUT` by Nix 2.19+) will update the input regardless of the prior override. The information about override is stored only in `flake.lock` (`flake.nix` is not altered by Nix).
---
Note, that override does not update flake inputs recursively (say, you have a flake nested inside your flake input). For recursive updates only `nix flake lock --update-input` and `nix flake update` mechanisms are suitable. However, as of 2024-01-10 none of the SP NixOS configuration inputs contain other flakes, hence override mechanism is fine (don't confuse with top-level flake which has nested inputs).

View File

@ -1,124 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.selfprivacy-api;
directionArg =
if cfg.direction == ""
then ""
else "--direction=${cfg.direction}";
in
{
options.services.selfprivacy-api = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Enable SelfPrivacy API service
'';
};
token = mkOption {
type = types.str;
description = ''
SelfPrivacy API token
'';
};
enableSwagger = mkOption {
default = false;
type = types.bool;
description = ''
Enable Swagger UI
'';
};
b2AccountId = mkOption {
type = types.str;
description = ''
B2 account ID
'';
};
b2AccountKey = mkOption {
type = types.str;
description = ''
B2 account key
'';
};
b2Bucket = mkOption {
type = types.str;
description = ''
B2 bucket
'';
};
resticPassword = mkOption {
type = types.str;
description = ''
Restic password
'';
};
};
config = lib.mkIf cfg.enable {
systemd.services.selfprivacy-api = {
description = "API Server used to control system from the mobile application";
environment = config.nix.envVars // {
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
PYTHONUNBUFFERED = "1";
AUTH_TOKEN = cfg.token;
ENABLE_SWAGGER = (if cfg.enableSwagger then "1" else "0");
B2_ACCOUNT_ID = cfg.b2AccountId;
B2_ACCOUNT_KEY = cfg.b2AccountKey;
B2_BUCKET = cfg.b2Bucket;
RESTIC_PASSWORD = cfg.resticPassword;
} // config.networking.proxy.envVars;
path = [ "/var/" "/var/dkim/" pkgs.coreutils pkgs.gnutar pkgs.xz.bin pkgs.gzip pkgs.gitMinimal config.nix.package.out pkgs.nixos-rebuild pkgs.restic pkgs.mkpasswd ];
after = [ "network-online.target" ];
wantedBy = [ "network-online.target" ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.selfprivacy-api}/bin/app.py";
Restart = "always";
RestartSec = "5";
};
};
# One shot systemd service to rebuild NixOS using nixos-rebuild
systemd.services.sp-nixos-rebuild = {
description = "Upgrade NixOS using nixos-rebuild";
environment = config.nix.envVars // {
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
} // config.networking.proxy.envVars;
path = [ pkgs.coreutils pkgs.gnutar pkgs.xz.bin pkgs.gzip pkgs.gitMinimal config.nix.package.out pkgs.nixos-rebuild ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch";
};
};
# One shot systemd service to upgrade NixOS using nixos-rebuild
systemd.services.sp-nixos-upgrade = {
description = "Upgrade NixOS using nixos-rebuild";
environment = config.nix.envVars // {
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
} // config.networking.proxy.envVars;
path = [ pkgs.coreutils pkgs.gnutar pkgs.xz.bin pkgs.gzip pkgs.gitMinimal config.nix.package.out pkgs.nixos-rebuild ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --upgrade";
};
};
# One shot systemd service to rollback NixOS using nixos-rebuild
systemd.services.sp-nixos-rollback = {
description = "Rollback NixOS using nixos-rebuild";
environment = config.nix.envVars // {
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
} // config.networking.proxy.envVars;
path = [ pkgs.coreutils pkgs.gnutar pkgs.xz.bin pkgs.gzip pkgs.gitMinimal config.nix.package.out pkgs.nixos-rebuild ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --rollback";
};
};
};
}

View File

@ -1,21 +0,0 @@
{ config, pkgs, ... }:
{
services.selfprivacy-api = {
enable = true;
token = config.services.userdata.api.token;
enableSwagger = config.services.userdata.api.enableSwagger;
b2AccountId = config.services.userdata.backblaze.accountId;
b2AccountKey = config.services.userdata.backblaze.accountKey;
b2Bucket = config.services.userdata.backblaze.bucket;
resticPassword = config.services.userdata.resticPassword;
};
users.users."selfprivacy-api" = {
isNormalUser = false;
isSystemUser = true;
extraGroups = [ "opendkim" ];
};
users.groups."selfprivacy-api" = {
members = [ "selfprivacy-api" ];
};
}

View File

@ -1,35 +0,0 @@
{ config, pkgs, ... }:
let
cfg = config.services.userdata;
in
{
services.restic.backups = {
options = {
passwordFile = "/etc/restic/resticPasswd";
repository = "s3:s3.anazonaws.com/${cfg.backblaze.bucket}";
initialize = true;
paths = [
"/var/dkim"
"/var/vmail"
];
timerConfig = {
OnCalendar = [ "daily" ];
};
user = "restic";
pruneOpts = [
"--keep-daily 5"
];
};
};
users.users.restic = {
isNormalUser = false;
isSystemUser = true;
};
environment.etc."restic/resticPasswd".text = ''
${cfg.resticPassword}
'';
environment.etc."restic/s3Passwd".text = ''
AWS_ACCESS_KEY_ID=${cfg.backblaze.accountId}
AWS_SECRET_ACCESS_KEY=${cfg.backblaze.accountKey}
'';
}

View File

@ -1,77 +1,138 @@
{ config, pkgs, lib, ... }:
let
url-overlay = "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nix-repo/archive/master.tar.gz";
nix-overlay = (import (builtins.fetchTarball url-overlay));
in
{
imports = [
./hardware-configuration.nix
./variables-module.nix
./variables.nix
./files.nix
./selfprivacy-module.nix
./volumes.nix
./users.nix
./mailserver/system/mailserver.nix
./mailserver/system/alps.nix
./vpn/ocserv.nix
./api/api.nix
./api/api-module.nix
./social/pleroma.nix
./letsencrypt/acme.nix
./letsencrypt/resolve.nix
./backup/restic.nix
./passmgr/bitwarden.nix
./webserver/nginx.nix
./webserver/memcached.nix
./nextcloud/nextcloud.nix
./resources/limits.nix
./videomeet/jitsi.nix
./git/gitea.nix
# ./resources/limits.nix
];
nixpkgs.overlays = [ (nix-overlay) ];
fileSystems."/".options = [ "noatime" ];
boot.cleanTmpDir = true;
services.selfprivacy-api.enable = true;
services.redis.servers.sp-api = {
enable = true;
save = [
[
30
1
]
[
10
10
]
];
port = 0;
settings = {
notify-keyspace-events = "KEA";
};
};
services.do-agent.enable = if config.selfprivacy.server.provider == "DIGITALOCEAN" then true else false;
boot.tmp.cleanOnBoot = true;
networking = {
hostName = config.services.userdata.hostname;
hostName = config.selfprivacy.hostname;
domain = config.selfprivacy.domain;
usePredictableInterfaceNames = false;
firewall = {
allowedTCPPorts = lib.mkForce [ 22 25 80 143 443 465 587 993 8443 ];
allowedUDPPorts = lib.mkForce [ 8443 ];
allowedTCPPorts = lib.mkForce [ 22 25 80 143 443 465 587 993 4443 8443 ];
allowedUDPPorts = lib.mkForce [ 8443 10000 ];
extraCommands = ''
iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
iptables --append FORWARD --in-interface vpn00 -j ACCEPT
'';
};
nameservers = [ "1.1.1.1" "1.0.0.1" ];
};
time.timeZone = config.services.userdata.timezone;
time.timeZone = config.selfprivacy.timezone;
i18n.defaultLocale = "en_GB.UTF-8";
users.users.root.openssh.authorizedKeys.keys = config.services.userdata.ssh.rootKeys;
users.users.root.openssh.authorizedKeys.keys = config.selfprivacy.ssh.rootKeys;
services.openssh = {
enable = config.services.userdata.ssh.enable;
passwordAuthentication = config.services.userdata.ssh.passwordAuthentication;
permitRootLogin = "yes";
enable = config.selfprivacy.ssh.enable;
settings = {
PasswordAuthentication = config.selfprivacy.ssh.passwordAuthentication;
PermitRootLogin = "yes";
};
openFirewall = false;
};
programs.ssh = {
pubkeyAcceptedKeyTypes = [ "ssh-ed25519" "ssh-rsa" ];
pubkeyAcceptedKeyTypes = [ "ssh-ed25519" "ssh-rsa" "ecdsa-sha2-nistp256" ];
hostKeyAlgorithms = [ "ssh-ed25519" "ssh-rsa" ];
};
environment.systemPackages = with pkgs; [
git
jq
];
environment.variables = {
DOMAIN = config.services.userdata.domain;
# consider environment.defaultPackages = lib.mkForce [];
documentation.enable = false; # no {man,info}-pages & docs, etc to save space
# (or create a systemd service with `ConditionFirstBoot=yes`?)
systemd.tmpfiles.rules = [
"# Completely remove remnants of NIXOS_LUSTRATE."
"R! /old-root"
];
system.stateVersion =
lib.mkIf (config.selfprivacy.stateVersion != null)
config.selfprivacy.stateVersion;
system.autoUpgrade = {
enable = config.selfprivacy.autoUpgrade.enable;
allowReboot = config.selfprivacy.autoUpgrade.allowReboot;
# TODO get attribute name from selfprivacy options
flake = "/etc/nixos#default";
};
system.autoUpgrade.enable = config.services.userdata.autoUpgrade.enable;
system.autoUpgrade.allowReboot = config.services.userdata.autoUpgrade.allowReboot;
system.autoUpgrade.channel = https://nixos.org/channels/nixos-21.05-small;
systemd.services.nixos-upgrade.serviceConfig.WorkingDirectory = "/etc/nixos";
# TODO parameterize URL somehow; run nix flake update as non-root user
systemd.services.nixos-upgrade.serviceConfig.ExecCondition =
pkgs.writeShellScript "flake-update-script" ''
set -o xtrace
if ${config.nix.package.out}/bin/nix flake update \
--override-input selfprivacy-nixos-config git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-config.git?ref=flakes
then
if ${pkgs.diffutils}/bin/diff -u -r /etc/selfprivacy/nixos-config-source/ /etc/nixos/
then
set +o xtrace
echo "No configuration changes detected. Nothing to upgrade."
exit 1
fi
else
# ExecStart must not start after 255 exit code, service must fail.
exit 255
fi
'';
nix = {
optimise.automatic = true;
channel.enable = false;
# daemonCPUSchedPolicy = "idle";
# daemonIOSchedClass = "idle";
# daemonIOSchedPriority = 7;
# this is superseded by nix.settings.auto-optimise-store.
# optimise.automatic = true;
gc = {
automatic = true;
automatic = true; # TODO it's debatable, because of IO&CPU load
options = "--delete-older-than 7d";
};
};
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
nix.settings = {
sandbox = true;
experimental-features = [ "nix-command" "flakes" "repl-flake" ];
# auto-optimise-store = true;
# evaluation restrictions:
# restrict-eval = true;
# allowed-uris = [];
allow-dirty = false;
};
services.journald.extraConfig = "SystemMaxUse=500M";
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1; # TODO why is it here by default, for VPN only?
};
# TODO must be configurable and determined at nixos-infect stage
swapDevices = [
{
device = "/swapfile";
@ -79,9 +140,12 @@ in
size = 2048;
}
];
# TODO why is sudo needed?
security = {
sudo = {
enable = true;
};
};
systemd.enableEmergencyMode = false;
systemd.coredump.enable = false;
}

View File

@ -1,37 +0,0 @@
{ config, pkgs, ... }:
let
cfg = config.services.userdata;
in
{
systemd.tmpfiles.rules =
let
nextcloudDBPass = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] cfg.nextcloud.databasePassword;
nextcloudAdminPass = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] cfg.nextcloud.adminPassword;
resticPass = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] cfg.resticPassword;
domain = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] cfg.domain;
cloudflareCredentials = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] ''
CF_API_KEY=${cfg.cloudflare.apiKey}
CLOUDFLARE_DNS_API_TOKEN=${cfg.cloudflare.apiKey}
CLOUDFLARE_ZONE_API_TOKEN=${cfg.cloudflare.apiKey}
'';
rcloneConfig = builtins.replaceStrings [ "\n" "\"" "\\" ] [ "\\n" "\\\"" "\\\\" ] ''
[backblaze]
type = b2
account = ${cfg.backblaze.accountId}
key = ${cfg.backblaze.accountKey}
'';
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/backup 0777 bitwarden_rs bitwarden_rs -" else "")
(if cfg.pleroma.enable then "d /var/lib/pleroma 0700 pleroma pleroma - -" else "")
"d /var/lib/restic 0600 restic - - -"
"f+ /var/lib/restic/pass 0400 restic - - ${resticPass}"
"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 "")
"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/admin-pass 0440 nextcloud nextcloud - ${nextcloudAdminPass}" else "")
"f+ /var/lib/cloudflare/Credentials.ini 0440 nginx acmerecievers - ${cloudflareCredentials}"
];
}

47
flake.lock Normal file
View File

@ -0,0 +1,47 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1714531828,
"narHash": "sha256-ILsf3bdY/hNNI/Hu5bSt2/KbmHaAVhBbNUOdGztTHEg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "0638fe2715d998fa81d173aad264eb671ce2ebc1",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"selfprivacy-api": "selfprivacy-api"
}
},
"selfprivacy-api": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1709843377,
"narHash": "sha256-lQGd4xtKWsIlD5vVurrA/xtNYxYFGfLGyev4oOUeMmY=",
"ref": "master",
"rev": "1f1fcc223be4c6ae65eef1d50918aed0826e5ad1",
"revCount": 1259,
"type": "git",
"url": "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git"
},
"original": {
"type": "git",
"url": "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git"
}
}
},
"root": "root",
"version": 7
}

98
flake.nix Normal file
View File

@ -0,0 +1,98 @@
{
description = "SelfPrivacy NixOS configuration flake";
inputs = {
nixpkgs.url = github:nixos/nixpkgs;
selfprivacy-api.url =
git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git;
# make selfprivacy-api use the same shared nixpkgs
selfprivacy-api.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, selfprivacy-api }: {
nixosConfigurations-fun =
{ hardware-configuration
, deployment
, userdata
, top-level-flake
, sp-modules
}:
{
default = nixpkgs.lib.nixosSystem {
modules = [
hardware-configuration
deployment
./configuration.nix
selfprivacy-api.nixosModules.default
{
# pass userdata (parsed from JSON) options to selfprivacy module
selfprivacy = userdata;
# embed top-level flake source folder into the build
environment.etc."selfprivacy/nixos-config-source".source =
top-level-flake;
# for running "nix search nixpkgs", etc
nix.registry.nixpkgs.flake = nixpkgs;
# embed commit sha1 for `nixos-version --configuration-revision`
system.configurationRevision = self.rev
or "@${self.lastModifiedDate}"; # for development
# TODO assertion to forbid dirty builds caused by top-level-flake
# reset contents of /etc/nixos to match running NixOS generation
system.activationScripts.selfprivacy-nixos-config-source = ''
rm -rf /etc/nixos/{*,.[!.]*}
cp -r --no-preserve=all ${top-level-flake}/ -T /etc/nixos/
'';
}
]
++
# add SP modules, but contrain available config attributes for each
# (TODO revise evaluation performance of the code below)
nixpkgs.lib.attrsets.mapAttrsToList
(name: sp-module: args@{ config, pkgs, ... }:
let
lib = nixpkgs.lib;
configPathsNeeded = sp-module.configPathsNeeded or
(abort "allowed config paths not set for module \"${name}\"");
constrainConfigArgs = args'@{ pkgs, ... }: args' // {
config =
# TODO use lib.attrsets.mergeAttrsList from nixpkgs 23.05
(builtins.foldl' lib.attrsets.recursiveUpdate { }
(map
(p: lib.attrsets.setAttrByPath p
(lib.attrsets.getAttrFromPath p config))
configPathsNeeded
)
);
};
constrainImportsArgsRecursive = lib.attrsets.mapAttrsRecursive
(p: v:
# TODO traverse only imports and imports of imports, etc
# without traversing all attributes
if lib.lists.last p == "imports"
then
map
(m:
(args'@{ pkgs, ... }: constrainImportsArgsRecursive
(if builtins.isPath m
then import m (constrainConfigArgs args')
else
if builtins.isFunction m
then m (constrainConfigArgs args')
else m))
)
v
else v);
in
constrainImportsArgsRecursive
(sp-module.nixosModules.default (constrainConfigArgs args))
)
sp-modules;
};
};
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt;
};
}

View File

@ -1,57 +0,0 @@
{ config, pkgs, ... }:
let
cfg = config.services.userdata;
in
{
services = {
gitea = {
enable = cfg.gitea.enable;
stateDir = "/var/lib/gitea";
log = {
rootPath = "/var/lib/gitea/log";
level = "Warn";
};
user = "gitea";
database = {
type = "sqlite3";
host = "127.0.0.1";
name = "gitea";
user = "gitea";
path = "/var/lib/gitea/data/gitea.db";
createDatabase = true;
};
ssh = {
enable = true;
clonePort = 22;
};
lfs = {
enable = true;
contentDir = "/var/lib/gitea/lfs";
};
appName = "SelfPrivacy git Service";
repositoryRoot = "/var/lib/gitea/repositories";
domain = "git.${cfg.domain}";
rootUrl = "https://${cfg.domain}/";
httpAddress = "0.0.0.0";
httpPort = 3000;
cookieSecure = true;
settings = {
mailer = {
ENABLED = false;
};
ui = {
DEFAULT_THEME = "arc-green";
};
picture = {
DISABLE_GRAVATAR = true;
};
admin = {
ENABLE_KANBAN_BOARD = true;
};
repository = {
FORCE_PRIVATE = false;
};
};
};
};
}

View File

@ -1,22 +1,63 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.services.userdata;
cfg = config.selfprivacy;
dnsCredentialsTemplates = {
DIGITALOCEAN = "DO_AUTH_TOKEN=$TOKEN";
CLOUDFLARE = ''
CF_API_KEY=$TOKEN
CLOUDFLARE_DNS_API_TOKEN=$TOKEN
CLOUDFLARE_ZONE_API_TOKEN=$TOKEN
CLOUDFLARE_POLLING_INTERVAL=30
'';
DESEC = ''
DESEC_TOKEN=$TOKEN
DESEC_POLLING_INTERVAL=30
DESEC_PROPAGATION_TIMEOUT=180
DESEC_TTL=3600
'';
};
dnsCredentialsTemplate = dnsCredentialsTemplates.${cfg.dns.provider};
acme-env-filepath = "/var/lib/selfprivacy/acme-env";
secrets-filepath = "/etc/selfprivacy/secrets.json";
dnsPropagationCheckExceptions = [ "DIGITALOCEAN" "DESEC" ];
in
{
users.groups.acmerecievers = {
members = [ "nginx" "dovecot2" "postfix" "virtualMail" "ocserv" ];
};
users.groups.acmereceivers.members = [ "nginx" ];
security.acme = {
acceptTerms = true;
email = "${cfg.username}@${cfg.domain}";
defaults = {
email = "${cfg.username}@${cfg.domain}";
server = if cfg.dns.useStagingACME then "https://acme-staging-v02.api.letsencrypt.org/directory" else "https://acme-v02.api.letsencrypt.org/directory";
reloadServices = [ "nginx" ];
};
certs = {
"${cfg.domain}" = {
domain = "*.${cfg.domain}";
extraDomainNames = [ "${cfg.domain}" ];
group = "acmerecievers";
dnsProvider = "cloudflare";
credentialsFile = "/var/lib/cloudflare/Credentials.ini";
group = "acmereceivers";
dnsProvider = lib.strings.toLower cfg.dns.provider;
credentialsFile = acme-env-filepath;
dnsPropagationCheck =
! (lib.elem cfg.dns.provider dnsPropagationCheckExceptions);
};
};
};
systemd.services.acme-secrets = {
before = [ "acme-${cfg.domain}.service" ];
requiredBy = [ "acme-${cfg.domain}.service" ];
serviceConfig.Type = "oneshot";
path = with pkgs; [ coreutils jq ];
script = ''
set -o nounset
TOKEN="$(jq -re '.dns.apiKey' ${secrets-filepath})"
filecontents=$(cat <<- EOF
${dnsCredentialsTemplate}
EOF
)
install -m 0440 -o root -g acmereceivers -DT \
<(printf "%s\n" "$filecontents") ${acme-env-filepath}
'';
};
}

View File

@ -1,6 +1,6 @@
{ config, pkgs, ... }:
{ config, lib, ... }:
let
domain = config.services.userdata.domain;
domain = config.selfprivacy.domain;
in
{
systemd = {
@ -12,11 +12,6 @@ in
Restart = "on-failure";
};
};
"nginx-config-reload" = {
serviceConfig = {
After = [ "acme-${domain}.service" ];
};
};
};
};
}

View File

@ -1,30 +0,0 @@
{ lib, fetchgit, buildGoModule, ... }:
buildGoModule rec {
pname = "alps";
version = "v1.0.0"; # latest available tag at the moment
src = fetchGit {
url = "https://git.selfprivacy.org/ilchub/selfprivacy-alps";
rev = "dc2109ca2fdabfbda5d924faa4947f5694d5d758";
};
vendorSha256 = "0bqg0qjam4mvh07wfil6l5spz32mk5a7kfxxnwfyva805pzmn6dk";
deleteVendor = false;
runVend = true;
buildPhase = ''
go build ./cmd/alps
'';
installPhase = ''
mkdir -p $out/bin
cp -r * $out/bin
'';
meta = with lib; {
description = "Webmail application for the dovecot/postfix mailserver";
homepage = "https://git.selfprivacy.org/ilchub/selfprivacy-alps";
license = licenses.mit;
};
}

View File

@ -1,18 +0,0 @@
{ pkgs, config, lib, fetchgit, buildGoModule, ... }:
let domain = config.services.userdata.domain;
in
{
nixpkgs.overlays =
[ (self: super: { alps = self.callPackage ./alps-package.nix { }; }) ];
systemd.services = {
alps = {
path = [ pkgs.alps pkgs.coreutils ];
serviceConfig = {
ExecStart =
"${pkgs.alps}/bin/alps -theme sourcehut imaps://${domain}:993 smtps://${domain}:465";
WorkingDirectory = "${pkgs.alps}/bin";
};
};
};
}

View File

@ -1,34 +0,0 @@
{ pkgs, config, ... }:
let
cfg = config.services.userdata;
in
{
services.nextcloud = {
enable = cfg.nextcloud.enable;
package = pkgs.nextcloud22;
hostName = "cloud.${cfg.domain}";
# Use HTTPS for links
https = false;
# Auto-update Nextcloud Apps
autoUpdateApps.enable = true;
# Set what time makes sense for you
autoUpdateApps.startAt = "05:00:00";
config = {
# Further forces Nextcloud to use HTTPS
overwriteProtocol = "https";
# Nextcloud PostegreSQL database configuration, recommended over using SQLite
dbtype = "sqlite";
dbuser = "nextcloud";
dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself
dbname = "nextcloud";
dbpassFile = "/var/lib/nextcloud/db-pass";
adminpassFile = "/var/lib/nextcloud/admin-pass";
adminuser = "admin";
};
};
}

View File

@ -1,16 +0,0 @@
{ pkgs, config, ... }:
let
cfg = config.services.userdata;
in
{
services.bitwarden_rs = {
enable = cfg.bitwarden.enable;
dbBackend = "sqlite";
backupDir = "/var/lib/bitwarden/backup";
config = {
domain = "https://password.${cfg.domain}/";
signupsAllowed = true;
rocketPort = 8222;
};
};
}

View File

@ -1,47 +1,46 @@
{ pkgs, ... }:
{
systemd.services = {
dovecot2 = {
serviceConfig = {
cpuAccounting = true;
cpuQuota = "20%";
memoryAccounting = true;
memoryMax = "256M";
startLimitIntervalSec = 500;
startLimitBurst = 5;
blockIOWeigth = 25;
CpuAccounting = true;
CpuQuota = "20%";
MemoryAccounting = true;
MemoryMax = "256M";
StartLimitIntervalSec = 500;
StartLimitBurst = 5;
BlockIOWeight = 25;
};
};
postfix = {
serviceConfig = {
cpuAccounting = true;
cpuQuota = "20%";
memoryAccounting = true;
memoryMax = "256M";
startLimitIntervalSec = 500;
startLimitBurst = 5;
blockIOWeigth = 25;
CpuAccounting = true;
CpuQuota = "20%";
MemoryAccounting = true;
MemoryMax = "256M";
StartLimitIntervalSec = 500;
StartLimitBurst = 5;
BlockIOWeight = 25;
};
};
ocserv = {
serviceConfig = {
cpuAccounting = true;
cpuQuota = "70%";
memoryAccounting = true;
memoryMax = "512M";
startLimitIntervalSec = 500;
startLimitBurst = 5;
CpuAccounting = true;
CpuQuota = "70%";
MemoryAccounting = true;
MemoryMax = "512M";
StartLimitIntervalSec = 500;
StartLimitBurst = 5;
};
};
nginx = {
serviceConfig = {
cpuAccounting = true;
cpuQuota = "70%";
memoryAccounting = true;
memoryMax = "768M";
startLimitIntervalSec = 500;
startLimitBurst = 5;
blockIOWeigth = 10;
CpuAccounting = true;
CpuQuota = "70%";
MemoryAccounting = true;
MemoryMax = "768M";
StartLimitIntervalSec = 500;
StartLimitBurst = 5;
BlockIOWeight = 10;
};
};
};

133
selfprivacy-module.nix Normal file
View File

@ -0,0 +1,133 @@
{ lib, ... }:
with lib;
{
options.selfprivacy = {
# General server options
hostname = mkOption {
description = "The hostname of the server.";
type = types.nullOr types.str;
};
domain = mkOption {
description = ''
Domain used by the server
'';
# see: https://regexr.com/7p7ep, https://stackoverflow.com/a/26987741
type = lib.types.strMatching ''^(xn--)?[a-z0-9][a-z0-9_-]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$'';
};
timezone = mkOption {
description = ''
Timezone used by the server
'';
type = types.nullOr types.str;
default = "Etc/UTC";
};
autoUpgrade = {
enable = mkOption {
description = "Enable auto-upgrade of the server.";
default = false;
type = types.nullOr types.bool;
};
allowReboot = mkOption {
description = "Allow the server to reboot during the upgrade.";
default = false;
type = types.nullOr types.bool;
};
};
stateVersion = mkOption {
description = "State version of the server";
type = types.nullOr types.str;
default = null;
};
########################
# Server admin options #
########################
username = mkOption {
description = ''
Username that was defined at the initial setup process
'';
type = types.nullOr types.str;
};
hashedMasterPassword = mkOption {
description = ''
Hash of the password that was defined at the initial setup process
'';
type = types.nullOr types.str;
};
sshKeys = mkOption {
description = ''
SSH keys of the user that was defined at the initial setup process
'';
type = types.nullOr (types.listOf types.str);
default = [ ];
};
#############
# DNS #
#############
dns = {
provider = mkOption {
description = "DNS provider that was defined at the initial setup process.";
type = types.nullOr types.str;
};
useStagingACME = mkOption {
description = "Use staging ACME server. Default is false";
type = types.nullOr types.bool;
default = false;
};
};
server = {
provider = mkOption {
description = "Server provider that was defined at the initial setup process.";
type = types.str;
};
};
#########
# SSH #
#########
ssh = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
rootKeys = mkOption {
description = ''
Root SSH authorized keys
'';
type = types.nullOr (types.listOf types.str);
default = [ "" ];
};
passwordAuthentication = mkOption {
description = ''
Password authentication for SSH
'';
default = false;
type = types.nullOr types.bool;
};
};
###########
# Users #
###########
users = mkOption {
description = ''
Users that will be created on the server
'';
type = types.nullOr (types.listOf (types.attrsOf types.anything));
default = [ ];
};
##############
# Volumes #
##############
volumes = mkOption {
description = ''
Volumes that will be created on the server
'';
type = types.nullOr (types.listOf (types.attrsOf types.anything));
default = [ ];
};
useBinds = mkOption {
type = types.nullOr types.bool;
default = false;
description = "Whether to bind-mount vmail and sieve folders";
};
};
}

View File

@ -1,133 +0,0 @@
{ config, options, lib, pkgs, stdenv, ... }:
let
cfg = config.services.pleroma;
in
{
options = {
services.pleroma = with lib; {
enable = mkEnableOption "pleroma";
package = mkOption {
type = types.package;
default = pkgs.pleroma-otp;
description = "Pleroma package to use.";
};
user = mkOption {
type = types.str;
default = "pleroma";
description = "User account under which pleroma runs.";
};
group = mkOption {
type = types.str;
default = "pleroma";
description = "Group account under which pleroma runs.";
};
stateDir = mkOption {
type = types.str;
default = "/var/lib/pleroma";
readOnly = true;
description = "Directory where the pleroma service will save the uploads and static files.";
};
configs = mkOption {
type = with types; listOf str;
description = ''
Pleroma public configuration.
This list gets appended from left to
right into /etc/pleroma/config.exs. Elixir evaluates its
configuration imperatively, meaning you can override a
setting by appending a new str to this NixOS option list.
<emphasis>DO NOT STORE ANY PLEROMA SECRET
HERE</emphasis>, use
<link linkend="opt-services.pleroma.secretConfigFile">services.pleroma.secretConfigFile</link>
instead.
This setting is going to be stored in a file part of
the Nix store. The Nix store being world-readable, it's not
the right place to store any secret
Have a look to Pleroma section in the NixOS manual for more
informations.
'';
};
secretConfigFile = mkOption {
type = types.str;
default = "/var/lib/pleroma/secrets.exs";
description = ''
Path to the file containing your secret pleroma configuration.
<emphasis>DO NOT POINT THIS OPTION TO THE NIX
STORE</emphasis>, the store being world-readable, it'll
compromise all your secrets.
'';
};
};
};
config = lib.mkIf cfg.enable {
users = {
users."${cfg.user}" = {
description = "Pleroma user";
home = cfg.stateDir;
extraGroups = [ cfg.group ];
};
groups."${cfg.group}" = { };
};
environment.systemPackages = [ cfg.package ];
environment.etc."/pleroma/config.exs".text = ''
${lib.concatMapStrings (x: "${x}") cfg.configs}
# The lau/tzdata library is trying to download the latest
# timezone database in the OTP priv directory by default.
# This directory being in the store, it's read-only.
# Setting that up to a more appropriate location.
config :tzdata, :data_dir, "/var/lib/pleroma/elixir_tzdata_data"
import_config "${cfg.secretConfigFile}"
'';
systemd.services.pleroma = {
description = "Pleroma social network";
after = [ "network-online.target" "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
restartTriggers = [ config.environment.etc."/pleroma/config.exs".source ];
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Type = "exec";
WorkingDirectory = "~";
StateDirectory = "pleroma pleroma/static pleroma/uploads";
StateDirectoryMode = "700";
# Checking the conf file is there then running the database
# migration before each service start, just in case there are
# some pending ones.
#
# It's sub-optimal as we'll always run this, even if pleroma
# has not been updated. But the no-op process is pretty fast.
# Better be safe than sorry migration-wise.
ExecStartPre =
let preScript = pkgs.writers.writeBashBin "pleromaStartPre"
"${cfg.package}/bin/pleroma_ctl migrate";
in "${preScript}/bin/pleromaStartPre";
ExecStart = "${cfg.package}/bin/pleroma start";
ExecStop = "${cfg.package}/bin/pleroma stop";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
# Systemd sandboxing directives.
# Taken from the upstream contrib systemd service at
# pleroma/installation/pleroma.service
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "full";
PrivateDevices = false;
NoNewPrivileges = true;
CapabilityBoundingSet = "~CAP_SYS_ADMIN";
};
};
};
meta.maintainers = with lib.maintainers; [ ninjatrappeur ];
}

View File

@ -1,69 +0,0 @@
{ lib
, stdenv
, autoPatchelfHook
, fetchurl
, file
, makeWrapper
, ncurses
, nixosTests
, openssl
, unzip
, zlib
}:
stdenv.mkDerivation {
pname = "pleroma-otp";
version = "2.3.0";
# To find the latest binary release stable link, have a look at
# the CI pipeline for the latest commit of the stable branch
# https://git.pleroma.social/pleroma/pleroma/-/tree/stable
src = {
aarch64-linux = fetchurl {
url = "https://git.pleroma.social/pleroma/pleroma/-/jobs/182392/artifacts/download";
sha256 = "1drpd6xh7m2damxi5impb8jwvjl6m3qv5yxynl12i8g66vi3rbwf";
};
x86_64-linux = fetchurl {
url = "https://git.pleroma.social/pleroma/pleroma/-/jobs/182388/artifacts/download";
sha256 = "1c6l04gga9iigm249ywwcrjg6wzy8iiid652mws3j9dnl71w2sim";
};
}."${stdenv.hostPlatform.system}";
nativeBuildInputs = [ unzip ];
buildInputs = [
autoPatchelfHook
file
makeWrapper
ncurses
openssl
zlib
];
# mkDerivation fails to detect the zip nature of $src due to the
# missing .zip extension.
# Let's unpack the archive explicitely.
unpackCmd = "unzip $curSrc";
installPhase = ''
mkdir $out
cp -r * $out'';
# Pleroma is using the project's root path (here the store path)
# as its TMPDIR.
# Patching it to move the tmp dir to the actual tmpdir
postFixup = ''
wrapProgram $out/bin/pleroma --set-default RELEASE_TMP "/tmp"
wrapProgram $out/bin/pleroma_ctl --set-default RELEASE_TMP "/tmp"'';
passthru.tests = {
pleroma = nixosTests.pleroma;
};
meta = with lib; {
description = "ActivityPub microblogging server";
homepage = https://git.pleroma.social/pleroma/pleroma;
license = licenses.agpl3;
maintainers = with maintainers; [ ninjatrappeur ];
platforms = [ "x86_64-linux" "aarch64-linux" ];
};
}

View File

@ -1,43 +0,0 @@
{ pkgs, config, ... }:
let
cfg = config.services.userdata;
in
{
nixpkgs.overlays = [
(self: super: {
pleroma-otp = self.callPackage ./pleroma-package.nix { };
})
];
services = {
pleroma = {
enable = cfg.pleroma.enable;
user = "pleroma";
group = "pleroma";
configs = [
(builtins.replaceStrings
[ "$DOMAIN" "$LUSER" "$DB_PASSWORD" ]
[ cfg.domain cfg.username cfg.databasePassword ]
(builtins.readFile ./config.exs))
];
};
postgresql = {
enable = true;
package = pkgs.postgresql_12;
initialScript = "/etc/setup.psql";
};
};
environment.etc."setup.psql".text = ''
CREATE USER pleroma WITH ENCRYPTED PASSWORD '${cfg.databasePassword}';
CREATE DATABASE pleroma OWNER pleroma;
\c pleroma;
--Extensions made by ecto.migrate that need superuser access
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
'';
users.users.pleroma = {
extraGroups = [ "postgres" ];
isNormalUser = false;
isSystemUser = true;
};
}

View File

@ -0,0 +1,17 @@
{ config, lib, ... }:
let
inherit (import ./common.nix config) bitwarden-env sp;
in
# FIXME do we really want to delete passwords on module deactivation!?
{
config = lib.mkIf (!sp.modules.bitwarden.enable) {
system.activationScripts.bitwarden =
lib.trivial.warn
(
"bitwarden service is disabled, ${bitwarden-env} will be removed!"
)
''
rm -f -v ${bitwarden-env}
'';
};
}

View File

@ -0,0 +1,5 @@
config:
{
sp = config.selfprivacy;
bitwarden-env = "/var/lib/bitwarden/.env";
}

View File

@ -0,0 +1,5 @@
[
[ "selfprivacy", "domain" ],
[ "selfprivacy", "useBinds" ],
[ "selfprivacy", "modules", "bitwarden" ]
]

View File

@ -0,0 +1,10 @@
{
description = "PoC SP module for Bitwarden password management solution";
outputs = { self }: {
nixosModules.default = _:
{ imports = [ ./module.nix ./cleanup-module.nix ]; };
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

View File

@ -0,0 +1,107 @@
{ config, lib, pkgs, ... }:
let
secrets-filepath = "/etc/selfprivacy/secrets.json";
backup-dir = "/var/lib/bitwarden/backup";
cfg = sp.modules.bitwarden;
inherit (import ./common.nix config) bitwarden-env sp;
in
{
options.selfprivacy.modules.bitwarden = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
location = lib.mkOption {
type = lib.types.str;
};
subdomain = lib.mkOption {
default = "password";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config = lib.mkIf config.selfprivacy.modules.bitwarden.enable {
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/bitwarden" = {
device = "/volumes/${cfg.location}/bitwarden";
options = [
"bind"
"x-systemd.required-by=bitwarden-secrets.service"
"x-systemd.required-by=backup-vaultwarden.service"
"x-systemd.required-by=vaultwarden.service"
"x-systemd.before=bitwarden-secrets.service"
"x-systemd.before=backup-vaultwarden.service"
"x-systemd.before=vaultwarden.service"
];
};
"/var/lib/bitwarden_rs" = {
device = "/volumes/${cfg.location}/bitwarden_rs";
options = [
"bind"
"x-systemd.required-by=bitwarden-secrets.service"
"x-systemd.required-by=backup-vaultwarden.service"
"x-systemd.required-by=vaultwarden.service"
"x-systemd.before=bitwarden-secrets.service"
"x-systemd.before=backup-vaultwarden.service"
"x-systemd.before=vaultwarden.service"
];
};
};
services.vaultwarden = {
enable = true;
dbBackend = "sqlite";
backupDir = backup-dir;
environmentFile = "${bitwarden-env}";
config = {
domain = "https://${cfg.subdomain}.${sp.domain}/";
signupsAllowed = true;
rocketPort = 8222;
};
};
systemd.services.bitwarden-secrets = {
before = [ "vaultwarden.service" ];
requiredBy = [ "vaultwarden.service" ];
serviceConfig.Type = "oneshot";
path = with pkgs; [ coreutils jq ];
script = ''
set -o nounset
token="$(jq -r '.bitwarden.adminToken' ${secrets-filepath})"
if [ "$token" == "null" ]; then
# If it's null, empty the contents of the file
bitwarden_env=""
else
bitwarden_env="ADMIN_TOKEN=$token"
fi
install -C -m 0700 -o vaultwarden -g vaultwarden \
-d /var/lib/bitwarden
install -C -m 0600 -o vaultwarden -g vaultwarden -DT \
<(printf "%s" "$bitwarden_env") ${bitwarden-env}
'';
};
services.nginx.virtualHosts."${cfg.subdomain}.${sp.domain}" = {
useACMEHost = sp.domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:8222";
};
};
};
# NixOS upstream bug? Otherwise, backup-vaultwarden cannot find sqlite DB.
systemd.services.backup-vaultwarden.unitConfig.ConditionPathExists =
"/var/lib/bitwarden_rs/db.sqlite3";
};
}

View File

@ -0,0 +1,5 @@
[
[ "selfprivacy", "domain" ],
[ "selfprivacy", "useBinds" ],
[ "selfprivacy", "modules", "gitea" ]
]

View File

@ -0,0 +1,9 @@
{
description = "PoC SP module for Gitea forge service";
outputs = { self }: {
nixosModules.default = import ./module.nix;
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

113
sp-modules/gitea/module.nix Normal file
View File

@ -0,0 +1,113 @@
{ config, lib, ... }:
let
sp = config.selfprivacy;
stateDir =
if sp.useBinds
then "/volumes/${cfg.location}/gitea"
else "/var/lib/gitea";
cfg = sp.modules.gitea;
in
{
options.selfprivacy.modules.gitea = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
location = lib.mkOption {
type = lib.types.str;
};
subdomain = lib.mkOption {
default = "git";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config = lib.mkIf cfg.enable {
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/gitea" = {
device = "/volumes/${cfg.location}/gitea";
options = [ "bind" ];
};
};
services.gitea = {
enable = true;
inherit stateDir;
# log = {
# rootPath = "/var/lib/gitea/log";
# level = "Warn";
# };
user = "gitea";
database = {
type = "sqlite3";
host = "127.0.0.1";
name = "gitea";
user = "gitea";
path = "${stateDir}/data/gitea.db";
createDatabase = true;
};
# ssh = {
# enable = true;
# clonePort = 22;
# };
lfs = {
enable = true;
contentDir = "${stateDir}/lfs";
};
appName = "SelfPrivacy git Service";
repositoryRoot = "${stateDir}/repositories";
# cookieSecure = true;
settings = {
server = {
DOMAIN = "${cfg.subdomain}.${sp.domain}";
ROOT_URL = "https://${cfg.subdomain}.${sp.domain}/";
HTTP_ADDR = "0.0.0.0";
HTTP_PORT = 3000;
};
mailer = {
ENABLED = false;
};
ui = {
DEFAULT_THEME = "arc-green";
SHOW_USER_EMAIL = false;
};
picture = {
DISABLE_GRAVATAR = true;
};
admin = {
ENABLE_KANBAN_BOARD = true;
};
repository = {
FORCE_PRIVATE = false;
};
session = {
COOKIE_SECURE = true;
};
log = {
ROOT_PATH = "${stateDir}/log";
LEVEL = "Warn";
};
};
};
services.nginx.virtualHosts."${cfg.subdomain}.${sp.domain}" = {
useACMEHost = sp.domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:3000";
};
};
};
systemd.services.gitea.unitConfig.RequiresMountsFor =
lib.mkIf sp.useBinds "/volumes/${cfg.location}/gitea";
};
}

View File

@ -0,0 +1,4 @@
[
[ "selfprivacy", "domain" ],
[ "selfprivacy", "modules", "jitsi-meet" ]
]

View File

@ -0,0 +1,9 @@
{
description = "PoC SP module for Jitsi Meet video conferences server";
outputs = { self }: {
nixosModules.default = import ./module.nix;
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

View File

@ -0,0 +1,34 @@
{ config, lib, ... }:
let
domain = config.selfprivacy.domain;
cfg = config.selfprivacy.modules.jitsi-meet;
in
{
options.selfprivacy.modules.jitsi-meet = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
subdomain = lib.mkOption {
default = "meet";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config = lib.mkIf cfg.enable {
services.jitsi-meet = {
enable = true;
hostName = "${cfg.subdomain}.${domain}";
nginx.enable = true;
interfaceConfig = {
SHOW_JITSI_WATERMARK = false;
SHOW_WATERMARK_FOR_GUESTS = false;
};
};
services.nginx.virtualHosts."${cfg.subdomain}.${domain}" = {
forceSSL = true;
useACMEHost = domain;
enableACME = false;
};
};
}

View File

@ -0,0 +1,19 @@
{ config, lib, ... }:
let
inherit (import ./common.nix config) sp db-pass-filepath admin-pass-filepath;
in
# FIXME do we really want to delete passwords on module deactivation!?
{
config = lib.mkIf (!sp.modules.nextcloud.enable) {
system.activationScripts.nextcloudSecrets =
lib.trivial.warn
(
"nextcloud service is disabled, " +
"${db-pass-filepath} and ${admin-pass-filepath} will be removed!"
)
''
rm -f -v ${db-pass-filepath}
rm -f -v ${admin-pass-filepath}
'';
};
}

View File

@ -0,0 +1,6 @@
config: rec {
sp = config.selfprivacy;
secrets-filepath = "/etc/selfprivacy/secrets.json";
db-pass-filepath = "/var/lib/nextcloud/db-pass";
admin-pass-filepath = "/var/lib/nextcloud/admin-pass";
}

View File

@ -0,0 +1,5 @@
[
[ "selfprivacy", "domain" ],
[ "selfprivacy", "useBinds" ],
[ "selfprivacy", "modules", "nextcloud" ]
]

View File

@ -0,0 +1,10 @@
{
description = "PoC SP module for nextcloud";
outputs = { self }: {
nixosModules.default = _:
{ imports = [ ./module.nix ./cleanup-module.nix ]; };
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

View File

@ -0,0 +1,85 @@
{ config, lib, pkgs, ... }:
{
options.selfprivacy.modules.nextcloud = with lib; {
enable = mkOption {
type = types.bool;
default = false;
};
location = mkOption {
type = types.str;
};
subdomain = lib.mkOption {
default = "cloud";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config =
let
inherit (import ./common.nix config)
sp secrets-filepath db-pass-filepath admin-pass-filepath;
cfg = sp.modules.nextcloud;
hostName = "${cfg.subdomain}.${sp.domain}";
in
lib.mkIf sp.modules.nextcloud.enable {
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/nextcloud" = {
device = "/volumes/${cfg.location}/nextcloud";
options = [
"bind"
"x-systemd.required-by=nextcloud-setup.service"
"x-systemd.required-by=nextcloud-secrets.service"
"x-systemd.before=nextcloud-setup.service"
"x-systemd.before=nextcloud-secrets.service"
];
};
};
systemd.services.nextcloud-secrets = {
before = [ "nextcloud-setup.service" ];
requiredBy = [ "nextcloud-setup.service" ];
serviceConfig.Type = "oneshot";
path = with pkgs; [ coreutils jq ];
script = ''
databasePassword=$(jq -re '.modules.nextcloud.databasePassword' ${secrets-filepath})
adminPassword=$(jq -re '.modules.nextcloud.adminPassword' ${secrets-filepath})
install -C -m 0440 -o nextcloud -g nextcloud -DT \
<(printf "%s\n" "$databasePassword") \
${db-pass-filepath}
install -C -m 0440 -o nextcloud -g nextcloud -DT \
<(printf "%s\n" "$adminPassword") \
${admin-pass-filepath}
'';
};
services.nextcloud = {
enable = true;
package = pkgs.nextcloud26;
inherit hostName;
# Use HTTPS for links
https = true;
# auto-update Nextcloud Apps
autoUpdateApps.enable = true;
# set what time makes sense for you
autoUpdateApps.startAt = "05:00:00";
config = {
# further forces Nextcloud to use HTTPS
overwriteProtocol = "https";
dbtype = "sqlite";
dbuser = "nextcloud";
dbname = "nextcloud";
dbpassFile = db-pass-filepath;
adminpassFile = admin-pass-filepath;
adminuser = "admin";
};
};
services.nginx.virtualHosts.${hostName} = {
useACMEHost = sp.domain;
forceSSL = true;
};
};
}

View File

@ -0,0 +1,5 @@
[
[ "security", "acme", "certs" ],
[ "selfprivacy", "domain" ],
[ "selfprivacy", "modules", "ocserv" ]
]

View File

@ -0,0 +1,9 @@
{
description = "PoC SP module for OpenConnect VPN server (ocserv)";
outputs = { self }: {
nixosModules.default = import ./module.nix;
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

View File

@ -0,0 +1,81 @@
{ config, lib, ... }:
let
domain = config.selfprivacy.domain;
cert = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
key = "${config.security.acme.certs.${domain}.directory}/key.pem";
cfg = config.selfprivacy.modules.ocserv;
in
{
options.selfprivacy.modules.ocserv = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
subdomain = lib.mkOption {
default = "vpn";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config = lib.mkIf cfg.enable {
users.groups.ocserv.members = [ "ocserv" ];
users.users.ocserv = {
isNormalUser = false;
isSystemUser = true;
extraGroups = [ "acmereceivers" ];
group = "ocserv";
};
services.ocserv = {
enable = true;
config = ''
socket-file = /var/run/ocserv-socket
auth = "pam"
tcp-port = 8443
udp-port = 8443
server-cert = ${cert}
server-key = ${key}
compression = true
max-clients = 0
max-same-clients = 6
try-mtu-discovery = true
idle-timeout=1200
mobile-idle-timeout=2400
default-domain = ${cfg.subdomain}.${domain}
device = vpn0
ipv4-network = 10.10.10.0
ipv4-netmask = 255.255.255.0
tunnel-all-dns = true
dns = 1.1.1.1
dns = 1.0.0.1
route = default
'';
};
services.nginx.virtualHosts."${cfg.subdomain}.${domain}" = {
useACMEHost = domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
};
systemd.services.ocserv.unitConfig.ConditionPathExists = [ cert key ];
};
}

View File

@ -0,0 +1,17 @@
{ config, lib, ... }:
let
inherit (import ./common.nix config) secrets-exs sp;
in
# FIXME do we really want to delete passwords on module deactivation!?
{
config = lib.mkIf (!sp.modules.pleroma.enable) {
system.activationScripts.pleroma =
lib.trivial.warn
(
"pleroma service is disabled, ${secrets-exs} will be removed!"
)
''
rm -f -v ${secrets-exs}
'';
};
}

View File

@ -0,0 +1,5 @@
config:
{
sp = config.selfprivacy;
secrets-exs = "/var/lib/pleroma/secrets.exs";
}

View File

@ -0,0 +1,6 @@
[
[ "selfprivacy", "domain" ],
[ "selfprivacy", "username" ],
[ "selfprivacy", "useBinds" ],
[ "selfprivacy", "modules", "pleroma" ]
]

View File

@ -22,9 +22,8 @@ config :pleroma, :media_proxy,
config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres,
username: "pleroma",
password: "$DB_PASSWORD",
database: "pleroma",
hostname: "localhost",
socket_dir: "/run/postgresql",
pool_size: 10
#config :web_push_encryption, :vapid_details,
@ -41,4 +40,4 @@ config :pleroma, :http_security,
#config :joken, default_signer: ""
config :pleroma, configurable_from_database: false
config :pleroma, configurable_from_database: true

View File

@ -0,0 +1,9 @@
{
description = "PoC SP module for Pleroma lightweight fediverse server";
outputs = { self }: {
nixosModules.default = import ./module.nix;
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
};
}

View File

@ -0,0 +1,131 @@
{ config, lib, pkgs, ... }:
let
secrets-filepath = "/etc/selfprivacy/secrets.json";
cfg = config.selfprivacy.modules.pleroma;
inherit (import ./common.nix config) secrets-exs sp;
in
{
options.selfprivacy.modules.pleroma = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
location = lib.mkOption {
type = lib.types.str;
};
subdomain = lib.mkOption {
default = "social";
type = lib.types.strMatching "[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]";
};
};
config = lib.mkIf cfg.enable {
fileSystems = lib.mkIf sp.useBinds {
"/var/lib/pleroma" = {
device = "/volumes/${cfg.location}/pleroma";
options = [
"bind"
"x-systemd.required-by=pleroma-secrets.service"
"x-systemd.required-by=pleroma.service"
"x-systemd.before=pleroma.service"
"x-systemd.before=pleroma-secrets.service"
];
};
"/var/lib/postgresql" = {
device = "/volumes/${cfg.location}/postgresql";
options = [
"bind"
"x-systemd.required-by=pleroma-secrets.service"
"x-systemd.required-by=pleroma.service"
"x-systemd.before=pleroma-secrets.service"
"x-systemd.before=pleroma.service"
];
};
};
services = {
pleroma = {
enable = true;
user = "pleroma";
group = "pleroma";
configs = [
(builtins.replaceStrings
[ "$DOMAIN" "$LUSER" ]
[ sp.domain sp.username ]
(builtins.readFile ./config.exs.in))
];
};
postgresql = {
enable = true;
package = pkgs.postgresql_12;
initialScript = "/etc/setup.psql";
ensureDatabases = [
"pleroma"
];
ensureUsers = [
{
name = "pleroma";
ensureDBOwnership = true;
}
];
};
};
systemd.services.pleroma-secrets = {
before = [ "pleroma.service" ];
requiredBy = [ "pleroma.service" ];
serviceConfig.Type = "oneshot";
path = with pkgs; [ coreutils jq ];
script = ''
set -o nounset
password="$(jq -re '.databasePassword' ${secrets-filepath})"
filecontents=$(cat <<- EOF
import Config
config :pleroma, Pleroma.Repo,
password: "$password"
EOF
)
install -C -m 0700 -o pleroma -g pleroma -d /var/lib/pleroma
install -C -m 0600 -o pleroma -g pleroma -DT \
<(printf "%s" "$filecontents") ${secrets-exs}
'';
};
environment.etc."setup.psql".text = ''
CREATE USER pleroma;
CREATE DATABASE pleroma OWNER pleroma;
\c pleroma;
--Extensions made by ecto.migrate that need superuser access
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
'';
users.users.pleroma = {
extraGroups = [ "postgres" ];
isNormalUser = false;
isSystemUser = true;
group = "pleroma";
};
# seems to be an upstream nixpkgs/nixos bug (missing hexdump)
systemd.services.pleroma.path = [ pkgs.util-linux ];
services.nginx.virtualHosts."${cfg.subdomain}.${sp.domain}" = {
useACMEHost = sp.domain;
root = "/var/www/${cfg.subdomain}.${sp.domain}";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:4000";
};
};
};
};
}

View File

@ -0,0 +1,16 @@
[
[ "mailserver" ],
[ "security", "acme", "certs" ],
[ "selfprivacy", "domain" ],
[ "selfprivacy", "hashedMasterPassword" ],
[ "selfprivacy", "useBinds" ],
[ "selfprivacy", "username" ],
[ "selfprivacy", "users" ],
[ "services", "dovecot2" ],
[ "services", "opendkim" ],
[ "services", "postfix", "group" ],
[ "services", "postfix", "user" ],
[ "services", "redis" ],
[ "services", "rspamd" ],
[ "selfprivacy", "modules", "simple-nixos-mailserver" ]
]

View File

@ -1,17 +1,30 @@
{ config, pkgs, lib, ... }:
{ config, lib, ... }:
let
cfg = config.services.userdata;
sp = config.selfprivacy;
in
lib.mkIf sp.modules.simple-nixos-mailserver.enable
{
imports = [
(builtins.fetchTarball {
# Pick a commit from the branch you are interested in
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/5675b122/nixos-mailserver-5675b122.tar.gz";
# And set its hash
sha256 = "1fwhb7a5v9c98nzhf3dyqf3a5ianqh7k50zizj8v5nmj3blxw4pi";
})
];
fileSystems = lib.mkIf sp.useBinds
{
"/var/vmail" = {
device =
"/volumes/${sp.modules.simple-nixos-mailserver.location}/vmail";
options = [
"bind"
"x-systemd.required-by=postfix.service"
"x-systemd.before=postfix.service"
];
};
"/var/sieve" = {
device =
"/volumes/${sp.modules.simple-nixos-mailserver.location}/sieve";
options = [
"bind"
"x-systemd.required-by=dovecot2.service"
"x-systemd.before=dovecot2.service"
];
};
};
users.users = {
virtualMail = {
@ -19,20 +32,23 @@ in
};
};
users.groups.acmereceivers.members = [ "dovecot2" "postfix" "virtualMail" ];
mailserver = {
enable = true;
fqdn = cfg.domain;
domains = [ cfg.domain ];
fqdn = sp.domain;
domains = [ sp.domain ];
localDnsResolver = false;
# A list of all login accounts. To create the password hashes, use
# mkpasswd -m sha-512 "super secret password"
loginAccounts = {
"${cfg.username}@${cfg.domain}" = {
hashedPassword = cfg.hashedMasterPassword;
"${sp.username}@${sp.domain}" = {
hashedPassword = sp.hashedMasterPassword;
sieveScript = ''
require ["fileinto", "mailbox"];
if header :contains "Chat-Version" "1.0"
{
{
fileinto :create "DeltaChat";
stop;
}
@ -40,28 +56,26 @@ in
};
} // builtins.listToAttrs (builtins.map
(user: {
name = "${user.username}@${cfg.domain}";
name = "${user.username}@${sp.domain}";
value = {
hashedPassword = user.hashedPassword;
sieveScript = ''
require ["fileinto", "mailbox"];
if header :contains "Chat-Version" "1.0"
{
{
fileinto :create "DeltaChat";
stop;
}
'';
};
})
cfg.users);
sp.users);
extraVirtualAliases = {
"admin@${cfg.domain}" = "${cfg.username}@${cfg.domain}";
"admin@${sp.domain}" = "${sp.username}@${sp.domain}";
};
certificateScheme = 1;
certificateFile = "/var/lib/acme/${cfg.domain}/fullchain.pem";
keyFile = "/var/lib/acme/${cfg.domain}/key.pem";
certificateScheme = "acme";
# Enable IMAP and POP3
enableImap = true;

View File

@ -0,0 +1,126 @@
{
"nodes": {
"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"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1668681692,
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"mailserver": {
"inputs": {
"blobs": "blobs",
"flake-compat": "flake-compat",
"nixpkgs": "nixpkgs",
"nixpkgs-22_11": "nixpkgs-22_11",
"nixpkgs-23_05": "nixpkgs-23_05",
"utils": "utils"
},
"locked": {
"lastModified": 1700085753,
"narHash": "sha256-qtib7f3eRwfaUF+VziJXiBcZFqpHCAXS4HlrFsnzzl4=",
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
"rev": "008d78cc21959e33d0d31f375b88353a7d7121ae",
"type": "gitlab"
},
"original": {
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
"type": "gitlab"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1670751203,
"narHash": "sha256-XdoH1v3shKDGlrwjgrNX/EN8s3c+kQV7xY6cLCE8vcI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "64e0bf055f9d25928c31fb12924e59ff8ce71e60",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixpkgs-22_11": {
"locked": {
"lastModified": 1669558522,
"narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.11",
"type": "indirect"
}
},
"nixpkgs-23_05": {
"locked": {
"lastModified": 1684782344,
"narHash": "sha256-SHN8hPYYSX0thDrMLMWPWYulK3YFgASOrCsIL3AJ78g=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8966c43feba2c701ed624302b6a935f97bcbdf88",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-23.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"mailserver": "mailserver"
}
},
"utils": {
"locked": {
"lastModified": 1605370193,
"narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5021eac20303a61fafe17224c087f5519baed54d",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@ -0,0 +1,22 @@
{
description = "PoC SP module for the simple-nixos-mailserver";
inputs.mailserver.url =
gitlab:simple-nixos-mailserver/nixos-mailserver;
outputs = { self, mailserver }: {
nixosModules.default = _: {
imports = [
mailserver.nixosModules.default
./options.nix
./config.nix
];
};
configPathsNeeded =
builtins.fromJSON (builtins.readFile ./config-paths-needed.json);
# TODO generate json docs from module? something like:
# nix eval --impure --expr 'let flake = builtins.getFlake (builtins.toPath ./.); pkgs = flake.inputs.mailserver.inputs.nixpkgs.legacyPackages.x86_64-linux; in (pkgs.nixosOptionsDoc { inherit (pkgs.lib.evalModules { modules = [ flake.nixosModules.default ]; }) options; }).optionsJSON'
# (doesn't work because of `assertions`)
};
}

View File

@ -0,0 +1,12 @@
{ lib, ... }:
{
options.selfprivacy.modules.simple-nixos-mailserver = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
location = lib.mkOption {
type = lib.types.str;
};
};
}

View File

@ -1,190 +0,0 @@
{
"$schema": "http://json-schema.org/schema#",
"$id": "https://git.selfprivacy.org/inex/selfprivacy-nixos-config/raw/branch/master/userdata/schema.json",
"type": "object",
"properties": {
"autoUpgrade": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"allowReboot": {
"type": "boolean"
}
}
},
"hostname": {
"type": "string"
},
"domain": {
"type": "string"
},
"username": {
"type": "string"
},
"hashedMasterPassword": {
"type": "string"
},
"sshKeys": {
"type": "array",
"items": {
"type": "string"
}
},
"timezone": {
"type": "string"
},
"api": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"enableSwagger": {
"type": "boolean"
},
"skippedMigrations": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"backblaze": {
"type": "object",
"properties": {
"bucket": {
"type": "string"
},
"accountId": {
"type": "string"
},
"accountKey": {
"type": "string"
}
},
"required": ["bucket", "accountId", "accountKey"]
},
"cloudflare": {
"type": "object",
"properties": {
"apiKey": {
"type": "string"
}
},
"required": ["apiKey"]
},
"databasePassword": {
"type": "string"
},
"bitwarden": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
}
}
},
"gitea": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
}
}
},
"nextcloud": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"databasePassword": {
"type": "string"
},
"adminPassword": {
"type": "string"
}
},
"required": ["databasePassword", "adminPassword"]
},
"pleroma": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
}
}
},
"jitsi": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
}
}
},
"ocserv": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
}
}
},
"resticPassword": {
"type": "string"
},
"ssh": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"rootKeys": {
"type": "array",
"items": {
"type": "string"
}
},
"passwordAuthentication": {
"type": "boolean"
}
}
},
"users": {
"type": "array",
"items": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"hashedPassword": {
"type": "string"
},
"sshKeys": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["username", "hashedPassword"]
}
}
},
"required": [
"hostname",
"domain",
"username",
"hashedMasterPassword",
"backblaze",
"cloudflare",
"databasePassword",
"nextcloud",
"resticPassword"
]
}

View File

@ -1,10 +1,11 @@
{ pkgs, config, ... }:
{ config, ... }:
let
cfg = config.services.userdata;
cfg = config.selfprivacy;
in
{
users.mutableUsers = false;
users = {
mutableUsers = false;
allowNoPasswordLogin = true;
users = {
"${cfg.username}" = {
isNormalUser = true;
@ -17,7 +18,7 @@ in
value = {
isNormalUser = true;
hashedPassword = user.hashedPassword;
openssh.authorizedKeys.keys = (if user ? sshKeys then user.sshKeys else []);
openssh.authorizedKeys.keys = (if user ? sshKeys then user.sshKeys else [ ]);
};
})
cfg.users);

View File

@ -1,218 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.userdata;
directionArg =
if cfg.direction == ""
then ""
else "--direction=${cfg.direction}";
in
{
options.services.userdata = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
# General server options
hostname = mkOption {
description = "The hostname of the server.";
type = types.nullOr types.str;
};
domain = mkOption {
description = ''
Domain used by the server
'';
type = types.nullOr types.str;
};
timezone = mkOption {
description = ''
Timezone used by the server
'';
type = types.nullOr types.str;
default = "Europe/Uzhgorod";
};
autoUpgrade = {
enable = mkOption {
description = "Enable auto-upgrade of the server.";
default = true;
type = types.nullOr types.bool;
};
allowReboot = mkOption {
description = "Allow the server to reboot during the upgrade.";
default = false;
type = types.nullOr types.bool;
};
};
########################
# Server admin options #
########################
username = mkOption {
description = ''
Username that was defined at the initial setup process
'';
type = types.nullOr types.str;
};
hashedMasterPassword = mkOption {
description = ''
Hash of the password that was defined at the initial setup process
'';
type = types.nullOr types.str;
};
sshKeys = mkOption {
description = ''
SSH keys of the user that was defined at the initial setup process
'';
type = types.nullOr (types.listOf types.str);
default = [ ];
};
###############
# API options #
###############
api = {
token = mkOption {
description = ''
API token used to authenticate with the server
'';
type = types.nullOr types.str;
};
enableSwagger = mkOption {
default = true;
description = ''
Enable Swagger UI
'';
type = types.bool;
};
skippedMigrations = mkOption {
default = [ ];
description = ''
List of migrations that should be skipped
'';
type = types.listOf types.str;
};
};
#############
# Secrets #
#############
backblaze = {
bucket = mkOption {
description = "Bucket name used for userdata backups";
type = types.nullOr types.str;
};
accountId = mkOption {
description = "Backblaze B2 Account ID";
type = types.nullOr types.str;
};
accountKey = mkOption {
description = "Backblaze B2 Account Key.";
type = types.nullOr types.str;
};
};
cloudflare = {
apiKey = mkOption {
description = "Cloudflare API Key.";
type = types.nullOr types.str;
};
};
##############
# Services #
##############
databasePassword = mkOption {
description = ''
Password for the database
'';
type = types.nullOr types.str;
};
bitwarden = {
enable = mkOption {
default = false;
type = types.nullOr types.bool;
};
};
gitea = {
enable = mkOption {
default = false;
type = types.nullOr types.bool;
};
};
nextcloud = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
databasePassword = mkOption {
description = ''
Password for the nextcloud database
'';
type = types.nullOr types.str;
};
adminPassword = mkOption {
description = ''
Password for the nextcloud admin user
'';
type = types.nullOr types.str;
};
};
pleroma = {
enable = mkOption {
default = false;
type = types.nullOr types.bool;
};
};
jitsi = {
enable = mkOption {
default = false;
type = types.nullOr types.bool;
};
};
ocserv = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
};
#############
# Backups #
#############
resticPassword = mkOption {
description = ''
Password for the restic
'';
type = types.nullOr types.str;
};
#########
# SSH #
#########
ssh = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
rootKeys = mkOption {
description = ''
Root SSH Keys
'';
type = types.nullOr (types.listOf types.str);
default = [ "" ];
};
passwordAuthentication = mkOption {
description = ''
Password authentication for SSH
'';
default = true;
type = types.nullOr types.bool;
};
};
###########
# Users #
###########
users = mkOption {
description = ''
Users that will be created on the server
'';
type = types.nullOr (types.listOf (types.attrsOf types.anything));
default = [ ];
};
};
}

View File

@ -1,6 +0,0 @@
{ pkgs, ... }:
{
services = {
userdata = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
};
}

View File

@ -1,15 +0,0 @@
{ pkgs, config, ... }:
let
domain = config.services.userdata.domain;
in
{
services.jitsi-meet = {
enable = config.services.userdata.jitsi.enable;
hostName = "meet.${domain}";
nginx.enable = false;
interfaceConfig = {
SHOW_JITSI_WATERMARK = false;
SHOW_WATERMARK_FOR_GUESTS = false;
};
};
}

15
volumes.nix Normal file
View File

@ -0,0 +1,15 @@
{ config, ... }:
let
cfg = config.selfprivacy;
in
{
fileSystems = builtins.listToAttrs (builtins.map
(volume: {
name = "${volume.mountPoint}";
value = {
device = "${volume.device}";
fsType = "${volume.fsType}";
};
})
cfg.volumes);
}

View File

@ -1,51 +0,0 @@
{ pkgs, config, ... }:
let
domain = config.services.userdata.domain;
in
{
users.groups.ocserv = {
members = [ "ocserv" ];
};
users.users.ocserv = {
isNormalUser = false;
isSystemUser = true;
extraGroups = [ "ocserv" "acmerecievers" ];
};
services.ocserv = {
enable = config.services.userdata.ocserv.enable;
config = ''
socket-file = /var/run/ocserv-socket
auth = "pam"
tcp-port = 8443
udp-port = 8443
server-cert = /var/lib/acme/${domain}/fullchain.pem
server-key = /var/lib/acme/${domain}/key.pem
compression = true
max-clients = 0
max-same-clients = 6
try-mtu-discovery = true
idle-timeout=1200
mobile-idle-timeout=2400
default-domain = vpn.${domain}
device = vpn0
ipv4-network = 10.10.10.0
ipv4-netmask = 255.255.255.0
tunnel-all-dns = true
dns = 1.1.1.1
dns = 1.0.0.1
route = default
'';
};
}

View File

@ -1,6 +1,6 @@
{ pkgs, config, lib, ... }:
{ config, lib, ... }:
let
domain = config.services.userdata.domain;
domain = config.selfprivacy.domain;
in
{
services.nginx = {
@ -16,42 +16,12 @@ in
map $scheme $hsts_header {
https "max-age=31536000; includeSubdomains; preload";
}
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 512;
'';
virtualHosts = {
"${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
};
"vpn.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
};
"git.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
useACMEHost = domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -65,96 +35,12 @@ in
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:3000";
};
};
};
"cloud.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:80/";
};
};
};
"meet.${domain}" = {
forceSSL = true;
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
root = pkgs.jitsi-meet;
extraConfig = ''
ssi on;
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"@root_path" = {
extraConfig = ''
rewrite ^/(.*)$ / break;
'';
};
"~ ^/([^/\\?&:'\"]+)$" = {
tryFiles = "$uri @root_path";
};
"=/http-bind" = {
proxyPass = "http://localhost:5280/http-bind";
extraConfig = ''
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
'';
};
"=/external_api.js" = {
alias = "${pkgs.jitsi-meet}/libs/external_api.min.js";
};
"=/config.js" = {
alias = "${pkgs.jitsi-meet}/config.js";
};
"=/interface_config.js" = {
alias = "${pkgs.jitsi-meet}/interface_config.js";
};
};
};
"password.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:8222";
root = "/var/www/root";
};
};
};
"api.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
useACMEHost = domain;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -169,30 +55,13 @@ in
locations = {
"/" = {
proxyPass = "http://127.0.0.1:5050";
};
};
};
"social.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
root = "/var/www/social.${domain}";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
add_header 'Referrer-Policy' 'origin-when-cross-origin';
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
proxyPass = "http://127.0.0.1:4000";
proxyWebsockets = true;
};
};
};
};
};
systemd.tmpfiles.rules = [
"d /var/www/root 0750 nginx nginx - -"
];
}