Compare commits

...

30 Commits

Author SHA1 Message Date
Inex Code 59562e9f27 Test pleroma fix 2022-07-19 15:58:14 +03:00
Inex Code cabe97f1e3 Fixes:
- Bitwarden-rs → vaultwarden
- Add folder creation for rclone config
2022-07-19 14:54:04 +03:00
Inex Code e6b6c10c66 Ensure credentials folders via activation scripts 2022-07-16 13:41:10 +03:00
Inex Code 38f9fe5ea0 Fix typo 2022-07-15 20:44:24 +03:00
Inex Code 3585911798 Roll back the setup.psql 2022-07-15 18:54:14 +03:00
Inex Code 5e000f850e Disable postgre initial script 2022-07-15 18:42:47 +03:00
Inex Code b6cb60302e Remove extensions 2022-07-15 18:39:47 +03:00
Inex Code 819df84cd3 Remove comma 2022-07-15 18:29:02 +03:00
Inex Code 6e6d21af62 Ensure folders for activation script are created 2022-07-15 18:20:10 +03:00
Inex Code b22bc3d6c3 Remove semicolon 2022-07-15 15:27:32 +03:00
Inex Code ea383780b6 Remove all secrets from nix store 2022-07-14 20:42:42 +03:00
Inex Code 17b927f700 Add force to deactivation script 2022-07-13 18:28:29 +03:00
Inex Code 47d63f2fcf Fix restic password init. 2022-07-13 18:16:02 +03:00
Inex Code c5e0713481 Try gnused 2022-07-13 18:12:34 +03:00
Inex Code 9fe0f9acd6 Provision sed and jq 2022-07-13 18:10:06 +03:00
Inex Code 6218abc375 Move from tmpfiles.d to init scripts. 2022-07-13 18:06:16 +03:00
Inex Code eaa6caa146 Use lib.attrsets.attrByPath 2022-07-13 15:57:03 +03:00
Inex Code fcb78ab487 forgot "?" 2022-07-13 15:14:07 +03:00
Inex Code 6b433f3928 Fix 2022-07-13 15:13:20 +03:00
Inex Code 3ca55578ac More ifs 2022-07-13 15:12:54 +03:00
Inex Code e428db106a Replace some nulls 2022-07-13 14:54:00 +03:00
Inex Code 2e40bf243b Default root ssh key (empty) 2022-07-13 14:50:03 +03:00
Inex Code b8bdb65e6d One more if 2022-07-13 14:48:53 +03:00
Inex Code 7293337546 Forgot some ifs 2022-07-13 14:48:02 +03:00
Inex Code 31c0d4a5d5 Linting 2022-07-13 14:47:13 +03:00
Inex Code 3707937d1e Ternaries 2022-07-13 14:41:47 +03:00
Inex Code ff536aa119 Change the way we read values from userdata 2022-07-13 14:18:43 +03:00
Inex Code 41187bb18f Read value directly from json 2022-07-13 14:08:29 +03:00
Inex Code 2d26ca545e Add channel for autoupgrades 2022-07-13 14:02:35 +03:00
Inex Code 3884d97240 Remove pleroma package definition 2022-07-13 13:08:52 +03:00
14 changed files with 209 additions and 331 deletions

View File

@ -12,18 +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;
@ -31,30 +25,12 @@ in
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,12 +40,8 @@ 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 ];
after = [ "network-online.target" ];

View File

@ -2,12 +2,8 @@
{
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" = {

View File

@ -26,11 +26,4 @@ in
isSystemUser = true;
group = "restic";
};
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

@ -58,12 +58,16 @@ in
};
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 = {
enable = config.services.userdata.autoUpgrade.enable;
allowReboot = config.services.userdata.autoUpgrade.allowReboot;
channel = "https://channel.selfprivacy.org/nixos-selfpricacy";
};
nix = {
optimise.automatic = true;
gc = {
@ -86,4 +90,4 @@ in
enable = true;
};
};
}
}

View File

@ -5,33 +5,78 @@ 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 vaultwarden vaultwarden -" else "")
(if cfg.bitwarden.enable then "d /var/lib/bitwarden/backup 0777 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 "")
"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}"
];
system.activationScripts =
let
jq = "${pkgs.jq}/bin/jq";
sed = "${pkgs.gnused}/bin/sed";
in
{
nextcloudSecrets =
if cfg.nextcloud.enable then ''
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 'CF_API_KEY=REPLACEME' > /var/lib/cloudflare/Credentials.ini
echo 'CLOUDFLARE_DNS_API_TOKEN=REPLACEME' >> /var/lib/cloudflare/Credentials.ini
echo 'CLOUDFLARE_ZONE_API_TOKEN=REPLACEME' >> /var/lib/cloudflare/Credentials.ini
${sed} -i "s/REPLACEME/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.cloudflare.apiKey')/g" /var/lib/cloudflare/Credentials.ini
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 '.backblaze.accountId')/g" /root/.config/rclone/rclone.conf
${sed} -i "s/REPLACEME2/$(cat /etc/nixos/userdata/userdata.json | ${jq} -r '.backblaze.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
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
'';
};
}

View File

@ -3,7 +3,7 @@ let
cfg = config.services.userdata;
in
{
services.bitwarden_rs = {
services.vaultwarden = {
enable = cfg.bitwarden.enable;
dbBackend = "sqlite";
backupDir = "/var/lib/bitwarden/backup";

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

@ -3,11 +3,7 @@ let
cfg = config.services.userdata;
in
{
nixpkgs.overlays = [
(self: super: {
pleroma-otp = self.callPackage ./pleroma-package.nix { };
})
];
systemd.services.pleroma.path = [ pkgs.util-linux pkgs.exiftool ];
services = {
pleroma = {
enable = cfg.pleroma.enable;
@ -15,8 +11,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 +20,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

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.";
@ -71,12 +67,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 = ''
@ -100,30 +90,10 @@ in
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;
@ -141,18 +111,6 @@ in
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 {
@ -172,15 +130,6 @@ in
type = types.nullOr types.bool;
};
};
#############
# Backups #
#############
resticPassword = mkOption {
description = ''
Password for the restic
'';
type = types.nullOr types.str;
};
#########
# SSH #
#########

View File

@ -1,6 +1,49 @@
{ 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;
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 = {
enableSwagger = lib.attrsets.attrByPath [ "api" "enableSwagger" ] false jsonData;
skippedMigrations = lib.attrsets.attrByPath [ "api" "skippedMigrations" ] [ ] jsonData;
};
backblaze = {
bucket = lib.attrsets.attrByPath [ "backblaze" "bucket" ] "" jsonData;
};
bitwarden = {
enable = lib.attrsets.attrByPath [ "bitwarden" "enable" ] false jsonData;
};
gitea = {
enable = lib.attrsets.attrByPath [ "gitea" "enable" ] false jsonData;
};
nextcloud = {
enable = lib.attrsets.attrByPath [ "nextcloud" "enable" ] false jsonData;
};
pleroma = {
enable = lib.attrsets.attrByPath [ "pleroma" "enable" ] false 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;
};
users = lib.attrsets.attrByPath [ "users" ] [ ] jsonData;
};
}