]> NullRing Git Server - monorepo.git/commitdiff
finish up most of the sysadmin work
authorPreston Pan <ret2pop@nullring.xyz>
Tue, 17 Feb 2026 07:13:47 +0000 (23:13 -0800)
committerPreston Pan <ret2pop@nullring.xyz>
Tue, 17 Feb 2026 07:13:47 +0000 (23:13 -0800)
22 files changed:
config/elfeed.org
config/emacs.org
config/nix.org
index.org
nix/data/public-inbox.css [new file with mode: 0644]
nix/init.el
nix/modules/conduit.nix
nix/modules/configuration.nix
nix/modules/gotosocial.nix [new file with mode: 0644]
nix/modules/home/default.nix
nix/modules/home/emacs.nix
nix/modules/home/mpd.nix
nix/modules/home/user.nix
nix/modules/maddy.nix
nix/modules/matrix-appservice-irc.nix [new file with mode: 0644]
nix/modules/nginx.nix
nix/modules/public_inbox.nix [new file with mode: 0644]
nix/modules/secrets.nix
nix/secrets/secrets.yaml
nix/secrets/vps_secrets.yaml
nix/systems/home.nix
nix/systems/spontaneity/default.nix

index b659f8e3b0d05c20d16959bfada088c6ad86000e..c114294dadc3b65e241e9daa044858b158e8e6db 100644 (file)
@@ -22,6 +22,8 @@ This is a podcast by Luke Smith that talks about anything that he wants to.
 ** Forums :forum:
 *** [[http://lesserwrong.com/feed.xml][LessWrong]]
 The birthplace of bay area rationalism.
+*** [[https://list.nullring.xyz/discussion/new.atom][Nullring Discussion]]
+My own mailing list feed.
 ** Science Journals :journal:
 I like to get new information about recent studies related to technology.
 *** [[http://www.nature.com/nmat/current_issue/rss/][Nature]]
index c919b965c9a8217105c6ac9714dcf79175903c23..69316e55ade902ec06e6ed93173dae5fb27edd43 100644 (file)
@@ -767,6 +767,8 @@ Email in emacs can be done with Mu4e.
 
   (use-package mu4e
     :after smtpmail
+    :hook
+    ((mu4e-compose-mode . mml-secure-message-sign-pgpmime))
     :custom
     (mu4e-drafts-folder "/Drafts" "Set drafts folder mu db")
     (mu4e-sent-folder   "/Sent" "Set sent folder in mu db")
@@ -784,6 +786,10 @@ Email in emacs can be done with Mu4e.
     (mu4e-headers-auto-update t "Auto-updates feed")
     (mu4e-view-show-images t "Shows images")
     (mu4e-compose-signature-auto-include nil)
+    (mml-secure-openpgp-sign-with-sender t)
+    (mml-secure-openpgp-signers (list system-gpgkey))
+    (mail-user-agent 'mu4e-user-agent)
+    (message-mail-user-agent 'mu4e-user-agent)
     (mu4e-use-fancy-chars t "Random option to make mu4e look nicer"))
 #+end_src
 ** Music
index 158fd991bf9f7a57fe3cc8108976dfefb6c5c89b..cf0e8c51f6ecc48a5b8a29686e76c259aa201d68 100644 (file)
@@ -472,6 +472,15 @@ the yaml file specified. Yes, this is safe to include in the repo.
 
 
       templates = if config.monorepo.profiles.server.enable then {
+        "public-inbox-netrc" = {
+          owner = "public-inbox";
+          group = "public-inbox";
+          mode = "0400";
+          content = ''
+  machine mail.${config.monorepo.vars.orgHost} login monorepo@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
+  machine mail.${config.monorepo.vars.orgHost} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
+      '';
+        };
         "matterbridge" = {
           owner = "matterbridge";
           content = ''
@@ -556,6 +565,17 @@ the yaml file specified. Yes, this is safe to include in the repo.
           format = "yaml";
           owner = "maddy";
         };
+
+        mail_monorepo_password = {
+          format = "yaml";
+          owner = "maddy";
+        };
+
+        mail_monorepo_password_pi = {
+          format = "yaml";
+          owner = "public-inbox";
+        };
+
         conduit_secrets = {
           format = "yaml";
         };
@@ -568,6 +588,10 @@ the yaml file specified. Yes, this is safe to include in the repo.
         discord_token = {
           format = "yaml";
         };
+        mpd_password = {
+          format = "yaml";
+          owner = "nginx";
+        };
         ntfy = {
           format = "yaml";
           owner = "ntfy-sh";
@@ -901,7 +925,7 @@ for lk-jwt and livekit which is important for configuring p2p calls in matrix.
     services.lk-jwt-service = {
       enable = lib.mkDefault config.monorepo.profiles.server.enable;
       port = 6495;
-      livekitUrl = "wss://livekit.nullring.xyz";
+      livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}";
       keyFile = "/run/secrets/livekit_secret";
     };
     services.livekit = {
@@ -929,17 +953,21 @@ for lk-jwt and livekit which is important for configuring p2p calls in matrix.
     };
   }
 #+end_src
-** Coturn
-This is important for p2p calls in matrix as well.
-#+begin_src nix :tangle ../nix/modules/coturn.nix
+** GoToSocial
+This is a basic ActivityPub server.
+#+begin_src nix :tangle ../nix/modules/gotosocial.nix
   { lib, config, ... }:
   {
-    services.coturn = {
-      enable = false;
-      use-auth-secret = true;
-      listening-ips = [ "0.0.0.0" ];
-      cert = "/var/lib/acme/matrix.${config.monorepo.vars.orgHost}/fullchain.pem";
-      static-auth-secret-file = "/run/secrets/coturn_secret";
+    services.gotosocial = {
+      enable = lib.mkDefault config.monorepo.profiles.server.enable;
+      setupPostgresqlDB = true;
+      settings = {
+        application-name = "Nullring GoToSocial Instance";
+        host = "gotosocial.${config.monorepo.vars.orgHost}";
+        protocol = "https";
+        bind-address = "127.0.0.1";
+        port = 8080;
+      };
     };
   }
 #+end_src
@@ -954,6 +982,19 @@ I want to connect IRC to discord with matterbridge.
     };
   }
 #+end_src
+** TODO matrix-appservice-irc
+#+begin_src nix :tangle ../nix/modules/matrix-appservice-irc.nix
+  { lib, config, ... }:
+  {
+    enable = lib.mkDefault config.monorepo.profiles.server.enable;
+    registrationUrl = "localhost";
+
+    settings = {
+      homeserver.url = "https://matrix.nullring.xyz";
+      homserver.domain = "matrix.nullring.xyz";
+    };
+  }
+#+end_src
 *** Mautrix
 I use this bridge to bridge myself from Matrix to Discord and vise versa, because Matterbridge is not maintained very well and therefore
 does not support conduit at the moment. Note that this is not fully declarative and requires that you add
@@ -1223,7 +1264,7 @@ to the outside world under a domain.
 
       gitweb = {
         enable = true;
-        virtualHost = "${config.monorepo.vars.remoteHost}";
+        virtualHost = "${config.monorepo.vars.orgHost}";
       };
 
       virtualHosts = {
@@ -1262,11 +1303,12 @@ to the outside world under a domain.
           };
           locations."= /.well-known/matrix/server" = {
             extraConfig = ''
+        default_type application/json;
         add_header Content-Type application/json;
         add_header Access-Control-Allow-Origin *;
       '';
             
-            return = ''200 '{"m.server": "matrix.nullring.xyz:443"}' ''; 
+            return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; 
           };
           locations."/.well-known/matrix/client" = {
             extraConfig = ''
@@ -1328,8 +1370,8 @@ to the outside world under a domain.
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
               proxy_set_header X-Forwarded-Proto $scheme;
-              proxy_set_header Upgrade $http_upgrade;
-              proxy_set_header Connection "upgrade";
+              proxy_set_header Upgrade $http_upgrade;
+              proxy_set_header Connection "upgrade";
 
               # --- CORS CONFIGURATION START ---
               # 1. Allow all origins (including app.element.io)
@@ -1374,6 +1416,39 @@ to the outside world under a domain.
              enableACME = true;
            };
 
+        "list.${config.monorepo.vars.orgHost}" = {
+          forceSSL = true;
+          enableACME = true;
+          locations."/" = {
+            proxyPass = "http://localhost:9090";
+            extraConfig = ''
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+          '';
+          };
+        };
+
+        # the port comes from ssh tunnelling
+        "music.${config.monorepo.vars.remoteHost}" = {
+          addSSL = true;
+          enableACME = true;
+          basicAuthFile = config.sops.secrets."mpd_password".path;
+          locations."/" = {
+            proxyPass = "http://localhost:8000";
+            extraConfig = ''
+  proxy_buffering off;
+  proxy_http_version 1.1;
+  proxy_set_header Connection "";
+  proxy_set_header Host $host;
+  proxy_set_header X-Real-IP $remote_addr;
+  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+  proxy_read_timeout 36000s;
+  '';
+          };
+        };
+
         "${config.monorepo.vars.orgHost}" = {
           serverName = "${config.monorepo.vars.orgHost}";
           root = "/var/www/nullring/";
@@ -1481,10 +1556,249 @@ There is a non declarative part of setting dkims and spf.
         "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = {
           passwordFile = "/run/secrets/mail_password";
         };
+        "monorepo@${config.monorepo.vars.orgHost}" = {
+          passwordFile = "/run/secrets/mail_monorepo_password";
+        };
+        "discussion@${config.monorepo.vars.orgHost}" = {
+          passwordFile = "/run/secrets/mail_monorepo_password";
+        };
       };
     };
   }
 #+end_src
+*** Public Inbox
+This is my mailing list software that I will use to develop software.
+#+begin_src nix :tangle ../nix/modules/public_inbox.nix
+  { lib, config, ... }:
+  {
+    systemd.tmpfiles.rules = [
+      "C+ /var/lib/public-inbox/style.css 0644 public-inbox public-inbox - ${../data/public-inbox.css}"
+    ];
+    systemd.services.public-inbox-httpd = if config.monorepo.profiles.server.enable then {
+      preStart = ''
+      # Copy or link the file. 
+      # Using 'cp' is often safer for sandboxed services than linking to the store. Lol.
+      cp -f ${../data/public-inbox.css} /var/lib/public-inbox/style.css
+      chmod 644 /var/lib/public-inbox/style.css
+    '';
+      
+      serviceConfig = {
+        # Allow the service to see the file it just created
+        BindPaths = [ 
+          "/var/lib/public-inbox" 
+        ];
+        ReadOnlyPaths = [ "/var/lib/public-inbox/style.css" ];
+        # Ensure it can actually write to the directory during preStart
+        ReadWritePaths = [ "/var/lib/public-inbox" ];
+      };
+    } else {};
+
+    systemd.services.public-inbox-watch = if config.monorepo.profiles.server.enable then {
+      after = [ "sops-nix.service" ];
+      confinement.enable = lib.mkForce false;
+      preStart = ''
+        mkdir -p /var/lib/public-inbox/.tmp
+        chmod 0700 /var/lib/public-inbox/.tmp
+        ln -sfn ${config.sops.templates."public-inbox-netrc".path} /var/lib/public-inbox/.netrc
+      '';
+      environment = {
+        PUBLIC_INBOX_FORCE_IPV4 = "1";
+        NETRC = config.sops.templates."public-inbox-netrc".path;
+        HOME = "/var/lib/public-inbox";
+        TMPDIR = "/var/lib/public-inbox/.tmp";
+      };
+
+      serviceConfig = {
+        RestrictSUIDSGID = lib.mkForce false;
+        ReadWritePaths = [ "/var/lib/public-inbox" ];
+        RestrictAddressFamilies = lib.mkForce [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+        PrivateNetwork = lib.mkForce false;
+        SystemCallFilter = lib.mkForce [];
+        RootDirectory = lib.mkForce "";
+
+        CapabilityBoundingSet = lib.mkForce [ "~" ];
+        UMask = lib.mkForce "0022";
+        ProtectSystem = lib.mkForce false;
+      };
+    } else {};
+
+    services.public-inbox = {
+      enable = lib.mkDefault config.monorepo.profiles.server.enable;
+      settings = {
+        publicinbox.css = ["/var/lib/public-inbox/style.css"];
+        publicinbox.wwwlisting = "all";
+      };
+      http = {
+        enable = true;
+        port = 9090;
+      };
+      inboxes = {
+        "monorepo" = {
+          description = "discussion of ret2pop's monorepo project and related work.";
+          address = [ "monorepo@${config.monorepo.vars.orgHost}" ];
+          inboxdir = "/var/lib/public-inbox/monorepo";
+          url = "https://list.${config.monorepo.vars.orgHost}/monorepo";
+          watch = [ "imaps://monorepo%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
+        };
+
+        "discussion" = {
+          description = "Main Nullring Discussion Mailing List";
+          address = [ "discussion@${config.monorepo.vars.orgHost}" ];
+          inboxdir = "/var/lib/public-inbox/discuss";
+          url = "https://list.${config.monorepo.vars.orgHost}/discussion";
+          watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
+        };
+      };
+    };
+  }
+#+end_src
+*** Public Inbox CSS
+This is a minimal stylesheet for public inbox so that I don't get eye cancer while reading it.
+#+begin_src nix :tangle ../nix/data/public-inbox.css
+  :root {
+    --bg: #f8f9fa;
+    --fg: #2e3440;
+    --link: #5e81ac;
+    --link-hover: #81a1c1;
+    --border: #d8dee9;
+    --card-bg: #ffffff;
+    --meta-fg: #4c566a; /* Darker gray for better legibility */
+    --btn-fg: #ffffff;
+    --max-width: 780px;
+  }
+
+  @media (prefers-color-scheme: dark) {
+    :root {
+      --bg: #1a1b26;
+      --fg: #a9b1d6;
+      --link: #7aa2f7;
+      --link-hover: #bb9af7;
+      --border: #414868; /* Distinct border for dark mode */
+      --card-bg: #1f2335;
+      --meta-fg: #9aa5ce; /* Brighter gray for dark mode */
+      --btn-fg: #1a1b26;
+    }
+  }
+
+  span.q {
+    color: var(--meta-fg);
+    font-style: italic;
+  }
+
+  body {
+    background-color: var(--bg);
+    color: var(--fg);
+    line-height: 1.6;
+    max-width: var(--max-width);
+    margin: 3rem auto;
+    padding: 0 1.5rem;
+    font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
+    
+    /* Keep this for smoother rendering on macOS/iOS */
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+  }
+
+  /* 1. Global Link Fixes */
+  body a, body a:visited {
+    color: var(--link);
+  }
+
+  /* 2. Card Styling */
+  body pre {
+    white-space: pre-wrap;
+    background: var(--card-bg);
+    padding: 2rem;
+    border-radius: 12px;
+    border: 1px solid var(--border);
+    margin-bottom: 2.5rem;
+  }
+
+  /* 3. Header Cleanup */
+  body pre b:first-of-type {
+    font-weight: 700;
+    color: var(--link);
+    font-size: 1.1rem;
+    display: block;
+    margin-bottom: 0.5rem;
+  }
+
+  /* 4. Fixing the "Permalink" label on documentation */
+  /* We target links ending in / but EXCLUDE system paths like help or mirror */
+  body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]) {
+    font-size: 0;
+    text-decoration: none;
+    margin-right: 10px;
+  }
+
+  body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]):after {
+    content: "permalink";
+    font-size: 11px;
+    font-weight: bold;
+    color: var(--fg); /* Use main text color for high contrast */
+    background: var(--bg);
+    border: 1px solid var(--link); /* Use link color for the border */
+    padding: 4px 10px;
+    border-radius: 4px;
+    display: inline-block;
+  }
+
+  /* 5. Fixing the "Raw" button contrast */
+  body pre a[href$="/raw"] {
+    font-size: 0;
+    text-decoration: none;
+  }
+
+  body pre a[href$="/raw"]:after {
+    content: "raw";
+    font-size: 11px;
+    font-weight: bold;
+    color: var(--fg);
+    background: var(--bg);
+    border: 1px solid var(--link);
+    padding: 4px 10px;
+    border-radius: 4px;
+    display: inline-block;
+  }
+
+  /* Hover effect for ghost buttons: solid color shift */
+  body pre a[href$="/"]:hover:after,
+  body pre a[href$="/raw"]:hover:after {
+    background: var(--link);
+    color: var(--btn-fg);
+  }
+
+  /* 6. The Reply Button (Primary Action) */
+  body pre a[href$="#R"], body pre a[href$="#R"]:visited {
+    font-size: 0;
+    text-decoration: none;
+  }
+
+  body pre a[href$="#R"]:after {
+    content: "REPLY";
+    font-size: 12px;
+    font-weight: bold;
+    padding: 6px 20px;
+    background: var(--link);
+    color: var(--btn-fg);
+    border-radius: 6px;
+    display: inline-block;
+    margin-left: 10px;
+  }
+
+  /* 7. Hide clutter */
+  body pre a[href^="#r"], body pre a[href^="#r"] + b, body hr {
+    display: none;
+  }
+
+  /* Fix: Mathematically outscore the header rule to keep link text inline */
+  body pre a[href] b:first-of-type {
+    display: inline;
+    font-size: inherit;
+    margin-bottom: 0;
+    color: inherit;
+  }
+#+end_src
 ** Fail2Ban
 This is a service that bans bots that try to sign in on my server.
 #+begin_src nix :tangle ../nix/modules/fail2ban.nix
@@ -1611,6 +1925,7 @@ because they enhance security.
   { config, pkgs, lib, ... }:
   {
     imports = [
+      ./public_inbox.nix
       ./matterbridge.nix
       ./mautrix.nix
       ./xserver.nix
@@ -2014,6 +2329,7 @@ because they enhance security.
     users.groups.matterbridge = lib.mkDefault {};
     users.groups.maddy = lib.mkDefault {};
     users.groups.ntfy-sh = lib.mkDefault {};
+    users.groups.public-inbox = lib.mkDefault {};
 
     users.users = {
       conduit = {
@@ -2037,11 +2353,18 @@ because they enhance security.
         extraGroups = [ "acme" "nginx" ];
       };
 
+      public-inbox = {
+        isSystemUser = lib.mkDefault true;
+        group = "public-inbox";
+
+        extraGroups = [ "acme" "nginx" ];
+      };
       ngircd = {
         isSystemUser = lib.mkDefault true;
         group = "ngircd";
         extraGroups = [ "acme" "nginx" ];
       };
+
       livekit = {
         isSystemUser = lib.mkDefault true;
         group = "livekit";
@@ -2073,6 +2396,7 @@ because they enhance security.
         group = "git";
         openssh.authorizedKeys.keys = [
           "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
+          "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCedJm0yYB0qLah/Y7PqLVgNh6qp+yujssGtuR05KbZLzSnsLUjUMObMyjFB9xTKrSGDqyoMkNe2l5VXMBJ9wBKLbzqMWbkakAWOj7EC/qZ6dFWA075mniwAuWKY/Q8QYohAJbbeU4j0ObWrltd4ar2Ac9vsVyftYF5efg8PEqVdOxzrBn5taY1zCCRjee5ISeRDIovnBbq7x86jsx5VnXTjMN9FZCI2qmz992Sg/PPXpXat+O1YQlG0eBHEny2Ug9gaAYnGOVr6kZKE4lrjz47nrXVXO6lJsNXmuzTVnEgo30DAA3dV4fws/M5ptM5Pgg2qe94HyHWhhmtXOekWmGtP3YxpVe3M/SPl31UL570ZDuuCcpJTsbe90ZyXC3CiSJkLKbmFkfOgZ6DI2LT8KSp09/2NCtZYriLN/nXObn6gQzByGMxVyKNx2hh8ENt9hzTCAk5lYDK3g3wS8eLCY3EH/caEqT9mLZEZeRHtAhtfozo1VJL7sSZ0Zm7wiIxHylwOshh1sYI1gb1MgMqNnrr1t8+8UK+Q0NERQW3yiphG36HXWy/DdCG0EF+N850KbgH1FFur+m+3hZCZCFVp3tGCcOC+bxWMBT3+9yC6LARi5cFjLQaWLsNO5xEs4vqX3+s3QjJ0pAYDkgtoeY2Fbh+imN+JasWn/cSy5p3UdE4ZQ== andrei@kiss"
         ];
       };
       "${config.monorepo.vars.userName}" = {
@@ -2346,19 +2670,19 @@ I have many imports that we'll go through next.
            email = {
                    email = lib.mkOption {
                            type = lib.types.str;
-                           default = "ret2pop@gmail.com";
+                           default = "ret2pop@nullring.xyz";
                            example = "john@example.com";
                            description = "Email address and imaps/smtps account";
                    };
                    imapsServer = lib.mkOption {
                            type = lib.types.str;
-                           default = "imap.gmail.com";
+                           default = "mail.nullring.xyz";
                            example = "imap.example.com";
                            description = "imaps server address";
                    };
                    smtpsServer = lib.mkOption {
                            type = lib.types.str;
-                           default = "smtp.gmail.com";
+                           default = "mail.nullring.xyz";
                            example = "smtp.example.com";
                            description = "smtp server address";
                    };
@@ -2858,6 +3182,7 @@ as an org file which gets automatically tangled to an emacs-lisp file.
   (setq system-email "${config.monorepo.profiles.email.email}")
   (setq system-username "${config.monorepo.vars.internetName}")
   (setq system-fullname "${config.monorepo.vars.fullName}")
+  (setq system-gpgkey "${config.monorepo.vars.gpgKey}")
   (load "${pkgs.writeText "init.el" (builtins.readFile ../../init.el)}")
   '';
 
@@ -3361,16 +3686,16 @@ in the ~~/music~ directory and then run ~mpc add /~ afterwards.
           type "pipewire"
           name "pipewire output"
         }
+
         audio_output {
           type         "httpd"
-          name         "My HTTP Stream"
+          name         "Ret2pop's Music Stream"
           encoder              "opus"          # optional
           port         "8000"
-       #       quality         "5.0"                   # do not define if bitrate is defined
-          bitrate              "128000"                        # do not define if quality is defined
+          bitrate              "128000"
           format               "48000:16:1"
-          always_on       "yes" # prevent MPD from disconnecting all listeners when playback is stopped.
-          tags            "yes" # httpd supports sending tags to listening streams.
+          always_on       "yes"
+          tags            "yes"
         }
 
   audio_output {
@@ -4013,6 +4338,8 @@ for these configurations.
       packages = with pkgs; (if config.monorepo.profiles.graphics.enable then [
         # wikipedia
         # kiwix kiwix-tools
+        gnupg
+        unzip
         mupdf
         zathura
 
@@ -4132,6 +4459,12 @@ for these configurations.
       '';
       };
     };
+    xdg.mimeApps = {
+      enable = true;
+      defaultApplications = {
+        "x-scheme-handler/mailto" = "emacsclient-mail.desktop";
+      };
+    };
 
     programs.bash.enable = true;
     fonts.fontconfig.enable = true;
@@ -4145,6 +4478,7 @@ the path.
   { config, sops-nix, ... }:
   {
     home-manager = {
+      backupFileExtension = "backup";
       sharedModules = [
         sops-nix.homeManagerModules.sops
       ];
@@ -4338,6 +4672,7 @@ some DNS records to match what you have on your system after deployment.
               7881
               8443
               8448
+              9418
             ];
             allowedUDPPorts = [
               3478 5349 7882
@@ -4389,6 +4724,7 @@ some DNS records to match what you have on your system after deployment.
               "ntfy.${config.monorepo.vars.remoteHost}" = {};
               "matrix.${config.monorepo.vars.remoteHost}" = {};
               "www.${config.monorepo.vars.remoteHost}" = {};
+              "music.${config.monorepo.vars.remoteHost}" = {};
               "mail.${config.monorepo.vars.remoteHost}" = {
               };
 
@@ -4396,6 +4732,8 @@ some DNS records to match what you have on your system after deployment.
               "${config.monorepo.vars.orgHost}" = {};
               "git.${config.monorepo.vars.orgHost}" = {};
               "matrix.${config.monorepo.vars.orgHost}" = {};
+              "social.${config.monorepo.vars.orgHost}" = {};
+              "list.${config.monorepo.vars.orgHost}" = {};
               "talk.${config.monorepo.vars.orgHost}" = {};
               "mail.${config.monorepo.vars.orgHost}" = {};
               "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {};
index 7d3ef8a08e20e93e60d6bb5ac4d58651fa718aff..3d4b26a2af331f350197fc918e67da5c76e27da6 100644 (file)
--- a/index.org
+++ b/index.org
@@ -52,7 +52,7 @@ can therefore publish them. So I did! Configurations include:
 - Qutebrowser
 â€¦and many more!
 * [[https://git.nullring.xyz][Projects]]
-My programming projects can be found on my [[https://ret2pop.net/gitweb][git server]]; other projects that do not directly pertain
+My programming projects can be found on my [[https://nullring.xyz/gitweb][git server]]; other projects that do not directly pertain
 to my projects on git or need a more in-depth explanation are explained further in my blog.
 I also have a [[https://github.com/ret2pop][github]] for those interested.
 * [[https://youtube.com/@ret2pop][Music and Media]]
@@ -65,9 +65,11 @@ but of course that won't be kept in a public repository.
 
 I think that it's cool to automatically and transparently let people know what I'm up to, so you
 don't have to ask. Also, it gives me some motivation to do things if a part of my agenda is public.
+* [[https://list.nullring.xyz][Mailing List]]
+Here, I keep a mailing list which you can figure out how to mail to by emailing me first (I don't want spammers).
+It's meant to be a general purpose mailing list as well as a collaborative space for working on projects with others.
 * [[file:about.org][About]]
 Who is the man behind ret2pop? How do you contact him? So many mysteries await…
-
 ** About this Website
 I wrote this website in org mode. For more information, see the [[file:README.org][README]]. Here is how I upload my
 website:
diff --git a/nix/data/public-inbox.css b/nix/data/public-inbox.css
new file mode 100644 (file)
index 0000000..df94873
--- /dev/null
@@ -0,0 +1,143 @@
+:root {
+  --bg: #f8f9fa;
+  --fg: #2e3440;
+  --link: #5e81ac;
+  --link-hover: #81a1c1;
+  --border: #d8dee9;
+  --card-bg: #ffffff;
+  --meta-fg: #4c566a; /* Darker gray for better legibility */
+  --btn-fg: #ffffff;
+  --max-width: 780px;
+}
+
+@media (prefers-color-scheme: dark) {
+  :root {
+    --bg: #1a1b26;
+    --fg: #a9b1d6;
+    --link: #7aa2f7;
+    --link-hover: #bb9af7;
+    --border: #414868; /* Distinct border for dark mode */
+    --card-bg: #1f2335;
+    --meta-fg: #9aa5ce; /* Brighter gray for dark mode */
+    --btn-fg: #1a1b26;
+  }
+}
+
+span.q {
+  color: var(--meta-fg);
+  font-style: italic;
+}
+
+body {
+  background-color: var(--bg);
+  color: var(--fg);
+  line-height: 1.6;
+  max-width: var(--max-width);
+  margin: 3rem auto;
+  padding: 0 1.5rem;
+  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
+  
+  /* Keep this for smoother rendering on macOS/iOS */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+/* 1. Global Link Fixes */
+body a, body a:visited {
+  color: var(--link);
+}
+
+/* 2. Card Styling */
+body pre {
+  white-space: pre-wrap;
+  background: var(--card-bg);
+  padding: 2rem;
+  border-radius: 12px;
+  border: 1px solid var(--border);
+  margin-bottom: 2.5rem;
+}
+
+/* 3. Header Cleanup */
+body pre b:first-of-type {
+  font-weight: 700;
+  color: var(--link);
+  font-size: 1.1rem;
+  display: block;
+  margin-bottom: 0.5rem;
+}
+
+/* 4. Fixing the "Permalink" label on documentation */
+/* We target links ending in / but EXCLUDE system paths like help or mirror */
+body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]) {
+  font-size: 0;
+  text-decoration: none;
+  margin-right: 10px;
+}
+
+body pre a[href$="/"]:not([href*="_/"]):not([href*="new.atom"]):after {
+  content: "permalink";
+  font-size: 11px;
+  font-weight: bold;
+  color: var(--fg); /* Use main text color for high contrast */
+  background: var(--bg);
+  border: 1px solid var(--link); /* Use link color for the border */
+  padding: 4px 10px;
+  border-radius: 4px;
+  display: inline-block;
+}
+
+/* 5. Fixing the "Raw" button contrast */
+body pre a[href$="/raw"] {
+  font-size: 0;
+  text-decoration: none;
+}
+
+body pre a[href$="/raw"]:after {
+  content: "raw";
+  font-size: 11px;
+  font-weight: bold;
+  color: var(--fg);
+  background: var(--bg);
+  border: 1px solid var(--link);
+  padding: 4px 10px;
+  border-radius: 4px;
+  display: inline-block;
+}
+
+/* Hover effect for ghost buttons: solid color shift */
+body pre a[href$="/"]:hover:after,
+body pre a[href$="/raw"]:hover:after {
+  background: var(--link);
+  color: var(--btn-fg);
+}
+
+/* 6. The Reply Button (Primary Action) */
+body pre a[href$="#R"], body pre a[href$="#R"]:visited {
+  font-size: 0;
+  text-decoration: none;
+}
+
+body pre a[href$="#R"]:after {
+  content: "REPLY";
+  font-size: 12px;
+  font-weight: bold;
+  padding: 6px 20px;
+  background: var(--link);
+  color: var(--btn-fg);
+  border-radius: 6px;
+  display: inline-block;
+  margin-left: 10px;
+}
+
+/* 7. Hide clutter */
+body pre a[href^="#r"], body pre a[href^="#r"] + b, body hr {
+  display: none;
+}
+
+/* Fix: Mathematically outscore the header rule to keep link text inline */
+body pre a[href] b:first-of-type {
+  display: inline;
+  font-size: inherit;
+  margin-bottom: 0;
+  color: inherit;
+}
index ac01689f58bc8c0a504377e8666dba08b1581ae8..a51afacaba12086fe121050a91305e316edade26 100644 (file)
 
 (use-package mu4e
   :after smtpmail
+  :hook
+  ((mu4e-compose-mode . mml-secure-message-sign-pgpmime))
   :custom
   (mu4e-drafts-folder "/Drafts" "Set drafts folder mu db")
   (mu4e-sent-folder   "/Sent" "Set sent folder in mu db")
   (mu4e-headers-auto-update t "Auto-updates feed")
   (mu4e-view-show-images t "Shows images")
   (mu4e-compose-signature-auto-include nil)
+  (mml-secure-openpgp-sign-with-sender t)
+  (mml-secure-openpgp-signers (list system-gpgkey))
+  (mail-user-agent 'mu4e-user-agent)
+  (message-mail-user-agent 'mu4e-user-agent)
   (mu4e-use-fancy-chars t "Random option to make mu4e look nicer"))
 
 (use-package emms
index 6e4611fa1b8c08d2146f83cc661e17c1f463bbe9..4d7a30c12ff7c474084b077dcbca1a9845476667 100644 (file)
@@ -18,7 +18,7 @@
   services.lk-jwt-service = {
     enable = lib.mkDefault config.monorepo.profiles.server.enable;
     port = 6495;
-    livekitUrl = "wss://livekit.nullring.xyz";
+    livekitUrl = "wss://livekit.${config.monorepo.vars.orgHost}";
     keyFile = "/run/secrets/livekit_secret";
   };
   services.livekit = {
index e09571b85c1e44a115d6e1ed5be45d3f87419521..02d4a94a3e50cc47dd92189b75eec2e7fc4b5e8b 100644 (file)
@@ -1,6 +1,7 @@
 { config, pkgs, lib, ... }:
 {
   imports = [
+    ./public_inbox.nix
     ./matterbridge.nix
     ./mautrix.nix
     ./xserver.nix
@@ -404,6 +405,7 @@ country=CA
   users.groups.matterbridge = lib.mkDefault {};
   users.groups.maddy = lib.mkDefault {};
   users.groups.ntfy-sh = lib.mkDefault {};
+  users.groups.public-inbox = lib.mkDefault {};
 
   users.users = {
     conduit = {
@@ -427,11 +429,18 @@ country=CA
       extraGroups = [ "acme" "nginx" ];
     };
 
+    public-inbox = {
+      isSystemUser = lib.mkDefault true;
+      group = "public-inbox";
+
+      extraGroups = [ "acme" "nginx" ];
+    };
     ngircd = {
       isSystemUser = lib.mkDefault true;
       group = "ngircd";
       extraGroups = [ "acme" "nginx" ];
     };
+
     livekit = {
       isSystemUser = lib.mkDefault true;
       group = "livekit";
@@ -463,6 +472,7 @@ country=CA
       group = "git";
       openssh.authorizedKeys.keys = [
         "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell"
+        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCedJm0yYB0qLah/Y7PqLVgNh6qp+yujssGtuR05KbZLzSnsLUjUMObMyjFB9xTKrSGDqyoMkNe2l5VXMBJ9wBKLbzqMWbkakAWOj7EC/qZ6dFWA075mniwAuWKY/Q8QYohAJbbeU4j0ObWrltd4ar2Ac9vsVyftYF5efg8PEqVdOxzrBn5taY1zCCRjee5ISeRDIovnBbq7x86jsx5VnXTjMN9FZCI2qmz992Sg/PPXpXat+O1YQlG0eBHEny2Ug9gaAYnGOVr6kZKE4lrjz47nrXVXO6lJsNXmuzTVnEgo30DAA3dV4fws/M5ptM5Pgg2qe94HyHWhhmtXOekWmGtP3YxpVe3M/SPl31UL570ZDuuCcpJTsbe90ZyXC3CiSJkLKbmFkfOgZ6DI2LT8KSp09/2NCtZYriLN/nXObn6gQzByGMxVyKNx2hh8ENt9hzTCAk5lYDK3g3wS8eLCY3EH/caEqT9mLZEZeRHtAhtfozo1VJL7sSZ0Zm7wiIxHylwOshh1sYI1gb1MgMqNnrr1t8+8UK+Q0NERQW3yiphG36HXWy/DdCG0EF+N850KbgH1FFur+m+3hZCZCFVp3tGCcOC+bxWMBT3+9yC6LARi5cFjLQaWLsNO5xEs4vqX3+s3QjJ0pAYDkgtoeY2Fbh+imN+JasWn/cSy5p3UdE4ZQ== andrei@kiss"
       ];
     };
     "${config.monorepo.vars.userName}" = {
diff --git a/nix/modules/gotosocial.nix b/nix/modules/gotosocial.nix
new file mode 100644 (file)
index 0000000..6b81128
--- /dev/null
@@ -0,0 +1,14 @@
+{ lib, config, ... }:
+{
+  services.gotosocial = {
+    enable = lib.mkDefault config.monorepo.profiles.server.enable;
+    setupPostgresqlDB = true;
+    settings = {
+      application-name = "Nullring GoToSocial Instance";
+      host = "gotosocial.${config.monorepo.vars.orgHost}";
+      protocol = "https";
+      bind-address = "127.0.0.1";
+      port = 8080;
+    };
+  };
+}
index b1c07c3601132e2225dfea83d5f9b6a13ca13a42..a45ce59d00b7f06e7b260b9fd9e8e3f1793ce95c 100644 (file)
            email = {
                    email = lib.mkOption {
                            type = lib.types.str;
-                           default = "ret2pop@gmail.com";
+                           default = "ret2pop@nullring.xyz";
                            example = "john@example.com";
                            description = "Email address and imaps/smtps account";
                    };
                    imapsServer = lib.mkOption {
                            type = lib.types.str;
-                           default = "imap.gmail.com";
+                           default = "mail.nullring.xyz";
                            example = "imap.example.com";
                            description = "imaps server address";
                    };
                    smtpsServer = lib.mkOption {
                            type = lib.types.str;
-                           default = "smtp.gmail.com";
+                           default = "mail.nullring.xyz";
                            example = "smtp.example.com";
                            description = "smtp server address";
                    };
index 4256d341d70a210219fe7ef22715669acd10274b..cdf1def3e69f0b89d75e069a4b80334813b9c4ee 100644 (file)
@@ -9,6 +9,7 @@
 (setq system-email "${config.monorepo.profiles.email.email}")
 (setq system-username "${config.monorepo.vars.internetName}")
 (setq system-fullname "${config.monorepo.vars.fullName}")
+(setq system-gpgkey "${config.monorepo.vars.gpgKey}")
 (load "${pkgs.writeText "init.el" (builtins.readFile ../../init.el)}")
 '';
 
index 8f646eac70c1235500c91ffc416345a26027fe89..2ab711b4b38f178e7c1f3df5396d41e65469be26 100644 (file)
         type "pipewire"
         name "pipewire output"
       }
+
       audio_output {
         type           "httpd"
-        name           "My HTTP Stream"
+        name           "Ret2pop's Music Stream"
         encoder                "opus"          # optional
         port           "8000"
-     # quality         "5.0"                   # do not define if bitrate is defined
-        bitrate                "128000"                        # do not define if quality is defined
+        bitrate                "128000"
         format         "48000:16:1"
-        always_on       "yes" # prevent MPD from disconnecting all listeners when playback is stopped.
-        tags            "yes" # httpd supports sending tags to listening streams.
+        always_on       "yes"
+        tags            "yes"
       }
 
 audio_output {
index 55e16fc2db98fd7f2bd3d4548768e0eaba61bc73..cb29b4cf7d37c5c600554c2aff06a827f813dfb9 100644 (file)
@@ -30,6 +30,8 @@
     packages = with pkgs; (if config.monorepo.profiles.graphics.enable then [
       # wikipedia
       # kiwix kiwix-tools
+      gnupg
+      unzip
       mupdf
       zathura
 
@@ -149,6 +151,12 @@ cd "$HOME"
     '';
     };
   };
+  xdg.mimeApps = {
+    enable = true;
+    defaultApplications = {
+      "x-scheme-handler/mailto" = "emacsclient-mail.desktop";
+    };
+  };
 
   programs.bash.enable = true;
   fonts.fontconfig.enable = true;
index 42f24f95563a13d3a8f9f660bd4d282a8b44671e..1d4710d64cb2ec98acd007fdf57d6a5f890bec97 100644 (file)
       "${config.monorepo.vars.internetName}@${config.monorepo.vars.orgHost}" = {
         passwordFile = "/run/secrets/mail_password";
       };
+      "monorepo@${config.monorepo.vars.orgHost}" = {
+        passwordFile = "/run/secrets/mail_monorepo_password";
+      };
+      "discussion@${config.monorepo.vars.orgHost}" = {
+        passwordFile = "/run/secrets/mail_monorepo_password";
+      };
     };
   };
 }
diff --git a/nix/modules/matrix-appservice-irc.nix b/nix/modules/matrix-appservice-irc.nix
new file mode 100644 (file)
index 0000000..518cdde
--- /dev/null
@@ -0,0 +1,10 @@
+{ lib, config, ... }:
+{
+  enable = lib.mkDefault config.monorepo.profiles.server.enable;
+  registrationUrl = "localhost";
+
+  settings = {
+    homeserver.url = "https://matrix.nullring.xyz";
+    homserver.domain = "matrix.nullring.xyz";
+  };
+}
index 87f11c1a097b8af35ca52d48f0a3834d27680954..621c9ef8ec6f40a71fc3b7effd4804f1a088fa95 100644 (file)
@@ -10,7 +10,7 @@
 
     gitweb = {
       enable = true;
-      virtualHost = "${config.monorepo.vars.remoteHost}";
+      virtualHost = "${config.monorepo.vars.orgHost}";
     };
 
     virtualHosts = {
         };
         locations."= /.well-known/matrix/server" = {
           extraConfig = ''
+      default_type application/json;
       add_header Content-Type application/json;
       add_header Access-Control-Allow-Origin *;
     '';
           
-          return = ''200 '{"m.server": "matrix.nullring.xyz:443"}' ''; 
+          return = ''200 '{"m.server": "matrix.${config.monorepo.vars.orgHost}:443"}' ''; 
         };
         locations."/.well-known/matrix/client" = {
           extraConfig = ''
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
-            proxy_set_header Upgrade $http_upgrade;
-            proxy_set_header Connection "upgrade";
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection "upgrade";
 
             # --- CORS CONFIGURATION START ---
             # 1. Allow all origins (including app.element.io)
              enableACME = true;
            };
 
+      "list.${config.monorepo.vars.orgHost}" = {
+        forceSSL = true;
+        enableACME = true;
+        locations."/" = {
+          proxyPass = "http://localhost:9090";
+          extraConfig = ''
+          proxy_set_header Host $host;
+          proxy_set_header X-Real-IP $remote_addr;
+          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+          proxy_set_header X-Forwarded-Proto $scheme;
+        '';
+        };
+      };
+
+      # the port comes from ssh tunnelling
+      "music.${config.monorepo.vars.remoteHost}" = {
+        addSSL = true;
+        enableACME = true;
+        basicAuthFile = config.sops.secrets."mpd_password".path;
+        locations."/" = {
+          proxyPass = "http://localhost:8000";
+          extraConfig = ''
+proxy_buffering off;
+proxy_http_version 1.1;
+proxy_set_header Connection "";
+proxy_set_header Host $host;
+proxy_set_header X-Real-IP $remote_addr;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+proxy_read_timeout 36000s;
+'';
+        };
+      };
+
       "${config.monorepo.vars.orgHost}" = {
         serverName = "${config.monorepo.vars.orgHost}";
         root = "/var/www/nullring/";
diff --git a/nix/modules/public_inbox.nix b/nix/modules/public_inbox.nix
new file mode 100644 (file)
index 0000000..9f1532c
--- /dev/null
@@ -0,0 +1,82 @@
+{ lib, config, ... }:
+{
+  systemd.tmpfiles.rules = [
+    "C+ /var/lib/public-inbox/style.css 0644 public-inbox public-inbox - ${../data/public-inbox.css}"
+  ];
+  systemd.services.public-inbox-httpd = if config.monorepo.profiles.server.enable then {
+    preStart = ''
+    # Copy or link the file. 
+    # Using 'cp' is often safer for sandboxed services than linking to the store. Lol.
+    cp -f ${../data/public-inbox.css} /var/lib/public-inbox/style.css
+    chmod 644 /var/lib/public-inbox/style.css
+  '';
+    
+    serviceConfig = {
+      # Allow the service to see the file it just created
+      BindPaths = [ 
+        "/var/lib/public-inbox" 
+      ];
+      ReadOnlyPaths = [ "/var/lib/public-inbox/style.css" ];
+      # Ensure it can actually write to the directory during preStart
+      ReadWritePaths = [ "/var/lib/public-inbox" ];
+    };
+  } else {};
+
+  systemd.services.public-inbox-watch = if config.monorepo.profiles.server.enable then {
+    after = [ "sops-nix.service" ];
+    confinement.enable = lib.mkForce false;
+    preStart = ''
+      mkdir -p /var/lib/public-inbox/.tmp
+      chmod 0700 /var/lib/public-inbox/.tmp
+      ln -sfn ${config.sops.templates."public-inbox-netrc".path} /var/lib/public-inbox/.netrc
+    '';
+    environment = {
+      PUBLIC_INBOX_FORCE_IPV4 = "1";
+      NETRC = config.sops.templates."public-inbox-netrc".path;
+      HOME = "/var/lib/public-inbox";
+      TMPDIR = "/var/lib/public-inbox/.tmp";
+    };
+
+    serviceConfig = {
+      RestrictSUIDSGID = lib.mkForce false;
+      ReadWritePaths = [ "/var/lib/public-inbox" ];
+      RestrictAddressFamilies = lib.mkForce [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+      PrivateNetwork = lib.mkForce false;
+      SystemCallFilter = lib.mkForce [];
+      RootDirectory = lib.mkForce "";
+
+      CapabilityBoundingSet = lib.mkForce [ "~" ];
+      UMask = lib.mkForce "0022";
+      ProtectSystem = lib.mkForce false;
+    };
+  } else {};
+
+  services.public-inbox = {
+    enable = lib.mkDefault config.monorepo.profiles.server.enable;
+    settings = {
+      publicinbox.css = ["/var/lib/public-inbox/style.css"];
+      publicinbox.wwwlisting = "all";
+    };
+    http = {
+      enable = true;
+      port = 9090;
+    };
+    inboxes = {
+      "monorepo" = {
+        description = "discussion of ret2pop's monorepo project and related work.";
+        address = [ "monorepo@${config.monorepo.vars.orgHost}" ];
+        inboxdir = "/var/lib/public-inbox/monorepo";
+        url = "https://list.${config.monorepo.vars.orgHost}/monorepo";
+        watch = [ "imaps://monorepo%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
+      };
+
+      "discussion" = {
+        description = "Main Nullring Discussion Mailing List";
+        address = [ "discussion@${config.monorepo.vars.orgHost}" ];
+        inboxdir = "/var/lib/public-inbox/discuss";
+        url = "https://list.${config.monorepo.vars.orgHost}/discussion";
+        watch = [ "imaps://discussion%40${config.monorepo.vars.orgHost}@mail.${config.monorepo.vars.orgHost}/INBOX" ];
+      };
+    };
+  };
+}
index f7deb5d8941c09596383d56c1f91aba0604abbc0..1a0965221cfd612c8ffd9fe66d7a6c872b588774 100644 (file)
@@ -7,6 +7,15 @@
 
 
     templates = if config.monorepo.profiles.server.enable then {
+      "public-inbox-netrc" = {
+        owner = "public-inbox";
+        group = "public-inbox";
+        mode = "0400";
+        content = ''
+machine mail.${config.monorepo.vars.orgHost} login monorepo@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
+machine mail.${config.monorepo.vars.orgHost} login discussion@${config.monorepo.vars.orgHost} password ${config.sops.placeholder."mail_monorepo_password_pi"}
+    '';
+      };
       "matterbridge" = {
         owner = "matterbridge";
         content = ''
@@ -91,6 +100,17 @@ channel="-5290629325"
         format = "yaml";
         owner = "maddy";
       };
+
+      mail_monorepo_password = {
+        format = "yaml";
+        owner = "maddy";
+      };
+
+      mail_monorepo_password_pi = {
+        format = "yaml";
+        owner = "public-inbox";
+      };
+
       conduit_secrets = {
         format = "yaml";
       };
@@ -103,6 +123,10 @@ channel="-5290629325"
       discord_token = {
         format = "yaml";
       };
+      mpd_password = {
+        format = "yaml";
+        owner = "nginx";
+      };
       ntfy = {
         format = "yaml";
         owner = "ntfy-sh";
index f2c3136773263989bd6841624b47ff7014a39181..6a15ac1f757c615a70f21f88a2debae845a0e8bf 100644 (file)
@@ -1,7 +1,9 @@
-mail: ENC[AES256_GCM,data:IFJnuVbshByUh5S3HoSnX5AyOg==,iv:gF0JlnBGAMLduMIG/hZtssdkHVL9/RDmDwBw/WoMDwQ=,tag:adDgcz/VrAN6/kfYTKa5XA==,type:str]
+mail: ENC[AES256_GCM,data:3gWbYL94WTUDNpSa/43Mrlc9Dj1zyWMpBqVCt+U=,iv:dqiIkQ0oF2lTbuQjZpEx6hp7jA+dijs8erfrITVF/KI=,tag:jOsR4RMUC7rUOQG5j8SASw==,type:str]
+mail_old: ENC[AES256_GCM,data:rZLF7iE+JZu6NNwmws3EDgSs4A==,iv:Cfy/Q4wPeD/nx9r/afqlTVo5KarNJpxsAUd2eFT5tUE=,tag:gjMk8cTs1/6da/o5loWriw==,type:str]
 digikey: ENC[AES256_GCM,data:U1c2HYB/YjwlyHvD3XVTqWJdb9/8BeS6,iv:DNsBoaqgUPdfO9knQLCMeJVO8kctQ9XNvcY2xcpI0NM=,tag:kuJ9BYqVx0GeTBSW5EsItg==,type:str]
 cloudflare-dns: ENC[AES256_GCM,data:Gztc/M+r/eRO2DwyLxlIBxS7B7MpOXimbFkQwlYhq9SzGG/fLl6Xqw==,iv:aDyNwbc8EyrNyhucULUkeg7VM7BmqNQTndSTh1SWqq0=,tag:HvysjKquD1g2PCrCgX2swg==,type:str]
 dn42: ENC[AES256_GCM,data:xSYssg7ReFjmf7LvmqmH/A==,iv:Gj/LZrxzRJLOLbP5rumjmViYWP6ufW3ocngektBW3V8=,tag:SA4f1vAnMFUO5Yk6NTr81Q==,type:str]
+nginx_password: ENC[AES256_GCM,data:/vDYWMEzNtu9h6jStzFlhdlfLDCimWUC/hmH4XoUWG1hW0RaQhn2vy+Qrr2O,iv:4YPQvar2qrFBMXvWyTn7M+WLpNPwrMB9mf7a9oyY2Yg=,tag:axsTqOuBdsbEIF+UvRuNfA==,type:str]
 sops:
     age:
         - recipient: age165ul43e8rc0qwzz2f2q9cw02psm2mkudsrwavq2e0pxs280p64yqy2z0dr
@@ -13,7 +15,7 @@ sops:
             OFFNeEtOTk5FSm9RaDFad0UyeWZ2WDgKIwGoB4a5WAIkE93gzqdUzNlo5vgQ1zLy
             yhEFrE1NbhyItnZIg/yRhqFG0dv7D3pEP3pq2Seew6pKJg/s9UTJ8Q==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2026-02-09T22:27:35Z"
-    mac: ENC[AES256_GCM,data:51iA4W4Sou4OC5pk5oFr9vAbBHDdbiZTi9jiLsSh4/IHx4SDQONc05EoMUsqjidodeAfQCpmvqBFKdVPIaaSZE+0fqyPTs/wjCtbZTAhsH+NTUKn4yU5/HBC3hw2QLz7tCLKgRLhfooHUDQxdFWGMJNB7xSjxdPVcy/1+gngOrE=,iv:TrWBcs/Px2bmh716Jl5xSP/SCXM7akaGrhsC6/pXbQg=,tag:AFqp09TkLkdu903jY5YjEw==,type:str]
+    lastmodified: "2026-02-16T06:29:48Z"
+    mac: ENC[AES256_GCM,data:EQ/faGU28DJlmfITjnVe/9W0Gq8RCYYQVxOtL9l4T6n68Tthj+F9cRujdfeNS/eLkrkyni4HQM4gj1yuwbWDe3/c3Fi2XXy8fY3NJq2T2LJn8M1O6GFR0lczJ4vg5C5vnhtJOMthhKfz2UwSbUYJ6WE/K4PF9T8NrZnxG923ckQ=,iv:yJRKxq/KnhVQM5KWxosoimGKT0tlUgQMxFGy5YrUqAM=,tag:QmlwF3t6E0Z7WirDzUuMug==,type:str]
     unencrypted_suffix: _unencrypted
     version: 3.11.0
index 87c513b3870a620a22e0191062c89aa3913bed85..ca862259a898536f7fd0fab5c9d72b2749acb3d0 100644 (file)
@@ -1,6 +1,7 @@
 livekit_secret: ENC[AES256_GCM,data:akkd9OREC024n5NfE/suM0B9SjBdPZbXMnz62Qwy2XNW+HhJw1ixhYoR8PQoR6K0unrAUAFhwWtQp+aJ1i+5q1rdpLV/3povvXYPaGg8EnE=,iv:uMuIfLYT1lvDWY8PYjnWWne7WOd0BBgBJn5mvd9ltAs=,tag:JQlRe5IY4f1RVvsq+56lKQ==,type:str]
 livekit: ENC[AES256_GCM,data:DFWsez5+O7fyI1P/3w8wKj2YpblP+fDR/r4Ry7lLJNnZxiCbT3iS0Rm9lfe3zqZbjHvhpnYtOMPApoegJFEonQ==,iv:SditYIuc+W+AdX4AgKx2j4A4K7FXXHpewcf7KzMB8qY=,tag:EwF9DKf7uGZZKf7kF8RsNg==,type:str]
 znc: ENC[AES256_GCM,data:iFNZ0tgciFU=,iv:oAAqMoov5Nv9AUBILlRpgTLJyu7l1uQshbag0ujewP4=,tag:RXtbn4EEH2523qX9MC0ODA==,type:str]
+mpd_password: ENC[AES256_GCM,data:yuSxdkf6ihe1a4qh6yGnrWLUzfe6+NiL9xdscw3mDNkDuqfhCcFAk4SSFNCH,iv:fJL42NDSPUk7b19nONu7pVwpfDaE//r/MgdoIpCI53w=,tag:OJst5kg3wvCU36YE7KuDGQ==,type:str]
 conduit_secrets: ENC[AES256_GCM,data:q6r4f275/6JKStX51+5qWozz+5L3UF4gTPaj4TOXskjRSn28cLKuoKix4mpKCqamef3SVU8THmPg3kwF5o4Gbm3XpZLieUyPaGCWxnwEaGZ8V5XaBZE=,iv:vsxezaahD0yCBmg0bAHMQfg9AjB52x/At5AowBTFARs=,tag:AXhgVDcTG7q1K91He7CFJA==,type:str]
 mautrix_env: ENC[AES256_GCM,data:Ab1mRgaXSS3VSB2sBo5AT0KaceubrcbAdomUEArmavbsjdWYQLkXbu8/BEALMTgif6c6+4u0iR3dLbRmmobBXGS03mdcR94MQbuWWH6VmHZ5VpydJQOMSl6FBcbOVgGBBp8srUmjVTLsDFobaZCCQJNfK2J3f2wbJqbDMgoUDb5B2LuElAJAuKABxCgl/isCovZpAKwbl65rK1GzZCDc9Z54o3BKLPH6Wa2K4RHnhnYjRl8HZCd/g4WRTVZh6kMIRluWtqdIVHPXAH0oc80=,iv:USZqyHzLt53mkveDxIUq0Tvyw08sUm+MpgsrjWeDiO8=,tag:4Ftfu3ALM77YnftxLkz/YQ==,type:str]
 matrix_bridge: ENC[AES256_GCM,data:w0BEETuDXVlKLlAs4JIQxMs=,iv:6IBAyKHmPJLqQWZFJD0NVT0rSXuGuAiCV2O6c3bP42o=,tag:oiyMCb4wtyqLIBrfvTirQw==,type:str]
@@ -9,6 +10,8 @@ znc_password_salt: ENC[AES256_GCM,data:e7YZkNB32RiqgCPGoehwsfZzOHM=,iv:GrhwBRBZ1
 telegram_token: ENC[AES256_GCM,data:hfstqM3NphVnK86LYp8EYe09kflMzQ1/SO5rm5UIkWN7wdl7mbq+sw3svc4YhQ==,iv:o6TbrGBCly0s3US9041cKmpLpThB/umhBEdZE9E3v54=,tag:WJ/KS4Uc9wtIcjpyfmzLfA==,type:str]
 discord_token: ENC[AES256_GCM,data:1mJ0lKTz2SmaP3PIn3ThWX6Mjbv3tywtLtF65SVkkCEtI79wcPeqK83l6jb3yG+ugntNR7lfQxLgbbURnTil3jc7yVOsYreL,iv:ExZ8xFkH6RR7rHATh8oBEEZWfV5Rt1YVEx8gUicQrV0=,tag:wKJ3P8ie/ppHU9VStQlk0Q==,type:str]
 mail_password: ENC[AES256_GCM,data:W24/1l9YrV+M1enkAgRv2uZuhUIYAjpcRkX7tbc=,iv:F8oLCpthhecllJvGSmHUaFgmBKDg/g3o85CPJ/nCcxU=,tag:bPxcZNXdQ/jkK+saaIKbSw==,type:str]
+mail_monorepo_password: ENC[AES256_GCM,data:jZ1QCB+BAMTEiLVD3FZ0LZBWHP+SSaI8uz5ln4e8be5w7rhJFw==,iv:yJe4mP4PmrJpgdpyjKajZP/F6PXglGY2EsRyIn+a7E0=,tag:LA1PkGXckc8huWI4QH6NdQ==,type:str]
+mail_monorepo_password_pi: ENC[AES256_GCM,data:9hEu6C9K7SidQtsJWoyOPBW3wSn1otg7fuXz2VUFWTPDYOHUjQ==,iv:R3I8bUHweR3UdfZkIHr7nkv8MqSPB8r/FaHA71mpxUg=,tag:aZuteMevsdX8PlZBVoXDjA==,type:str]
 ntfy: ENC[AES256_GCM,data:wKCZ/7GXRWPoVRoXDBD0E0sR6ZRQjSE8USwqHQFOT/QiqIx+aI0awcRuORyGbCE=,iv:aBO9I/528sX6ncnBHMBDVB6mLbc45A7xXiu9p7Kh0Ao=,tag:Xgp3UURxPYcO5DlN53sBVw==,type:str]
 sops:
     age:
@@ -21,7 +24,7 @@ sops:
             dDZONnI0bG5heTYzaDkxeGo3VlFmdm8K377mvFFxtFSURAWeFvLDJTkm8wppKr/B
             Y4qrdU3xBaTwqlsC/7lElQClaUbM+YMF/padENsD6IfyoGN8lGUQQw==
             -----END AGE ENCRYPTED FILE-----
-    lastmodified: "2026-02-12T08:21:04Z"
-    mac: ENC[AES256_GCM,data:537FYu1bJ+0KgbdtKt7kw3Wx4JT2Nb71L36cMZLEFUpwE+pvpe3+iYV/J28TzYVHwByoQ1Q4LYRc/EQqSlT0oaV7yOpfLNS+cb7devATEHhGVrDUThmnF8YvyQFiQsyq/PFNqQ3RLEmSeAsJBWrFB5r8uqRJZKAW/URfFjYqdj0=,iv:tXRflj6rvxewU0QhbsOUSmAHkfWExDZMA6Z8Z65/y0w=,tag:h+y17+ilWPQ4+I/WZIbWAQ==,type:str]
+    lastmodified: "2026-02-15T22:41:35Z"
+    mac: ENC[AES256_GCM,data:H/OmVDNzaOL4QIr+5WOL9hgdoRUcxYQqL9ykGX3CR2xYsrPI17ktkoUR6sxjg2oW9bgvRVU3cU8DryiwGgziFyP6cnA0FlTKGp2CGw3KoKYjDtzgKucT7e0mYOmktirQVaQR604gpbB33/yHLTpbz4vNKkiyxQsv+VCUg9tuDvE=,iv:EJqFMQgrq/w0jIpHg8rj0OKWWf02+unOIeyYPwXTCfw=,tag:b6HouUF7BMSrF4fPBit7PA==,type:str]
     unencrypted_suffix: _unencrypted
     version: 3.11.0
index 7d5939cd0584a5116ff3d897c22fa589afbf2fbc..ad5f096b183244455f928686aa30779c482d9564 100644 (file)
@@ -1,6 +1,7 @@
 { config, sops-nix, ... }:
 {
   home-manager = {
+    backupFileExtension = "backup";
     sharedModules = [
       sops-nix.homeManagerModules.sops
     ];
index 7bdcf74453bcdaac74c0df517056b1e1ad038146..e2df04b32c12a64ffc0ce6ef7ed99f849ab64ec9 100644 (file)
@@ -80,6 +80,7 @@
             7881
             8443
             8448
+            9418
           ];
           allowedUDPPorts = [
             3478 5349 7882
             "ntfy.${config.monorepo.vars.remoteHost}" = {};
             "matrix.${config.monorepo.vars.remoteHost}" = {};
             "www.${config.monorepo.vars.remoteHost}" = {};
+            "music.${config.monorepo.vars.remoteHost}" = {};
             "mail.${config.monorepo.vars.remoteHost}" = {
             };
 
             "${config.monorepo.vars.orgHost}" = {};
             "git.${config.monorepo.vars.orgHost}" = {};
             "matrix.${config.monorepo.vars.orgHost}" = {};
+            "social.${config.monorepo.vars.orgHost}" = {};
+            "list.${config.monorepo.vars.orgHost}" = {};
             "talk.${config.monorepo.vars.orgHost}" = {};
             "mail.${config.monorepo.vars.orgHost}" = {};
             "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {};