This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

machines.coaxmetal: run hermes-voice

+95
+1
machines/coaxmetal/config.nix
··· 24 24 ../../configs/crit.nix 25 25 ./strom.nix 26 26 ./hermes.nix 27 + ./hermes-voice.nix 27 28 ]; 28 29 29 30 system.stateVersion = "24.05";
+94
machines/coaxmetal/hermes-voice.nix
··· 1 + { 2 + config, 3 + lib, 4 + pkgs, 5 + self, 6 + ... 7 + }: 8 + let 9 + port = 8790; 10 + in 11 + { 12 + # hermes-voice (tools/hermes-voice): live voice conversations with Hermes 13 + # through OpenAI's gpt-live-1. Runs next to Hermes so its API key never 14 + # leaves this host; reachable over retiolum and publicly as 15 + # https://voice.lassul.us through neoprism (configs/hermes-proxy.nix). 16 + # 17 + # SECURITY: the page drives Hermes, which has terminal tools and code 18 + # execution as lass (machines/coaxmetal/hermes.nix). The access token below 19 + # is the gate on every API route; treat it like the hermes-api key. 20 + systemd.services.hermes-voice = { 21 + description = "hermes-voice: live voice conversations with Hermes"; 22 + wantedBy = [ "multi-user.target" ]; 23 + wants = [ "network-online.target" ]; 24 + after = [ 25 + "network-online.target" 26 + "hermes-agent.service" 27 + ]; 28 + serviceConfig = { 29 + ExecStart = lib.escapeShellArgs [ 30 + (lib.getExe self.packages.${pkgs.stdenv.hostPlatform.system}.hermes-voice) 31 + "--listen" 32 + "[::]:${toString port}" 33 + # The API server binds the retiolum address (hermes.nix), not 34 + # loopback; traffic to the host's own address goes through lo. 35 + "--hermes-url" 36 + "http://${config.networking.hostName}.r:8642" 37 + "--hermes-key-file" 38 + "%d/hermes-key" 39 + "--openai-key-file" 40 + "%d/openai-key" 41 + "--access-token-file" 42 + "%d/access-token" 43 + ]; 44 + LoadCredential = [ 45 + "hermes-key:${config.clan.core.vars.generators.hermes-api.files."api_key".path}" 46 + "openai-key:${config.clan.core.vars.generators.hermes-voice-openai.files."api-key".path}" 47 + "access-token:${config.clan.core.vars.generators.hermes-voice.files."access-token".path}" 48 + ]; 49 + DynamicUser = true; 50 + Restart = "on-failure"; 51 + CapabilityBoundingSet = ""; 52 + NoNewPrivileges = true; 53 + PrivateDevices = true; 54 + PrivateTmp = true; 55 + ProtectHome = true; 56 + ProtectSystem = "strict"; 57 + ProtectKernelTunables = true; 58 + ProtectKernelModules = true; 59 + ProtectControlGroups = true; 60 + RestrictAddressFamilies = [ 61 + "AF_INET" 62 + "AF_INET6" 63 + ]; 64 + RestrictNamespaces = true; 65 + LockPersonality = true; 66 + SystemCallArchitectures = "native"; 67 + }; 68 + }; 69 + 70 + # Only retiolum: neoprism's proxy and devices on the mesh. Every other 71 + # interface keeps the default DROP (configs/default.nix). 72 + networking.firewall.interfaces.retiolum.allowedTCPPorts = [ port ]; 73 + 74 + # OpenAI project key with GPT-Live access; billed per second of open voice 75 + # session. persist=true so the prompt value is stored once. 76 + clan.core.vars.generators.hermes-voice-openai.prompts.api-key = { 77 + description = "OpenAI API key for hermes-voice (gpt-live-1)"; 78 + type = "hidden"; 79 + persist = true; 80 + }; 81 + 82 + # What the page sends as its bearer token. Read it out for the phone with 83 + # clan vars get coaxmetal hermes-voice/access-token 84 + clan.core.vars.generators.hermes-voice = { 85 + files."access-token" = { }; 86 + runtimeInputs = [ 87 + pkgs.coreutils 88 + pkgs.openssl 89 + ]; 90 + script = '' 91 + openssl rand -hex 32 | tr -d '\n' > "$out/access-token" 92 + ''; 93 + }; 94 + }