diff --git a/modules/nixos/services/apps/ignis/default.nix b/modules/nixos/services/apps/ignis/default.nix index 37890a7..d33be87 100644 --- a/modules/nixos/services/apps/ignis/default.nix +++ b/modules/nixos/services/apps/ignis/default.nix @@ -12,9 +12,89 @@ networkCfg = getAttrByNamespace config "${namespace}.services.networking"; isEnabled = hostHasService networkCfg.network-services hostName "ignis"; - port = resolveServicePort networkCfg.network-services "ignis" 8081; + port = resolveServicePort networkCfg.network-services "ignis" 5125; + + vault-key-provision = import ./vault-key-provision.nix {inherit pkgs;}; + vault-sync = import ./vault-sync.nix {inherit pkgs;}; in { config = mkIf isEnabled { + systemd = { + services = { + ignis = { + description = "Ignis - Self-hosted Obsidian web app"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + path = with pkgs; [ + git + ]; + + environment = { + PORT = toString port; + VAULT_ROOT = "/var/lib/ignis/vaults"; + DATA_ROOT = "/var/lib/ignis/data"; + OBSIDIAN_ASSETS_PATH = "${pkgs.ignis}/lib/ignis/obsidian-app"; + OBSIDIAN_VERSION = "1.12.7"; + }; + + preStart = '' + mkdir -p /var/lib/ignis/vaults /var/lib/ignis/data + chown -R ignis:ignis /var/lib/ignis/vaults /var/lib/ignis/data + ''; + + serviceConfig = { + Type = "simple"; + User = "ignis"; + Group = "ignis"; + Restart = "always"; + RestartSec = 5; + ExecStart = "${pkgs.ignis}/bin/ignis-server"; + StateDirectory = "ignis"; + StateDirectoryMode = "0750"; + WorkingDirectory = "${pkgs.ignis}/lib/ignis"; + }; + }; + + ignis-vault-key-provision = { + description = "Provision SSH key and git config for ignis vault sync"; + after = ["network.target"]; + before = ["ignis-vault-sync.service"]; + wantedBy = ["multi-user.target"]; + environment.HOME = "/var/lib/ignis/data"; + serviceConfig = { + Type = "oneshot"; + User = "ignis"; + Group = "ignis"; + ExecStart = "${vault-key-provision}/bin/ignis-vault-key-provision"; + RemainAfterExit = true; + }; + }; + + ignis-vault-sync = { + description = "Auto-commit and pull ignis vaults"; + after = ["ignis-vault-key-provision.service"]; + path = with pkgs; [ + openssh + ]; + environment.HOME = "/var/lib/ignis/data"; + serviceConfig = { + Type = "oneshot"; + User = "ignis"; + Group = "ignis"; + ExecStart = "${vault-sync}/bin/ignis-vault-sync"; + }; + }; + }; + + timers = { + ignis-vault-sync = { + description = "Timer for ignis vault sync"; + wantedBy = ["timers.target"]; + timerConfig.OnUnitActiveSec = "1m"; + }; + }; + }; + users = { users.ignis = { isSystemUser = true; @@ -30,43 +110,8 @@ in { networking.firewall.allowedTCPPorts = [port]; - systemd.services.ignis = { - description = "Ignis - Self-hosted Obsidian web app"; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; - - path = with pkgs; [ - git - ]; - - environment = { - PORT = toString port; - VAULT_ROOT = "/var/lib/ignis/vaults"; - DATA_ROOT = "/var/lib/ignis/data"; - OBSIDIAN_ASSETS_PATH = "${pkgs.ignis}/lib/ignis/obsidian-app"; - OBSIDIAN_VERSION = "1.12.7"; - }; - - preStart = '' - mkdir -p /var/lib/ignis/vaults /var/lib/ignis/data - chown -R ignis:ignis /var/lib/ignis/vaults /var/lib/ignis/data - ''; - - serviceConfig = { - Type = "simple"; - User = "ignis"; - Group = "ignis"; - Restart = "always"; - RestartSec = 5; - ExecStart = "${pkgs.ignis}/bin/ignis-server"; - StateDirectory = "ignis"; - StateDirectoryMode = "0750"; - WorkingDirectory = "${pkgs.ignis}/lib/ignis"; - }; - }; - ${namespace}.services.storage.impermanence.folders = [ - "/var/lib/ignis/data" + "/var/lib/ignis" ]; }; } diff --git a/modules/nixos/services/apps/ignis/vault-key-provision.nix b/modules/nixos/services/apps/ignis/vault-key-provision.nix new file mode 100644 index 0000000..715a2b1 --- /dev/null +++ b/modules/nixos/services/apps/ignis/vault-key-provision.nix @@ -0,0 +1,29 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "ignis-vault-key-provision" '' + set -euo pipefail + + DATA_DIR="/var/lib/ignis/data" + SSH_DIR="$DATA_DIR/.ssh" + KEY_FILE="$SSH_DIR/id_ed25519" + PUBLIC_KEY_FILE="$KEY_FILE.pub" + HOSTNAME="$(< /proc/sys/kernel/hostname)" + + umask 077 + mkdir -p "$SSH_DIR" + + if [ ! -f "$KEY_FILE" ]; then + ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "$KEY_FILE" -C "ignis-vault-sync@$HOSTNAME" + + echo "# ===============================================================================" + echo "# IGNIS VAULT SYNC PUBLIC KEY" + echo "# ===============================================================================" + cat "$PUBLIC_KEY_FILE" + fi + + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" user.name "C4 Patino" + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" user.email "c4patino@gmail.com" + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" core.sshCommand "${pkgs.openssh}/bin/ssh -i $KEY_FILE -o StrictHostKeyChecking=accept-new" + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" gpg.format ssh + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" user.signingkey "$PUBLIC_KEY_FILE" + ${pkgs.git}/bin/git config -f "$DATA_DIR/.gitconfig" commit.gpgsign true +'' diff --git a/modules/nixos/services/apps/ignis/vault-sync.nix b/modules/nixos/services/apps/ignis/vault-sync.nix new file mode 100644 index 0000000..a3b4e43 --- /dev/null +++ b/modules/nixos/services/apps/ignis/vault-sync.nix @@ -0,0 +1,38 @@ +{pkgs}: +pkgs.writeShellScriptBin "ignis-vault-sync" '' + set -euo pipefail + set -x + + VAULT_ROOT="/var/lib/ignis/vaults" + DATA_DIR="/var/lib/ignis/data" + PULL_INTERVAL=300 + + for vault in "$VAULT_ROOT"/*/; do + [ -d "$vault/.git" ] || continue + + cd "$vault" + name=$(basename "$vault") + + now=$(date +%s) + + last_pull_file="$DATA_DIR/.last-pull-$name" + last_pull=0 + [ -f "$last_pull_file" ] && last_pull=$(cat "$last_pull_file") + + if [ $((now - last_pull)) -ge $PULL_INTERVAL ]; then + ${pkgs.git}/bin/git pull --rebase 2>/dev/null || true + echo "$now" > "$last_pull_file" + fi + + if ! ${pkgs.git}/bin/git diff --quiet 2>/dev/null || ! ${pkgs.git}/bin/git diff --cached --quiet 2>/dev/null || [ -n "$(${pkgs.git}/bin/git ls-files --others --exclude-standard 2>/dev/null)" ]; then + newest=$(${pkgs.findutils}/bin/find . -not -path './.git/*' -type f -printf '%T@\n' 2>/dev/null | sort -rn 2>/dev/null | head -1) || true + newest_int=$(echo "$newest" | cut -d. -f1) + + if [ -z "$newest_int" ] || [ $((now - newest_int)) -ge 60 ]; then + ${pkgs.git}/bin/git add -A 2>/dev/null + ${pkgs.git}/bin/git commit -m "$(date -u +"docs(%Y/%m/%d): obsidian automatic vault backup")" 2>/dev/null + ${pkgs.git}/bin/git push 2>/dev/null + fi + fi + done +''