mirror of
https://github.com/itme-brain/nixos.git
synced 2026-05-08 14:50:12 -04:00
Compare commits
11 commits
6692807229
...
042820fb2a
| Author | SHA1 | Date | |
|---|---|---|---|
| 042820fb2a | |||
| 9ad55ac79a | |||
| d8be05169c | |||
| 573f5ec95d | |||
| 46adf8e9f0 | |||
| 3feb5ddc6b | |||
| 54b2a18d66 | |||
| cb5b10493f | |||
| c41a6ff637 | |||
| 07586a80ee | |||
| 27f765fe22 |
8 changed files with 96 additions and 52 deletions
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"WebSearch",
|
|
||||||
"WebFetch(domain:forgejo.org)",
|
|
||||||
"Bash(ssh:*)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
*.qcow2
|
*.qcow2
|
||||||
result
|
result
|
||||||
.direnv
|
.direnv
|
||||||
|
.claude
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,19 @@ 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$
|
- path_regex: secrets/system/searxng\.yaml$ # searxng token
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *server
|
- *server
|
||||||
|
|
|
||||||
25
secrets/system/llama.yaml
Normal file
25
secrets/system/llama.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
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,6 +5,10 @@ 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
|
||||||
|
|
@ -19,6 +23,11 @@ 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,7 +22,6 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
searxng.enable = mkEnableOption "Publicly exposed SearXNG endpoint with secret path via sops";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
@ -92,17 +91,6 @@ 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;
|
||||||
|
|
@ -116,32 +104,49 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualHosts."searxng.${domain}" = mkIf cfg.searxng.enable {
|
virtualHosts."ai.${domain}" = let
|
||||||
useACMEHost = domain;
|
apiKeyAuth = ''
|
||||||
forceSSL = true;
|
set $api_key "";
|
||||||
locations."/".return = "404";
|
if ($http_authorization ~* "^Bearer (.+)$") {
|
||||||
extraConfig = ''
|
set $api_key $1;
|
||||||
include ${config.sops.templates."nginx-searxng-location.conf".path};
|
}
|
||||||
|
if ($api_key = "") {
|
||||||
|
return 401 '{"error": "Missing Authorization header"}';
|
||||||
|
}
|
||||||
|
include ${config.sops.templates."nginx-ai-auth.conf".path};
|
||||||
'';
|
'';
|
||||||
};
|
in {
|
||||||
|
|
||||||
virtualHosts."chat.${domain}" = {
|
|
||||||
useACMEHost = domain;
|
useACMEHost = domain;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://192.168.0.23:3080";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = privateAccessRules;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualHosts."ai.${domain}" = {
|
# Web UI + llama.cpp API (browser, /v1/* calls from the UI)
|
||||||
useACMEHost = domain;
|
# Auth handled by llama.cpp itself (--api-key flag)
|
||||||
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,20 +9,28 @@
|
||||||
# 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; };
|
||||||
searxng = { sopsFile = ../../../secrets/system/searxng.yaml; };
|
llama = { sopsFile = ../../../secrets/system/llama.yaml; };
|
||||||
in {
|
in {
|
||||||
"RTSP_USER" = cameras;
|
"RTSP_USER" = cameras;
|
||||||
"RTSP_PASS" = cameras;
|
"RTSP_PASS" = cameras;
|
||||||
"SEARXNG_TOKEN" = searxng;
|
"LLAMA_API_KEY" = llama // { owner = config.user.name; };
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.templates."nginx-searxng-location.conf" = {
|
# API key auth for ai.ramos.codes — nginx validates Bearer token against sops secret
|
||||||
|
sops.templates."nginx-ai-auth.conf" = {
|
||||||
content = ''
|
content = ''
|
||||||
location /${config.sops.placeholder."SEARXNG_TOKEN"}/ {
|
if ($api_key != "${config.sops.placeholder."LLAMA_API_KEY"}") {
|
||||||
proxy_pass http://192.168.0.23:8080/;
|
return 401 '{"error": "Invalid API key"}';
|
||||||
proxy_http_version 1.1;
|
}
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
'';
|
||||||
proxy_set_header Connection "upgrade";
|
owner = "nginx";
|
||||||
|
};
|
||||||
|
|
||||||
|
# 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";
|
||||||
|
|
@ -31,7 +39,6 @@
|
||||||
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 = import ./config/penpot.nix;
|
initExtra = "export LLAMA_API_KEY=$(cat /run/secrets/LLAMA_API_KEY)";
|
||||||
#};
|
};
|
||||||
direnv = {
|
direnv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableBashIntegration = true;
|
enableBashIntegration = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue