mirror of
https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-config.git
synced 2024-11-25 12:31:27 +00:00
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: https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-config/pulls/19 Co-authored-by: Inex Code <inex.code@selfprivacy.org> Co-committed-by: Inex Code <inex.code@selfprivacy.org>
This commit is contained in:
parent
dbb6757d77
commit
c1ed3a522c
|
@ -12,18 +12,12 @@ in
|
||||||
{
|
{
|
||||||
options.services.selfprivacy-api = {
|
options.services.selfprivacy-api = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
default = false;
|
default = true;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
description = ''
|
description = ''
|
||||||
Enable SelfPrivacy API service
|
Enable SelfPrivacy API service
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
token = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
SelfPrivacy API token
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
enableSwagger = mkOption {
|
enableSwagger = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -31,30 +25,12 @@ in
|
||||||
Enable Swagger UI
|
Enable Swagger UI
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
b2AccountId = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
B2 account ID
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
b2AccountKey = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
B2 account key
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
b2Bucket = mkOption {
|
b2Bucket = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = ''
|
description = ''
|
||||||
B2 bucket
|
B2 bucket
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
resticPassword = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
Restic password
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
@ -64,12 +40,8 @@ in
|
||||||
inherit (config.environment.sessionVariables) NIX_PATH;
|
inherit (config.environment.sessionVariables) NIX_PATH;
|
||||||
HOME = "/root";
|
HOME = "/root";
|
||||||
PYTHONUNBUFFERED = "1";
|
PYTHONUNBUFFERED = "1";
|
||||||
AUTH_TOKEN = cfg.token;
|
|
||||||
ENABLE_SWAGGER = (if cfg.enableSwagger then "1" else "0");
|
ENABLE_SWAGGER = (if cfg.enableSwagger then "1" else "0");
|
||||||
B2_ACCOUNT_ID = cfg.b2AccountId;
|
|
||||||
B2_ACCOUNT_KEY = cfg.b2AccountKey;
|
|
||||||
B2_BUCKET = cfg.b2Bucket;
|
B2_BUCKET = cfg.b2Bucket;
|
||||||
RESTIC_PASSWORD = cfg.resticPassword;
|
|
||||||
} // config.networking.proxy.envVars;
|
} // 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.restic pkgs.mkpasswd ];
|
||||||
after = [ "network-online.target" ];
|
after = [ "network-online.target" ];
|
||||||
|
|
|
@ -2,12 +2,8 @@
|
||||||
{
|
{
|
||||||
services.selfprivacy-api = {
|
services.selfprivacy-api = {
|
||||||
enable = true;
|
enable = true;
|
||||||
token = config.services.userdata.api.token;
|
|
||||||
enableSwagger = config.services.userdata.api.enableSwagger;
|
enableSwagger = config.services.userdata.api.enableSwagger;
|
||||||
b2AccountId = config.services.userdata.backblaze.accountId;
|
|
||||||
b2AccountKey = config.services.userdata.backblaze.accountKey;
|
|
||||||
b2Bucket = config.services.userdata.backblaze.bucket;
|
b2Bucket = config.services.userdata.backblaze.bucket;
|
||||||
resticPassword = config.services.userdata.resticPassword;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users."selfprivacy-api" = {
|
users.users."selfprivacy-api" = {
|
||||||
|
|
|
@ -26,11 +26,4 @@ in
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
group = "restic";
|
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}
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,12 +58,16 @@ in
|
||||||
};
|
};
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
git
|
git
|
||||||
|
jq
|
||||||
];
|
];
|
||||||
environment.variables = {
|
environment.variables = {
|
||||||
DOMAIN = config.services.userdata.domain;
|
DOMAIN = config.services.userdata.domain;
|
||||||
};
|
};
|
||||||
system.autoUpgrade.enable = config.services.userdata.autoUpgrade.enable;
|
system.autoUpgrade = {
|
||||||
system.autoUpgrade.allowReboot = config.services.userdata.autoUpgrade.allowReboot;
|
enable = config.services.userdata.autoUpgrade.enable;
|
||||||
|
allowReboot = config.services.userdata.autoUpgrade.allowReboot;
|
||||||
|
channel = "https://channel.selfprivacy.org/nixos-selfpricacy";
|
||||||
|
};
|
||||||
nix = {
|
nix = {
|
||||||
optimise.automatic = true;
|
optimise.automatic = true;
|
||||||
gc = {
|
gc = {
|
||||||
|
|
83
files.nix
83
files.nix
|
@ -5,33 +5,78 @@ in
|
||||||
{
|
{
|
||||||
systemd.tmpfiles.rules =
|
systemd.tmpfiles.rules =
|
||||||
let
|
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;
|
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
|
in
|
||||||
[
|
[
|
||||||
(if cfg.bitwarden.enable then "d /var/lib/bitwarden 0777 vaultwarden vaultwarden -" else "")
|
(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/backup 0777 vaultwarden vaultwarden -" else "")
|
||||||
(if cfg.pleroma.enable then "d /var/lib/pleroma 0700 pleroma pleroma - -" else "")
|
(if cfg.pleroma.enable then "d /var/lib/pleroma 0700 pleroma pleroma - -" else "")
|
||||||
"d /var/lib/restic 0600 restic - - -"
|
"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 0755 pleroma pleroma - -" else "")
|
||||||
"f+ /var/domain 0444 selfprivacy-api selfprivacy-api - ${domain}"
|
"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
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ let
|
||||||
cfg = config.services.userdata;
|
cfg = config.services.userdata;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
services.bitwarden_rs = {
|
services.vaultwarden = {
|
||||||
enable = cfg.bitwarden.enable;
|
enable = cfg.bitwarden.enable;
|
||||||
dbBackend = "sqlite";
|
dbBackend = "sqlite";
|
||||||
backupDir = "/var/lib/bitwarden/backup";
|
backupDir = "/var/lib/bitwarden/backup";
|
||||||
|
|
|
@ -22,9 +22,8 @@ config :pleroma, :media_proxy,
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
adapter: Ecto.Adapters.Postgres,
|
adapter: Ecto.Adapters.Postgres,
|
||||||
username: "pleroma",
|
username: "pleroma",
|
||||||
password: "$DB_PASSWORD",
|
|
||||||
database: "pleroma",
|
database: "pleroma",
|
||||||
hostname: "localhost",
|
socket_dir: "/run/postgresql",
|
||||||
pool_size: 10
|
pool_size: 10
|
||||||
|
|
||||||
#config :web_push_encryption, :vapid_details,
|
#config :web_push_encryption, :vapid_details,
|
||||||
|
@ -41,4 +40,4 @@ config :pleroma, :http_security,
|
||||||
|
|
||||||
#config :joken, default_signer: ""
|
#config :joken, default_signer: ""
|
||||||
|
|
||||||
config :pleroma, configurable_from_database: false
|
config :pleroma, configurable_from_database: true
|
||||||
|
|
|
@ -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 ];
|
|
||||||
}
|
|
|
@ -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" ];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -3,11 +3,6 @@ let
|
||||||
cfg = config.services.userdata;
|
cfg = config.services.userdata;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
nixpkgs.overlays = [
|
|
||||||
(self: super: {
|
|
||||||
pleroma-otp = self.callPackage ./pleroma-package.nix { };
|
|
||||||
})
|
|
||||||
];
|
|
||||||
services = {
|
services = {
|
||||||
pleroma = {
|
pleroma = {
|
||||||
enable = cfg.pleroma.enable;
|
enable = cfg.pleroma.enable;
|
||||||
|
@ -15,8 +10,8 @@ in
|
||||||
group = "pleroma";
|
group = "pleroma";
|
||||||
configs = [
|
configs = [
|
||||||
(builtins.replaceStrings
|
(builtins.replaceStrings
|
||||||
[ "$DOMAIN" "$LUSER" "$DB_PASSWORD" ]
|
[ "$DOMAIN" "$LUSER" ]
|
||||||
[ cfg.domain cfg.username cfg.databasePassword ]
|
[ cfg.domain cfg.username ]
|
||||||
(builtins.readFile ./config.exs))
|
(builtins.readFile ./config.exs))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -24,10 +19,21 @@ in
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.postgresql_12;
|
package = pkgs.postgresql_12;
|
||||||
initialScript = "/etc/setup.psql";
|
initialScript = "/etc/setup.psql";
|
||||||
|
ensureDatabases = [
|
||||||
|
"pleroma"
|
||||||
|
];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "pleroma";
|
||||||
|
ensurePermissions = {
|
||||||
|
"DATABASE pleroma" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
environment.etc."setup.psql".text = ''
|
environment.etc."setup.psql".text = ''
|
||||||
CREATE USER pleroma WITH ENCRYPTED PASSWORD '${cfg.databasePassword}';
|
CREATE USER pleroma;
|
||||||
CREATE DATABASE pleroma OWNER pleroma;
|
CREATE DATABASE pleroma OWNER pleroma;
|
||||||
\c pleroma;
|
\c pleroma;
|
||||||
--Extensions made by ecto.migrate that need superuser access
|
--Extensions made by ecto.migrate that need superuser access
|
||||||
|
|
72
userdata/tokens_schema.json
Normal file
72
userdata/tokens_schema.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ in
|
||||||
value = {
|
value = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
hashedPassword = user.hashedPassword;
|
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);
|
cfg.users);
|
||||||
|
|
|
@ -11,10 +11,6 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.userdata = {
|
options.services.userdata = {
|
||||||
enable = mkOption {
|
|
||||||
default = true;
|
|
||||||
type = types.nullOr types.bool;
|
|
||||||
};
|
|
||||||
# General server options
|
# General server options
|
||||||
hostname = mkOption {
|
hostname = mkOption {
|
||||||
description = "The hostname of the server.";
|
description = "The hostname of the server.";
|
||||||
|
@ -71,12 +67,6 @@ in
|
||||||
# API options #
|
# API options #
|
||||||
###############
|
###############
|
||||||
api = {
|
api = {
|
||||||
token = mkOption {
|
|
||||||
description = ''
|
|
||||||
API token used to authenticate with the server
|
|
||||||
'';
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
};
|
|
||||||
enableSwagger = mkOption {
|
enableSwagger = mkOption {
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
|
@ -100,30 +90,10 @@ in
|
||||||
description = "Bucket name used for userdata backups";
|
description = "Bucket name used for userdata backups";
|
||||||
type = types.nullOr types.str;
|
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 #
|
# Services #
|
||||||
##############
|
##############
|
||||||
databasePassword = mkOption {
|
|
||||||
description = ''
|
|
||||||
Password for the database
|
|
||||||
'';
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
};
|
|
||||||
bitwarden = {
|
bitwarden = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
|
@ -141,18 +111,6 @@ in
|
||||||
default = true;
|
default = true;
|
||||||
type = types.nullOr types.bool;
|
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 = {
|
pleroma = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
|
@ -172,15 +130,6 @@ in
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#############
|
|
||||||
# Backups #
|
|
||||||
#############
|
|
||||||
resticPassword = mkOption {
|
|
||||||
description = ''
|
|
||||||
Password for the restic
|
|
||||||
'';
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
};
|
|
||||||
#########
|
#########
|
||||||
# SSH #
|
# SSH #
|
||||||
#########
|
#########
|
||||||
|
|
|
@ -1,6 +1,49 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
jsonData = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
|
||||||
|
in
|
||||||
{
|
{
|
||||||
services = {
|
services.userdata = {
|
||||||
userdata = builtins.fromJSON (builtins.readFile ./userdata/userdata.json);
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue