Compare commits

...

83 Commits

Author SHA1 Message Date
Inex Code 40f92d15d3 feat: Migrate to flakes 2024-01-19 14:50:25 +03:00
Inex Code 2c2bb80006 Merge pull request 'add nix experimental-features for flakes' (#49) from experimental-features into master
Reviewed-on: SelfPrivacy/selfprivacy-nixos-config#49
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
2023-11-09 15:43:17 +02:00
Alexander Tomokhov 5685a9e128 add nix experimental-features for flakes 2023-11-09 17:35:24 +04:00
Inex Code f8befb0e3d Merge pull request 'Disable password auth and allow serving static files at root domain' (#48) from inex-oct-31 into master
Reviewed-on: SelfPrivacy/selfprivacy-nixos-config#48
2023-10-31 18:28:19 +02:00
Inex Code 1464d7f3bd feat(nginx): Allow serving static files at root domain 2023-10-31 17:27:46 +03:00
Inex Code d02524bb8f refactor(ssh): Disable password auth by default 2023-10-31 17:22:15 +03:00
Inex Code 23155b3c96 feat(ssh): Allow ecdsa-sha2-nistp256 keys 2023-10-03 16:34:47 +03:00
Inex Code 6c07cc024b fix: permissions for vaultwarden backups were too broad 2023-08-25 13:56:01 +03:00
Inex Code 5710f5892b fix(email): make sure /var/sieve owned my mail user 2023-07-28 03:41:06 +03:00
Inex Code 325dc40f34 fix(acme): add dns propagation check exceptions 2023-07-28 03:01:30 +03:00
Inex Code 25d7bc6ec5 fix(acme): enable DNS propagation check 2023-07-22 00:01:29 +03:00
Inex Code 29b855818d fix: acme retrieval 2023-07-21 20:59:34 +03:00
Inex Code e0ad80b4ca Revert "fix: rename the cert name"
This reverts commit e8a25ec565.
2023-07-21 20:36:40 +03:00
Inex Code e8a25ec565 fix: rename the cert name 2023-07-21 20:35:37 +03:00
Inex Code d41cf6a4db fix: do not use DNS challenge for root domain TLS
Previous solution made ACME create two TXT records
on the same subdomain, creating the conflict
2023-07-21 20:32:03 +03:00
Inex Code 2f0107ce3b refactor: remove unused restic-related code 2023-07-21 17:51:12 +03:00
Inex Code 8f72f60286 refactor: remove restic credentials from post-installation scripts
These are handled by API now.
2023-07-20 19:58:54 +03:00
Inex Code 58e4f3acd8 feat: update API deps 2023-07-20 19:52:24 +03:00
Inex Code 65b5a19777 Merge pull request 'fix: Reloading nginx after ACME' (#34) from nginx-reload-fix into master
Reviewed-on: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#16
2022-02-28 13:09:24 +02:00
Inex Code 4bf80d7a2d Added fixes for VPN networking
(cherry picked from commit d1620a9680392e4c5e545cfa878fff5b956d6479)
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: SelfPrivacy/selfprivacy-nixos-config#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: SelfPrivacy/selfprivacy-nixos-config#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
26 changed files with 523 additions and 531 deletions

4
.gitignore vendored
View File

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

View File

@ -12,49 +12,12 @@ in
{
options.services.selfprivacy-api = {
enable = mkOption {
default = false;
default = true;
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 {
@ -64,19 +27,67 @@ in
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 ];
path = [
"/var/"
"/var/dkim/"
pkgs.coreutils
pkgs.gnutar
pkgs.xz.bin
pkgs.gzip
pkgs.gitMinimal
config.nix.package.out
pkgs.nixos-rebuild
pkgs.rclone
pkgs.restic
pkgs.mkpasswd
pkgs.util-linux
pkgs.e2fsprogs
pkgs.iproute2
pkgs.fuse-overlayfs
pkgs.fuse
];
after = [ "network-online.target" ];
wantedBy = [ "network-online.target" ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.selfprivacy-api}/bin/app.py";
ExecStart = "${pkgs.selfprivacy-graphql-api}/bin/app.py";
Restart = "always";
RestartSec = "5";
};
};
systemd.services.selfprivacy-api-worker = {
description = "Task worker for SelfPrivacy API";
environment = config.nix.envVars // {
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
PYTHONUNBUFFERED = "1";
PYTHONPATH = pkgs.selfprivacy-graphql-api.pythonPath + ":${pkgs.selfprivacy-graphql-api}/lib/python3.10/site-packages/";
} // 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.rclone
pkgs.restic
pkgs.mkpasswd
pkgs.util-linux
pkgs.e2fsprogs
pkgs.iproute2
pkgs.fuse-overlayfs
pkgs.fuse
];
after = [ "network-online.target" ];
wantedBy = [ "network-online.target" ];
serviceConfig = {
User = "root";
ExecStart = "${pkgs.python310Packages.huey}/bin/huey_consumer.py selfprivacy_api.task_registry.huey";
Restart = "always";
RestartSec = "5";
};
@ -92,6 +103,8 @@ in
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch";
KillMode = "none";
SendSIGKILL = "no";
};
};
# One shot systemd service to upgrade NixOS using nixos-rebuild
@ -105,6 +118,8 @@ in
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --upgrade";
KillMode = "none";
SendSIGKILL = "no";
};
};
# One shot systemd service to rollback NixOS using nixos-rebuild
@ -118,6 +133,8 @@ in
serviceConfig = {
User = "root";
ExecStart = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --rollback";
KillMode = "none";
SendSIGKILL = "no";
};
};
};

View File

@ -2,18 +2,13 @@
{
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" ];
group = "selfprivacy-api";
};
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,25 +1,23 @@
{ config, pkgs, lib, ... }:
let
url-overlay = "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nix-repo/archive/master.tar.gz";
url-overlay = "https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nix-repo/archive/test-migration.tar.gz";
nix-overlay = (import (builtins.fetchTarball url-overlay));
in
{
imports = [
./hardware-configuration.nix
./variables-module.nix
./variables.nix
./files.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
@ -31,12 +29,37 @@ in
nixpkgs.overlays = [ (nix-overlay) ];
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.services.userdata.server.provider == "DIGITALOCEAN" then true else false;
boot.cleanTmpDir = true;
networking = {
hostName = config.services.userdata.hostname;
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" ];
};
@ -50,25 +73,33 @@ in
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;
};
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;
system.autoUpgrade = {
enable = config.services.userdata.autoUpgrade.enable;
allowReboot = config.services.userdata.autoUpgrade.allowReboot;
channel = "https://channel.selfprivacy.org/nixos-selfpricacy";
};
system.stateVersion = config.services.userdata.stateVersion;
nix = {
optimise.automatic = true;
gc = {
automatic = true;
options = "--delete-older-than 7d";
};
extraOptions = ''
experimental-features = nix-command flakes repl-flake
'';
};
services.journald.extraConfig = "SystemMaxUse=500M";
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
};

100
files.nix
View File

@ -1,37 +1,89 @@
{ config, pkgs, ... }:
let
cfg = config.services.userdata;
dnsCredentialsTemplates = {
DIGITALOCEAN = "DO_AUTH_TOKEN=REPLACEME";
CLOUDFLARE = ''
CF_API_KEY=REPLACEME
CLOUDFLARE_DNS_API_TOKEN=REPLACEME
CLOUDFLARE_ZONE_API_TOKEN=REPLACEME
'';
DESEC = "DESEC_TOKEN=REPLACEME";
};
dnsCredentialsTemplate = dnsCredentialsTemplates.${cfg.dns.provider};
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}
'';
domain = builtins.replaceStrings [ "\n" "\"" "\\" "%" ] [ "\\n" "\\\"" "\\\\" "%%" ] cfg.domain;
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.bitwarden.enable then "d /var/lib/bitwarden 0770 vaultwarden vaultwarden -" else "")
(if cfg.bitwarden.enable then "d /var/lib/bitwarden/backup 0770 vaultwarden vaultwarden -" 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 "")
(if cfg.pleroma.enable then "f /var/lib/pleroma/secrets.exs 0750 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}"
(if cfg.bitwarden.enable then "f /var/lib/bitwarden/.env 0640 vaultwarden vaultwarden - -" else "")
"d /var/sieve 0770 virtualMail virtualMail - -"
"d /var/www/root 0750 nginx nginx - -"
];
system.activationScripts =
let
jq = "${pkgs.jq}/bin/jq";
sed = "${pkgs.gnused}/bin/sed";
in
{
nextcloudSecrets =
if cfg.nextcloud.enable then ''
mkdir -p /var/lib/nextcloud
cat /etc/nixos/userdata/userdata.json | ${jq} -r '.nextcloud.databasePassword' > /var/lib/nextcloud/db-pass
chmod 0440 /var/lib/nextcloud/db-pass
chown nextcloud:nextcloud /var/lib/nextcloud/db-pass
cat /etc/nixos/userdata/userdata.json | ${jq} -r '.nextcloud.adminPassword' > /var/lib/nextcloud/admin-pass
chmod 0440 /var/lib/nextcloud/admin-pass
chown nextcloud:nextcloud /var/lib/nextcloud/admin-pass
''
else ''
rm -f /var/lib/nextcloud/db-pass
rm -f /var/lib/nextcloud/admin-pass
'';
cloudflareCredentials = ''
mkdir -p /var/lib/cloudflare
chmod 0440 /var/lib/cloudflare
chown nginx:acmerecievers /var/lib/cloudflare
echo '${dnsCredentialsTemplate}' > /var/lib/cloudflare/Credentials.ini
${sed} -i "s/REPLACEME/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.dns.apiKey')/g" /var/lib/cloudflare/Credentials.ini
chmod 0440 /var/lib/cloudflare/Credentials.ini
chown nginx:acmerecievers /var/lib/cloudflare/Credentials.ini
'';
pleromaCredentials =
if cfg.pleroma.enable then ''
echo 'import Config' > /var/lib/pleroma/secrets.exs
echo 'config :pleroma, Pleroma.Repo,' >> /var/lib/pleroma/secrets.exs
echo ' password: "REPLACEME"' >> /var/lib/pleroma/secrets.exs
${sed} -i "s/REPLACEME/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.databasePassword')/g" /var/lib/pleroma/secrets.exs
chmod 0750 /var/lib/pleroma/secrets.exs
chown pleroma:pleroma /var/lib/pleroma/secrets.exs
'' else ''
rm -f /var/lib/pleroma/secrets.exs
'';
bitwardenCredentials =
if cfg.bitwarden.enable then ''
mkdir -p /var/lib/bitwarden
token=$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.bitwarden.adminToken')
if [ "$token" == "null" ]; then
# If it's null, delete the contents of the file
> /var/lib/bitwarden/.env
else
echo "ADMIN_TOKEN=$token" > /var/lib/bitwarden/.env
fi
chmod 0640 /var/lib/bitwarden/.env
chown vaultwarden:vaultwarden /var/lib/bitwarden/.env
'' else ''
rm -f /var/lib/bitwarden/.env
'';
};
}

View File

@ -1,16 +1,22 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.services.userdata;
in
{
fileSystems = lib.mkIf cfg.useBinds {
"/var/lib/gitea" = {
device = "/volumes/${cfg.gitea.location}/gitea";
options = [ "bind" ];
};
};
services = {
gitea = {
enable = cfg.gitea.enable;
stateDir = "/var/lib/gitea";
log = {
rootPath = "/var/lib/gitea/log";
level = "Warn";
};
# log = {
# rootPath = "/var/lib/gitea/log";
# level = "Warn";
# };
user = "gitea";
database = {
type = "sqlite3";
@ -20,10 +26,10 @@ in
path = "/var/lib/gitea/data/gitea.db";
createDatabase = true;
};
ssh = {
enable = true;
clonePort = 22;
};
# ssh = {
# enable = true;
# clonePort = 22;
# };
lfs = {
enable = true;
contentDir = "/var/lib/gitea/lfs";
@ -31,16 +37,17 @@ in
appName = "SelfPrivacy git Service";
repositoryRoot = "/var/lib/gitea/repositories";
domain = "git.${cfg.domain}";
rootUrl = "https://${cfg.domain}/";
rootUrl = "https://git.${cfg.domain}/";
httpAddress = "0.0.0.0";
httpPort = 3000;
cookieSecure = true;
# cookieSecure = true;
settings = {
mailer = {
ENABLED = false;
};
ui = {
DEFAULT_THEME = "arc-green";
SHOW_USER_EMAIL = false;
};
picture = {
DISABLE_GRAVATAR = true;
@ -51,6 +58,13 @@ in
repository = {
FORCE_PRIVATE = false;
};
session = {
COOKIE_SECURE = true;
};
log = {
ROOT_PATH = "/var/lib/gitea/log";
LEVEL = "Warn";
};
};
};
};

View File

@ -1,6 +1,7 @@
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
let
cfg = config.services.userdata;
dnsPropagationCheckExceptions = [ "DIGITALOCEAN" ];
in
{
users.groups.acmerecievers = {
@ -8,15 +9,24 @@ in
};
security.acme = {
acceptTerms = true;
email = "${cfg.username}@${cfg.domain}";
certs = {
"${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";
dnsPropagationCheck = if lib.elem cfg.dns.provider dnsPropagationCheckExceptions then false else true;
reloadServices = [ "nginx" ];
};
certs = lib.mkForce {
"wildcard-${cfg.domain}" = {
domain = "*.${cfg.domain}";
extraDomainNames = [ "${cfg.domain}" ];
group = "acmerecievers";
dnsProvider = "cloudflare";
dnsProvider = lib.strings.toLower cfg.dns.provider;
credentialsFile = "/var/lib/cloudflare/Credentials.ini";
};
"${cfg.domain}" = {
domain = cfg.domain;
group = "acmerecievers";
webroot = "/var/lib/acme/acme-challenge";
};
};
};
}

View File

@ -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

@ -6,13 +6,24 @@ in
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";
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/6d0d9fb9/nixos-mailserver-6d0d9fb9.tar.gz";
# And set its hash
sha256 = "1fwhb7a5v9c98nzhf3dyqf3a5ianqh7k50zizj8v5nmj3blxw4pi";
sha256 = "sha256:0h35al73p15z9v8zb6hi5nq987sfl5wp4rm5c8947nlzlnsjl61x";
})
];
fileSystems = lib.mkIf cfg.useBinds {
"/var/vmail" = {
device = "/volumes/${cfg.email.location}/vmail";
options = [ "bind" ];
};
"/var/sieve" = {
device = "/volumes/${cfg.email.location}/sieve";
options = [ "bind" ];
};
};
users.users = {
virtualMail = {
isNormalUser = false;
@ -32,7 +43,7 @@ in
sieveScript = ''
require ["fileinto", "mailbox"];
if header :contains "Chat-Version" "1.0"
{
{
fileinto :create "DeltaChat";
stop;
}
@ -46,7 +57,7 @@ in
sieveScript = ''
require ["fileinto", "mailbox"];
if header :contains "Chat-Version" "1.0"
{
{
fileinto :create "DeltaChat";
stop;
}

View File

@ -1,11 +1,17 @@
{ pkgs, config, ... }:
{ pkgs, lib, config, ... }:
let
cfg = config.services.userdata;
in
{
fileSystems = lib.mkIf cfg.useBinds {
"/var/lib/nextcloud" = {
device = "/volumes/${cfg.nextcloud.location}/nextcloud";
options = [ "bind" ];
};
};
services.nextcloud = {
enable = cfg.nextcloud.enable;
package = pkgs.nextcloud22;
package = pkgs.nextcloud25;
hostName = "cloud.${cfg.domain}";
# Use HTTPS for links

View File

@ -1,12 +1,23 @@
{ pkgs, config, ... }:
{ pkgs, lib, config, ... }:
let
cfg = config.services.userdata;
in
{
services.bitwarden_rs = {
fileSystems = lib.mkIf cfg.useBinds {
"/var/lib/bitwarden" = {
device = "/volumes/${cfg.bitwarden.location}/bitwarden";
options = [ "bind" ];
};
"/var/lib/bitwarden_rs" = {
device = "/volumes/${cfg.bitwarden.location}/bitwarden_rs";
options = [ "bind" ];
};
};
services.vaultwarden = {
enable = cfg.bitwarden.enable;
dbBackend = "sqlite";
backupDir = "/var/lib/bitwarden/backup";
environmentFile = "/var/lib/bitwarden/.env";
config = {
domain = "https://password.${cfg.domain}/";
signupsAllowed = true;

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

@ -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,13 +1,18 @@
{ pkgs, config, ... }:
{ pkgs, lib, config, ... }:
let
cfg = config.services.userdata;
in
{
nixpkgs.overlays = [
(self: super: {
pleroma-otp = self.callPackage ./pleroma-package.nix { };
})
];
fileSystems = lib.mkIf cfg.useBinds {
"/var/lib/pleroma" = {
device = "/volumes/${cfg.pleroma.location}/pleroma";
options = [ "bind" ];
};
"/var/lib/postgresql" = {
device = "/volumes/${cfg.pleroma.location}/postgresql";
options = [ "bind" ];
};
};
services = {
pleroma = {
enable = cfg.pleroma.enable;
@ -15,8 +20,8 @@ in
group = "pleroma";
configs = [
(builtins.replaceStrings
[ "$DOMAIN" "$LUSER" "$DB_PASSWORD" ]
[ cfg.domain cfg.username cfg.databasePassword ]
[ "$DOMAIN" "$LUSER" ]
[ cfg.domain cfg.username ]
(builtins.readFile ./config.exs))
];
};
@ -24,10 +29,21 @@ in
enable = true;
package = pkgs.postgresql_12;
initialScript = "/etc/setup.psql";
ensureDatabases = [
"pleroma"
];
ensureUsers = [
{
name = "pleroma";
ensurePermissions = {
"DATABASE pleroma" = "ALL PRIVILEGES";
};
}
];
};
};
environment.etc."setup.psql".text = ''
CREATE USER pleroma WITH ENCRYPTED PASSWORD '${cfg.databasePassword}';
CREATE USER pleroma;
CREATE DATABASE pleroma OWNER pleroma;
\c pleroma;
--Extensions made by ecto.migrate that need superuser access
@ -39,5 +55,6 @@ in
extraGroups = [ "postgres" ];
isNormalUser = false;
isSystemUser = true;
group = "pleroma";
};
}

View File

@ -0,0 +1,72 @@
{
"$schema": "http://json-schema.org/schema#",
"$id": "https://git.selfprivacy.org/inex/selfprivacy-nixos-config/raw/branch/master/userdata/tokens_schema.json",
"type": "object",
"properties": {
"tokens": {
"type": "array",
"items": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"name": {
"type": "string"
},
"date": {
"type": "string"
}
},
"required": [
"token",
"name",
"date"
]
}
},
"recovery_token": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"date": {
"type": "string"
},
"expiration": {
"type": "string"
},
"uses_left": {
"type": "integer"
}
},
"required": [
"token",
"date"
]
},
"new_device": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"date": {
"type": "string"
},
"expiration": {
"type": "string"
}
},
"required": [
"token",
"date",
"expiration"
]
}
},
"required": [
"tokens"
]
}

View File

@ -17,7 +17,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

@ -11,10 +11,6 @@ let
in
{
options.services.userdata = {
enable = mkOption {
default = true;
type = types.nullOr types.bool;
};
# General server options
hostname = mkOption {
description = "The hostname of the server.";
@ -45,6 +41,13 @@ in
type = types.nullOr types.bool;
};
};
stateVersion = mkOption {
description = ''
State version of the server
'';
type = types.str;
default = "22.11";
};
########################
# Server admin options #
########################
@ -71,19 +74,6 @@ in
# 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 = ''
@ -95,62 +85,64 @@ in
#############
# Secrets #
#############
backblaze = {
dns = {
provider = mkOption {
description = "DNS provider that was defined at the initial setup process. Default is ClOUDFLARE";
type = types.nullOr types.str;
};
useStagingACME = mkOption {
description = "Use staging ACME server. Default is false";
type = types.nullOr types.bool;
};
};
backup = {
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.";
server = {
provider = mkOption {
description = "Server provider that was defined at the initial setup process. Default is HETZNER";
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;
};
location = mkOption {
default = "sda1";
type = types.nullOr types.str;
};
};
email = {
location = mkOption {
default = "sda1";
type = types.nullOr types.str;
};
};
gitea = {
enable = mkOption {
default = false;
type = types.nullOr types.bool;
};
location = mkOption {
default = "sda1";
type = types.nullOr types.str;
};
};
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
'';
location = mkOption {
default = "sda1";
type = types.nullOr types.str;
};
};
@ -159,6 +151,10 @@ in
default = false;
type = types.nullOr types.bool;
};
location = mkOption {
default = "sda1";
type = types.nullOr types.str;
};
};
jitsi = {
enable = mkOption {
@ -172,15 +168,6 @@ in
type = types.nullOr types.bool;
};
};
#############
# Backups #
#############
resticPassword = mkOption {
description = ''
Password for the restic
'';
type = types.nullOr types.str;
};
#########
# SSH #
#########
@ -200,7 +187,7 @@ in
description = ''
Password authentication for SSH
'';
default = true;
default = false;
type = types.nullOr types.bool;
};
};
@ -214,5 +201,19 @@ in
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;
};
};
}

View File

@ -1,6 +1,65 @@
{ pkgs, ... }:
{ pkgs, lib, ... }:
let
jsonData = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
in
{
services = {
userdata = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
services.userdata = {
hostname = lib.attrsets.attrByPath [ "hostname" ] null jsonData;
domain = lib.attrsets.attrByPath [ "domain" ] null jsonData;
timezone = lib.attrsets.attrByPath [ "timezone" ] "Europe/Uzhgorod" jsonData;
stateVersion = lib.attrsets.attrByPath [ "stateVersion" ] "22.05" jsonData;
autoUpgrade = {
enable = lib.attrsets.attrByPath [ "autoUpgrade" "enable" ] true jsonData;
allowReboot = lib.attrsets.attrByPath [ "autoUpgrade" "allowReboot" ] true jsonData;
};
username = lib.attrsets.attrByPath [ "username" ] null jsonData;
hashedMasterPassword = lib.attrsets.attrByPath [ "hashedMasterPassword" ] null jsonData;
sshKeys = lib.attrsets.attrByPath [ "sshKeys" ] [ ] jsonData;
api = {
skippedMigrations = lib.attrsets.attrByPath [ "api" "skippedMigrations" ] [ ] jsonData;
};
dns = {
provider = lib.attrsets.attrByPath [ "dns" "provider" ] "CLOUDFLARE" jsonData;
useStagingACME = lib.attrsets.attrByPath [ "dns" "useStagingACME" ] false jsonData;
};
backup = {
bucket = lib.attrsets.attrByPath [ "backup" "bucket" ] (lib.attrsets.attrByPath [ "backblaze" "bucket" ] "" jsonData) jsonData;
};
server = {
provider = lib.attrsets.attrByPath [ "server" "provider" ] "HETZNER" jsonData;
};
bitwarden = {
enable = lib.attrsets.attrByPath [ "bitwarden" "enable" ] false jsonData;
location = lib.attrsets.attrByPath [ "bitwarden" "location" ] "sda1" jsonData;
};
gitea = {
enable = lib.attrsets.attrByPath [ "gitea" "enable" ] false jsonData;
location = lib.attrsets.attrByPath [ "gitea" "location" ] "sda1" jsonData;
};
nextcloud = {
enable = lib.attrsets.attrByPath [ "nextcloud" "enable" ] false jsonData;
location = lib.attrsets.attrByPath [ "nextcloud" "location" ] "sda1" jsonData;
};
pleroma = {
enable = lib.attrsets.attrByPath [ "pleroma" "enable" ] false jsonData;
location = lib.attrsets.attrByPath [ "pleroma" "location" ] "sda1" jsonData;
};
jitsi = {
enable = lib.attrsets.attrByPath [ "jitsi" "enable" ] false jsonData;
};
ocserv = {
enable = lib.attrsets.attrByPath [ "ocserv" "enable" ] false jsonData;
};
ssh = {
enable = lib.attrsets.attrByPath [ "ssh" "enable" ] true jsonData;
rootKeys = lib.attrsets.attrByPath [ "ssh" "rootKeys" ] [ "" ] jsonData;
passwordAuthentication = lib.attrsets.attrByPath [ "ssh" "passwordAuthentication" ] true jsonData;
};
email = {
location = lib.attrsets.attrByPath [ "email" "location" ] "sda1" jsonData;
};
users = lib.attrsets.attrByPath [ "users" ] [ ] jsonData;
volumes = lib.attrsets.attrByPath [ "volumes" ] [ ] jsonData;
useBinds = lib.attrsets.attrByPath [ "useBinds" ] false jsonData;
};
}

View File

@ -6,7 +6,7 @@ in
services.jitsi-meet = {
enable = config.services.userdata.jitsi.enable;
hostName = "meet.${domain}";
nginx.enable = false;
nginx.enable = true;
interfaceConfig = {
SHOW_JITSI_WATERMARK = false;
SHOW_WATERMARK_FOR_GUESTS = false;

15
volumes.nix Normal file
View File

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

View File

@ -10,6 +10,7 @@ in
isNormalUser = false;
isSystemUser = true;
extraGroups = [ "ocserv" "acmerecievers" ];
group = "ocserv";
};
services.ocserv = {
enable = config.services.userdata.ocserv.enable;

View File

@ -20,8 +20,7 @@ in
virtualHosts = {
"${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
enableACME = true;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -33,10 +32,15 @@ in
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
expires 10m;
'';
locations = {
"/" = {
root = "/var/www/root";
};
};
};
"vpn.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -50,8 +54,8 @@ in
'';
};
"git.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -70,8 +74,8 @@ in
};
};
"cloud.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -89,52 +93,9 @@ in
};
};
};
"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";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -153,8 +114,8 @@ in
};
};
"api.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security $hsts_header;
@ -169,12 +130,13 @@ in
locations = {
"/" = {
proxyPass = "http://127.0.0.1:5050";
proxyWebsockets = true;
};
};
};
"social.${domain}" = {
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
root = "/var/www/social.${domain}";
forceSSL = true;
extraConfig = ''
@ -193,6 +155,13 @@ in
};
};
};
"meet.${domain}" = {
sslCertificate = "/var/lib/acme/wildcard-${domain}/fullchain.pem";
sslCertificateKey = "/var/lib/acme/wildcard-${domain}/key.pem";
forceSSL = true;
useACMEHost = "wildcard-${domain}";
enableACME = false;
};
};
};
}