diff --git a/nixos-infect b/nixos-infect
index 221a4ae..a8034d7 100755
--- a/nixos-infect
+++ b/nixos-infect
@@ -12,6 +12,7 @@ makeConf() {
mkdir -p /etc/nixos/mailserver/system
mkdir /etc/nixos/mailserver/userdata
mkdir /etc/nixos/api
+ mkdir /etc/nixos/social
mkdir /etc/nixos/letsencrypt
mkdir /etc/nixos/backup
mkdir /etc/nixos/passmgr
@@ -44,6 +45,8 @@ makeConf() {
./vpn/ocserv.nix
./api/api.nix
./api/api-service.nix
+ ./social/pleroma-module.nix
+ ./social/pleroma.nix
./letsencrypt/acme.nix
./backup/restic.nix
./passmgr/bitwarden.nix
@@ -79,14 +82,7 @@ makeConf() {
};
environment.systemPackages = with pkgs; [
git
- wget
- curl
- python3
- ] ++ (with python38Packages; [
- pip
- flask
- pandas
- ]);
+ ];
environment.variables = {
DOMAIN = "$DOMAIN";
AWS_ACCESS_KEY_ID = "$AWS_ACCESS_KEY_ID";
@@ -115,7 +111,6 @@ makeConf() {
security = {
sudo = {
enable = true;
- wheelNeedsPassword = true;
};
};
users.mutableUsers = false;
@@ -151,14 +146,10 @@ EOF
resticPass = builtins.replaceStrings [ "\n" "\"" "\\\" ] [ "\\\n" "\\\\\"" "\\\\\\\\" ] ''
$PASSWORD
'';
- shadowsocksPass = builtins.replaceStrings [ "\n" "\"" "\\\" ] [ "\\\n" "\\\\\"" "\\\\\\\\" ] ''
- $PASSWORD
- '';
domain = builtins.replaceStrings [ "\n" "\"" "\\\" ] [ "\\\n" "\\\\\"" "\\\\\\\\" ] ''
$DOMAIN
'';
cloudflareCredentials = builtins.replaceStrings [ "\n" "\"" "\\\" ] [ "\\\n" "\\\\\"" "\\\\\\\\" ] ''
- # Cloudflare API token used by Certbot
CF_API_KEY=$CF_TOKEN
CLOUDFLARE_DNS_API_TOKEN=$CF_TOKEN
CLOUDFLARE_ZONE_API_TOKEN=$CF_TOKEN
@@ -356,10 +347,6 @@ EOF
locations = {
"/" = {
proxyPass = "http://127.0.0.1:3000";
- extraConfig = ''
-proxy_headers_hash_max_size 512;
-proxy_headers_hash_bucket_size 128;
- '';
};
};
};
@@ -370,10 +357,6 @@ proxy_headers_hash_bucket_size 128;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:80/";
- extraConfig = ''
-proxy_headers_hash_max_size 512;
-proxy_headers_hash_bucket_size 128;
- '';
};
};
};
@@ -384,12 +367,8 @@ proxy_headers_hash_bucket_size 128;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:8222";
- extraConfig = ''
-proxy_headers_hash_max_size 512;
-proxy_headers_hash_bucket_size 128;
- '';
- };
- };
+ };
+ };
};
"api.$DOMAIN" = {
sslCertificate = "/var/lib/acme/$DOMAIN/fullchain.pem";
@@ -398,13 +377,23 @@ proxy_headers_hash_bucket_size 128;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:5050";
- extraConfig = ''
-proxy_headers_hash_max_size 512;
-proxy_headers_hash_bucket_size 128;
- '';
};
};
};
+ "social.$DOMAIN" = {
+ sslCertificate = "/var/lib/acme/$DOMAIN/fullchain.pem";
+ sslCertificateKey = "/var/lib/acme/$DOMAIN/key.pem";
+ root = "/var/www/social.$DOMAIN";
+ forceSSL = true;
+ locations = {
+ "/" = {
+ proxyPass = "http://127.0.0.1:4000";
+ };
+ };
+ extraConfig = ''
+ client_max_body_size 1024m;
+ '';
+ };
};
};
}
@@ -710,6 +699,299 @@ route = default
'';
};
}
+EOF
+
+cat > /etc/nixos/social/pleroma-package.nix << EOF
+{ lib
+, stdenv
+, autoPatchelfHook
+, fetchurl
+, file
+, makeWrapper
+, ncurses
+, nixosTests
+, openssl
+, unzip
+, zlib
+}:
+stdenv.mkDerivation {
+ pname = "pleroma-otp";
+ version = "2.2.2";
+
+ # 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/175288/artifacts/download";
+ sha256 = "107kp5zqwq1lixk1cwkx4v7zpm0h248xzlm152aj36ghb43j2snw";
+ };
+ x86_64-linux = fetchurl {
+ url = "https://git.pleroma.social/pleroma/pleroma/-/jobs/175284/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" ];
+ };
+}
+EOF
+
+cat > /etc/nixos/social/pleroma-package.nix << EOF
+{ 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.
+ DO NOT STORE ANY PLEROMA SECRET
+ HERE, use
+ services.pleroma.secretConfigFile
+ 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.
+ DO NOT POINT THIS OPTION TO THE NIX
+ STORE, 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 ];
+}
+EOF
+
+cat > /etc/nixos/social/pleroma-package.nix << EOF
+{ pkgs, ... }:
+{
+ nixpkgs.overlays = [(self: super: {
+ pleroma-otp = self.callPackage ./pleroma-package.nix {};
+ })];
+ services = {
+ pleroma = {
+ enable = true;
+ user = "pleroma";
+ group = "pleroma";
+ configs = [
+ (builtins.readFile ./config.exs)
+ ];
+ };
+ postgresql = {
+ enable = true;
+ package = pkgs.postgresql_12;
+ initialScript = "/etc/setup.psql";
+ };
+ };
+ environment.etc."pleroma_setup.psql".text = ''
+CREATE USER pleroma WITH ENCRYPTED PASSWORD '$DB_PASSWORD';
+CREATE DATABASE pleroma OWNER pleroma;
+\\c pleroma;
+--Extensions made by ecto.migrate that need superuser access
+CREATE EXTENSION IF NOT EXISTS citext;
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+ '';
+ users.users.pleroma = {
+ extraGroups = [ "postgres" ];
+ };
+}
+EOF
+
+cat > /etc/nixos/social/config.exs << EOF
+import Config
+
+config :pleroma, Pleroma.Web.Endpoint,
+ url: [host: "social.$DOMAIN", scheme: "https", port: 443],
+ http: [ip: {127, 0, 0, 1}, port: 4000],
+ #secret_key_base: "",
+ #signing_salt: ""
+
+config :pleroma, :instance,
+ name: "social.$DOMAIN",
+ email: "$LUSER@$DOMAIN",
+ notify_email: "$LUSER@$DOMAIN",
+ limit: 5000,
+ upload_limit: 1073741824,
+ registrations_open: true
+
+config :pleroma, :media_proxy,
+ enabled: false,
+ redirect_on_failure: true
+ #base_url: "https://cache.pleroma.social"
+
+config :pleroma, Pleroma.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "pleroma",
+ password: "$DB_PASSWORD",
+ database: "pleroma",
+ hostname: "localhost",
+ pool_size: 10
+
+config :web_push_encryption, :vapid_details,
+ #subject: "",
+ #public_key: "",
+ #private_key: ""
+
+config :pleroma, :database, rum_enabled: false
+config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
+config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
+
+config :pleroma, :http_security,
+ sts: true
+
+#config :joken, default_signer: ""
+
+config :pleroma, configurable_from_database: false
+
EOF
[[ -n "$doNetConf" ]] && makeNetworkingConf || true