mirror of
https://github.com/itme-brain/nixos.git
synced 2026-05-08 14:50:12 -04:00
Compare commits
No commits in common. "042820fb2a88c46389e477abf5181b78d02222a3" and "66928072293bf73596690d578ec6f3be6675ebe9" have entirely different histories.
042820fb2a
...
6692807229
8 changed files with 53 additions and 97 deletions
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"WebSearch",
|
||||||
|
"WebFetch(domain:forgejo.org)",
|
||||||
|
"Bash(ssh:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
*.qcow2
|
*.qcow2
|
||||||
result
|
result
|
||||||
.direnv
|
.direnv
|
||||||
.claude
|
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,13 @@ creation_rules:
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *desktop
|
- *desktop
|
||||||
# Shared secrets (desktop + server)
|
|
||||||
- path_regex: secrets/system/llama\.yaml$ # llama.cpp API key
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *desktop
|
|
||||||
- *server
|
|
||||||
# Server secrets (cameras)
|
# Server secrets (cameras)
|
||||||
- path_regex: secrets/system/cameras\.yaml$ # RTSP Feed
|
- path_regex: secrets/system/cameras\.yaml$ # RTSP Feed
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *server
|
- *server
|
||||||
# Server secrets (searxng)
|
# Server secrets (searxng)
|
||||||
- path_regex: secrets/system/searxng\.yaml$ # searxng token
|
- path_regex: secrets/system/searxng\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *server
|
- *server
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
LLAMA_API_KEY: ENC[AES256_GCM,data:ZVDpwGAxnHbHxt+JW3mYGyyBU5JfFAbjc/byq6Ok9wTlpQZBx969Z0wV74F5pR4axmpdGs7XlZDh1rJaQTn7lg==,iv:oAG9G25x+1FRkRNBRzLW2UJmbSxgx5Cu64Qo/6VzAyw=,tag:nkO/SdzjjLxH4fkgIdwUYQ==,type:str]
|
|
||||||
sops:
|
|
||||||
age:
|
|
||||||
- recipient: age17ejyzyk52unr6eyaa9rpunxpmf7u9726v6sx7me3ww3mdu5xzgjqsgj9gl
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzUmV6Q2dCMWU3TUFkZ0I0
|
|
||||||
dHA3dXd2U0RSRzNtL3YvdG8rYWdnOTZoTkMwCkNnYnVlVmMyRDNnS1FmWktlNU9N
|
|
||||||
UW1OMlJYODVzSHNIZWZMRkpPY05Ed3cKLS0tIDg0b0VkT0NrS3NIWE9EdWtWYXc1
|
|
||||||
NjNESHpYbVptcnVRYWFKb3RlYkJ6OWMK3JsRXPDvJdKv2UyYIH8kr/WKbXgUDXbc
|
|
||||||
fYOD0Huo73BA0vr8PlrsF4STVgJr/arKCMdI1C0bDdcwjExKnR1tIw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age198jg29ryg3c0qj3yg6y9ha4ce2ue4hjdaa9kalf49fxju74dhchsquvjzp
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFTGNKOWczaityaXowWi9I
|
|
||||||
dmh0MjJoelV3bVlzeGpLZmVTVzJjckwwQUFzCk81ZHlTcm5oWHRQNklreUR4bWNS
|
|
||||||
OVdQelQ4YXkzeWZqOWZoNWlOVkZpWUkKLS0tIDZKQUU3LzV0UUhnRHVHQkFadkxm
|
|
||||||
djRyUEYyZ2srMlVxR0JtQlFqSWV1QWcKMIF9Sq4TUUmpVZAukjTjFbIrMxcE3+el
|
|
||||||
QSrHIm1HXLXwCKLDQ2N6b8Q9iUo/XMV0wsD3TLxdnUfegpQpfsDhag==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2026-04-14T05:45:37Z"
|
|
||||||
mac: ENC[AES256_GCM,data:G+o6OhNF5AFBDKQEU3f1MZ+GOkxQj/m7NNk4Ti8PxPPOHdByoCrauvgB78SdQf5ubcfupElcNB0yF5QsG3/m7eGaSA+8J0cDL6jB3NEE5EUbW1Fuzzg2Ez1JnFu4BstkLiDRD/TribXMNFAjykmNrHt4zee6fhU3H0MOn7+Acok=,iv:IqBLSBq1kOMRHQn1IvU8OgmWGn6EFJcef/rNr38txmY=,tag:/mSWgbPbhUNoIm3x+6zyRA==,type:str]
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.12.1
|
|
||||||
|
|
@ -5,10 +5,6 @@ let
|
||||||
(user: user.modules.user.security.gpg.enable or false)
|
(user: user.modules.user.security.gpg.enable or false)
|
||||||
(lib.attrValues config.home-manager.users);
|
(lib.attrValues config.home-manager.users);
|
||||||
|
|
||||||
devEnabled = lib.any
|
|
||||||
(user: user.modules.user.utils.dev.enable or false)
|
|
||||||
(lib.attrValues config.home-manager.users);
|
|
||||||
|
|
||||||
sysModules = config.modules.system;
|
sysModules = config.modules.system;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
@ -23,11 +19,6 @@ in
|
||||||
"WIFI_HOME_PSK" = wifi;
|
"WIFI_HOME_PSK" = wifi;
|
||||||
"WIFI_CAMS_SSID" = wifi;
|
"WIFI_CAMS_SSID" = wifi;
|
||||||
"WIFI_CAMS_PSK" = wifi;
|
"WIFI_CAMS_PSK" = wifi;
|
||||||
} // lib.optionalAttrs devEnabled {
|
|
||||||
"LLAMA_API_KEY" = {
|
|
||||||
sopsFile = ../../../secrets/system/llama.yaml;
|
|
||||||
owner = config.user.name;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.templates."wifi-env".content = ''
|
sops.templates."wifi-env".content = ''
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
searxng.enable = mkEnableOption "Publicly exposed SearXNG endpoint with secret path via sops";
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
@ -91,6 +92,17 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtualHosts."test.${domain}" = {
|
||||||
|
useACMEHost = domain;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
return = "200 'nginx is working'";
|
||||||
|
extraConfig = ''
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
virtualHosts."wg.${domain}" = {
|
virtualHosts."wg.${domain}" = {
|
||||||
useACMEHost = domain;
|
useACMEHost = domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
|
@ -104,49 +116,32 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualHosts."ai.${domain}" = let
|
virtualHosts."searxng.${domain}" = mkIf cfg.searxng.enable {
|
||||||
apiKeyAuth = ''
|
|
||||||
set $api_key "";
|
|
||||||
if ($http_authorization ~* "^Bearer (.+)$") {
|
|
||||||
set $api_key $1;
|
|
||||||
}
|
|
||||||
if ($api_key = "") {
|
|
||||||
return 401 '{"error": "Missing Authorization header"}';
|
|
||||||
}
|
|
||||||
include ${config.sops.templates."nginx-ai-auth.conf".path};
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
useACMEHost = domain;
|
useACMEHost = domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
locations."/".return = "404";
|
||||||
|
extraConfig = ''
|
||||||
|
include ${config.sops.templates."nginx-searxng-location.conf".path};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# Web UI + llama.cpp API (browser, /v1/* calls from the UI)
|
virtualHosts."chat.${domain}" = {
|
||||||
# Auth handled by llama.cpp itself (--api-key flag)
|
useACMEHost = domain;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://192.168.0.23:3080";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = privateAccessRules;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualHosts."ai.${domain}" = {
|
||||||
|
useACMEHost = domain;
|
||||||
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://192.168.0.23:8000";
|
proxyPass = "http://192.168.0.23:8000";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Llama Stack API (opencode, programmatic clients)
|
|
||||||
# Clients use baseURL: https://ai.ramos.codes/stack/v1
|
|
||||||
locations."/stack/v1/" = {
|
|
||||||
proxyPass = "http://192.168.0.23:8321/v1/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = apiKeyAuth + ''
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# MCP servers (namespaced, for llama.cpp web UI + direct access)
|
|
||||||
locations."/mcp/web_search/" = {
|
|
||||||
proxyPass = "http://192.168.0.23:8002/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
include ${config.sops.templates."nginx-mcp-auth.conf".path};
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualHosts."comfy.${domain}" = {
|
virtualHosts."comfy.${domain}" = {
|
||||||
|
|
|
||||||
|
|
@ -9,28 +9,20 @@
|
||||||
# Camera RTSP credentials (used by frigate/go2rtc)
|
# Camera RTSP credentials (used by frigate/go2rtc)
|
||||||
sops.secrets = let
|
sops.secrets = let
|
||||||
cameras = { sopsFile = ../../../secrets/system/cameras.yaml; };
|
cameras = { sopsFile = ../../../secrets/system/cameras.yaml; };
|
||||||
llama = { sopsFile = ../../../secrets/system/llama.yaml; };
|
searxng = { sopsFile = ../../../secrets/system/searxng.yaml; };
|
||||||
in {
|
in {
|
||||||
"RTSP_USER" = cameras;
|
"RTSP_USER" = cameras;
|
||||||
"RTSP_PASS" = cameras;
|
"RTSP_PASS" = cameras;
|
||||||
"LLAMA_API_KEY" = llama // { owner = config.user.name; };
|
"SEARXNG_TOKEN" = searxng;
|
||||||
};
|
};
|
||||||
|
|
||||||
# API key auth for ai.ramos.codes — nginx validates Bearer token against sops secret
|
sops.templates."nginx-searxng-location.conf" = {
|
||||||
sops.templates."nginx-ai-auth.conf" = {
|
|
||||||
content = ''
|
content = ''
|
||||||
if ($api_key != "${config.sops.placeholder."LLAMA_API_KEY"}") {
|
location /${config.sops.placeholder."SEARXNG_TOKEN"}/ {
|
||||||
return 401 '{"error": "Invalid API key"}';
|
proxy_pass http://192.168.0.23:8080/;
|
||||||
}
|
proxy_http_version 1.1;
|
||||||
'';
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
owner = "nginx";
|
proxy_set_header Connection "upgrade";
|
||||||
};
|
|
||||||
|
|
||||||
# MCP endpoint auth — validates X-API-Key header
|
|
||||||
sops.templates."nginx-mcp-auth.conf" = {
|
|
||||||
content = ''
|
|
||||||
if ($http_x_api_key != "${config.sops.placeholder."LLAMA_API_KEY"}") {
|
|
||||||
return 401 '{"error": "Unauthorized"}';
|
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
owner = "nginx";
|
owner = "nginx";
|
||||||
|
|
@ -39,6 +31,7 @@
|
||||||
modules.system = {
|
modules.system = {
|
||||||
nginx = {
|
nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
searxng.enable = true;
|
||||||
};
|
};
|
||||||
sandpack.enable = true;
|
sandpack.enable = true;
|
||||||
forgejo.enable = true;
|
forgejo.enable = true;
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
bash = {
|
#bash = {
|
||||||
initExtra = "export LLAMA_API_KEY=$(cat /run/secrets/LLAMA_API_KEY)";
|
# initExtra = import ./config/penpot.nix;
|
||||||
};
|
#};
|
||||||
direnv = {
|
direnv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableBashIntegration = true;
|
enableBashIntegration = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue