Compare commits
5 Commits
feature/se
...
7d3d072961
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d3d072961 | ||
| 4cceab05d0 | |||
|
|
bcf5cadaa0 | ||
| f0e21d95e4 | |||
| 18df45819d |
@@ -61,6 +61,7 @@
|
|||||||
./modules/nixos/services/open_code_server.nix
|
./modules/nixos/services/open_code_server.nix
|
||||||
./modules/nixos/services/ollama_init_custom_models.nix
|
./modules/nixos/services/ollama_init_custom_models.nix
|
||||||
./modules/nixos/services/openclaw_node.nix
|
./modules/nixos/services/openclaw_node.nix
|
||||||
|
./modules/nixos/security/ai-worker-restricted.nix
|
||||||
./users/gortium.nix
|
./users/gortium.nix
|
||||||
./users/ai-worker.nix
|
./users/ai-worker.nix
|
||||||
];
|
];
|
||||||
|
|||||||
105
modules/nixos/security/README-ai-worker.md
Normal file
105
modules/nixos/security/README-ai-worker.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# AI Worker Restricted Access
|
||||||
|
|
||||||
|
This module provides SSH access for the AI worker (hermes-agent) to run ollama benchmarks on the host.
|
||||||
|
|
||||||
|
## Security Model
|
||||||
|
|
||||||
|
The `ai-worker` user has:
|
||||||
|
|
||||||
|
### Filesystem Access
|
||||||
|
- **Home directory**: `/home/ai-worker` (standard user home)
|
||||||
|
- **No bind mounts**: Cannot access `/home/gortium/infra` or other host files
|
||||||
|
- **Cannot access**: Any files outside standard system paths
|
||||||
|
|
||||||
|
### Sudo Access
|
||||||
|
- **NONE**: ai-worker has no sudo privileges
|
||||||
|
- Cannot run `nh`, `nixos-rebuild`, `nixpkgs-fmt`, or `nix` with elevated permissions
|
||||||
|
|
||||||
|
### Docker Access
|
||||||
|
- Member of `docker` group - can run `docker` and `docker exec` commands
|
||||||
|
- Primary use: `docker exec ollama ollama ...` for benchmarking
|
||||||
|
- Can run `docker exec --privileged ollama rocm-smi ...` for VRAM monitoring
|
||||||
|
|
||||||
|
## Workflow: SSH + Docker Benchmarking
|
||||||
|
|
||||||
|
The AI worker connects from the Hermes container to the host via SSH, runs ollama benchmarks, then returns to save results.
|
||||||
|
|
||||||
|
### Example Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From Hermes container, SSH to host
|
||||||
|
ssh -i /path/to/ssh/key ai-worker@host.docker.internal
|
||||||
|
|
||||||
|
# On host, run ollama benchmarks via docker
|
||||||
|
docker exec ollama ollama pull devstral-small-2:24b
|
||||||
|
|
||||||
|
# Create test modelfile
|
||||||
|
docker exec ollama bash -c 'cat <<EOF > /root/.ollama/test.modelfile
|
||||||
|
FROM devstral-small-2:24b
|
||||||
|
PARAMETER num_ctx 65536
|
||||||
|
PARAMETER num_gpu 99
|
||||||
|
PARAMETER flash_attn true
|
||||||
|
EOF'
|
||||||
|
|
||||||
|
# Create and test model
|
||||||
|
docker exec ollama ollama create test-model -f /root/.ollama/test.modelfile
|
||||||
|
docker exec ollama ollama run test-model "Write a Python async function"
|
||||||
|
|
||||||
|
# Check VRAM usage
|
||||||
|
docker exec --privileged ollama rocm-smi --showmeminfo vram
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
docker exec ollama ollama rm test-model
|
||||||
|
|
||||||
|
# Exit SSH, return to Hermes container
|
||||||
|
exit
|
||||||
|
|
||||||
|
# Save results in Hermes container
|
||||||
|
# /opt/data/ai-optimizer/state.json
|
||||||
|
# /opt/data/ai-optimizer/results.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
## SSH Access
|
||||||
|
|
||||||
|
Connect as:
|
||||||
|
```bash
|
||||||
|
ssh ai-worker@lazyworkhorse
|
||||||
|
```
|
||||||
|
|
||||||
|
The working directory will be `/home/ai-worker`. No infra repo access.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
Check ai-worker permissions:
|
||||||
|
```bash
|
||||||
|
# On the host, as root or gortium:
|
||||||
|
sudo -u ai-worker sudo -l
|
||||||
|
# Should show: no sudo access
|
||||||
|
|
||||||
|
# Check docker group membership
|
||||||
|
groups ai-worker
|
||||||
|
# Should show: ai-worker docker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If ai-worker cannot run docker commands:
|
||||||
|
```bash
|
||||||
|
# Check docker group membership
|
||||||
|
groups ai-worker
|
||||||
|
|
||||||
|
# Verify ollama container is running
|
||||||
|
docker ps | grep ollama
|
||||||
|
|
||||||
|
# Test docker access
|
||||||
|
sudo -u ai-worker docker exec ollama ollama list
|
||||||
|
```
|
||||||
|
|
||||||
|
If SSH connection fails:
|
||||||
|
```bash
|
||||||
|
# Check SSH key is authorized
|
||||||
|
cat /home/ai-worker/.ssh/authorized_keys
|
||||||
|
|
||||||
|
# Check SSH service
|
||||||
|
systemctl status sshd
|
||||||
|
```
|
||||||
17
modules/nixos/security/ai-worker-restricted.nix
Normal file
17
modules/nixos/security/ai-worker-restricted.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.aiWorkerAccess = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable AI worker SSH access with docker group membership for ollama benchmarking";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.aiWorkerAccess {
|
||||||
|
# ai-worker is member of docker group - can run docker commands via SSH
|
||||||
|
# No bind mounts, no sudo access - docker-only for ollama benchmarking
|
||||||
|
users.groups.docker.members = [ "ai-worker" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -14,8 +14,25 @@
|
|||||||
local base_model=$2
|
local base_model=$2
|
||||||
if ! ${pkgs.docker}/bin/docker exec ollama ollama list | grep -q "$model_name"; then
|
if ! ${pkgs.docker}/bin/docker exec ollama ollama list | grep -q "$model_name"; then
|
||||||
echo "$model_name not found, creating from $base_model..."
|
echo "$model_name not found, creating from $base_model..."
|
||||||
|
|
||||||
|
# We use a custom TEMPLATE block to strip the 'currentDate' function
|
||||||
|
# which is unsupported in Ollama 0.5.7 but present in Devstral's default manifest.
|
||||||
${pkgs.docker}/bin/docker exec ollama sh -c "cat <<EOF > /root/.ollama/$model_name.modelfile
|
${pkgs.docker}/bin/docker exec ollama sh -c "cat <<EOF > /root/.ollama/$model_name.modelfile
|
||||||
FROM $base_model
|
FROM $base_model
|
||||||
|
TEMPLATE \"\"\"{{- if .System }}
|
||||||
|
[SYSTEM_PROMPT]
|
||||||
|
{{ .System }}
|
||||||
|
[/SYSTEM_PROMPT]
|
||||||
|
{{- end }}
|
||||||
|
{{- range .Messages }}
|
||||||
|
{{- if eq .Role \"user\" }}
|
||||||
|
[INST]
|
||||||
|
{{ .Content }}
|
||||||
|
[/INST]
|
||||||
|
{{- else if eq .Role \"assistant\" }}
|
||||||
|
{{ .Content }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}\"\"\"
|
||||||
PARAMETER num_ctx 131072
|
PARAMETER num_ctx 131072
|
||||||
PARAMETER num_predict 4096
|
PARAMETER num_predict 4096
|
||||||
PARAMETER num_keep 1024
|
PARAMETER num_keep 1024
|
||||||
@@ -26,6 +43,7 @@ PARAMETER stop \"[/INST]\"
|
|||||||
PARAMETER stop \"</s>\"
|
PARAMETER stop \"</s>\"
|
||||||
EOF"
|
EOF"
|
||||||
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f "/root/.ollama/$model_name.modelfile"
|
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f "/root/.ollama/$model_name.modelfile"
|
||||||
|
${pkgs.docker}/bin/docker exec ollama rm "/root/.ollama/$model_name.modelfile"
|
||||||
else
|
else
|
||||||
echo "$model_name already exists, skipping."
|
echo "$model_name already exists, skipping."
|
||||||
fi
|
fi
|
||||||
@@ -36,6 +54,10 @@ EOF"
|
|||||||
|
|
||||||
# Create Devstral
|
# Create Devstral
|
||||||
create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
|
create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
|
||||||
|
|
||||||
|
# create_model_if_missing "qwen2.5-coder:32b-128k" "qwen2.5-coder:32b"
|
||||||
|
|
||||||
|
# create_model_if_missing "mistral-large-planner:123b" "mistral-large:123b-instruct-v2407-q4_K_S"
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
|
|||||||
@@ -9,8 +9,20 @@
|
|||||||
openssh.authorizedKeys.keys = [
|
openssh.authorizedKeys.keys = [
|
||||||
keys.users.ai-worker.main
|
keys.users.ai-worker.main
|
||||||
];
|
];
|
||||||
|
# No password login - SSH key only
|
||||||
|
hashedPassword = "!";
|
||||||
};
|
};
|
||||||
users.groups.ai-worker = {};
|
users.groups.ai-worker = {};
|
||||||
|
|
||||||
|
# Enable restricted AI worker SSH access for ollama benchmarking
|
||||||
|
# SECURITY: ai-worker can only:
|
||||||
|
# - SSH into host from Hermes container
|
||||||
|
# - Run docker commands (docker exec ollama ...) via docker group
|
||||||
|
# - Run specific security audit commands
|
||||||
|
# - NO access to infra repo (no bind mount)
|
||||||
|
# - NO sudo access (no nh, nixos-rebuild, nixpkgs-fmt, nix)
|
||||||
|
# WORKFLOW: SSH from Hermes container, run docker benchmarks, return and save results to /opt/data/ai-optimizer/
|
||||||
|
services.aiWorkerAccess = true;
|
||||||
|
|
||||||
# Restricted sudo for ai-worker - security checks only
|
# Restricted sudo for ai-worker - security checks only
|
||||||
security.sudo.extraRules = [
|
security.sudo.extraRules = [
|
||||||
|
|||||||
Reference in New Issue
Block a user