This repository has no description
0

Configure Feed

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

superconfig / configs / crit.nix
7.5 kB 214 lines
1# crit (https://crit.md): agents run `crit` to open their diff/plan for review 2# in the browser and block until it is finished. Each review session is its 3# own daemon on its own port, reachable over retiolum as 4# http://<host>.r:<port>, and publicly as https://<id>.review.lassul.us 5# through neoprism (configs/crit-proxy.nix) and the router nginx below. 6# 7# SECURITY: crit has no authentication, and comments left in a review are fed 8# to the agent as instructions. Whoever can reach a daemon can steer an agent 9# running here, so the ports are only open on retiolum. On the public side the 10# random 10-char hostname (~51 bits, fresh per review, only on a wildcard cert 11# so it never shows up in CT logs) is the only protection. Only members of 12# group crit can register a route (via /run/crit-routes.sock), and the 13# ids are generated by the root service, callers cannot choose them. 14{ 15 self, 16 config, 17 pkgs, 18 ... 19}: 20let 21 firstPort = 7700; 22 lastPort = 7719; 23 # router nginx, neoprism proxies *.review.lassul.us here 24 routerPort = 7720; 25 domain = "review.lassul.us"; 26 # one file per port, "<id> <port>", written by crit-routes-register (root) 27 routesDir = "/var/lib/crit-routes"; 28 mapDir = "/run/crit-routes"; 29 socket = "/run/crit-routes.sock"; 30 crit-unwrapped = self.inputs.llm-agents.packages.${pkgs.system}.crit; 31 32 # crit binds 127.0.0.1 on a random port by default. Bind all interfaces on a 33 # free port from the firewalled range instead and advertise the public URL. 34 # Only the invocation that starts a daemon binds the port; reconnecting to a 35 # running session uses the port and URL recorded in ~/.crit/sessions. 36 crit = pkgs.symlinkJoin { 37 name = "crit"; 38 paths = [ 39 (pkgs.writeShellScriptBin "crit" '' 40 if [ -z "''${CRIT_PORT:-}" ]; then 41 for p in $(${pkgs.coreutils}/bin/seq ${toString firstPort} ${toString lastPort}); do 42 if [ -z "$(${pkgs.iproute2}/bin/ss -Htln "sport = :$p")" ]; then 43 export CRIT_PORT=$p 44 # Fresh unguessable hostname per daemon, picked by the root 45 # service. Replacing the port's route kills the link of 46 # whichever review used the port before. 47 id=$(printf '%s\n' "$p" | ${pkgs.socat}/bin/socat -t 10 - UNIX-CONNECT:${socket} 2>/dev/null) 48 if [[ $id =~ ^[a-z0-9]{10}$ ]]; then 49 export CRIT_PUBLIC_URL="''${CRIT_PUBLIC_URL:-https://$id.${domain}}" 50 else 51 echo "crit: cannot register at ${socket} (not in group crit?), no public URL" >&2 52 fi 53 break 54 fi 55 done 56 fi 57 if [ -n "''${CRIT_PORT:-}" ]; then 58 echo "crit: retiolum: http://${config.networking.hostName}.r:$CRIT_PORT" >&2 59 export CRIT_PUBLIC_URL="''${CRIT_PUBLIC_URL:-http://${config.networking.hostName}.r:$CRIT_PORT}" 60 else 61 echo "crit: ports ${toString firstPort}-${toString lastPort} all busy, using a random port (not reachable over retiolum)" >&2 62 fi 63 export CRIT_HOST="''${CRIT_HOST:-0.0.0.0}" 64 export CRIT_ALLOW_UNAUTHENTICATED_NETWORK=1 65 exec ${crit-unwrapped}/bin/crit "$@" 66 '') 67 crit-unwrapped 68 ]; 69 }; 70 71 # Only well-formed routes make it into the nginx config. 72 crit-routes-map = pkgs.writeShellApplication { 73 name = "crit-routes-map"; 74 runtimeInputs = [ pkgs.coreutils ]; 75 text = '' 76 routes=$1 77 out=$2 78 mkdir -p "$(dirname "$out")" 79 tmp=$(mktemp "$out.XXXXXX") 80 for f in "$routes"/*; do 81 [ -f "$f" ] || continue 82 id=''' port=''' 83 read -r id port _ <"$f" || [ -n "$id" ] || continue 84 if [[ $id =~ ^[a-z0-9]{10}$ && $port =~ ^[0-9]{4}$ ]] && 85 ((port >= ${toString firstPort} && port <= ${toString lastPort})); then 86 printf '%s.${domain} %s;\n' "$id" "$port" 87 fi 88 done >"$tmp" 89 chmod 644 "$tmp" 90 mv -f "$tmp" "$out" 91 ''; 92 }; 93 94 # One connection of crit-routes.socket: reads a port, gives it a fresh 95 # route and answers with the route's id. 96 crit-routes-register = pkgs.writeShellApplication { 97 name = "crit-routes-register"; 98 runtimeInputs = [ 99 pkgs.coreutils 100 pkgs.util-linux 101 crit-routes-map 102 ]; 103 text = '' 104 routes=$1 105 map=$2 106 port=''' 107 read -r -t 5 port || true 108 if ! [[ $port =~ ^[0-9]{4}$ ]] || ((port < ${toString firstPort} || port > ${toString lastPort})); then 109 echo "crit-routes-register: invalid port" >&2 110 exit 1 111 fi 112 # tr dies of SIGPIPE once head has its 10 chars 113 id=$(LC_ALL=C tr -dc a-z0-9 </dev/urandom | head -c 10) || true 114 [[ $id =~ ^[a-z0-9]{10}$ ]] 115 # concurrent registrations must not lose each other's map update 116 exec 9<"$routes" 117 flock 9 118 printf '%s %s\n' "$id" "$port" >"$routes/.$port.tmp" 119 mv -f "$routes/.$port.tmp" "$routes/$port" 120 crit-routes-map "$routes" "$map" 121 systemctl try-reload-or-restart nginx.service 122 echo "$id" 123 ''; 124 }; 125in 126{ 127 environment.systemPackages = [ crit ]; 128 129 users.groups.crit.members = [ 130 config.users.users.mainUser.name 131 "hermes" 132 ]; 133 # root-only; tmpfiles also tightens the group-writable dir of before 134 systemd.tmpfiles.rules = [ "d ${routesDir} 0700 root root -" ]; 135 136 # A unix socket rather than a writable dir: connecting works for agents 137 # under ProtectSystem=strict. The group controls who may register. 138 systemd.sockets.crit-routes = { 139 wantedBy = [ "sockets.target" ]; 140 socketConfig = { 141 ListenStream = socket; 142 SocketUser = "root"; 143 SocketGroup = "crit"; 144 SocketMode = "0660"; 145 Accept = true; 146 }; 147 }; 148 systemd.services."crit-routes@" = { 149 description = "Register a crit review hostname"; 150 serviceConfig = { 151 ExecStart = "${pkgs.lib.getExe crit-routes-register} ${routesDir} ${mapDir}/routes.map"; 152 StandardInput = "socket"; 153 StandardOutput = "socket"; 154 StandardError = "journal"; 155 }; 156 }; 157 # map from the routes of before the reboot, so nginx starts with one 158 systemd.services.crit-routes-map = { 159 description = "Generate the nginx map of crit review hostnames"; 160 wantedBy = [ "multi-user.target" ]; 161 before = [ "nginx.service" ]; 162 serviceConfig = { 163 Type = "oneshot"; 164 ExecStart = "${pkgs.lib.getExe crit-routes-map} ${routesDir} ${mapDir}/routes.map"; 165 }; 166 }; 167 168 # Routes <id>.review.lassul.us to the daemon's port. A daemon that has gone 169 # away gives 502, unknown ids 404. 170 services.nginx = { 171 enable = true; 172 # the glob tolerates a missing file before crit-routes ran 173 appendHttpConfig = '' 174 map $host $crit_port { 175 default ""; 176 include ${mapDir}/*.map; 177 } 178 ''; 179 virtualHosts.crit-routes = { 180 listen = [ 181 { 182 addr = "0.0.0.0"; 183 port = routerPort; 184 } 185 { 186 addr = "[::]"; 187 port = routerPort; 188 } 189 ]; 190 extraConfig = '' 191 if ($crit_port = "") { 192 return 404; 193 } 194 ''; 195 # the UI follows the review over SSE 196 locations."/" = { 197 recommendedProxySettings = true; 198 proxyPass = "http://127.0.0.1:$crit_port"; 199 extraConfig = '' 200 proxy_buffering off; 201 proxy_read_timeout 1h; 202 ''; 203 }; 204 }; 205 }; 206 207 networking.firewall.interfaces.retiolum.allowedTCPPorts = [ routerPort ]; 208 networking.firewall.interfaces.retiolum.allowedTCPPortRanges = [ 209 { 210 from = firstPort; 211 to = lastPort; 212 } 213 ]; 214}