turny: fix SPI/GPIO config for newer kernels
- Add complete config.txt settings with u-boot boot lines + spi=on - Override sdImage.populateFirmwareCommands to use configtxt module output - Mount firmware partition and add activation script to sync config.txt - Load spi_bcm2835 and bcm2835_gpiomem kernel modules - Add udev rule for gpiomem subsystem (not just gpio) - Relax ProtectKernelTunables so service can access GPIO - Update turny flake input to rppal-based CS pin fix
This commit is contained in:
@@ -2,3 +2,4 @@
|
||||
/.direnv
|
||||
/.gcroots
|
||||
*.qcow2
|
||||
hosts/turny/ssh_host_ed25519_key
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- `nix build .#nixosConfigurations.<host>.config.system.build.toplevel` - Build specific host
|
||||
|
||||
## Code Style
|
||||
- **Format**: Use `nixfmt-rfc-style` for all .nix files
|
||||
- **Format**: Use `nixfmt` for all .nix files
|
||||
- **Imports**: List imports first, group by: local modules, external inputs (inputs.*)
|
||||
- **Function args**: Multi-line with trailing comma when >3 args: `{ config, lib, pkgs, ... }:`
|
||||
- **Options**: Define in `options.<service>` block, implement in `config = lib.mkIf cfg.enable { ... }`
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
util,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
util.package { inherit lib; }
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
}:
|
||||
let
|
||||
version = "4.9.9";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "kreuzberg-dev";
|
||||
repo = "kreuzberg";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-eu0qjyxoRiDLHsBLPPPAqb/DKVaPzqgP/4hHPjgOBoM=";
|
||||
};
|
||||
in
|
||||
pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "kreuzberg-cli";
|
||||
inherit version src;
|
||||
|
||||
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
|
||||
inherit src;
|
||||
hash = "sha256-j1tmjQ7KQQAMz3QxhQGTGracMqqdcaX/+74lpUfU/kE=";
|
||||
};
|
||||
|
||||
buildFeatures = [ "all" ];
|
||||
doCheck = false;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.makeWrapper
|
||||
pkgs.pkg-config
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
pkgs.pdfium-binaries
|
||||
pkgs.openssl
|
||||
pkgs.onnxruntime
|
||||
pkgs.tesseract
|
||||
pkgs.leptonica
|
||||
];
|
||||
|
||||
dontUseCmakeConfigure = true;
|
||||
|
||||
env = {
|
||||
KREUZBERG_PDFIUM_PREBUILT = pkgs.pdfium-binaries;
|
||||
ORT_LIB_PATH = "${pkgs.onnxruntime}/lib";
|
||||
ORT_PREFER_DYNAMIC_LINK = "1";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace crates/kreuzberg/Cargo.toml \
|
||||
--replace 'kreuzberg-tesseract = { path = "../kreuzberg-tesseract", version = "4.9.9", optional = true }' \
|
||||
'kreuzberg-tesseract = { path = "../kreuzberg-tesseract", version = "4.9.9", optional = true, default-features = false, features = ["dynamic-linking"] }'
|
||||
|
||||
for f in crates/kreuzberg-tesseract/src/*.rs; do
|
||||
substituteInPlace "$f" \
|
||||
--replace 'any(feature = "build-tesseract", feature = "build-tesseract-wasm")' \
|
||||
'any(feature = "build-tesseract", feature = "build-tesseract-wasm", feature = "dynamic-linking")'
|
||||
done
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
wrapProgram $out/bin/kreuzberg \
|
||||
--prefix LD_LIBRARY_PATH : ${
|
||||
lib.makeLibraryPath [
|
||||
pkgs.tesseract
|
||||
pkgs.onnxruntime
|
||||
]
|
||||
} \
|
||||
--set TESSDATA_PREFIX ${pkgs.tesseract}/share
|
||||
ln -s kreuzberg $out/bin/kreuzberg-cli
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "High-performance document intelligence CLI with a Rust core";
|
||||
homepage = "https://github.com/kreuzberg-dev/kreuzberg";
|
||||
license = lib.licenses.unfree;
|
||||
platforms = [ "x86_64-linux" ];
|
||||
mainProgram = "kreuzberg";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
util,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
util.package { inherit lib; }
|
||||
@@ -0,0 +1,160 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
}:
|
||||
let
|
||||
stylesheet = pkgs.writeText "md2pdf-style.css" ''
|
||||
body {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
font-size: 11px;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
border-bottom: 2px solid #333;
|
||||
padding-bottom: 5px;
|
||||
break-after: avoid;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
margin-top: 25px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-bottom: 3px;
|
||||
break-after: avoid;
|
||||
}
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
margin-top: 15px;
|
||||
break-after: avoid;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
font-size: 10px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
th {
|
||||
background: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
padding: 4px 6px;
|
||||
text-align: left;
|
||||
break-after: avoid;
|
||||
break-inside: avoid;
|
||||
}
|
||||
td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 4px 6px;
|
||||
vertical-align: top;
|
||||
break-inside: avoid;
|
||||
}
|
||||
tr {
|
||||
break-inside: avoid;
|
||||
break-after: auto;
|
||||
}
|
||||
code {
|
||||
background: #f5f5f5;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
font-family: "Noto Sans Mono", monospace;
|
||||
font-size: 10px;
|
||||
}
|
||||
pre {
|
||||
background: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
font-size: 10px;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
blockquote {
|
||||
border-left: 3px solid #ccc;
|
||||
margin-left: 0;
|
||||
padding-left: 10px;
|
||||
color: #555;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 1px solid #ddd;
|
||||
margin: 5px 0;
|
||||
break-inside: avoid;
|
||||
}
|
||||
em {
|
||||
color: #666;
|
||||
}
|
||||
a {
|
||||
color: #0066cc;
|
||||
}
|
||||
'';
|
||||
|
||||
md-to-pdf = pkgs.buildNpmPackage {
|
||||
pname = "md-to-pdf";
|
||||
version = "5.2.5";
|
||||
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "simonhaenisch";
|
||||
repo = "md-to-pdf";
|
||||
rev = "v5.2.5";
|
||||
hash = "sha256-6Zr4jidQ6cX2t6jKFqEnCSqvRtw4gZkqDKdv9SIyDC4=";
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-AGn8g/nbkvWi4o6ENCnt7VexjfBIoDz+tl9eYvy+bao=";
|
||||
|
||||
# canvas is an optional native dependency that fails to build in nix;
|
||||
# md-to-pdf works fine without it (puppeteer is used for PDF generation)
|
||||
npmFlags = [ "--ignore-scripts" ];
|
||||
|
||||
postInstall = ''
|
||||
rm -rf $out/lib/node_modules/md-to-pdf/node_modules/canvas
|
||||
'';
|
||||
};
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "md2pdf";
|
||||
version = "1.0.0";
|
||||
|
||||
src = ./.;
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
nativeBuildInputs = [ ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/bin $out/share/md2pdf
|
||||
|
||||
cp ${stylesheet} $out/share/md2pdf/style.css
|
||||
|
||||
cat > $out/bin/md2pdf << 'WRAPPER'
|
||||
#!/bin/sh
|
||||
export PUPPETEER_EXECUTABLE_PATH="@chromium@/bin/chromium"
|
||||
export PATH="@chromium@/bin''${PATH:+:''${PATH}}"
|
||||
exec "@md-to-pdf@/bin/md-to-pdf" \
|
||||
--stylesheet "@stylesheet@" \
|
||||
--pdf-options '{"format":"A4","margin":{"top":"10mm","bottom":"10mm","left":"12mm","right":"12mm"},"printBackground":true}' \
|
||||
"$@"
|
||||
WRAPPER
|
||||
|
||||
substituteInPlace $out/bin/md2pdf \
|
||||
--replace-fail "@chromium@" "${pkgs.chromium}" \
|
||||
--replace-fail "@md-to-pdf@" "${md-to-pdf}" \
|
||||
--replace-fail "@stylesheet@" "$out/share/md2pdf/style.css"
|
||||
|
||||
chmod +x $out/bin/md2pdf
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Convert Markdown to PDF with Noto Sans styling and tight margins";
|
||||
mainProgram = "md2pdf";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
||||
Generated
+90
-176
@@ -92,11 +92,11 @@
|
||||
"stable": "stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1762034856,
|
||||
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
|
||||
"lastModified": 1781446832,
|
||||
"narHash": "sha256-/6+NHQstxRqkbNjtNcQgCojzu59SEbdwwpWqBw7Fm9s=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
|
||||
"rev": "938cb5cdd9b25d9774b6168e5f03d0afd04d321f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -107,11 +107,11 @@
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1779130139,
|
||||
"narHash": "sha256-BLrtr42azquO7MdGFU5a7KiMl3YpFlTeIXqy1fT5GlQ=",
|
||||
"lastModified": 1781825982,
|
||||
"narHash": "sha256-SlXKwIRIhrOSAcTjCB3ftPLzJWZStQIPS7J1FlZPnKk=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "edb38893982a3338972bb4a2ec7ce7c29ba10fd9",
|
||||
"rev": "469fd08d0bcf6926321fa973c6777fbc87785dd7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -336,25 +336,7 @@
|
||||
},
|
||||
"flake-utils_5": {
|
||||
"inputs": {
|
||||
"systems": "systems_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_6": {
|
||||
"inputs": {
|
||||
"systems": "systems_8"
|
||||
"systems": "systems_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
@@ -544,11 +526,11 @@
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779865172,
|
||||
"narHash": "sha256-QZuox/4ww6vOmUu9lCpKlQbU3MER1kmgnJmXP1LO1K0=",
|
||||
"lastModified": 1782160136,
|
||||
"narHash": "sha256-APwmLI4UuSTim0JO/kZ6FXDPiZVp3zIj0uGDF2UZ5kU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lanzaboote",
|
||||
"rev": "f42b84f9fb03db98dee2073e932010f3a76eeb9a",
|
||||
"rev": "6650fb7c6b48177c8200e21ffac99a4adc72b08d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -569,11 +551,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1780050433,
|
||||
"narHash": "sha256-90mQY7VUvn6WoNh+m4LSqS+XTcofWOBLgYYmSJVyr98=",
|
||||
"lastModified": 1782366663,
|
||||
"narHash": "sha256-hcxEl/eWQQaYkUqygP4ca8S7WlX9c6vqgvQCqtV3vuw=",
|
||||
"owner": "numtide",
|
||||
"repo": "llm-agents.nix",
|
||||
"rev": "0fb42103f93cd5c1152254856d7eccb3e91c8bf6",
|
||||
"rev": "5f9d86061f538b3f5f3568583c001fb9c0705b71",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -585,11 +567,11 @@
|
||||
"models-dev": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1780068026,
|
||||
"narHash": "sha256-OkMHzM1//oPQFbQTyi3a09HdTZyLstR+Lamhoje+tpU=",
|
||||
"lastModified": 1782405514,
|
||||
"narHash": "sha256-E25yt4q3YruuxZSepv2hXdNX4FyGk60LnbxlcthJL18=",
|
||||
"owner": "anomalyco",
|
||||
"repo": "models.dev",
|
||||
"rev": "277ac8577eb6d5543fc65193974228dcb0d021ef",
|
||||
"rev": "7ceac334bbacc5ece7fbaea510ac5d7b850cfdf0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -610,11 +592,11 @@
|
||||
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1780062130,
|
||||
"narHash": "sha256-3XF+oy0PX4aajJw2RNB8rlMpyu0eXCG4pGH7fe94yBg=",
|
||||
"lastModified": 1782333733,
|
||||
"narHash": "sha256-QYrNYMNPKErRgNlxWwk0cjNKftnq6WzSs84pcZnUskM=",
|
||||
"owner": "sodiboo",
|
||||
"repo": "niri-flake",
|
||||
"rev": "3cb351d73c357a4e413f59c4551d219118791c14",
|
||||
"rev": "a6351044a3d69877d1c23be54971d18f8531c930",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -643,11 +625,11 @@
|
||||
"niri-unstable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1780056110,
|
||||
"narHash": "sha256-t7lKVshV/srD0G06j4r5P5qj9zaDeZ9JYFCxHDGROZU=",
|
||||
"lastModified": 1781781064,
|
||||
"narHash": "sha256-Ii/koEm/sRyg65qbAQWqEgboSEIhdH0EL4KglAc14p0=",
|
||||
"owner": "YaLTeR",
|
||||
"repo": "niri",
|
||||
"rev": "f9f43d826ab4014a7c302be28d7da33e12f5be37",
|
||||
"rev": "49fc6117fd6c043adaa2ead316b82db5ed735d36",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -700,11 +682,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1780065812,
|
||||
"narHash": "sha256-SCSLUKBmwlSLGQ8Xbr8PjRFtiHNk0l9ktqkcmqdBkfE=",
|
||||
"lastModified": 1782379505,
|
||||
"narHash": "sha256-zPvPiU+a7pqtH47xrtZLNRABJKpOjfZQclDbcvNtH+I=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "b76b5639c0593e0aeb0b5879ad62d4b30596c144",
|
||||
"rev": "603d3afd1b6145bd66e97ae38a34d91c95df70cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -730,6 +712,22 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-25_11": {
|
||||
"locked": {
|
||||
"lastModified": 1782847189,
|
||||
"narHash": "sha256-twXPFqFsrrY5r28Zh7Homgcp2gUMBgQ6WDS98Q/3xFI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b6018f87da91d19d0ab4cf979885689b469cdd41",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1777168982,
|
||||
@@ -771,11 +769,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1779796641,
|
||||
"narHash": "sha256-ZsIrKmhp4vbBXoXXmR/tBXA/UCsAQiJL9vsgZEduhVY=",
|
||||
"lastModified": 1782188297,
|
||||
"narHash": "sha256-imdcA5fgbHK259bhHlyiiSr7bMY1AZ6onOWDdAcydc4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "25f538306313eae3927264466c70d7001dcea1df",
|
||||
"rev": "9a1a7dbb18f0eb31c49b031babb8def7eab0af54",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -787,11 +785,11 @@
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1779560665,
|
||||
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
|
||||
"lastModified": 1781577229,
|
||||
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
|
||||
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -819,61 +817,48 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1779796641,
|
||||
"narHash": "sha256-ZsIrKmhp4vbBXoXXmR/tBXA/UCsAQiJL9vsgZEduhVY=",
|
||||
"lastModified": 1782233679,
|
||||
"narHash": "sha256-QyuGP5+QOtmXpy4i2X4DhBVBaySBdDKQEhqKcphcp34=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "25f538306313eae3927264466c70d7001dcea1df",
|
||||
"rev": "667d5cf1c59585031d743c78b394b0a647537c35",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"ref": "nixos-26.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1781577229,
|
||||
"narHash": "sha256-rcUHdUtJEvMdNEl2Wq+YpHraHKfcer3KsBscpZEF2Yg=",
|
||||
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
|
||||
"type": "tarball",
|
||||
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1017464.567a49d1913c/nixexprs.tar.xz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
|
||||
}
|
||||
},
|
||||
"noctalia": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
],
|
||||
"noctalia-qs": "noctalia-qs"
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779763713,
|
||||
"narHash": "sha256-as2Vo4PitnWfXezfkQB2H3Rsr/DXJPp4Oe+dE+dZ0Xo=",
|
||||
"lastModified": 1782405004,
|
||||
"narHash": "sha256-7uAqPz5SmLBoIETAvZPeHu1e22suVEEcNWIZKoen2/8=",
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia-shell",
|
||||
"rev": "272cd91408b5ff6e329e6397eed042fe422069e7",
|
||||
"repo": "noctalia",
|
||||
"rev": "6779a947a14738bf81c0d66ee083acff105f66a2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia-shell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"noctalia-qs": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"noctalia",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems_6",
|
||||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779588472,
|
||||
"narHash": "sha256-CVonDVo41DqdqS/kNeXFatwEuTltyXcppm9zkVOnrsM=",
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia-qs",
|
||||
"rev": "70fea8a39a908e395de63024a4dfdb829bff1ffe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia-qs",
|
||||
"repo": "noctalia",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
@@ -906,11 +891,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778507602,
|
||||
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
|
||||
"lastModified": 1781733627,
|
||||
"narHash": "sha256-U3yTuGBnmXvXoQI3qkpfEDsn9RovQPAjN7ndRco+3u0=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
|
||||
"rev": "3bbec39bc90eadfa031e6f3b77272f3f60803e39",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -937,10 +922,10 @@
|
||||
"nix-flatpak": "nix-flatpak",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs-25_11": "nixpkgs-25_11",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"noctalia": "noctalia",
|
||||
"syntax-renderer": "syntax-renderer",
|
||||
"tonearm": "tonearm",
|
||||
"tree_hugger": "tree_hugger",
|
||||
"turny": "turny",
|
||||
"voidauth": "voidauth",
|
||||
@@ -956,11 +941,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1779592685,
|
||||
"narHash": "sha256-p9d56GezhHRf4QfANxwa1d+fvwShvjB5XUhdIl7WEd0=",
|
||||
"lastModified": 1782012058,
|
||||
"narHash": "sha256-9mWUnReOUXfKjZuJAL/bAFH3LUyECTRtXgSNVjRw3UY=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "3a58b199e7c83a80b85c28044f808085ba7e941c",
|
||||
"rev": "8534567325bd8a8d2928e6afd81e0a87d19efd3c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1077,21 +1062,6 @@
|
||||
}
|
||||
},
|
||||
"systems_6": {
|
||||
"locked": {
|
||||
"lastModified": 1689347949,
|
||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_7": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
@@ -1106,40 +1076,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_8": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tonearm": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_5",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769118914,
|
||||
"narHash": "sha256-ASM7MVDWxT+BBtcAJ1z8XNjyNdL5E1Kc0miCWIepf+o=",
|
||||
"rev": "68ea2190d1b37f9030b7586d2030f9dc48915a85",
|
||||
"type": "tarball",
|
||||
"url": "https://codeberg.org/api/v1/repos/dergs/Tonearm/archive/68ea2190d1b37f9030b7586d2030f9dc48915a85.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://codeberg.org/dergs/Tonearm/archive/v1.0.0.tar.gz"
|
||||
}
|
||||
},
|
||||
"tree_hugger": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@@ -1168,33 +1104,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775636079,
|
||||
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
|
||||
"lastModified": 1780220602,
|
||||
"narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"noctalia",
|
||||
"noctalia-qs",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1775636079,
|
||||
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
|
||||
"rev": "db947814a175b7ca6ded66e21383d938df01c227",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1213,11 +1127,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1752874301,
|
||||
"narHash": "sha256-A6IZz46Lfopm5UhMtFfBDimepEUt9lGwhWoEIEQHsgk=",
|
||||
"lastModified": 1783206624,
|
||||
"narHash": "sha256-7CJbANk1mhnMIJmxIpWaHdnH3ao7huH4XyTP0YO+6dU=",
|
||||
"owner": "~repomaa",
|
||||
"repo": "turny",
|
||||
"rev": "133c05151e77616c7973c1c1038506b2fdee8eab",
|
||||
"rev": "a50c0e7f45ffc40e63e75ce52d9943e97e904102",
|
||||
"type": "sourcehut"
|
||||
},
|
||||
"original": {
|
||||
@@ -1252,17 +1166,17 @@
|
||||
},
|
||||
"voxtype": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_6",
|
||||
"flake-utils": "flake-utils_5",
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1780001111,
|
||||
"narHash": "sha256-zsOG1mBTXN4gdsTb1pUPKXATfhV5ZjgEsIUk07asaGo=",
|
||||
"lastModified": 1782311621,
|
||||
"narHash": "sha256-K8mog5N+Qv01VyM5n74sOeXCn+2OYgrSZnVDAKQ33zc=",
|
||||
"owner": "peteonrails",
|
||||
"repo": "voxtype",
|
||||
"rev": "56b04aa142150f1d503e62f3c6125df38a42840f",
|
||||
"rev": "31b7f38c4e22c4ce75d6350945729e5db001cb9a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1311,11 +1225,11 @@
|
||||
"xwayland-satellite-unstable": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1779745227,
|
||||
"narHash": "sha256-yqY7RtEJGJiENzR0GwL6q69tSAy6xAAmAcLuIhLjPf8=",
|
||||
"lastModified": 1781226823,
|
||||
"narHash": "sha256-28696iIw8uE0ZUyFTtzhEM8xMh85clCYypMxkvUi+sc=",
|
||||
"owner": "Supreeeme",
|
||||
"repo": "xwayland-satellite",
|
||||
"rev": "5d1efbc9dc3ab1c10160b656e0247f3325daf0f2",
|
||||
"rev": "8575d0ef55d70f9b4c46b6bffb3accf912217e1e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
inputs = {
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
||||
nixpkgs-25_11.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
gtrackmap = {
|
||||
url = "github:gtrackmap/gtrackmap";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@@ -53,10 +54,6 @@
|
||||
inputs.flake-parts.follows = "flake-parts";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
tonearm = {
|
||||
url = "https://codeberg.org/dergs/Tonearm/archive/v1.0.0.tar.gz";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
voidauth = {
|
||||
url = "github:repomaa/voidauth/feat/nix-packaging";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
@@ -74,10 +71,7 @@
|
||||
url = "github:anomalyco/models.dev";
|
||||
flake = false;
|
||||
};
|
||||
noctalia = {
|
||||
url = "github:noctalia-dev/noctalia-shell";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
noctalia.url = "github:noctalia-dev/noctalia";
|
||||
niri-flake = {
|
||||
url = "github:sodiboo/niri-flake";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
@@ -121,7 +115,6 @@
|
||||
packages = with pkgs; [
|
||||
agenix.packages.${system}.default
|
||||
colmena.packages.${system}.colmena
|
||||
colmena.packages.${system}.manual
|
||||
(writeShellScriptBin "build" ''
|
||||
colmena build --keep-result "$@"
|
||||
'')
|
||||
@@ -131,6 +124,49 @@
|
||||
(writeShellScriptBin "apply-local" ''
|
||||
nh os switch .
|
||||
'')
|
||||
(writeShellScriptBin "build-sd" ''
|
||||
set -euo pipefail
|
||||
|
||||
echo "Building SD image for turny..."
|
||||
nix build .#images.turny --system aarch64-linux --print-build-logs
|
||||
|
||||
STORE_IMG=$(readlink -f result/sd-image/*.img)
|
||||
if [ -z "$STORE_IMG" ]; then
|
||||
echo "Error: No .img file found in result/sd-image/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KEY_DIR="$(git rev-parse --show-toplevel)/hosts/turny"
|
||||
if [ ! -f "$KEY_DIR/ssh_host_ed25519_key" ]; then
|
||||
echo "Error: SSH host key not found at $KEY_DIR/ssh_host_ed25519_key"
|
||||
echo "Generate it with: ssh-keygen -t ed25519 -f hosts/turny/ssh_host_ed25519_key -N \"\" -C turny"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMG="/tmp/turny-sd-image.img"
|
||||
echo "Copying image to writable location: $IMG"
|
||||
cp "$STORE_IMG" "$IMG"
|
||||
|
||||
echo "Injecting SSH host key into image..."
|
||||
LOOP=$(sudo losetup --show -P -f "$IMG")
|
||||
MNT=$(sudo mktemp -d)
|
||||
cleanup() {
|
||||
sudo umount "$MNT" 2>/dev/null || true
|
||||
sudo rmdir "$MNT" 2>/dev/null || true
|
||||
sudo losetup -d "$LOOP" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
sudo mount "''${LOOP}p2" "$MNT"
|
||||
sudo mkdir -p "$MNT/etc/ssh"
|
||||
sudo cp "$KEY_DIR/ssh_host_ed25519_key" "$MNT/etc/ssh/ssh_host_ed25519_key"
|
||||
sudo cp "$KEY_DIR/ssh_host_ed25519_key.pub" "$MNT/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
sudo chmod 600 "$MNT/etc/ssh/ssh_host_ed25519_key"
|
||||
sudo chmod 644 "$MNT/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
|
||||
echo "Done! Image ready at: $IMG"
|
||||
echo "Flash with: sudo dd if=$IMG of=/dev/sdX bs=4M conv=fsync status=progress"
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
@@ -241,4 +277,10 @@
|
||||
};
|
||||
}
|
||||
);
|
||||
nixConfig = {
|
||||
extra-substituters = [ "https://noctalia.cachix.org" ];
|
||||
extra-trusted-public-keys = [
|
||||
"noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
+83
-123
@@ -8,16 +8,13 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
noctalia-package = inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||
calendarSupport = true;
|
||||
};
|
||||
noctalia-package = inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
ns = lib.getExe noctalia-package;
|
||||
ns-ipc =
|
||||
args:
|
||||
[
|
||||
ns
|
||||
"ipc"
|
||||
"call"
|
||||
"msg"
|
||||
]
|
||||
++ args;
|
||||
in
|
||||
@@ -72,7 +69,7 @@ in
|
||||
gnumeric
|
||||
gh
|
||||
neovim-remote
|
||||
pkgs-unstable.gradia
|
||||
gradia
|
||||
crystal
|
||||
shards
|
||||
moreutils
|
||||
@@ -98,7 +95,7 @@ in
|
||||
protonmail-bridge
|
||||
hydroxide
|
||||
imapsync
|
||||
nixfmt-rfc-style
|
||||
nixfmt
|
||||
tree
|
||||
virt-manager
|
||||
pkgs-unstable.ncspot
|
||||
@@ -137,128 +134,91 @@ in
|
||||
'')
|
||||
inputs.tree_hugger.packages.${stdenv.hostPlatform.system}.default
|
||||
(writeShellScriptBin "ns" "${lib.join " " (ns-ipc [ ''"$@"'' ])}")
|
||||
libnotify
|
||||
supersonic-wayland
|
||||
]
|
||||
++ (with inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}; [
|
||||
pi
|
||||
opencode
|
||||
crush
|
||||
opencode
|
||||
]);
|
||||
|
||||
programs = {
|
||||
noctalia-shell = {
|
||||
noctalia = {
|
||||
enable = true;
|
||||
settings = {
|
||||
bar = {
|
||||
density = "compact";
|
||||
bar.main = {
|
||||
position = "top";
|
||||
showCapsule = false;
|
||||
widgets = {
|
||||
left = [
|
||||
{
|
||||
id = "Workspace";
|
||||
hideUnoccupied = true;
|
||||
labelMode = "none";
|
||||
}
|
||||
];
|
||||
center = [
|
||||
{
|
||||
id = "Clock";
|
||||
formatHorizontal = "HH:mm";
|
||||
formatVertical = "HH mm";
|
||||
usePrimaryColor = true;
|
||||
}
|
||||
];
|
||||
right = [
|
||||
{
|
||||
id = "plugin:privacy-indicator";
|
||||
}
|
||||
{
|
||||
id = "Battery";
|
||||
warningThreshold = 20;
|
||||
}
|
||||
{
|
||||
id = "NotificationHistory";
|
||||
}
|
||||
{
|
||||
id = "Network";
|
||||
}
|
||||
{
|
||||
id = "Bluetooth";
|
||||
}
|
||||
{
|
||||
id = "VPN";
|
||||
}
|
||||
{
|
||||
id = "ControlCenter";
|
||||
useDistroLogo = true;
|
||||
}
|
||||
];
|
||||
auto_hide = true;
|
||||
reserve_space = false;
|
||||
margin_edge = 5;
|
||||
capsule = false;
|
||||
start = [ "workspaces" ];
|
||||
center = [ "clock" ];
|
||||
end = [
|
||||
"battery"
|
||||
"notifications"
|
||||
"network"
|
||||
"bluetooth"
|
||||
"control-center"
|
||||
];
|
||||
};
|
||||
widget = {
|
||||
workspaces = {
|
||||
labels_only_when_occupied = true;
|
||||
display = "none";
|
||||
};
|
||||
clock = {
|
||||
format = "{:%H:%M}";
|
||||
vertical_format = "{:%H\n%M}";
|
||||
tooltip_format = "{:%A, %d. %B %Y}";
|
||||
};
|
||||
battery.warning_threshold = 20;
|
||||
control-center.glyph = "snowflake";
|
||||
};
|
||||
|
||||
audio.visualizerType = "linear";
|
||||
|
||||
wallpaper = {
|
||||
overviewEnabled = true;
|
||||
directory = "~/Pictures/Wallpapers";
|
||||
automationEnabled = true;
|
||||
automation.enabled = true;
|
||||
};
|
||||
|
||||
controlCenter.shortcuts = {
|
||||
right = [
|
||||
{ id = "PowerProfile"; }
|
||||
{ id = "KeepAwake"; }
|
||||
{ id = "NightLight"; }
|
||||
{ id = "DarkMode"; }
|
||||
];
|
||||
backdrop.enabled = true;
|
||||
location.auto_locate = true;
|
||||
|
||||
control_center.shortcuts = [
|
||||
{ type = "power_profile"; }
|
||||
{ type = "caffeine"; }
|
||||
{ type = "nightlight"; }
|
||||
{ type = "dark_mode"; }
|
||||
];
|
||||
|
||||
calendar = {
|
||||
enabled = true;
|
||||
account = {
|
||||
mailbox = {
|
||||
type = "caldav";
|
||||
name = "Yhteinen Kalenteri";
|
||||
provider = "custom";
|
||||
server_url = "https://dav.mailbox.org/caldav/Y2FsOi8vMC82NA";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sessionMenu = {
|
||||
countdownDuration = 5000;
|
||||
powerOptions =
|
||||
let
|
||||
powerOption =
|
||||
action: options:
|
||||
{
|
||||
inherit action;
|
||||
enabled = true;
|
||||
}
|
||||
// options;
|
||||
in
|
||||
[
|
||||
(powerOption "lock" {
|
||||
keybind = "1";
|
||||
countdownEnabled = false;
|
||||
})
|
||||
(powerOption "suspend" {
|
||||
keybind = "2";
|
||||
countdownEnabled = false;
|
||||
})
|
||||
(powerOption "hibernate" { keybind = "3"; })
|
||||
(powerOption "reboot" { keybind = "4"; })
|
||||
(powerOption "logout" { keybind = "5"; })
|
||||
(powerOption "shutdown" { keybind = "6"; })
|
||||
(powerOption "rebootToUefi" { keybind = "7"; })
|
||||
];
|
||||
};
|
||||
|
||||
colorSchemes.useWallpaperColors = true;
|
||||
nightLight.enabled = true;
|
||||
nightlight.enabled = true;
|
||||
idle.enabled = true;
|
||||
general = {
|
||||
avatarImage = "~/.face";
|
||||
radiusRatio = 0.2;
|
||||
clockStyle = "analog";
|
||||
shell = {
|
||||
avatar_path = "~/.face";
|
||||
};
|
||||
location = {
|
||||
monthBeforeDay = false;
|
||||
analogClockInCalendar = true;
|
||||
firstDayOfWeek = 0;
|
||||
showWeekNumberInCalendar = true;
|
||||
autoLocate = true;
|
||||
theme = {
|
||||
mode = "auto";
|
||||
source = "wallpaper";
|
||||
wallpaper_scheme = "m3-tonal-spot";
|
||||
};
|
||||
package = noctalia-package;
|
||||
hooks.theme_mode_changed = "gsettings set org.gnome.desktop.interface color-scheme prefer-\${NOCTALIA_THEME_MODE}";
|
||||
};
|
||||
package = noctalia-package;
|
||||
};
|
||||
|
||||
nh = {
|
||||
@@ -823,6 +783,7 @@ in
|
||||
|
||||
packages = [
|
||||
"dev.diegovsky.Riff"
|
||||
"app.zen_browser.zen"
|
||||
];
|
||||
};
|
||||
|
||||
@@ -883,10 +844,10 @@ in
|
||||
|
||||
xdg.configFile."opencode/opencode.jsonc".text = builtins.toJSON {
|
||||
"$schema" = "https://opencode.ai/config.json";
|
||||
model = "firepass/accounts/fireworks/routers/kimi-k2p6-turbo";
|
||||
small_model = "firepass/accounts/fireworks/routers/kimi-k2p6-turbo";
|
||||
model = "fireworks-ai/accounts/fireworks/models/glm-5p2";
|
||||
small_model = "fireworks-ai/accounts/fireworks/models/minimax-m3";
|
||||
agent = {
|
||||
explore.model = "firepass/accounts/fireworks/routers/kimi-k2p6-turbo";
|
||||
explore.model = "fireworks-ai/accounts/fireworks/models/minimax-m3";
|
||||
};
|
||||
theme = "system";
|
||||
lsp = {
|
||||
@@ -1065,7 +1026,7 @@ in
|
||||
|
||||
layer-rules = [
|
||||
{
|
||||
matches = [ { namespace = "^noctalia-overview*"; } ];
|
||||
matches = [ { namespace = "^noctalia-backdrop*"; } ];
|
||||
place-within-backdrop = true;
|
||||
}
|
||||
];
|
||||
@@ -1094,7 +1055,12 @@ in
|
||||
# blur = true;
|
||||
# xray = false;
|
||||
# };
|
||||
#}
|
||||
{
|
||||
matches = [ { app-id = "dev.noctalia.Noctalia.Settings"; } ];
|
||||
open-floating = true;
|
||||
default-column-width.fixed = 1080;
|
||||
default-window-height.fixed = 920;
|
||||
}
|
||||
];
|
||||
|
||||
binds = lib.foldl' (acc: x: acc // x) { } (
|
||||
@@ -1117,43 +1083,39 @@ in
|
||||
"Mod+Alt+L" = {
|
||||
hotkey-overlay.title = "Lock the Screen: hyprlock";
|
||||
action.spawn = ns-ipc [
|
||||
"lockScreen"
|
||||
"session"
|
||||
"lock"
|
||||
];
|
||||
};
|
||||
"XF86AudioRaiseVolume" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"volume"
|
||||
"increase"
|
||||
"volume-up"
|
||||
];
|
||||
};
|
||||
"XF86AudioLowerVolume" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"volume"
|
||||
"decrease"
|
||||
"volume-down"
|
||||
];
|
||||
};
|
||||
"XF86AudioMute" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"volume"
|
||||
"muteOutput"
|
||||
"volume-mute"
|
||||
];
|
||||
};
|
||||
"XF86AudioMicMute" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"volume"
|
||||
"muteInput"
|
||||
"mic-mute"
|
||||
];
|
||||
};
|
||||
"XF86AudioPlay" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"media"
|
||||
"playPause"
|
||||
"toggle"
|
||||
];
|
||||
};
|
||||
"XF86AudioPrev" = {
|
||||
@@ -1173,15 +1135,13 @@ in
|
||||
"XF86MonBrightnessUp" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"brightness"
|
||||
"increase"
|
||||
"brightness-up"
|
||||
];
|
||||
};
|
||||
"XF86MonBrightnessDown" = {
|
||||
allow-when-locked = true;
|
||||
action.spawn = ns-ipc [
|
||||
"brightness"
|
||||
"decrease"
|
||||
"brightness-down"
|
||||
];
|
||||
};
|
||||
"Mod+O" = {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
gimp
|
||||
lftp
|
||||
inkscape
|
||||
wineWowPackages.waylandFull
|
||||
wineWow64Packages.waylandFull
|
||||
reaper
|
||||
inputs.ksoloti-pr.legacyPackages.${pkgs.stdenv.hostPlatform.system}.ksoloti
|
||||
calibre
|
||||
|
||||
@@ -52,6 +52,8 @@ in
|
||||
${ykman} oath accounts code -s 'MOCO Reto' | ${nmcli} c up moco --ask
|
||||
fi
|
||||
'')
|
||||
kreuzberg-cli
|
||||
tesseract
|
||||
];
|
||||
};
|
||||
|
||||
@@ -217,4 +219,11 @@ in
|
||||
user = "butler";
|
||||
};
|
||||
};
|
||||
|
||||
programs.noctalia.settings.calendar.account.moco = {
|
||||
type = "caldav";
|
||||
provider = "custom";
|
||||
name = "MOCO";
|
||||
server_url = "https://intern.mocoapp.com/users/933620701/calendar/9df64d69e29c97a75cd6d93aeec0d5ae.ics";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ let
|
||||
"opencode"
|
||||
"opencode-go"
|
||||
"fireworks-ai"
|
||||
"firepass"
|
||||
];
|
||||
|
||||
openaiCompatibleProviders = builtins.listToAttrs (
|
||||
@@ -142,8 +141,8 @@ in
|
||||
agent = {
|
||||
enabled = true;
|
||||
default_model = {
|
||||
provider = "opencode-go";
|
||||
model = "glm-5";
|
||||
provider = "fireworks-ai";
|
||||
model = "accounts/fireworks/models/glm-5p2";
|
||||
};
|
||||
};
|
||||
agent_servers = {
|
||||
@@ -181,7 +180,7 @@ in
|
||||
};
|
||||
Nix = {
|
||||
formatter.external = {
|
||||
command = lib.getExe pkgs.nixfmt-rfc-style;
|
||||
command = lib.getExe pkgs.nixfmt;
|
||||
arguments = [ "-q" ];
|
||||
};
|
||||
};
|
||||
@@ -256,7 +255,7 @@ in
|
||||
arguments = [ "--stdio" ];
|
||||
};
|
||||
json-language-server.binary = {
|
||||
path = lib.getExe nodePackages.vscode-json-languageserver;
|
||||
path = lib.getExe vscode-json-languageserver;
|
||||
arguments = [ "--stdio" ];
|
||||
};
|
||||
package-version-server.binary.path = lib.getExe pkgs-unstable.package-version-server;
|
||||
@@ -277,7 +276,13 @@ in
|
||||
};
|
||||
edit_predictions = {
|
||||
mode = "eager";
|
||||
provider = "copilot";
|
||||
provider = "open_ai_compatible_api";
|
||||
open_ai_compatible_api = {
|
||||
api_url = "https://api.fireworks.ai/inference/v1/completions";
|
||||
model = "accounts/fireworks/models/qwen3p6-plus";
|
||||
prompt_format = "qwen";
|
||||
max_output_tokens = 1024;
|
||||
};
|
||||
};
|
||||
buffer_font_family = "Iosevka Nerd Font";
|
||||
buffer_font_size = 16;
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
host = "0.0.0.0";
|
||||
port = 8282;
|
||||
secretKeyFile = config.age.secrets.invidious-companion.path;
|
||||
binaryHash = "sha256-nZXKpExKCc2zgSdVT3qo05NyFdpM9H9NJB5UWo+MVWI=";
|
||||
binaryHash = "sha256-RU18Zt/dSMVF/hLeAg+J3BrmDUnO7L4mv/+g7A91WL8=";
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
|
||||
@@ -20,6 +20,8 @@ in
|
||||
"flakes"
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
min-free = 5 * 1024 * 1024 * 1024;
|
||||
max-free = 10 * 1024 * 1024 * 1024;
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
@@ -28,6 +30,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.journald.extraConfig = "SystemMaxUse=500M";
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.binfmt.emulatedSystems = [ "x86_64-linux" ];
|
||||
@@ -164,6 +168,8 @@ in
|
||||
"builder"
|
||||
];
|
||||
|
||||
modules.tempBuildStorage.enable = true;
|
||||
|
||||
# List packages installed in system profile. To search, run:
|
||||
# $ nix search wget
|
||||
environment.systemPackages = with pkgs; [
|
||||
|
||||
@@ -58,5 +58,9 @@
|
||||
file = ../../secrets/invidious.age;
|
||||
owner = config.systemd.services.invidious.serviceConfig.User;
|
||||
};
|
||||
"grafana/secret-key" = lib.mkIf config.services.grafana.enable {
|
||||
file = ../../secrets/grafana/secret-key.age;
|
||||
owner = config.systemd.services.grafana.serviceConfig.User;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ in
|
||||
user = smtp.username;
|
||||
from_address = smtp.from;
|
||||
};
|
||||
security.secret_key = "$__file{${secrets."grafana/secret-key".path}}";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -327,14 +328,6 @@ in
|
||||
subdomain = "irc";
|
||||
};
|
||||
|
||||
sillytavern = {
|
||||
enable = true;
|
||||
subdomain = "st";
|
||||
listen = true;
|
||||
whitelist = false;
|
||||
port = 3100;
|
||||
};
|
||||
|
||||
nginx.virtualHosts."isarepomaa.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
package = pkgs-unstable.podman;
|
||||
dockerCompat = true;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ pkgs-unstable, ... }:
|
||||
{ lib, pkgs-unstable, ... }:
|
||||
{
|
||||
services.displayManager.gdm.enable = true;
|
||||
services.desktopManager.gnome.enable = true;
|
||||
@@ -24,7 +24,7 @@
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
alsa.support32Bit = lib.mkForce false;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
ssh,
|
||||
config,
|
||||
inputs,
|
||||
@@ -57,10 +58,10 @@ in
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
# Define a user account. Don't forget to set a password with 'passwd'.
|
||||
users.users.jokke = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
extraGroups = [ "wheel" ]; # Enable 'sudo' for the user.
|
||||
packages = [ pkgs.nh ];
|
||||
openssh.authorizedKeys.keys = [ ssh.publicKeys.yubikey ];
|
||||
initialPassword = "changeme";
|
||||
@@ -74,7 +75,7 @@ in
|
||||
wget
|
||||
htop
|
||||
git
|
||||
inputs.turny.packages.${stdenv.hostPlatform.system}.default
|
||||
alsa-utils
|
||||
];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
@@ -88,11 +89,157 @@ in
|
||||
allInterfaces = [ "ssh" ];
|
||||
};
|
||||
|
||||
# Enable audio (ALSA)
|
||||
hardware.alsa.enable = true;
|
||||
|
||||
# Complete config.txt settings: boot-critical u-boot lines plus SPI enable.
|
||||
# The configtxt module generates the full config.txt, overriding the
|
||||
# hardcoded one in sd-image-aarch64.nix which ignores these settings.
|
||||
hardware.raspberry-pi.configtxt.settings = {
|
||||
pi3 = {
|
||||
kernel = "u-boot-rpi3.bin";
|
||||
core_freq = 250;
|
||||
};
|
||||
pi02 = {
|
||||
kernel = "u-boot-rpi3.bin";
|
||||
};
|
||||
pi4 = {
|
||||
kernel = "u-boot-rpi4.bin";
|
||||
enable_gic = true;
|
||||
armstub = "armstub8-gic.bin";
|
||||
};
|
||||
all = {
|
||||
arm_64bit = true;
|
||||
enable_uart = true;
|
||||
avoid_warnings = true;
|
||||
dtparam = [
|
||||
"audio=on"
|
||||
"spi=on"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Use the configtxt module's generated config.txt when building SD images
|
||||
sdImage.populateFirmwareCommands = let
|
||||
inherit (config.hardware.raspberry-pi.configtxt) file;
|
||||
in ''
|
||||
(cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
|
||||
|
||||
cp ${file} firmware/config.txt
|
||||
|
||||
cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin firmware/u-boot-rpi3.bin
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-2-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-3-b-plus.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-cm3.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2710-rpi-zero-2-w.dtb firmware/
|
||||
|
||||
cp ${pkgs.ubootRaspberryPi4_64bit}/u-boot.bin firmware/u-boot-rpi4.bin
|
||||
cp ${pkgs.raspberrypi-armstubs}/armstub8-gic.bin firmware/armstub8-gic.bin
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-4-b.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-400.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4.dtb firmware/
|
||||
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4s.dtb firmware/
|
||||
'';
|
||||
|
||||
# Load SPI and GPIO kernel modules so /dev/spidev* and /dev/gpiomem exist
|
||||
boot.kernelModules = [
|
||||
"spi_bcm2835"
|
||||
"bcm2835_gpiomem"
|
||||
];
|
||||
|
||||
# Use the firmware-passed device tree (with dtparam/dtoverlay applied)
|
||||
# instead of u-boot loading a fresh DTB from FDTDIR
|
||||
boot.loader.generic-extlinux-compatible.useGenerationDeviceTree = false;
|
||||
|
||||
# Mount the firmware partition so config.txt is accessible and can be
|
||||
# updated on deploys. The sd-image module defaults to noauto; we need it
|
||||
# mounted so the activation script can sync config.txt.
|
||||
fileSystems."/boot/firmware".options = [
|
||||
"nofail"
|
||||
"defaults"
|
||||
];
|
||||
|
||||
# Sync the generated config.txt to the firmware partition on each deploy
|
||||
# so dtparam/dtoverlay changes take effect without reflashing the SD card.
|
||||
system.activationScripts.syncConfigTxt = {
|
||||
text = ''
|
||||
if mountpoint -q /boot/firmware; then
|
||||
cp -f ${config.hardware.raspberry-pi.configtxt.file} /boot/firmware/config.txt
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Turny service
|
||||
systemd.services.turny = {
|
||||
description = "Turny Spotify RFID Controller";
|
||||
documentation = [ "https://github.com/repomaa/turny" ];
|
||||
after = [
|
||||
"network.target"
|
||||
"sound.target"
|
||||
];
|
||||
wants = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = lib.getExe inputs.turny.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
User = "turny";
|
||||
Group = "turny";
|
||||
WorkingDirectory = "/var/lib/turny";
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
RestartPreventExitStatus = 23;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ReadWritePaths = [ "/var/lib/turny" ];
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
LimitNOFILE = 1024;
|
||||
MemoryAccounting = true;
|
||||
MemoryMax = "100M";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
SyslogIdentifier = "turny";
|
||||
};
|
||||
environment = {
|
||||
RUST_LOG = "info";
|
||||
RUST_BACKTRACE = "1";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.turny = {
|
||||
isSystemUser = true;
|
||||
group = "turny";
|
||||
extraGroups = [
|
||||
"gpio"
|
||||
"spi"
|
||||
"audio"
|
||||
];
|
||||
home = "/var/lib/turny";
|
||||
createHome = true;
|
||||
};
|
||||
users.groups.turny = { };
|
||||
users.groups.gpio = { };
|
||||
users.groups.spi = { };
|
||||
|
||||
# Udev rules for GPIO and SPI access
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
|
||||
SUBSYSTEM=="gpiomem", GROUP="gpio", MODE="0660"
|
||||
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
|
||||
'';
|
||||
|
||||
# This value determines the NixOS release from which the default
|
||||
# settings for stateful data, like file locations and database versions
|
||||
# on your system were taken. It's perfectly fine and recommended to leave
|
||||
# settings for stateful data, like user locations and database versions
|
||||
# on the system were taken. It's perfectly fine and recommended to leave
|
||||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
|
||||
sdImage.compressImage = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM3To9DeTGzwiQN+uqNWZXKzGG1BJnLvYRgLm0/iI92Y turny
|
||||
@@ -11,6 +11,7 @@
|
||||
./vlans.nix
|
||||
./firewall.nix
|
||||
./storage-box-mounts.nix
|
||||
./temp-build-storage.nix
|
||||
./services
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
./weechat.nix
|
||||
./hledger-web.nix
|
||||
./glance.nix
|
||||
./sillytavern.nix
|
||||
./nqptp.nix
|
||||
./actual.nix
|
||||
./voidauth.nix
|
||||
|
||||
@@ -86,18 +86,17 @@ def get_leases(interface : String, networkctl_path : String? = nil) : Array(Leas
|
||||
cmd = networkctl_path ? "#{networkctl_path}" : "networkctl"
|
||||
args = ["status", interface, "--json=short"]
|
||||
|
||||
Process.run(cmd, args, output: Process::Redirect::Pipe, error: Process::Redirect::Pipe) do |process|
|
||||
result = process.wait
|
||||
output = process.output.to_s
|
||||
process = Process.new(cmd, args, output: Process::Redirect::Pipe, error: Process::Redirect::Pipe)
|
||||
output = process.output.gets_to_end
|
||||
error = process.error.gets_to_end
|
||||
result = process.wait
|
||||
|
||||
unless result.success?
|
||||
error = process.error.to_s
|
||||
raise "networkctl failed (exit code #{result.exit_code}): #{error.empty? ? output : error}"
|
||||
end
|
||||
|
||||
status = NetworkStatus.from_json(output)
|
||||
status.dhcp_server.try(&.leases) || [] of Lease
|
||||
unless result.success?
|
||||
raise "networkctl failed (exit code #{result.exit_code}): #{error.empty? ? output : error}"
|
||||
end
|
||||
|
||||
status = NetworkStatus.from_json(output)
|
||||
status.dhcp_server.try(&.leases) || [] of Lease
|
||||
end
|
||||
|
||||
def write_if_changed(content : String, path : String) : Bool
|
||||
@@ -154,12 +153,12 @@ def reload_unbound(unbound_control_path : String?)
|
||||
cmd = unbound_control_path ? "#{unbound_control_path}" : "unbound-control"
|
||||
puts "Reloading Unbound..."
|
||||
|
||||
Process.run(cmd, ["reload"], output: Process::Redirect::Pipe, error: Process::Redirect::Pipe) do |process|
|
||||
result = process.wait
|
||||
process = Process.new(cmd, ["reload"], output: Process::Redirect::Pipe, error: Process::Redirect::Pipe)
|
||||
error = process.error.gets_to_end
|
||||
result = process.wait
|
||||
|
||||
unless result.success?
|
||||
raise "unbound reload failed (exit code #{result.exit_code}): #{process.error}"
|
||||
end
|
||||
unless result.success?
|
||||
raise "unbound reload failed (exit code #{result.exit_code}): #{error}"
|
||||
end
|
||||
|
||||
puts "Unbound reloaded successfully."
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.sillytavern;
|
||||
fqdn = "${cfg.subdomain}.${config.networking.domain}";
|
||||
in
|
||||
{
|
||||
options.services.sillytavern = {
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "sillytavern";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.webserver = {
|
||||
enable = lib.mkDefault true;
|
||||
vHosts.${fqdn} = {
|
||||
tailscaleAuth = true;
|
||||
proxyBuffering = false;
|
||||
locations."/".proxyPort = cfg.port;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.modules.tempBuildStorage;
|
||||
in
|
||||
{
|
||||
options.modules.tempBuildStorage = {
|
||||
enable = lib.mkEnableOption "temporary build storage volume";
|
||||
|
||||
device = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/dev/sdb";
|
||||
description = "Block device to mount for temporary nix build storage.";
|
||||
};
|
||||
|
||||
mountPoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/mnt/build";
|
||||
description = "Mount point for the temporary build storage.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
fileSystems.${cfg.mountPoint} = {
|
||||
device = cfg.device;
|
||||
fsType = "ext4";
|
||||
options = [
|
||||
"nofail"
|
||||
"defaults"
|
||||
];
|
||||
};
|
||||
|
||||
nix.settings.build-dir = cfg.mountPoint;
|
||||
};
|
||||
}
|
||||
+8
-9
@@ -1,10 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA n8TUqlE5mEfKa7aPdefBjIKAhydL1vrCZK8cLTs+j3w
|
||||
ayrirgnGn6dTBKShBRDHJAI3t040hf5LEo8ZuHUGNHg
|
||||
-> ssh-ed25519 DFiohQ +rVCacN11divc55NH2fKsYXa6IJ0ieW18riYz9nkrwo
|
||||
4qv06+QnvPKYRRkQauDwKfnT1c4/GHDkxHVrgkfrHNw
|
||||
-> ssh-ed25519 PT7ffg wklac2cEzzfMQaItzsAv6I1az8HxZ15s3ANwxYO59To
|
||||
abdf65f0BT2sE52T60lnfqY/iDCgLAzgRQlPqjRp6Y4
|
||||
--- Wi4+L0OzsduT8T7G4+H8pp05EzbTjNlJowwBDWUN1mU
|
||||
ÛŸþf޹“Íå¸ÁºTL®›`‚ý¬—F„F»‡í$S1†ºqÐv3nÙOu‰Xªf␍AþÂn‡e’¥Sý©ªEãM_¿ ï^VÀŽ‘ä4p.øäBIO¹Ô÷
|
||||
Bñ`�Œsï)Z4œÜHŸßRvÓ/MÓÕ-> 5òÓå ⢃;ü~¹÷ÿ
|
||||
-> ssh-ed25519 osOCZA tKc6OuybMhchwMgREDpacwxz/IlBCOOD9OQp/UMLBys
|
||||
7mOmTzMUnLYnQPHOWwIiZ4vFyPxQpwzPmnQMuWsQWfA
|
||||
-> ssh-ed25519 DFiohQ +ysb8W20OD73awl7we7/XfiX5q8sRtMlerr5r4gavTA
|
||||
5OHmlJHoVRXho2Swe/XDTtQKn0pW9PH1Ky4rvhR7o/8
|
||||
-> ssh-ed25519 PT7ffg 0vvEHkjNJFH/UUcwX8O+F0StVBqNkQNp7u2qasHZLCE
|
||||
xKySMrX3T59dCKEUHyR/cdT+8KCFdCerUyUg7r7ZBYQ
|
||||
--- ielXPF0xxxqSrBc1yeOxLdz50ZjCLnZJ45Wsg84yPso
|
||||
×S;ëqø»äá û˜…Å@ðŒ±S,a¾¬ÛÜH3;(¥¡%o#‘ýx$Qgw”žãÊ>ô�ias °ù»%fjr¼ÊÜ^cïrô©´Ñ‚â°`ä—e›¼níû_�–w›×¶çõvÓCØÅ‡x}|µFnÿjݹ°²À ß
|
||||
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA 9ZHiyWiFLySuINTKXSjysD9u7LKyhK2bJo6JmVskDGc
|
||||
IDUB5fbYwEwZDIRwOAAWdDkHOrmMwlZT+2UhObhHVXg
|
||||
-> ssh-ed25519 DFiohQ OFE+xiH2zIXccj3axHbN8TBKS927ldBtlC80ZCVH2To
|
||||
E50Dr6cyllIN66QVGYvonpSRV0nERdstsEGUeXrVDoE
|
||||
-> ssh-ed25519 hRPDBg Z9ItEkrFay5918/EY2RCl0a9PZx3z8amW4yMyfgEqQI
|
||||
rEs5eqfdnpwnxzPRlMi1vBrtzsbQCwCupkGEXFs7rVA
|
||||
--- op5RVwxhxkxflXvoAM7ZcEXLutkF9Op70tUxsJundN4
|
||||
è$À;Åå1ÒO`bBMÆLŸf“<î”ã%>1p�kvMØ]?x|ù¬zäFƶ~ÖÙÕ¬pL␍úIÝ(␍u¢ÉDØÈZNž÷ªÏ•Qv˜îŒr88ð¹[²Ãü
|
||||
-> ssh-ed25519 osOCZA IY+dU1oe5ps4gli4bqRVdIaKaOWfEieIX0b/8q6+Pys
|
||||
L5Bkf3dTH9k0HUYrrTvLq5hvS7CK1nJp1mJumBlVGb8
|
||||
-> ssh-ed25519 DFiohQ BjbGXY9CmrAEcv4+hk+A1AIP06NeP4NhymTeByfxi3c
|
||||
94qpDg6nEowmkNUzeDGtNw8VgT8vsWR4y28/lMyfZmc
|
||||
-> ssh-ed25519 hRPDBg 7Lq1rjiz1FhgFkWaZJaLR24k+HAKLraw9YjVsWPspVE
|
||||
3eBnzsN96eLmIlu9MNiBhv41csudd4WQUF5Q9vpGkj0
|
||||
--- l10qNh0gcX57lTZsiTsuzwhVGnKM5hH5+ZbjI9yfr/Q
|
||||
ûK¿;n},ijæ6uîȧMŤ'ülÿÓÂò–?ÜÜå'„MtÙš.¢ßšžô.I‹Qó³öy)&|=¨½@1ãmSRD"&&áWUgið}'ˆ¹¶¥�
|
||||
+8
-8
@@ -1,9 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA sWXC8tg44GfsKCFIDhvmkSfO1NnQ/GdP7s7yKnn/wwk
|
||||
tulj+EsIi91rXw7XV0elKyVpamDNnEdy1GikcmPGLlE
|
||||
-> ssh-ed25519 DFiohQ 8Cxy6QZkviBPw51+3m6JYtcOPTbYy6C7m7uomdFwAgY
|
||||
4GuwAQKMtKI7cZCg2/yl4IAd98Zeai+/rXScSRRmS9E
|
||||
-> ssh-ed25519 PT7ffg dnDE79EVRVys94oHOSduzhcyd8oHA8/scK98By5g9FE
|
||||
RFfMpq56KDvIJcOg5JdaOiEN6wupKFUNbcHYCS/kyp0
|
||||
--- Tg+Gw0uAEFItHT00VDs9BmhvX2f8afcRwuh8OSqLEh4
|
||||
È*Í�¦ciðÜ~P+c÷{p™“²Û…£yé\©â'a“<x6Xsá¡zógŸ~=´è0¸–6=sÞ5ÐÆlØ5BŒÎ3ÌÜ5í»š§
|
||||
-> ssh-ed25519 osOCZA /DM/QULRCY6cCkuqi0h+PVXW+lFcvUwTaNI4vVHoG3w
|
||||
f/U+q+Y6zoIcg0ttN+JgFc0GqXKWV08nmWUeeeC+b5k
|
||||
-> ssh-ed25519 DFiohQ kgrVGGqMrBn8W1trnR116ODUHTeDR60BLnWfqANr/QA
|
||||
ys8CLK1XHkOQvp3xlcQkQ3me2a2/Nu94o5L9swWhsAs
|
||||
-> ssh-ed25519 PT7ffg 3jg8xsvEsjZ8Gzap1Q0T5cZpi/lmk8/DuE1Zsk7ByGY
|
||||
gfrFh5M2GWWa+5IaO7yL8LRlMThRWt/XdZIYDXxo8zU
|
||||
--- U2Rbi2kHkOIW8AErxfFCUwf2HayX+J4QjKVz/4aGn9k
|
||||
¤c Ý“øÉ�‘ôºœ2kž7ˆÿ)ýí,h~Ó1!¦ÓÁjaÍé`ÊVz Æ-␍n}<ÎØºKä+Rrw¿’Wð†Æ®3éCRªòV©yÙ{
|
||||
Binary file not shown.
@@ -1,10 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA ynIsrUjxXEYLRtKoiyBKCn83JeZ5rFhGD3xi61ypVBc
|
||||
ZuKEpntuTCMigOf/jeQ3V6oklmqzuxyDpi4oVhtWsc4
|
||||
-> ssh-ed25519 DFiohQ /0VJWz6hK+0FNjBciDbPHX+ader97UxCiQYB1BFZh3E
|
||||
SiqY0KS5wBWHMgEbJMAU1WgvXqEJjBAOQ3l/eMuETdI
|
||||
-> ssh-ed25519 hRPDBg KSXXiPwj27sKoXMiwW7IqQJvE72lYIgUjiPnpvVSSmE
|
||||
ioQGtUPSMj4flm9j84PLGm4C/P0sHVmYX38SgB6Yl2c
|
||||
--- jUadITulpzJjYp3oWxkG0Qk5RwDXisrKgmXYMlcxCss
|
||||
ç[ ,J"ø$¥Èµå½Mõ.ã0ט½Œcë§~ã,�CŸ
|
||||
‰“s•¤×u1�™órDTf:FtwAÉtÿ„™hE¿›„Af
|
||||
-> ssh-ed25519 osOCZA q6tH0FVLeK0IAAlBAQfpQJScvePOK3+TSZ38NAfQHWo
|
||||
63rJwFLyI3TRkjR8j7Ek4ELE4Se+alHCl1tO5ujmzMA
|
||||
-> ssh-ed25519 DFiohQ fc1aSau4DbXn8XzqgAFYbgw1T3U3IMva/RpUTqlBR2Y
|
||||
G+qY9wIDOvyOWmQnNmnaasdlFVUGR6cBWpK2Zce5LHM
|
||||
-> ssh-ed25519 hRPDBg FT7EbwtMJF9hjfcCc2PqWmRoYYFWkCvQ06DbVfpOg1Y
|
||||
8j8Rwfmu+tckffMKMQ0h3/un09mUCi7/hymgqjSNz8U
|
||||
--- C03Wle22666W4khdQVHeC9eP+ZJ8AcP3dB+jfCHpeP0
|
||||
öÚ†µi•lÎ|G~¸DUô2í¶�åÐóä"׆ÎÁ¸}j,Ì\|w,°–0ÜO5�ζ¹?~•"ÊÃÖy»fl¢nËõÍÆT
|
||||
@@ -1,9 +1,10 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA sGsltqSPiC3jkgZcpRXobfPgKiuPYzU3XiNptcyniB4
|
||||
0Q7X+YuaRHT2/1sCrqyhnXCRGIcUKlHQKoo7W8TCwD0
|
||||
-> ssh-ed25519 DFiohQ o982CBPZ8MYPkm+ngw0WxJKc4vC0yo1poTz3ICnbJVM
|
||||
Ac600G8Gr8dhPaXxl8k7A7XpaX70iyLTzfFFTc+14Ag
|
||||
-> ssh-ed25519 hRPDBg Pf8NvKBZy/afSlFjZIySg6aSregAeMtUCj7e90b0qXw
|
||||
kW4Ph56hKVtR0MUaulZpSS28Kna1Wigcvcf1Uv2ESf8
|
||||
--- Jbu+08V6cvPbTBjwiZvIRtsdOPOtn/e3VCzQuyrCgLw
|
||||
®î|xÌ=׺6ú»ÙÄ)ؘjYy6¤Ê`Ø‚ÛØào wÔ¬ËZ€\LLfK,(œØq¸>AŽ_tM£êqŽü°°£Y‘>Õí
|
||||
-> ssh-ed25519 osOCZA ylc8vGyAOgdlAWSFGDQ7rjIoPCXtCgTdjyq7jiJLtF4
|
||||
HG7y2EyaHKB9664gfH3Q+YxL2ArAEKIIlwtC8YKtHh8
|
||||
-> ssh-ed25519 DFiohQ XPjQk3y/Dmsh8mHqUD3oLdRR9drDB29sCRjoaYlbGkw
|
||||
BfGPDs5n1IoYgAZzEgRnmvhxqvY+BrYLVASJOR/szeI
|
||||
-> ssh-ed25519 hRPDBg s1AkS3NGpW8yAQwXqx9UgHc2SaiA+AcE4vCbYlHENH0
|
||||
e9bhxPNYUct/dQEVirOkX1A+ulPiE1PHGh8M6qrM67k
|
||||
--- Ov/CzZKVSYIKK4Z4W5duNQd/Bu9tkMwXhPXhzW9KOjk
|
||||
žã«1ÿkVyôG||8ÊÚD„dÙÓòk*ŽÅhɽ~{»Ð1T�,¾?ht%Þ!ƃ§°ýÎÜbÍ·µË¼�ßtÚ
|
||||
ø5ÀH{ÿä
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA wpN3yvRvjDjs45jISvWHluVYjgt7KBlDBbWubMtgn3U
|
||||
SzZZWcc8NpYA08kafMwsvYQWoAsNBN+9AXYxqQmiEkA
|
||||
-> ssh-ed25519 DFiohQ R2vygwm3+reW5mJTUdFrEhExA0uI3yhHngNhp4hLBRI
|
||||
tmY3D32TOK/CMrLlzwE8vYr2vIxYXkcqHPgq/a0QO0M
|
||||
-> ssh-ed25519 PT7ffg IkM8NFdkSef9sB1LuBB3joDyKNwcJkKa7B30mrCufVk
|
||||
nzj1ccl0DU/Ubt6I0PMscftvra0Y4n2gRB7oBtTGoaY
|
||||
--- OtT3fPqZXKVCWQ/35+9XZMfhtEuUHaio+zxqVBeyJVs
|
||||
æ÷Ðc¯�cÛ‰Œ¨©¤i�B©sò8ÐaDJb•,¡åHz-yÕ6lÅNÓ{Ó#•¤&�)x+‚M1¹û‰=ñ,3%»ý8ãX�ªÛª¿î,Øo8ã×Ý¡úªfšÛˆZô˜]ZõoWO›Ã>T
|
||||
-> ssh-ed25519 osOCZA Wnc3PL++j3i07tkKyKdfwjUwZEg5tnXQfWW+JhRSIQU
|
||||
eOYYoPvzsta+BdGqRGUw60upA7da+xAKkgY5SULrz98
|
||||
-> ssh-ed25519 DFiohQ Zw+DAeYPLTSTm64f/xoxaSHaBjfeuX977Hw2xBNLPlc
|
||||
pNl3S10RF2N9lcgMtGuodnyaIyGgqC1vuYqyqaeRiJA
|
||||
-> ssh-ed25519 PT7ffg KUcvZ2YR4pV1pJrQzIUmEs2U0azDcu/PCxBKaiuYrC0
|
||||
EX9rhh1XtpGOWjQ4OzBVxD+hRtRc1caLgB2EJ1isYKg
|
||||
--- OUJ/fR74TEgXceG3Dml7d9o0+rzdzUQu83Q3IkW//TY
|
||||
Ú6␍ãѱ¤ëÉ<£xit¹YWèª!�™út–ß=CÚ;Ù'üéR½ÚÓMŠÖaš—:?(]†–dY·ü<…␍r0ÑD1”ÜOŸAÿˆX‹ÑÅVÍG␍\"îŒzzõ·ŸÅØúD‹P’Óø
|
||||
@@ -1,10 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA wVGyI0bVEaVUbXMiumjhqdno2VD6ZHmvJM0NRUoesk0
|
||||
kW8Zs6KV+KBmyg/imOzVHHPg/K3oHyB05ayMQsT01CQ
|
||||
-> ssh-ed25519 DFiohQ h+C13tChA1OrCdmJO9rkjW3ER/d8OW7P2IGd5spsd2Y
|
||||
7LOIjam4k8lmglNEuNs7lkRpt3UbYkxFxXPwkj2Fbc8
|
||||
-> ssh-ed25519 PT7ffg 33/HLpIkjfw+QC1qm1Tmr4YqMjgtt4bsVoFqUNinhno
|
||||
8+PGKzffQT2DuM8l9mqgGieHiQCpBsbWbHDIdxFapBk
|
||||
--- lzyw/qQSELbYc8TWYFGD57JBF4JorTLhBPNdlxYjVqY
|
||||
lÞHºaEM9ÅóüÀS0(Š¥¦lâJxø-
|
||||
—sÔ¸éžc¬H EÖ˜Í0_{|K‚p2
|
||||
-> ssh-ed25519 osOCZA X80qdaNMdIz7sy+tLmTYlati/SKucc03gW5FXE9/xlM
|
||||
5ZvMFxd3MOl4SyBEYR9xawjREi8UwEmW9DyuCC+E8jk
|
||||
-> ssh-ed25519 DFiohQ NPghTlceQTcZh4VGASPeFZy8G2VLURxykc0JjvAdW2s
|
||||
MkIN+sOI3yD8UzSmHOabeVnFHfXDDWMSWwFIuHGJGFE
|
||||
-> ssh-ed25519 PT7ffg mc6TmlrgBEBQeOECY6SzHaLhpi4SrYc/9m9nml/2GGY
|
||||
VDNZtQSSGG1+/84Y5TcyiJytoAoPCyj9PlYV7WZiKE8
|
||||
--- GPLaSoO3+AZXfY9gIweM+dDAb+hBSadz++DqYEkR2ug
|
||||
;ܬl‘öj…Ãå˜æ?Ã§ÚøÆQ²}©„NÁìû/ªº)à·[xØö%‹F!¼0µ†ª
|
||||
@@ -1,9 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA tO/H34qaDDLUWG7ovv4wD8At0v+nRLxgozIHFRCxIG4
|
||||
AU0szD79hzM5rLSYQhki+Ukc2CbATwdU5uWPNLn1Oa0
|
||||
-> ssh-ed25519 DFiohQ hwThntCOC9a5eSAay4zWW044NoC4JggBXgh3KAZdGAA
|
||||
z2EDIRJH9jGTKYuxm++ns1yqFyUYrA091Q22VMNgqec
|
||||
-> ssh-ed25519 PT7ffg tNGBQvJnGvnGB0Mk24Hyh75ZJAMbZMKk60wkc/PMEiE
|
||||
ijewL+qajDYN7abihSAvAySqcx3idkstsriVVw9Fj+A
|
||||
--- HuLF80Z9VHyeMVTyN9CLKIRn0HFUpIhaWC9KgLHXrlI
|
||||
:™Â3ÿö:ïžéÔRàöó1™Ä„ɰŠBÀo�&Qd1BXU¤ìí¨qÑ ßšüÙfÂ�€êQPÝ—8
|
||||
-> ssh-ed25519 osOCZA t6j6GnCmxIYZKfYZ+dthOAaJqjHtbsIZSOYaonDvDxo
|
||||
KWhOeO95ExUHgcHtm5BYwZnG4EOMZpcKB7h/UM7yxZ8
|
||||
-> ssh-ed25519 DFiohQ XlRVp8vYYbCbrCGIYpXLsewZkceQJRqUlegTnAp4gSo
|
||||
4yu21bl6xEodz/lVBV/imCresblG89uyz8fzWhSjBJ8
|
||||
-> ssh-ed25519 PT7ffg UN3WxuZZrVq4xG/fOYdfyMBBvqO5aKLF+0DZ+8SYjFk
|
||||
DSGXD5GeYKIwT/GLG2n16660x3R4JASnzPI0vBvi1kw
|
||||
--- mobBb6GglqgnpHy9IaTX6FwjIuv+g31FpC0V4tKJ9mg
|
||||
ábwøysqéõfØÖ½Çøâ÷ùE§KvYt&²1ÿ�WzÙì«ÊZ+ɳ×rœ¼ ”o·‹ƒŠG
|
||||
@@ -1,10 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA VAbqavKlZzuLT1XwcdWuRX39bNPbuVvsGPXNv5lwd2g
|
||||
4mMBgBCfnnbY6lo7WAnppqEk8tA1A5MGvXjjZ84cr5k
|
||||
-> ssh-ed25519 DFiohQ hzICSaoG/iPl1VEm7gF49mXCzhVZypQN00/9dqbAfgI
|
||||
VM5O8wLvzFyFkttqP4YWQ0bR5iKkAvpYFPsep2nYt7E
|
||||
-> ssh-ed25519 PT7ffg +FbUxPiTEBDl4QdwYUSuqD0+xzHWe4X9l1cqRePwZzQ
|
||||
tfKlhCQ0mK67E8UcXki9y4SmgTLsrZwD6kKBQz1NiSI
|
||||
--- tnLRJm+/eP6KzNV7vD1d2KtDe6SRyo2MoIsow4CDyrU
|
||||
±lù•þe–bö±¹D.Û␍c‰Y.êÓdÎNáWä݃ξ^®Å´ï©PщSFd.Ú=ýŸ3øA@I9/޼˜læó›Í�~;FÒR5[|
|
||||
s‹
|
||||
-> ssh-ed25519 osOCZA OKLTpDP78xbkZ2uxMaJtOIVCd3/jbAV98E9yFGg0SHk
|
||||
1RwoL09ZccJhYWJxy/JgMxJSHc74RsKD22L3c13BARo
|
||||
-> ssh-ed25519 DFiohQ us/uB+O7gBPPJ3ewzn1Vpkc59obSQcwSORFIhPsw0Wo
|
||||
dW/6eaPCKI0Z59PPtoNiOWoaNPNFqy1WPhI2y+AXXok
|
||||
-> ssh-ed25519 PT7ffg Shf65NGS/njVgmsKYzH0G+R3Lbul24ov1YX0D8yCVlE
|
||||
+V8lgVMK4tIIvjWXDRSK15Ko4lf9dBbd3BVnLm4zl7Y
|
||||
--- YLhHK7p69aBksuFUcoRIfh9xej8HsQcDgrCUEyw4x64
|
||||
#\)V×¹ç{÷ËÆ½OøHK1lNæ(ˆß*ÒQ ^\aÉ�z(Ì?A»ý©·(#$Õè3Q” ·„¸£�K ã…p"I‘s)¼‡‹;½É1%
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,12 +1,11 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA 9wZ3G4vjwJhYungj/utZ/jgnQRD7qGHsMXM51gNFLyY
|
||||
SvdeK7R1AxveXXFJng21JK1fy+y7lh6OINB4CtUdS1Q
|
||||
-> ssh-ed25519 DFiohQ 1NIsoZWR4fY+bcROkw7iq+X0cYIE9g5IiWOqO0FvymQ
|
||||
igfAuxzfUSlhE3jaTMjqCYeF8ccKVyuUW+uD8JdH75c
|
||||
-> ssh-ed25519 wU682A g5y8TFpeJ0myejb8r7gL96JBk/q21KlDOBE6ZpCqv2A
|
||||
I/3aFKq2ne3gVeg+/1LmlKoDyg723yyjUdVdzgFzhV4
|
||||
--- JsRdNjJ285V+RGktIxJv29Alef95kpB2TOnYH66Wr4Q
|
||||
z¿
|
||||
n
|
||||
–´²xÇ‘␍Û¸"‹KA›x)ñÑ8 é…
|
||||
bçµ.)9„è#Š?ØxÔfMW/<Òîy• ÔHÜçݶOøš
|
||||
-> ssh-ed25519 osOCZA MFFVCO90Gx4QdHymLlxU4yjRdJr3JQR1Bvvjz57+D34
|
||||
xgGfp/ECiRGiWyp8sAjriHvy9b7GsiHQMCKYVHl1CSA
|
||||
-> ssh-ed25519 DFiohQ A5iL8qI5AcaXUmpplE5J0xQIWAryxM1E82VwWc2DhGo
|
||||
1dv2EqTkz6Z4HswQOYU5Q79Be0GZvc4HUyyqHWthtPk
|
||||
-> ssh-ed25519 wU682A qPkbSVvvQKJI0wcw7syZfKl7ZxTQpZdCwyT4CwjnbFw
|
||||
eT/8Z3Ei3/1oi0MEuqiBN/e9Rg8r3zRlUm3vtigl8cE
|
||||
--- 3hc/9smt2J3sIJLMDC/QByjE8bqlcNjR7FE9NBgOQp8
|
||||
¾>IÑY
|
||||
7wgö¼
|
||||
;ÏÇyî,øpå43@B3F‚;k(¼\ÊN&àÔÿÑÇý4Q•8Iúž‡MÿÁg!ÃîÜÚ£³
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA rqLqt3IrvBiIXneOWHFLJ3sBz3+dmNsl8LO6whM3Y2s
|
||||
5MSFsCQoaF97Ve6ossfYA+JezYy5Rod3Se4/y1kl7Go
|
||||
-> ssh-ed25519 DFiohQ 33r7cd+b7CKR2rVcPFlRIVwcLfHrEgXgD/bD//86IG4
|
||||
Jg/Nripa9RCtbXaS+1vHBwVBG2q3VMi56lnhEnZvqmo
|
||||
-> ssh-ed25519 PT7ffg uEatAaPQspVG41/O6d1oTkvhZUn2Au1TeJOlxBaVsXA
|
||||
0IATY8BEgVuVpYneH12F59Y+wIxnTh4QOTTajbQmWgY
|
||||
--- 22zYI0N7UXX09jMLZ6FXgXaeijamAiKWVSv02kF/HKY
|
||||
9$éN[”mÞŽò–ñN’fîq)`qgúÐÃnÏÅ?„˜ Ô1’«õs,´ü°u(x…µf Ŷ¨é›[\‘£vø:ÉákµòƒB1½ƒlš+5ß[ÛòèŽ ¹5ðž<æió1gÿ!ÆEµ8SŠ ¶xü.kÔaÒƒ�NåáãÍÁ‹ìÿN
|
||||
-> ssh-ed25519 osOCZA xdLLgxnXF6YwP6PA158Jk5PLd9DqMdD7iWzgxcig5ks
|
||||
mmjqlmU/6MyTaLUD63nyubvr+62SWik0a5wnlhuLQXY
|
||||
-> ssh-ed25519 DFiohQ BbxdetgH/z1ZUmzdKYLYFbSPx9y6vhqwZmMwlwRuCWM
|
||||
IpNVv3/EtML29RT9Ca8zrWM8gnGfk2iweW5RnXrTm94
|
||||
-> ssh-ed25519 PT7ffg f2BPj7TYxAnf1Os/VgMmxQ8g7DIhMdohUUe5y97WK1A
|
||||
zmNAbvgrV3tYQ8ZylZZ2P8v5FW7kklQt7XIkPqeIY9k
|
||||
--- 5RXgn5pqVJqKRAiZ9aA5uVL83P7fJHAs98R/iUC3tLs
|
||||
Ÿòb÷q§ÇA‰3ÇÒDâ”&kâK±Lï‰,û§|¤(�Àn8·žH‚'Q-µùJ$”ãÐZ°Ò�ïÓµ␍²�ûÀ¾ b;ˆ¾ññ Ñt®ç?Eÿ.±Ï=š�’E`åy£ÀcOËAc�ÍUt¨A.Úºýsº57¢²—CÖMÖemš‡÷˜ö ô
|
||||
@@ -1,9 +1,10 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA 5eUNORBIp4Nm9KJYBGsirBGNmJQTw2jjUW6qNzZZ+XU
|
||||
kEnw58503E8dVhigC/gq5LdsMCf/cQ6JE7qDVP04Gf4
|
||||
-> ssh-ed25519 DFiohQ IGSUfX4LH1HkCI+Na95AK4uoDi9sribs4ViL4B2Xo2Q
|
||||
X/BG7S7fU5b9K0tgeGJxLaeFUljaMCt8+y7+67M2zH0
|
||||
-> ssh-ed25519 PT7ffg OlYiDqfh3auTa8QvOmK3RMmCu3rCnrqxh2tyCwkQcRg
|
||||
/KFTAcZaTgq5Obq+27dTmI1F3gXxuW2leoUeLB+Xptg
|
||||
--- 2GuL6Gd+bx/V7KoFwa00YxEFS/WRoKCjYP89i9RoYOY
|
||||
„Öe44IÕ»3�¦Ô¹jóB½”G€9VýïìX¶Ò-ñ[£/…$íãà0E®Á8ºøð8lTF™â¡DCépMßÂNòN¬ªKžP‡ö¦[s{vúØ3QˆùƒöhÇiàÍ0™ç6Š$ÓÍrx/?ÉeØ“áM@˜2‘FRÖ2‰‚˜ÿ‘AB³+sÈÒ
|
||||
-> ssh-ed25519 osOCZA kxEAkm22oi+LCgW2w7T1GtuqBxz4m9aU4ceOf+0KInw
|
||||
oJ43lhfBnq03g4OWyIclsoyUjJM4IRXQcN+H8xUfOzs
|
||||
-> ssh-ed25519 DFiohQ UcmlGnwNYUjALCKI/90wC96JaeBU5NwX742yZ4JBpXQ
|
||||
l8Wwh7zdA6Ww/CSqI0UffuuL6/oD3nW5/ZcDm62a2b8
|
||||
-> ssh-ed25519 PT7ffg ViIZQL9IEiMKxsYkZSewoQlEtHCS2K66HWs22dCtsHM
|
||||
LkZwHCQWPP11iacPOC2HtGq6qpp+5owzSulTzGpDhzg
|
||||
--- gsZQ6BVOUwRjzTAED6JZHNo/Vz+m0wgN1VrCbJwS3Vo
|
||||
·‘ù
|
||||
›{V-ó/Ûñ]Ã"•)œ¹×ÕA'YÔ6>ؾíUý␍eÎp³¦<¬�±úɺ@ ŽpèwHÒ©eß蟖ñNןótsæq[Cí-£°õ{‘p 2ޝ“Ä»7ÀFÇZÔWYŠ1ïéû¯ž•£9j�QS�/9'A£8•�f×þuª
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
-1
@@ -9,7 +9,7 @@ let
|
||||
apu = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICAZkIuXtpP9a9bHkBl+MJI//q3ClMqzx03Rd/Xe4rjc";
|
||||
freun-dev = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEvCSjIjipog1Xf9mPc683r5VSGSjVc8v1UZg5VrbbxM";
|
||||
radish = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIQ0fy4n3yyD64+g55eZazeI5g9FurJnlC6fRiOXbbks";
|
||||
turny = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIODeWhDvzDGyTGkCoxay80NtgU2OVPL37qXjbhJP7oPJ";
|
||||
turny = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM3To9DeTGzwiQN+uqNWZXKzGG1BJnLvYRgLm0/iI92Y";
|
||||
in
|
||||
{
|
||||
"gotosocial.age".publicKeys = users ++ [ freun-dev ];
|
||||
@@ -49,6 +49,7 @@ in
|
||||
"open-webui.age".publicKeys = users ++ [ freun-dev ];
|
||||
"open-terminal-api-key.age".publicKeys = users ++ [ freun-dev ];
|
||||
"searx.age".publicKeys = users ++ [ freun-dev ];
|
||||
"grafana/secret-key.age".publicKeys = users ++ [ freun-dev ];
|
||||
"everii-vpn/de1.key.age".publicKeys = users ++ [ radish ];
|
||||
"everii-vpn/ch1.key.age".publicKeys = users ++ [ radish ];
|
||||
"everii-vpn/fi1.key.age".publicKeys = users ++ [ radish ];
|
||||
|
||||
Binary file not shown.
@@ -1,9 +1,10 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA PDFhOJbsfxCd5u8kqaeCMyFkeAYwRZriF1/OaF/4NU4
|
||||
4D63DStz2EiqVqKs75v2WqZb5yFJC6dyNw9g2Ew7flA
|
||||
-> ssh-ed25519 DFiohQ LedJzIxbcY0X/avsMfMmpFf+bzobyqVQbCJq+EzWiwg
|
||||
CNJIzwEETb9fkcnwUD6wSlhVEgXsZCX2vceHVWHC1lA
|
||||
-> ssh-ed25519 PT7ffg DdwjbqndzOwW9T8KR3HAWuL11UaGLwBLUl9Xistu8WY
|
||||
gBJSXMjqYsebwey4b0gT1Xv0FSsw6cLuQ09fOuOaDJQ
|
||||
--- mcc4EdBkqiYh1L9QQV3wTQCnZDdxqCOLzkp4eNu3TDQ
|
||||
!%ÛH0cSô¨ôÀÈ;¥èÙœCmk…<f¥¶–_Yð|ù␍ª72S°Êõ¹ñ€±–ujŒE.¸„Zƒ‚Z„¤Øö]×0–T
|
||||
-> ssh-ed25519 osOCZA PQtiqZbb169B6Ovwy86AExmBbrVteTQOFbjnDGJq3UM
|
||||
LFCbg+9gFnt4p5xHGHrfJXMJRjSGPPmpXd4pEIFtp2A
|
||||
-> ssh-ed25519 DFiohQ RqRirsYRaJ3RRLzvQIOohbF3uX6/5axomxhrO/SAjzA
|
||||
jUMEf1YYetb1JWYzeWT4cyT81O36KNm0fN8I5rmuRrE
|
||||
-> ssh-ed25519 PT7ffg ISuGZoBIQVdZv/17EKV+MNQHvqSTcj4ChLGvGew4KGQ
|
||||
QzjajsmaW+6CQc28cYAOuCLCwFY3c9qP0/uSa4z9yPM
|
||||
--- aDY1WIHOhshB9Yfv6tZ9Xip7Ms+88v4D++tGiSSI1A4
|
||||
mÎÔr¼&³A@j×
|
||||
B¯_W½r»1°½RúÆôv|Ð|ú|·Õd-TD¤VÝ&ÎãƒÍêɧˆøá3sÓŸ(S#*åF¾
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,11 +1,9 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 osOCZA 10afz8Gsoaz0OhJcU2my2bpsgAWNdMGN9FNo4jWgVm0
|
||||
yO9aFe0wbyp/5ZJeo3oK68FV3+C9wmp4o+PeMoRQ9qQ
|
||||
-> ssh-ed25519 DFiohQ 4VXaRz0iCATfp06eq1hnqKpd45jEGGeD1yMXuusKkTc
|
||||
eLQaUgEddJqyFwv8FZY9UufA5htvgYsNOvpNUWkVY/U
|
||||
-> ssh-ed25519 dLdKaA Mmr7xPZNZpRToQJmXKTJCT1SFNMeqDj8exP3p72iSEI
|
||||
ZPlltf6OR2yezsu1m58dx2H1Vr+2Gkh8ZYVEb508Zk8
|
||||
--- qSi+xziv//Wk/qkyYLkLMFqouti465SB8HxwsjZVmHk
|
||||
£žöw�G<ýEaA–|ÂâÉÛlv>nî²Î &(
|
||||
!øE3ÒñbB»ä6ï¥�nFð
|
||||
OßÚ„B´â ªsÑC,ÃÀÑd‡ê”Úú§ˆ-“Þí¥ÁltÉ^ê†iºx‚¢§¸è©$²uô1
|
||||
-> ssh-ed25519 osOCZA Ep20gMNYxJVHQMDKMp/TnHVy3Zmj/iwWtBfces/6AzQ
|
||||
fraHe346gWGZ18nupF+XFFT9aztAJ09HbP6v9MjutLA
|
||||
-> ssh-ed25519 DFiohQ UTM2LV9aG34x0hwvjYmY4HeYNUkZIxWbs/VX5/5W/WE
|
||||
5pO0tJeI+MIs+MTR90wpHrzPLtJAKQ0VXhF+hAel53M
|
||||
-> ssh-ed25519 ao8+sg 7fEP6GCczoek0RFPWoq06TbGnTJImS71p/otSAWR7hA
|
||||
+QkTcWOBuhQSKFH+eiImuTsk9SGZ2dnU2ZhQS63Ux8A
|
||||
--- gGwSfyEQWYSupnY3B4g8fwu9Pp2PpfPNPQ/mvtEpD8E
|
||||
ÆvQ6Èôæ‰ãú>“^¥N"Æôÿ�zdùº&Xì÷�u<È:üÔ%�»u|>P¾¨Èì.—aD×VÖ2LK=�øz¥¸%ÁÜÎõ¤¦[Á!ïæ¾êT� BÕ`7x/Ñd¦9ïN¤«'ïP
|
||||
@@ -0,0 +1,497 @@
|
||||
# Abdominal pain and tingling diagnosis
|
||||
|
||||
**Session ID:** ses_0fd155dc9ffew6VgVF3JAGjbxc
|
||||
**Created:** 6/26/2026, 10:52:39 AM
|
||||
**Updated:** 6/26/2026, 11:08:58 AM
|
||||
|
||||
---
|
||||
|
||||
## User
|
||||
|
||||
I describe a health issue and maybe you can try to make educated guesses what it might be. Research online if it helps.
|
||||
|
||||
Long enduring (months) very mild pain in the abdomen area. Feels a bit like the pain would be in the muscles. It's usually localized to one area but the area might be different on another day. At a later stage the symptoms included a feeling of stuffedness even though the person hasn't eaten much. Stool consistency and color normal. Latest symptom: A tingling feeling in the penis, a bit like it would be numb after being cut off circulation. Blood test results:
|
||||
|
||||
P-Kreatiniini: 75 umol/l
|
||||
P-Alaniiniaminotransferaasi: 31 U/l
|
||||
P-C-reaktiivinen proteiini: <4 mg/l
|
||||
B-Leukosyytit: 6.0 E9/l
|
||||
B-Erytrosyytit: 5.37 E12/l
|
||||
B-Hemoglobiini: 156 g/l
|
||||
E-Erytrosyytit, keskitilavuus: 86 fl
|
||||
E-Punasolujen kokojakauma: 12%
|
||||
E-Hemoglobiini, keskimassa: 29 pg
|
||||
E-Hemoglobiini, keskimassakonsentraatio: 339 g/l
|
||||
B-Trombosyytit: 267 E9/l
|
||||
Pt-Glomerulussuodatusnopeus, estimoitu: 111 ml/min/1.7
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
I'll research some of these symptoms to give you better-informed guesses. Let me look up a few things.
|
||||
|
||||
**Important disclaimer:** I'm a coding assistant, not a doctor. This is for informational purposes only — please see a healthcare professional.
|
||||
|
||||
Let me analyze the blood work first and research the symptom combination.
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
Let me try some other sources for research.
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
Let me search for a couple more conditions to round out my analysis.
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
Now let me search for one more condition that might be relevant.
|
||||
|
||||
**Tool: webfetch**
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
Here's my comprehensive analysis. **Disclaimer: I'm not a doctor — this is for informational purposes only. Please consult a healthcare professional.**
|
||||
|
||||
---
|
||||
|
||||
## Blood Work Analysis
|
||||
|
||||
**All values are within normal ranges:**
|
||||
|
||||
| Test | Value | Reference (male) | Status |
|
||||
|------|-------|-------------------|--------|
|
||||
| Creatinine | 75 µmol/l | 60-100 | Normal |
|
||||
| ALT | 31 U/l | <45 | Normal |
|
||||
| CRP | <4 mg/l | <5 | Normal (no inflammation) |
|
||||
| WBC | 6.0 E9/l | 3.4-8.5 | Normal (no infection) |
|
||||
| RBC | 5.37 E12/l | 4.2-5.7 | Normal |
|
||||
| Hemoglobin | 156 g/l | 134-167 | Normal (no anemia) |
|
||||
| MCV | 86 fl | 82-98 | Normal |
|
||||
| RDW | 12% | 11.5-14.5% | Normal |
|
||||
| MCH | 29 pg | 27-33 | Normal |
|
||||
| MCHC | 339 g/l | 320-360 | Normal |
|
||||
| Platelets | 267 E9/l | 150-360 | Normal |
|
||||
| eGFR | 111 ml/min/1.73m² | >90 | Excellent |
|
||||
|
||||
The completely normal panel **rules out** systemic infection, significant inflammation, anemia, liver dysfunction, and kidney dysfunction. This actually narrows things down considerably — it points toward functional, neurological, or musculoskeletal causes rather than inflammatory/infectious ones.
|
||||
|
||||
**Notably NOT tested** (worth requesting):
|
||||
- **Fasting glucose / HbA1c** — diabetes/pre-diabetes can cause neuropathy *and* gastroparesis (early satiety)
|
||||
- **PSA** — prostate issues
|
||||
- **TSH** — thyroid dysfunction
|
||||
- **Vitamin B12** — deficiency causes neuropathy
|
||||
- **Urinalysis** — urinary tract issues
|
||||
|
||||
---
|
||||
|
||||
## Ranked Differential Diagnoses
|
||||
|
||||
### 1. Chronic Pelvic Pain Syndrome (CP/CPPS) — *Best overall fit*
|
||||
|
||||
This is my top candidate. Also called chronic nonbacterial prostatitis (NIH Category III). Affects ~2-6% of men, peak age 35-45.
|
||||
|
||||
**Why it fits almost everything:**
|
||||
- **Mild, migrating abdominal pain** — Wikipedia lists "abdominal pain" as a symptom; pain can be in perineum, testicles, tip of penis, pubic/bladder area, and can radiate/wax and wane
|
||||
- **"Feels muscular"** — A key mechanism is **pelvic floor dysfunction with myofascial trigger points** — chronic unconscious contraction of pelvic floor muscles. The pain literally *is* muscular
|
||||
- **Migrating location** — Different trigger points in different muscle groups on different days explains why the pain area changes
|
||||
- **Penile tingling/numbness** — Wikipedia explicitly mentions "pain can be present in... tip of penis" and "constant burning pain in the penis"; the UPOINT classification system includes a Neurologic category
|
||||
- **Early satiety** — CP/CPPS is strongly associated with **IBS** (gut-bladder-brain axis); the MAPP Research Network specifically groups these conditions together
|
||||
- **Normal stool** — CP/CPPS itself doesn't typically affect stool consistency
|
||||
- **Normal blood work** — Characteristic; no infection found, no systemic inflammation
|
||||
- **Progressive symptoms** — The condition can worsen/expand over time, which matches the progression you describe (abdomen → fullness → penile tingling)
|
||||
|
||||
**Key quote from Wikipedia:** *"Symptoms may wax and wane. Pain can range from mild to debilitating. Pain may radiate to the back and rectum... Pain can be present in the perineum, testicles, tip of penis, pubic or bladder area... abdominal pain, constant burning pain in the penis..."*
|
||||
|
||||
**Treatment direction:** Pelvic floor physical therapy (trigger point release), stress management, possibly alpha-blockers or quercetin. Not antibiotics (unless clear infection evidence).
|
||||
|
||||
---
|
||||
|
||||
### 2. Pudendal Neuralgia / Nerve Entrapment — *Best fit for penile symptoms*
|
||||
|
||||
Compression or irritation of the pudendal nerve (S2-S4 nerve roots). Relatively uncommon but often underdiagnosed.
|
||||
|
||||
**Why it fits:**
|
||||
- **Penile tingling/numbness** — Wikipedia explicitly states: *"numbness of the penis"* and *"paresthesia (tingling / pins and needles)"* are characteristic symptoms. The dorsal nerve of the penis is a terminal branch of the pudendal nerve
|
||||
- **Lower abdominal pain** — Pain can be perceived in the perineum, genitals, suprapubic region, and lower abdomen
|
||||
- **Gradual onset** — *"The onset of pain symptoms is usually gradual without any single causative event"*
|
||||
- **Normal blood work** — No systemic markers expected
|
||||
- **Risk factor: prolonged sitting** — Wikipedia specifically lists **"programmers, office workers... drivers"** as at-risk. If you sit at a computer for long periods, this is highly relevant
|
||||
|
||||
**Why it's not #1:**
|
||||
- Pain is typically **worsened by sitting and relieved by standing/toilet seat** — you didn't mention this pattern (but also didn't say it's absent)
|
||||
- The **migrating** nature of the pain is somewhat atypical (pudendal pain is usually more fixed to one side/area)
|
||||
- **Early satiety** is not well explained by pudendal nerve issues alone
|
||||
- Pain character is usually more neuropathic (burning, electric shock-like) rather than "muscular"
|
||||
|
||||
**Diagnostic criteria (Nantes):** Pain in pudendal nerve territory, worsened by sitting, relieved by standing/lying, no objective sensory loss, positive pudendal nerve block.
|
||||
|
||||
---
|
||||
|
||||
### 3. Pelvic Floor Dysfunction / Myofascial Pain Syndrome — *Best fit for "muscular" feeling*
|
||||
|
||||
This is actually a key mechanism *behind* CP/CPPS, but can also exist independently.
|
||||
|
||||
**Why it fits:**
|
||||
- **"Feels like muscle pain"** — This *is* muscle pain; chronic tension in pelvic floor muscles (levator ani, coccygeus, piriformis) creates trigger points
|
||||
- **Migrating pain** — Different muscles/trigger points on different days
|
||||
- **Referred pain to abdomen and genitals** — Pelvic floor trigger points refer pain to the lower abdomen, groin, and penis
|
||||
- **Fullness/stuffedness** — Pelvic floor tension can affect bowel function and create a sensation of pelvic/abdominal fullness
|
||||
- **Penile tingling** — Nerve compression from tense muscles can cause paresthesia
|
||||
- **Normal blood work** — Expected
|
||||
|
||||
This often co-occurs with CP/CPPS and pudendal neuralgia — it may be the common underlying mechanism.
|
||||
|
||||
---
|
||||
|
||||
### 4. Irritable Bowel Syndrome (IBS) + Overlapping Pelvic Pain
|
||||
|
||||
**Why it partially fits:**
|
||||
- **Migrating abdominal pain** — Classic IBS symptom
|
||||
- **Early satiety/bloating** — Common in IBS
|
||||
- **Normal blood work** — Characteristic
|
||||
- **Comorbid with CP/CPPS** — Wikipedia on CP/CPPS: *"Men with CP/CPPS are more likely than the general population to have... irritable bowel syndrome (IBS)"*
|
||||
|
||||
**Why it's not higher:**
|
||||
- **Normal stool** — Atypical for IBS, which usually involves changes in bowel habits (diarrhea/constipation/mixed). You specifically noted stool consistency and color are normal
|
||||
- **Doesn't explain penile tingling** — IBS alone cannot cause this. IBS Wikipedia article mentions ~1/3 of IBS patients report sexual dysfunction (reduced libido), but not genital numbness/tingling
|
||||
- The "muscular" quality of pain is less typical for IBS (which is usually described as crampy/visceral)
|
||||
|
||||
However, IBS could be a **co-existing condition** alongside a pelvic floor/nerve issue, explaining the GI symptoms while the pelvic floor issue explains the penile symptoms.
|
||||
|
||||
---
|
||||
|
||||
### 5. Functional Dyspepsia (Postprandial Distress Syndrome subtype)
|
||||
|
||||
**Why it partially fits:**
|
||||
- **Early satiety** — This is the **hallmark symptom** of the PDS subtype. Wikipedia: *"troublesome early satiation"* is a diagnostic criterion
|
||||
- **Epigastric pain/discomfort** — Matches abdominal discomfort
|
||||
- **Normal blood work** — Characteristic
|
||||
- **Chronic, sporadic** — Matches the months-long duration with varying intensity
|
||||
|
||||
**Why it's not higher:**
|
||||
- Doesn't explain **migrating** pain (FD pain is typically epigastric)
|
||||
- Doesn't explain **penile tingling** at all
|
||||
- Doesn't explain the **"muscular"** quality
|
||||
|
||||
This could be a **separate co-existing condition** — one condition explaining the GI symptoms (functional dyspepsia) and another explaining the pelvic/penile symptoms (CP/CPPS or pudendal neuralgia).
|
||||
|
||||
---
|
||||
|
||||
### 6. Small Fiber Neuropathy — *Interesting unifying possibility*
|
||||
|
||||
Damage to small unmyelinated nerve fibers. Can be "patchy" and migrating.
|
||||
|
||||
**Why it's interesting:**
|
||||
- **Tingling/numbness** — Characteristic symptom (penile tingling fits)
|
||||
- **Migrating/patchy pain** — Non-length-dependent variant can affect many areas sporadically
|
||||
- **Autonomic involvement** — If autonomic fibers are affected, could explain early satiety (gastroparesis-like) and possibly bowel/bladder issues
|
||||
- **Normal routine blood work** — Standard panels don't detect it; requires skin biopsy for diagnosis
|
||||
|
||||
**Why it's lower:**
|
||||
- Pain is usually described as **burning/stabbing**, not "mild muscular pain"
|
||||
- Usually starts in **feet/hands** (length-dependent pattern), though non-length-dependent variants exist
|
||||
- Common causes include **diabetes/pre-diabetes** — and glucose was **not tested** in this panel
|
||||
- Would be a less common explanation for this symptom cluster
|
||||
|
||||
**If suspected:** Request fasting glucose, HbA1c, vitamin B12, and possibly a skin punch biopsy for intraepidermal nerve fiber density.
|
||||
|
||||
---
|
||||
|
||||
### 7. Lumbosacral Radiculopathy (Nerve Root Irritation)
|
||||
|
||||
**Why it's possible:**
|
||||
- **Migrating pain** — Different nerve roots irritated on different days
|
||||
- **Penile tingling** — Pudendal nerve roots (S2-S4) in the sacral spine
|
||||
- **Abdominal wall pain** — Referred pain from thoracic/lumbar nerve roots
|
||||
- **Normal blood work** — Expected
|
||||
|
||||
**Why it's lower:**
|
||||
- Usually accompanied by **back pain** (not mentioned)
|
||||
- Early satiety not well explained
|
||||
- Would need MRI of lumbar/sacral spine to diagnose
|
||||
- The "muscular" quality is less typical (radicular pain is usually sharp/shooting)
|
||||
|
||||
---
|
||||
|
||||
### 8. Abdominal Cutaneous Nerve Entrapment Syndrome (ACNES)
|
||||
|
||||
**Why it partially fits:**
|
||||
- **Localized abdominal wall pain** that feels superficial/muscular
|
||||
- Can change locations (different nerve branches)
|
||||
- Normal blood work
|
||||
- Often missed by doctors
|
||||
|
||||
**Why it's low:**
|
||||
- Doesn't explain **penile tingling**
|
||||
- Doesn't explain **early satiety**
|
||||
- Only explains the abdominal pain component
|
||||
|
||||
---
|
||||
|
||||
### 9. Occult Inguinal Hernia
|
||||
|
||||
**Why it's possible:**
|
||||
- Localized pain that can vary
|
||||
- Can affect nerves (genital branch of genitofemoral nerve) → penile tingling
|
||||
- May cause fullness sensation
|
||||
- Normal blood work
|
||||
|
||||
**Why it's low:**
|
||||
- Migrating pain is atypical
|
||||
- Usually more groin-specific pain
|
||||
- Early satiety not well explained
|
||||
- Would need physical exam/ultrasound to detect
|
||||
|
||||
---
|
||||
|
||||
## Summary & Synthesis
|
||||
|
||||
The most coherent single explanation is **CP/CPPS with pelvic floor dysfunction**, possibly with overlapping **IBS or functional dyspepsia** explaining the early satiety. The symptom progression (abdominal pain → fullness → penile tingling) fits a pelvic floor/neurological condition that's gradually affecting more areas.
|
||||
|
||||
The **completely normal blood work** is reassuring — it rules out infection, inflammation, and organ dysfunction. This strongly points toward a **functional/neurological/musculoskeletal** cause rather than a structural or inflammatory disease.
|
||||
|
||||
**Key questions to consider:**
|
||||
1. Is the pain **worsened by sitting** and relieved by standing? (→ pudendal neuralgia)
|
||||
2. Do you sit for prolonged periods? (→ both pudendal and pelvic floor issues)
|
||||
3. Has blood glucose ever been checked? (→ neuropathy/gastroparesis possibility)
|
||||
4. Any urinary symptoms? (frequency, urgency, pain with urination?) (→ CP/CPPS)
|
||||
5. Any lower back pain? (→ radiculopathy)
|
||||
|
||||
**Suggested next steps with a doctor:**
|
||||
- **Urology referral** — for prostate/pelvic floor evaluation (CP/CPPS assessment)
|
||||
- **Fasting glucose / HbA1c** — rule out diabetes/pre-diabetes
|
||||
- **Pelvic floor physical therapy evaluation** — assess for trigger points and muscle tension
|
||||
- Consider **abdominal/pelvic ultrasound** to rule out structural causes
|
||||
- **PSA** if age-appropriate
|
||||
- **Vitamin B12** — deficiency can cause neuropathy
|
||||
|
||||
The good news is that the normal blood work and absence of red flag symptoms (no weight loss, no bleeding, no anemia, normal stool) make serious organic disease unlikely.
|
||||
|
||||
---
|
||||
|
||||
## User
|
||||
|
||||
The patient rides a bike 60 minutes a day at least and reports of numbness in the penis after unmounting the bicycle some times if the saddle is in a bad position. Could this be a contributing factor or change your hypothesis?
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
This is a **major** piece of information that significantly strengthens the pudendal neuralgia/entrapment hypothesis and likely makes it the primary diagnosis.
|
||||
|
||||
## Why This Changes Things
|
||||
|
||||
The Wikipedia article on pudendal nerve entrapment literally has a section called **"In cyclists"** and lists the condition's alternate name as **"cyclist syndrome"**:
|
||||
|
||||
> *"In male competitive cyclists, it is often called 'cyclist syndrome'. This is a rare condition in which recurrent numbness of the penis and scrotum develops after prolonged cycling."*
|
||||
|
||||
> *"Nerve entrapment syndromes, presenting as genital numbness, are amongst the most common bicycling associated urogenital problems."*
|
||||
|
||||
> *"Pudendal nerve entrapment can develop in cyclists; likely due to both the compression and stretching of the pudendal nerve for prolonged time."*
|
||||
|
||||
The patient is **already experiencing the acute version** of this — temporary penile numbness after cycling with a bad saddle position. That's the pudendal nerve being compressed against the saddle/ischial rami through Alcock's canal. Over months of daily 60-minute rides, this repeated compression can progress to **chronic pudendal neuralgia** — which explains the symptom progression.
|
||||
|
||||
## Revised Hypothesis
|
||||
|
||||
**Pudendal nerve compression/neuralgia from cycling** is now the leading diagnosis, with **secondary pelvic floor dysfunction** explaining the muscular-quality migrating abdominal pain:
|
||||
|
||||
| Symptom | Explanation via Pudendal Neuralgia |
|
||||
|---------|-------------------------------------|
|
||||
| Penile tingling/numbness | **Direct** — dorsal nerve of penis is terminal branch of pudendal nerve; already demonstrably compressed by cycling |
|
||||
| Migrating "muscular" abdominal pain | **Secondary** — chronic nerve irritation → pelvic floor muscle tension → trigger points in different muscle groups on different days |
|
||||
| Early satiety/stuffedness | Pelvic floor tension affecting bowel function; pudendal nerve has autonomic fibers; possible overlap with IBS (common comorbidity) |
|
||||
| Progressive course | Cumulative nerve damage from repeated daily compression |
|
||||
| Normal blood work | Expected — nerve compression doesn't show in standard panels |
|
||||
| Migrating location | Different nerve branches/muscle groups irritated on different days |
|
||||
|
||||
## What Doesn't Quite Fit Pudendal Neuralgia Alone
|
||||
|
||||
- **Migrating pain** — pudendal pain is usually more fixed (perineum/genitals/suprapubic), though central sensitization can spread it
|
||||
- **Early satiety** — not a classic pudendal symptom, though pelvic floor secondary effects could explain it
|
||||
- **Mild pain** — pudendal neuralgia is usually more severe/burning, but early-stage or mild compression could present this way
|
||||
|
||||
This is likely **pudendal nerve compression (from cycling) + secondary pelvic floor dysfunction**, possibly with an overlapping functional GI component (IBS/functional dyspepsia) explaining the satiety — the MAPP Network research groups all these as related urologic chronic pelvic pain syndromes (UCPPS).
|
||||
|
||||
## Practical Recommendations
|
||||
|
||||
**Immediate (before seeing a doctor):**
|
||||
- **Saddle change** — get a saddle with a perineal cutout or a no-nose saddle (removes pressure from the pudendal canal area)
|
||||
- **Saddle tilt** — tilt the nose slightly down to shift weight to the sit bones (ischial tuberosities) instead of the perineum
|
||||
- **Saddle height/position** — have a bike shop do a proper fit; too high = more perineal pressure
|
||||
- **Stand regularly** — get out of the saddle every 10-15 minutes during rides
|
||||
- **Consider temporarily reducing** cycling frequency to see if symptoms improve
|
||||
|
||||
**Medical next steps:**
|
||||
- **Urologist or pelvic pain specialist** — specifically one familiar with pudendal neuralgia / cyclist syndrome
|
||||
- Mention the cycling and the post-ride numbness explicitly — this is the key diagnostic clue
|
||||
- A **diagnostic pudendal nerve block** (local anesthetic injection) can confirm the diagnosis — if pain temporarily resolves, it's pudendal
|
||||
- **Pelvic floor physical therapy** — to address secondary muscle tension/trigger points
|
||||
- Still worth checking **fasting glucose/HbA1c** to rule out diabetic neuropathy as a cofactor
|
||||
|
||||
The encouraging part: if caught before permanent nerve damage, pudendal neuralgia from cycling often improves with conservative measures (saddle change, positioning, PT). The fact that the numbness is already position-dependent suggests the nerve isn't permanently damaged yet — it's still a dynamic compression issue.
|
||||
|
||||
---
|
||||
|
||||
## User
|
||||
|
||||
Any questions you'd ask the patient?
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
Here are the questions I'd ask, grouped by what they'd help distinguish:
|
||||
|
||||
## Pudendal Neuralgia vs. CP/CPPS vs. Other
|
||||
|
||||
1. **Is the pain worsened by sitting, and relieved by standing up or sitting on a toilet seat?** — The single most diagnostic question for pudendal nerve entrapment (Nantes criteria). If yes → strongly pudendal. If no → more likely CP/CPPS or pelvic floor dysfunction.
|
||||
|
||||
2. **Is the pain always on the same side, or does it switch sides?** — Pudendal neuralgia is usually unilateral or bilateral but fixed. Migrating sides suggests pelvic floor trigger points or a more systemic cause.
|
||||
|
||||
3. **Does the pain wake you up at night?** — Pudendal neuralgia typically does *not* wake patients at night (pain is position-dependent). Night pain that disrupts sleep would suggest other causes (inflammatory, neoplastic).
|
||||
|
||||
## Prostate / Urinary (CP/CPPS Assessment)
|
||||
|
||||
4. **Any urinary symptoms?** — Frequency, urgency, hesitancy, weak stream, pain with urination, or waking to urinate at night? These would point toward CP/CPPS or BPH.
|
||||
|
||||
5. **Any pain during or after ejaculation?** — A hallmark of CP/CPPS. Wikipedia: *"Post-ejaculatory pain is a hallmark of the condition."*
|
||||
|
||||
6. **Any pain in the perineum (area between scrotum and anus), testicles, or rectum?** — Core CP/CPPS and pudendal territories.
|
||||
|
||||
## Cycling Details
|
||||
|
||||
7. **How long has the post-ride numbness been happening, and has it gotten worse or more frequent over time?** — Progression from temporary numbness to persistent tingling would confirm cumulative nerve damage.
|
||||
|
||||
8. **Does the penile tingling persist even on days you don't cycle?** — If yes → the nerve irritation has become chronic/independent of cycling. If it only happens after riding → still purely positional/compression-related.
|
||||
|
||||
9. **What type of saddle, and have you tried different ones?** — Narrow racing saddles cause more perineal pressure than wider/cutout saddles.
|
||||
|
||||
10. **Do you use padded cycling shorts?** — No chamois = more direct pressure.
|
||||
|
||||
## GI / Functional Dyspepsia / IBS
|
||||
|
||||
11. **Is the "stuffedness" related to meals, or is it constant regardless of eating?** — Meal-related early satiety → functional dyspepsia. Constant fullness → pelvic floor tension or IBS overlap.
|
||||
|
||||
12. **Any nausea, heartburn, or bloating?** — Would support functional dyspepsia or gastroparesis.
|
||||
|
||||
13. **Has there been any change in bowel habits at all — even subtle?** — Frequency changes, urgency, or alternating constipation/diarrhea would suggest IBS. The patient says stool is normal, but frequency/urgency weren't specified.
|
||||
|
||||
14. **Any unintentional weight loss?** — Red flag for organic disease (malignancy, IBD). The normal blood work makes this unlikely but it's important to confirm.
|
||||
|
||||
## Neuropathy / Systemic
|
||||
|
||||
15. **Any tingling or numbness anywhere else — feet, hands, legs?** — Would suggest a more generalized small fiber neuropathy (diabetes, B12 deficiency) rather than isolated pudendal compression.
|
||||
|
||||
16. **Has blood sugar ever been checked? Any family history of diabetes?** — Pre-diabetes/diabetes is the most common cause of small fiber neuropathy and could also cause gastroparesis (early satiety).
|
||||
|
||||
17. **Any history of lower back injury, herniated disc, or sciatica?** — Could point to lumbosacral radiculopathy affecting S2-S4 roots (which include pudendal nerve roots).
|
||||
|
||||
## General / Red Flags
|
||||
|
||||
18. **How old is the patient?** — CP/CPPS peaks at 35-45. Pudendal neuralgia can occur at any age. Prostate issues (BPH, cancer) become more relevant >45-50.
|
||||
|
||||
19. **Any fever, night sweats, or fatigue?** — Would suggest infection or systemic illness (all absent from blood work, but worth confirming clinically).
|
||||
|
||||
20. **Has the patient taken any medications, especially PPIs (omeprazole etc.) or NSAIDs, long-term?** — PPIs can cause SIBO → IBS-like symptoms. Chronic NSAIDs can cause gastric issues → functional dyspepsia-like symptoms.
|
||||
|
||||
21. **Any prior abdominal surgeries or hernias?** — Could cause adhesions or nerve entrapment.
|
||||
|
||||
22. **Stress levels / anxiety?** — Both CP/CPPS and functional dyspepsia are strongly linked to the gut-brain axis and stress; Wikipedia on CP/CPPS: *"anxiety or stress results in chronic, unconscious contraction of the pelvic floor muscles."*
|
||||
|
||||
---
|
||||
|
||||
The **three highest-yield questions** would be #1 (sitting/standing pattern), #5 (ejaculatory pain), and #15 (tingling elsewhere) — those alone would substantially narrow the differential.
|
||||
|
||||
---
|
||||
|
||||
## User
|
||||
|
||||
1. Unconclusive, 2. not always on the same side. 3. No, 4. No, 5, No, 6. No, 7. Has been happening pretty much since the patient started bike commuting. 8. Since yesterday, yes. 9. It's a pretty comfortable one with suspension (commuter bike). 10. No, 11. Unconclusive, maybe unrelated to eating. 12. No. 13. Sometimes (rarely, maybe once every two weeks) diarrhea or very loose stool, no constipation. 14. No, 15. No, 16. No, but the patient has a blood sugar meter available and could check. 17. No, 18: 38, 19: No, 20: No, 21: No, 22. Very mild if at all.
|
||||
|
||||
---
|
||||
|
||||
## Assistant
|
||||
|
||||
This is very informative. Let me reassess.
|
||||
|
||||
## What the Answers Rule Out or Weaken
|
||||
|
||||
**CP/CPPS is now significantly less likely.** The absence of its three hallmark features is telling:
|
||||
- No urinary symptoms (common in CP/CPPS)
|
||||
- No ejaculatory pain (Wikipedia calls this a *"hallmark of the condition"*)
|
||||
- No perineal/testicular/rectal pain (core CP/CPPS territory)
|
||||
- Low stress (stress is a key driver)
|
||||
|
||||
**Functional dyspepsia is weaker** — stuffedness may not be meal-related, and there's no nausea, heartburn, or bloating.
|
||||
|
||||
**Small fiber neuropathy is much less likely** — no tingling anywhere else, no known diabetes.
|
||||
|
||||
**Radiculopathy is unlikely** — no back pain, no other neurological symptoms.
|
||||
|
||||
## What Remains Strong
|
||||
|
||||
**The critical new finding is answer #8** — tingling now persists on non-cycling days (started yesterday). This suggests the nerve irritation is transitioning from **reversible positional compression** to **chronic neuralgia**. This is a turning point and arguably a reason to act soon.
|
||||
|
||||
The picture now looks like **two related cycling overuse problems**:
|
||||
|
||||
### Problem 1: Pudendal nerve compression (specifically dorsal nerve of penis)
|
||||
- Penile numbness after cycling (confirmed, long-standing)
|
||||
- Now tingling persisting off-bike (new development as of yesterday)
|
||||
- The dorsal nerve of the penis is a terminal branch of the pudendal nerve that runs along the ischiopubic ramus — directly where a saddle presses
|
||||
- This could be **Type IV entrapment** (terminal branch, 13% of cases in the Wikipedia article) which would explain why there's no perineal/rectal pain — only the penile branch is affected
|
||||
- **No padded shorts** (answer #10) is a significant risk factor — more direct perineal pressure every ride
|
||||
|
||||
### Problem 2: Pelvic floor / hip flexor muscle tension from cycling
|
||||
- Migrating "muscular" abdominal pain, not always same side
|
||||
- Sensation of fullness/stuffedness unrelated to meals
|
||||
- Cycling engages hip flexors, adductors, and pelvic floor muscles continuously; chronic tension in these muscles refers pain to the lower abdomen and can create a sensation of pelvic fullness
|
||||
- Occasional loose stools (every ~2 weeks) could be explained by pelvic floor dysfunction affecting bowel function
|
||||
|
||||
These two problems may be **independent consequences of the same activity** rather than one causing the other — simpler and more parsimonious than my earlier CP/CPPS hypothesis.
|
||||
|
||||
## Immediate Actions I'd Recommend
|
||||
|
||||
**Today:**
|
||||
1. **Check fasting blood sugar** with the available meter — quick, free, rules out diabetes as a neuropathy cofactor
|
||||
2. **Stop or significantly reduce cycling** temporarily — the transition to persistent off-bike tingling is a warning sign. Give the nerve a chance to recover before it becomes permanent
|
||||
|
||||
**This week:**
|
||||
3. **Get padded cycling shorts** if continuing to ride — this is the lowest-hanging fruit
|
||||
4. **Try a no-nose or cutout saddle** — removes perineal pressure entirely
|
||||
5. **Book a urology appointment** — mention cycling, penile numbness, and that tingling is now persisting off-bike. This is the key clinical detail that should get their attention
|
||||
|
||||
**If symptoms don't improve within 2-4 weeks of stopping cycling:**
|
||||
6. **Pelvic floor physical therapy** — for the muscular abdominal pain and fullness
|
||||
7. **Consider a pudendal nerve block** (diagnostic) if a specialist suspects neuralgia
|
||||
|
||||
## One More Question
|
||||
|
||||
**Has the patient ever tried completely stopping cycling for a week or more, and if so, did the symptoms improve?** — This would be the natural experiment that confirms or refutes cycling as the cause. If the abdominal pain and fullness also improve with stopping, it strongly confirms that both problems are cycling-related.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user