1
0
mirror of https://github.com/kmein/niveum synced 2026-03-20 12:01:06 +01:00

9 Commits

Author SHA1 Message Date
2b59d2a68e opencrow: open up 2026-02-17 23:08:26 +01:00
722b1e9d14 add opencrow Matrix bot on ful
Uses upstream NixOS module (systemd-nspawn container with sandboxing).

- User: @fable:4d2.org on matrix.4d2.org
- Provider: GitHub Copilot (OAuth, one-time interactive login)
- pkgs.pi added via extraPackages (available on PATH inside container)
- Secrets via agenix: matrix token as environmentFile,
  soul bind-mounted into the container
- Sessions + pi-agent state in /var/lib/opencrow, backed up via restic

To complete setup:
1. Create secrets/opencrow-matrix-token.age (OPENCROW_MATRIX_ACCESS_TOKEN=...)
2. Create secrets/opencrow-soul.age (SOUL.md content)
3. One-time Copilot login inside the container:
   sudo nixos-container root-login opencrow
   PI_CODING_AGENT_DIR=/var/lib/opencrow/pi-agent pi
   # Run /login, select GitHub Copilot, complete OAuth flow
2026-02-17 22:37:16 +01:00
bfbe2da850 openclaw: soften the hardening 2026-02-17 22:30:38 +01:00
c34647a800 pi llm 2026-02-17 22:30:38 +01:00
e5c86818d9 nextcloud: upgrade 2026-02-17 22:28:09 +01:00
e885753c7f weechat: run in screen 2026-02-17 22:28:09 +01:00
87e39cc30b aerc: use correct cock port 2026-02-17 22:28:09 +01:00
b46f06a462 add opencrow Matrix bot on ful
Uses upstream NixOS module (systemd-nspawn container with sandboxing).

- User: @fable:4d2.org on matrix.4d2.org
- Provider: GitHub Copilot (OAuth, one-time interactive login)
- Secrets via agenix: matrix token as environmentFile,
  soul bind-mounted into the container
- Sessions + pi-agent state in /var/lib/opencrow, backed up via restic

To complete setup:
1. Create secrets/opencrow-matrix-token.age (OPENCROW_MATRIX_ACCESS_TOKEN=...)
2. Create secrets/opencrow-soul.age (SOUL.md content)
3. One-time Copilot login inside the container:
   sudo nixos-container root-login opencrow
   PI_CODING_AGENT_DIR=/var/lib/opencrow/pi-agent pi
   # Run /login, select GitHub Copilot, complete OAuth flow
2026-02-17 22:25:42 +01:00
9041e4cb11 restore secrets.txt
Accidentally emptied by a previous 'git add -A' in a working tree
where the secrets submodule was not initialized.
2026-02-17 21:55:24 +01:00
12 changed files with 229 additions and 11 deletions

View File

@@ -91,7 +91,7 @@
imap.host = mailhost;
imap.port = 993;
smtp.host = mailhost;
smtp.port = 25;
smtp.port = 587;
smtp.tls.useStartTls = true;
};
ical-ephemeris =

View File

@@ -88,7 +88,7 @@ in
{
sxiv = swallow "${pkgs.nsxiv}/bin/nsxiv";
zathura = swallow "${pkgs.zathura}/bin/zathura";
im = "${pkgs.openssh}/bin/ssh weechat@makanek -t tmux attach-session -t IM";
im = "${pkgs.openssh}/bin/ssh weechat@makanek -t screen -x weechat";
yt = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata -ic"; # Download video link
yta = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata --audio-format mp3 --audio-quality 0 -xic"; # Download with audio
};

View File

@@ -129,6 +129,7 @@ in
polyglot
qrpaste
ttspaste
pi # llm agent
new-mac # get a new mac address
scanned
default-gateway

View File

@@ -26,6 +26,7 @@
wetter.url = "github:4z3/wetter";
wrappers.url = "github:lassulus/wrappers";
llm-agents.url = "github:numtide/llm-agents.nix";
opencrow.url = "github:pinpox/opencrow";
voidrice.flake = false;
@@ -62,6 +63,7 @@
wetter.inputs.nixpkgs.follows = "nixpkgs";
niphas.inputs.nixpkgs.follows = "nixpkgs-unstable";
wrappers.inputs.nixpkgs.follows = "nixpkgs";
opencrow.inputs.nixpkgs.follows = "nixpkgs";
};
outputs =
@@ -78,6 +80,7 @@
tinc-graph,
nix-topology,
llm-agents,
opencrow,
nixpkgs-unstable,
nixos-hardware,
niphas,
@@ -290,6 +293,7 @@
menstruation-backend =
menstruation-backend.packages.${prev.stdenv.hostPlatform.system}.menstruation-backend;
telebots = telebots.packages.${prev.stdenv.hostPlatform.system}.telebots;
pi-llm = llm-agents.packages.${prev.stdenv.hostPlatform.system}.pi;
hesychius = scripts.packages.${prev.stdenv.hostPlatform.system}.hesychius;
autorenkalender = autorenkalender.packages.${prev.stdenv.hostPlatform.system}.default;
onomap = scripts.packages.${prev.stdenv.hostPlatform.system}.onomap;
@@ -303,6 +307,7 @@
radio-news = prev.callPackage packages/radio-news { };
untilport = prev.callPackage packages/untilport.nix { };
weechat-declarative = prev.callPackage packages/weechat-declarative.nix { };
pi = prev.callPackage packages/pi.nix { };
# my packages
betacode = prev.callPackage packages/betacode.nix { };
@@ -443,6 +448,7 @@
self.nixosModules.panoptikon
self.nixosModules.go-webring
stockholm.nixosModules.reaktor2
opencrow.nixosModules.default
nur.modules.nixos.default
{
nixpkgs.overlays = [
@@ -618,6 +624,7 @@
obsidian-vim
opustags
pdf-ocr
pi
picoclaw
pls
polyglot

69
packages/pi.nix Normal file
View File

@@ -0,0 +1,69 @@
{
runCommand,
nodejs,
writeShellApplication,
lib,
jq,
cacert,
pi-llm,
}:
let
# Pre-install pi plugins into a fake npm global prefix
pluginPrefixRaw =
runCommand "pi-plugins-raw"
{
nativeBuildInputs = [
nodejs
cacert
];
outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = "sha256-hfYl0Slxg3nuN6KTtvpWW0QUxtg3JRE0n9N7rIXBTOc=";
impureEnvVars = [
"http_proxy"
"https_proxy"
];
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
}
''
export HOME=$TMPDIR
export npm_config_prefix=$out
npm install -g pi-hooks shitty-extensions
'';
# Remove the resistance extension (annoying terminator quote widget)
pluginPrefix = runCommand "pi-plugins" { } ''
cp -a ${pluginPrefixRaw} $out
chmod -R u+w $out
pkg=$out/lib/node_modules/shitty-extensions/package.json
${lib.getExe jq} '.pi.extensions |= map(select(contains("resistance") | not))' "$pkg" > "$pkg.tmp"
mv "$pkg.tmp" "$pkg"
'';
in
writeShellApplication {
name = "pi";
runtimeInputs = [ nodejs ];
text = ''
set -efu
export npm_config_prefix="${pluginPrefix}"
# Ensure settings.json has our plugins listed
SETTINGS_DIR="''${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}"
SETTINGS_FILE="$SETTINGS_DIR/settings.json"
mkdir -p "$SETTINGS_DIR"
# Add packages to settings if not already present
if [ ! -f "$SETTINGS_FILE" ]; then
echo '{"packages":["npm:pi-hooks","npm:shitty-extensions"]}' > "$SETTINGS_FILE"
else
for pkg in "npm:pi-hooks" "npm:shitty-extensions"; do
if ! grep -q "$pkg" "$SETTINGS_FILE"; then
${lib.getExe jq} --arg p "$pkg" '.packages = ((.packages // []) + [$p] | unique)' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
fi
done
fi
exec ${lib.getExe pi-llm} "$@"
'';
}

Submodule secrets updated: 55417d0835...2309c34eb6

View File

@@ -0,0 +1,89 @@
secrets/alertmanager-token-reporters.age
secrets/brevo-key.age
secrets/cifs-credentials-zodiac.age
secrets/copecart-ipn.age
secrets/di-fm-key.age
secrets/email-password-cock.age
secrets/email-password-fysi.age
secrets/email-password-ical-ephemeris.age
secrets/email-password-letos.age
secrets/email-password-meinhak99.age
secrets/email-password-posteo.age
secrets/fatteh-retiolum-privateKey-ed25519.age
secrets/fatteh-retiolum-privateKey-rsa.age
secrets/fatteh-syncthing-cert.age
secrets/fatteh-syncthing-key.age
secrets/fatteh-wireguard-aether-key.age
secrets/fatteh-wireguard-aether-psk.age
secrets/ful-retiolum-privateKey-ed25519.age
secrets/ful-retiolum-privateKey-rsa.age
secrets/ful-root.age
secrets/fu-sftp-key.age
secrets/gemini-api-key.age
secrets/github-token-i3status-rust.age
secrets/grafana-password-admin.age
secrets/hetzner-storagebox-credentials.age
secrets/home-assistant-token.age
secrets/kabsa-retiolum-privateKey-ed25519.age
secrets/kabsa-retiolum-privateKey-rsa.age
secrets/kabsa-syncthing-cert.age
secrets/kabsa-syncthing-key.age
secrets/kabsa-wireguard-aether-key.age
secrets/kabsa-wireguard-aether-psk.age
secrets/kfm-password.age
secrets/kibbeh-retiolum-privateKey-ed25519.age
secrets/kibbeh-retiolum-privateKey-rsa.age
secrets/kibbeh-syncthing-cert.age
secrets/kibbeh-syncthing-key.age
secrets/ledger-basicAuth.age
secrets/makanek-retiolum-privateKey-ed25519.age
secrets/makanek-retiolum-privateKey-rsa.age
secrets/manakish-retiolum-privateKey-ed25519.age
secrets/manakish-retiolum-privateKey-rsa.age
secrets/manakish-syncthing-cert.age
secrets/manakish-syncthing-key.age
secrets/manakish-wireguard-aether-key.age
secrets/manakish-wireguard-aether-psk.age
secrets/mastodon-token-celan.age
secrets/mastodon-token-hesychius.age
secrets/mastodon-token-nietzsche.age
secrets/mastodon-token-smyth.age
secrets/mastodon-token-tlgwotd.age
secrets/mastodon-token-transits.age
secrets/matrix-token-lakai.age
secrets/matrix-token-lakai-env.age
secrets/maxmind-license-key.age
secrets/mega-password.age
secrets/miniflux-api-token.age
secrets/miniflux-credentials.age
secrets/nextcloud-password-admin.age
secrets/nextcloud-password-database.age
secrets/nextcloud-password-fysi.age
secrets/nextcloud-password-kieran.age
secrets/onlyoffice-jwt-key.age
secrets/opencrow-matrix-token.age
secrets/opencrow-soul.age
secrets/openweathermap-api-key.age
secrets/restic.age
secrets/secrets.nix
secrets/spotify-password.age
secrets/spotify-username.age
secrets/stw-berlin-card-code.age
secrets/tabula-retiolum-privateKey-ed25519.age
secrets/tabula-retiolum-privateKey-rsa.age
secrets/tahina-retiolum-privateKey-ed25519.age
secrets/tahina-retiolum-privateKey-rsa.age
secrets/telegram-token-betacode.age
secrets/telegram-token-kmein.age
secrets/telegram-token-menstruation.age
secrets/telegram-token-nachtischsatan.age
secrets/telegram-token-proverb.age
secrets/telegram-token-reverse.age
secrets/telegram-token-streaming-link.age
secrets/weechat-sec.conf.age
secrets/wifi.age
secrets/zaatar-moodle-dl-basicAuth.age
secrets/zaatar-moodle-dl-tokens.json.age
secrets/zaatar-retiolum-privateKey-ed25519.age
secrets/zaatar-retiolum-privateKey-rsa.age
secrets/zaatar-ympd-basicAuth.age

View File

@@ -17,6 +17,7 @@
./wallabag.nix
./nethack.nix
./openclaw.nix
./opencrow.nix
];
niveum.passport = {

View File

@@ -43,11 +43,11 @@
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RemoveIPC = true;
AmbientCapabilities = ["CAP_NET_RAW"]; # access chromium websockets
RestrictSUIDSGID = true;
RestrictNamespaces = true;
RestrictNamespaces = false; # might be used by websocket library
RestrictRealtime = true;
LockPersonality = true;
UMask = "0077";

48
systems/ful/opencrow.nix Normal file
View File

@@ -0,0 +1,48 @@
{
config,
pkgs,
...
}:
{
age.secrets = {
opencrow-matrix-token = {
file = ../../secrets/opencrow-matrix-token.age;
};
opencrow-soul = {
file = ../../secrets/opencrow-soul.age;
};
};
services.opencrow = {
enable = true;
extraPackages = [ pkgs.pi pkgs.nix ];
environmentFiles = [
config.age.secrets.opencrow-matrix-token.path
];
extraBindMounts."/run/secrets/opencrow-soul" = {
hostPath = config.age.secrets.opencrow-soul.path;
isReadOnly = true;
};
extraBindMounts."/nix/var/nix/daemon-socket" = {
hostPath = "/nix/var/nix/daemon-socket";
isReadOnly = false;
};
environment = {
PI_PERMISSION_LEVEL= "high";
OPENCROW_MATRIX_HOMESERVER = "https://matrix.4d2.org";
OPENCROW_MATRIX_USER_ID = "@fable:4d2.org";
OPENCROW_PI_PROVIDER = "github-copilot";
OPENCROW_PI_MODEL = "gemini-3-flash-preview";
OPENCROW_SOUL_FILE = "/run/secrets/opencrow-soul";
};
};
services.restic.backups.niveum.paths = [
"/var/lib/opencrow"
];
}

View File

@@ -55,7 +55,7 @@ in
services.nextcloud = {
enable = true;
package = pkgs.nextcloud31;
package = pkgs.nextcloud32;
https = true;

View File

@@ -187,16 +187,19 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
restartIfChanged = true;
path = [ pkgs.alacritty.terminfo ];
environment.WEECHAT_HOME = weechatHome;
path = [ pkgs.alacritty.terminfo pkgs.screen ];
environment = {
WEECHAT_HOME = weechatHome;
};
# preStart = "${pkgs.coreutils}/bin/rm $WEECHAT_HOME/*.conf";
script = "${tmux} -2 new-session -d -s IM ${weechat}/bin/weechat";
preStop = "${tmux} kill-session -t IM";
script = "${pkgs.screen}/bin/screen -S weechat -d -m ${weechat}/bin/weechat";
preStop = "${pkgs.screen}/bin/screen -S weechat -X quit";
serviceConfig = {
User = "weechat";
Group = "weechat";
RemainAfterExit = true;
Type = "oneshot";
RuntimeDirectory = "weechat-tmux";
};
};
@@ -210,7 +213,7 @@ in
group = "weechat";
home = "/var/lib/weechat";
isSystemUser = true;
packages = [ pkgs.tmux ];
packages = [ pkgs.screen ];
};
age.secrets.weechat-sec = {