Compare commits

...

26 Commits

Author SHA1 Message Date
Alexander Tomokhov fcbde507fc sp-extensions.json is read from /etc/nixos flake input 2023-11-08 21:01:11 +04:00
Alexander Tomokhov c20bef314e add sp-extensions-json flake input 2023-11-08 20:55:31 +04:00
Alexander Tomokhov e1204fb065 all flake inputs into nix.registry 2023-11-08 18:32:30 +04:00
Alexander Tomokhov 049ecd3e32 embed etc-nixos 2023-11-08 16:27:52 +04:00
Alexander Tomokhov b9dad899de pass /etc/nixos folder as an input to override
This way it is expected to have access to this path from build results,
making it possible to reproduce the build.
2023-11-08 16:27:52 +04:00
Alexander Tomokhov 2d7680d456 do not try to embed flake's git revision 2023-10-18 16:25:18 +04:00
Inex Code f11d8cc902 feat(ssh): Allow ecdsa-sha2-nistp256 keys 2023-10-18 13:59:42 +03:00
Inex Code e417c57a60 fix: permissions for vaultwarden backups were too broad 2023-10-18 13:59:42 +03:00
Inex Code 5cbb31bac6 fix(email): make sure /var/sieve owned my mail user 2023-10-18 13:59:42 +03:00
Inex Code 17cadf4ffc fix(acme): add dns propagation check exceptions 2023-10-18 13:59:42 +03:00
Inex Code 8b68457c71 fix(acme): enable DNS propagation check 2023-10-18 13:59:42 +03:00
Inex Code c26abadbec fix: acme retrieval 2023-10-18 13:59:42 +03:00
Inex Code 3872646e97 Revert "fix: rename the cert name"
This reverts commit e8a25ec565.
2023-10-18 13:59:42 +03:00
Inex Code 3487513e34 fix: rename the cert name 2023-10-18 13:59:42 +03:00
Inex Code ab27cbd27a 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-10-18 13:59:42 +03:00
Inex Code 306a572e12 refactor: remove unused restic-related code 2023-10-18 13:59:42 +03:00
Inex Code 5d49b8b416 refactor: remove restic credentials from post-installation scripts
These are handled by API now.
2023-10-18 13:59:42 +03:00
Inex Code 2f07bb37ce feat: update API deps 2023-10-18 13:59:42 +03:00
Alexander Tomokhov 11567d4db9 flake: revert from self.dirtyRev to self.rev 2023-10-09 02:23:45 +04:00
Alexander Tomokhov 9370d17b82 flake: embed dirty revision of NixOS configuration instead
The inevitable `--override-input` nix build (and nixos-rebuild) option
induces dirty state of the NixOS flake, thus `self.rev` couldn't be used
together.
2023-10-09 02:07:49 +04:00
Alexander Tomokhov 5643877cc1 flake: embed NixOS configuration git commit sha1 into nixos.label 2023-09-28 00:56:47 +04:00
Alexander Tomokhov 3bf91c25c3 readme: add build command for flakes 2023-09-18 17:23:22 +04:00
Alexander Tomokhov e4473ec733 do not import selfprivacy overlay path, but use flake overlay output 2023-09-18 17:22:13 +04:00
Alexander Tomokhov 50c554e6e7 don't pass selfprivacy-overlay to configuration.nix; nix flake lock 2023-08-23 02:06:33 +04:00
Alexander Tomokhov d1d025dda6 use hardware-configuration.nix as a flake input 2023-08-23 00:37:16 +04:00
Alexander Tomokhov afcec981bc experiment with userdata flake input to override by caller 2023-08-22 22:22:13 +04:00
12 changed files with 78 additions and 115 deletions

4
.gitignore vendored
View File

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

View File

@ -64,4 +64,12 @@ Example JSON config:
}
]
}
```
```
# flakes edition
Build with:
```console
$ nixos-rebuild build --flake .#just-nixos
```

View File

@ -18,19 +18,6 @@ in
Enable SelfPrivacy API service
'';
};
enableSwagger = mkOption {
default = false;
type = types.bool;
description = ''
Enable Swagger UI
'';
};
b2Bucket = mkOption {
type = types.str;
description = ''
B2 bucket
'';
};
};
config = lib.mkIf cfg.enable {
@ -40,8 +27,6 @@ in
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
PYTHONUNBUFFERED = "1";
ENABLE_SWAGGER = (if cfg.enableSwagger then "1" else "0");
B2_BUCKET = cfg.b2Bucket;
} // config.networking.proxy.envVars;
path = [
"/var/"
@ -53,11 +38,14 @@ in
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" ];
@ -74,8 +62,6 @@ in
inherit (config.environment.sessionVariables) NIX_PATH;
HOME = "/root";
PYTHONUNBUFFERED = "1";
ENABLE_SWAGGER = (if cfg.enableSwagger then "1" else "0");
B2_BUCKET = cfg.b2Bucket;
PYTHONPATH = pkgs.selfprivacy-graphql-api.pythonPath + ":${pkgs.selfprivacy-graphql-api}/lib/python3.10/site-packages/";
} // config.networking.proxy.envVars;
path = [
@ -88,11 +74,14 @@ in
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" ];

View File

@ -2,8 +2,6 @@
{
services.selfprivacy-api = {
enable = true;
enableSwagger = config.services.userdata.api.enableSwagger;
b2Bucket = config.services.userdata.backup.bucket;
};
users.users."selfprivacy-api" = {

View File

@ -1,29 +0,0 @@
{ config, pkgs, ... }:
let
cfg = config.services.userdata;
in
{
services.restic.backups = {
options = {
passwordFile = "/etc/restic/resticPasswd";
repository = "s3:s3.anazonaws.com/${cfg.backup.bucket}";
initialize = true;
paths = [
"/var/dkim"
"/var/vmail"
];
timerConfig = {
OnCalendar = [ "daily" ];
};
user = "restic";
pruneOpts = [
"--keep-daily 5"
];
};
};
users.users.restic = {
isNormalUser = false;
isSystemUser = true;
group = "restic";
};
}

View File

@ -1,7 +1,6 @@
{ userdata, selfprivacy-overlay, config, pkgs, lib, ... }:
{ userdata, config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
./variables-module.nix
./variables.nix
./files.nix
@ -14,7 +13,6 @@
./social/pleroma.nix
./letsencrypt/acme.nix
./letsencrypt/resolve.nix
./backup/restic.nix
./passmgr/bitwarden.nix
./webserver/nginx.nix
./webserver/memcached.nix
@ -24,7 +22,6 @@
./git/gitea.nix
];
nixpkgs.overlays = [ (import selfprivacy-overlay) ];
# this should be specified in hardware-configuration.nix?
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
@ -72,7 +69,7 @@
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; [

View File

@ -18,13 +18,13 @@ in
domain = builtins.replaceStrings [ "\n" "\"" "\\" "%" ] [ "\\n" "\\\"" "\\\\" "%%" ] cfg.domain;
in
[
(if cfg.bitwarden.enable then "d /var/lib/bitwarden 0777 vaultwarden vaultwarden -" else "")
(if cfg.bitwarden.enable then "d /var/lib/bitwarden/backup 0777 vaultwarden vaultwarden -" 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 - - -"
(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.bitwarden.enable then "f /var/lib/bitwarden/.env 0640 vaultwarden vaultwarden - -" else "")
"d /var/sieve 0770 virtualMail virtualMail - -"
];
system.activationScripts =
let
@ -56,25 +56,6 @@ in
chmod 0440 /var/lib/cloudflare/Credentials.ini
chown nginx:acmerecievers /var/lib/cloudflare/Credentials.ini
'';
resticCredentials = ''
mkdir -p /root/.config/rclone
chmod 0400 /root/.config/rclone
chown root:root /root/.config/rclone
echo '[backblaze]' > /root/.config/rclone/rclone.conf
echo 'type = b2' >> /root/.config/rclone/rclone.conf
echo 'account = REPLACEME1' >> /root/.config/rclone/rclone.conf
echo 'key = REPLACEME2' >> /root/.config/rclone/rclone.conf
${sed} -i "s/REPLACEME1/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.backup.accountId')/g" /root/.config/rclone/rclone.conf
${sed} -i "s/REPLACEME2/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.backup.accountKey')/g" /root/.config/rclone/rclone.conf
chmod 0400 /root/.config/rclone/rclone.conf
chown root:root /root/.config/rclone/rclone.conf
cat /etc/nixos/userdata/userdata.json | ${jq} -r '.resticPassword' > /var/lib/restic/pass
chmod 0400 /var/lib/restic/pass
chown restic /var/lib/restic/pass
'';
pleromaCredentials =
if cfg.pleroma.enable then ''
echo 'import Config' > /var/lib/pleroma/secrets.exs

View File

@ -2,23 +2,46 @@
description = "Selfprivacy NixOS configuration flake";
inputs = {
#nixpkgs.url = "https://github.com/NixOS/nixpkgs/archive/eef86b8a942913a828b9ef13722835f359deef29.tar.gz";
nixpkgs.url = "github:nixos/nixpkgs";
selfprivacy-overlay.url =
"git+https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nix-repo.git";
# the /etc/nixos folder input is expected to be set by the caller
# for example, upon nix build using --override-input
etc-nixos.flake = false;
};
outputs = { self, nixpkgs, selfprivacy-overlay }:
outputs =
{ self
, etc-nixos
, nixpkgs
, selfprivacy-overlay
} @ inputs:
let
system = "x86_64-linux";
userdata =
builtins.fromJSON (builtins.readFile "${etc-nixos}/userdata.json");
sp-extensions =
builtins.fromJSON (builtins.readFile "${etc-nixos}/sp-extensions.json");
lib = nixpkgs.legacyPackages.${system}.lib;
in
{
nixosConfigurations-fun = userdata: {
just-nixos = nixpkgs.lib.nixosSystem {
specialArgs = { inherit system selfprivacy-overlay userdata; };
modules = [ ./configuration.nix ];
};
nixosConfigurations.just-nixos = nixpkgs.lib.nixosSystem {
specialArgs = { inherit system userdata; };
modules = [
# SelfPrivacy overlay
{
nixpkgs.overlays = builtins.trace (sp-extensions.mailserver) [ selfprivacy-overlay.overlay ];
environment.etc.selfprivacy-nixos-config-source.source =
etc-nixos.outPath;
nix.registry = lib.mapAttrs (_n: flake: { inherit flake; }) inputs;
}
# machine specifics
"${etc-nixos}/hardware-configuration.nix"
# main configuration part
./configuration.nix
];
};
};
}

View File

@ -1,6 +1,7 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.userdata;
dnsPropagationCheckExceptions = [ "DIGITALOCEAN" ];
in
{
users.groups.acmerecievers = {
@ -11,17 +12,21 @@ in
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 = false;
dnsPropagationCheck = if lib.elem cfg.dns.provider dnsPropagationCheckExceptions then false else true;
reloadServices = [ "nginx" ];
};
certs = lib.mkForce {
"${cfg.domain}" = {
"wildcard-${cfg.domain}" = {
domain = "*.${cfg.domain}";
extraDomainNames = [ "${cfg.domain}" ];
group = "acmerecievers";
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

@ -74,13 +74,6 @@ in
# API options #
###############
api = {
enableSwagger = mkOption {
default = true;
description = ''
Enable Swagger UI
'';
type = types.bool;
};
skippedMigrations = mkOption {
default = [ ];
description = ''

View File

@ -16,7 +16,6 @@ in
hashedMasterPassword = lib.attrsets.attrByPath [ "hashedMasterPassword" ] null jsonData;
sshKeys = lib.attrsets.attrByPath [ "sshKeys" ] [ ] jsonData;
api = {
enableSwagger = lib.attrsets.attrByPath [ "api" "enableSwagger" ] false jsonData;
skippedMigrations = lib.attrsets.attrByPath [ "api" "skippedMigrations" ] [ ] jsonData;
};
dns = {

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;
@ -35,8 +34,8 @@ in
'';
};
"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 +49,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 +69,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;
@ -90,8 +89,8 @@ in
};
};
"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;
@ -110,8 +109,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;
@ -131,8 +130,8 @@ in
};
};
"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 = ''
@ -152,10 +151,10 @@ in
};
};
"meet.${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;
useACMEHost = domain;
useACMEHost = "wildcard-${domain}";
enableACME = false;
};
};