Compare commits
17 Commits
feat/herme
...
feat/nixos
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef7f06166b | ||
|
|
e70516e78b | ||
|
|
ce3a327ff7 | ||
|
|
af38655170 | ||
| dcf5ac6b5e | |||
| d78de94f94 | |||
| 28ab52209c | |||
|
|
e6f7f0c263 | ||
|
|
5c136e0765 | ||
|
|
f722af7803 | ||
|
|
c07debf088 | ||
| 6806898f04 | |||
| 96e77c5ef2 | |||
| ff7303cf6a | |||
|
|
7d3d072961 | ||
| f0e21d95e4 | |||
| 18df45819d |
33
.gitea/workflows/build-nixos.yml
Normal file
33
.gitea/workflows/build-nixos.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Build NixOS config
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- '**.nix'
|
||||||
|
- 'flake.lock'
|
||||||
|
- 'secrets/**'
|
||||||
|
- 'hosts/**'
|
||||||
|
- 'modules/**'
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- '**.nix'
|
||||||
|
- 'flake.lock'
|
||||||
|
- 'secrets/**'
|
||||||
|
- 'hosts/**'
|
||||||
|
- 'modules/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: nixos-builder
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
git clone -b "${{ github.head_ref || github.ref_name }}" \
|
||||||
|
https://gitea:${{ secrets.GITHUB_TOKEN }}@code.lazyworkhorse.net/gortium/infra.git .
|
||||||
|
git log --oneline -3
|
||||||
|
|
||||||
|
- name: Build NixOS config (lazyworkhorse)
|
||||||
|
run: |
|
||||||
|
nix --version
|
||||||
|
nh os build .#lazyworkhorse 2>&1
|
||||||
Submodule assets/compose updated: 46241d10c5...6b82a26c25
@@ -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
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -191,6 +191,7 @@
|
|||||||
services.dockerStacks = {
|
services.dockerStacks = {
|
||||||
versioncontrol = {
|
versioncontrol = {
|
||||||
path = self + "/assets/compose/versioncontrol";
|
path = self + "/assets/compose/versioncontrol";
|
||||||
|
envFile = config.age.secrets.containers_env.path;
|
||||||
ports = [ 2222 ];
|
ports = [ 2222 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
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" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,67 +1,87 @@
|
|||||||
{ pkgs, ... }: {
|
{ pkgs, ... }: {
|
||||||
systemd.services.init-ollama-model = {
|
systemd.services.init-ollama-model = {
|
||||||
description = "Initialize LLM models with extra context in Ollama Docker";
|
description = "Initialize LLM models with extra context in Ollama Docker";
|
||||||
after = [ "docker-ollama.service" ];
|
|
||||||
|
# On s'assure que Docker tourne avant de lancer ce script
|
||||||
|
after = [ "docker.service" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
script = ''
|
script = ''
|
||||||
# Wait for Ollama
|
# Fonction de création asynchrone pour ne pas bloquer le démarrage
|
||||||
while ! ${pkgs.curl}/bin/curl -s http://localhost:11434/api/tags > /dev/null; do
|
(
|
||||||
sleep 2
|
echo "Starting asynchronous Ollama initialization..."
|
||||||
done
|
|
||||||
|
# Attente d'Ollama (maximum 120 secondes pour éviter une boucle infinie)
|
||||||
|
TIMEOUT=60
|
||||||
|
COUNT=0
|
||||||
|
while ! ${pkgs.curl}/bin/curl -s -f http://127.0.0.1:11434/api/tags > /dev/null; do
|
||||||
|
if [ $COUNT -ge $TIMEOUT ]; then
|
||||||
|
echo "Ollama did not become ready in time. Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Waiting for Ollama API to be reachable..."
|
||||||
|
sleep 5
|
||||||
|
COUNT=$((COUNT + 5))
|
||||||
|
done
|
||||||
|
|
||||||
create_model_if_missing() {
|
create_model_if_missing() {
|
||||||
local model_name=$1
|
local model_name=$1
|
||||||
local base_model=$2
|
local base_model=$2
|
||||||
if ! ${pkgs.docker}/bin/docker exec ollama ollama list | grep -q "$model_name"; then
|
|
||||||
echo "$model_name not found, creating from $base_model..."
|
|
||||||
|
|
||||||
# We use a custom TEMPLATE block to strip the 'currentDate' function
|
# Vérification robuste via l'API HTTP d'Ollama plutôt que docker exec (évite les conflits de tty)
|
||||||
# which is unsupported in Ollama 0.5.7 but present in Devstral's default manifest.
|
if ! ${pkgs.curl}/bin/curl -s http://127.0.0.1:11434/api/tags | ${pkgs.jq}/bin/jq -e ".models[] | select(.name == \"$model_name\")" > /dev/null; then
|
||||||
${pkgs.docker}/bin/docker exec ollama sh -c "cat <<EOF > /root/.ollama/$model_name.modelfile
|
echo "$model_name not found, creating from $base_model..."
|
||||||
|
|
||||||
|
# Utilisation d'un fichier temporaire sur l'hôte pour l'injecter proprement dans Docker
|
||||||
|
TMP_FILE=$(mktemp)
|
||||||
|
cat <<EOF > "$TMP_FILE"
|
||||||
FROM $base_model
|
FROM $base_model
|
||||||
TEMPLATE \"\"\"{{- if .System }}
|
TEMPLATE """{{- if .System }}
|
||||||
[SYSTEM_PROMPT]
|
[SYSTEM_PROMPT]
|
||||||
{{ .System }}
|
{{ .System }}
|
||||||
[/SYSTEM_PROMPT]
|
[/SYSTEM_PROMPT]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- range .Messages }}
|
{{- range .Messages }}
|
||||||
{{- if eq .Role \"user\" }}
|
{{- if eq .Role "user" }}
|
||||||
[INST]
|
[INST]
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
[/INST]
|
[/INST]
|
||||||
{{- else if eq .Role \"assistant\" }}
|
{{- else if eq .Role "assistant" }}
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- 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
|
||||||
PARAMETER repeat_penalty 1.1
|
PARAMETER repeat_penalty 1.1
|
||||||
PARAMETER top_k 40
|
PARAMETER top_k 40
|
||||||
PARAMETER stop \"[INST]\"
|
PARAMETER stop "[INST]"
|
||||||
PARAMETER stop \"[/INST]\"
|
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 rm "/root/.ollama/$model_name.modelfile"
|
|
||||||
else
|
|
||||||
echo "$model_name already exists, skipping."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create Nemotron
|
# Copie et création dans le conteneur
|
||||||
create_model_if_missing "nemotron-3-nano:30b-128k" "nemotron-3-nano:30b"
|
${pkgs.docker}/bin/docker cp "$TMP_FILE" ollama:/tmp/model.modelfile
|
||||||
|
${pkgs.docker}/bin/docker exec ollama ollama create "$model_name" -f /tmp/model.modelfile
|
||||||
# Create Devstral
|
${pkgs.docker}/bin/docker exec ollama rm /tmp/model.modelfile
|
||||||
create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
|
rm -f "$TMP_FILE"
|
||||||
|
else
|
||||||
# create_model_if_missing "qwen2.5-coder:32b-128k" "qwen2.5-coder:32b"
|
echo "$model_name already exists, skipping."
|
||||||
|
fi
|
||||||
# create_model_if_missing "mistral-large-planner:123b" "mistral-large:123b-instruct-v2407-q4_K_S"
|
}
|
||||||
|
|
||||||
|
# Create Nemotron
|
||||||
|
create_model_if_missing "nemotron-3-nano:30b-128k" "nemotron-3-nano:30b"
|
||||||
|
|
||||||
|
# Create Devstral
|
||||||
|
create_model_if_missing "devstral-small-2:24b-128k" "devstral-small-2:24b"
|
||||||
|
|
||||||
|
) &
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "forking"; # Permet à systemd de savoir que le script passe en arrière-plan via '&'
|
||||||
RemainAfterExit = true;
|
User = "root";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSBWNEpt
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSBMcVY2
|
||||||
cGFNeVBBaDRqb3pLSEZGQW0wb3VmVnBoZCswUFkzbnBLUnJ0QTNrClRqVkk4RUVO
|
eWRnb05sMEZVZUpicGVYN2ZSUm1mUmVsdUsrSHR4c2I2SXVRWDF3CnlhUkxoeEx5
|
||||||
d29KYjd5YUcwankvaTFmVHUxQVpDT2ZYWHRaY3JXTUtQMU0KLT4gKXBtQ3UsXi1n
|
M1NNcGR3bmx6ZW5RaHU3L2l4WEowdWYzQk0xa3E4ZUtwNkkKLT4gIi1ncmVhc2Ug
|
||||||
cmVhc2UgNnwxYCBXVyA/KCQmIHt9NAo3OTZVUHR2UXkvaEFwY0ZBdEJsaFpsbHJ0
|
SllwSzlIIEdAKltUKSBjSWpmCnljSXlZTXZBL2xuMEtma1NUNjdCM0dMNHJuVjFS
|
||||||
cklKcDVHcEdWMEdPSkpnN0FiRU43RW5hUWFMdjR3WFRRSFBLSGlmClM3cTNJWlNM
|
enV5LzF1NlYzbFNURW1rTlI2aUxCRFFxK2ZJdktsTTU1ZSsKNUZiZmVQWQotLS0g
|
||||||
TExkdHdXUHJISkNIaE1TTUxUc1NUWkV1a09HeFU3bVZwQXMKLS0tIGhOcXFTUElS
|
bTVrZEdWMHFWK0Q5RzZUc09PYmlEQjNweXRxU2FETWNWTXRUVEFKUUFpdwqtUbmM
|
||||||
azJJNnEreUhMWTJBaVZGSTJPRUFqQkVYS01KRENUVVpZSDgK8+8onFejroBo7MeO
|
kbnj4Q+9QlnJHuWBVu+BcWPl5HuiPUjrrxnWAuN6rFYd79H7qk9MagDB/2BAEk82
|
||||||
dW+so4lOsq4zJKn3f0cxmCFg1f0X8zt6h4Uc3A5Cvr1uU+6yw1FWmJ7xa3jJz3lO
|
iuQeqS0r8wAmp9bTzhbiMQEbtN96huSGA2aO9I/RoPU1jv1Upi8bNy+KX0jSsfV9
|
||||||
EEaKQJXYC+xIIKGcA7qILa0SFp4a/4OuYjcg27HrlPhg7u5wDhQrd0LdVEe1Xngp
|
+cGFm0JsBZ4o5acq4isanC+3YkNq+IHxyDqUdwWMIHiEkR26pwndyMAaJTCBAgTN
|
||||||
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
|
||||||
Qjv0Z1gMA+tsuBbVszwsMfneZ5+B9Q==
|
wrdoMa9hWmDFzf3+ThqfUuHOtxxJXReL7vC4J7K8iU6nCVIGJN7axifk
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
|||||||
9
secrets/wireguard_preshared_key.age
Normal file
9
secrets/wireguard_preshared_key.age
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSA3VG9Z
|
||||||
|
MVFPVFc2VVJ3d0h0dmtBUnI3WHl2SzUxTkRZbjFCaGloWmV3dnd3ClcxdnVPeGd6
|
||||||
|
SU4zR0Q0K1dtVjRRVHd0VW5XSFI0dVFpTjZnYk1DNjRxTVEKLT4gQzlgRy1ncmVh
|
||||||
|
c2UKeUozOWgyUytSTVF0NjY2STBEb2VadwotLS0gblI3bmJCUWxxU3QrYTEyVFBI
|
||||||
|
Snc4NC9rTkh0NnZYbUtxUE9hRWRkelpmMAq58fmH6cK13GeD7wGLxKmx10hmJeW4
|
||||||
|
b7KqnCD1ZP7uG85s32xzVRwRG8RrG4xZo5nR9Mrtg1CoTSFfUGeFnf5xveN+Ej0X
|
||||||
|
wDVB1LwC+Q==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
11
secrets/wireguard_private_key.age
Normal file
11
secrets/wireguard_private_key.age
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSA5dzVG
|
||||||
|
WUNvT3NlRmcrWS81bzJqSWlTekVYaDFFTE10SkI2dEgzaGpxcUI4Cmk5Y0FGYTRZ
|
||||||
|
K0NGYzY3VUp4aS9ZZGRmWTgybDJFUURva2pZNmVOS3QxdEUKLT4gPnVRTCtldGMt
|
||||||
|
Z3JlYXNlCk04OTJZeFRNeDI5aGpMVTk1ZTE0Y2FMMnFEMjlJalJpMHRlaTE4ZWIx
|
||||||
|
d2lCRGQ5RHVjcktOMGJCb1VERlNWcTYKaSt0L1Z6dVJ0QWIyZkhsYzFEVjZSQWUr
|
||||||
|
ZWpwVlo1TmhoUFJZdkEvR0gxNlVhcXF2ZTRnCi0tLSBLcmM2MThNVkdWclpHUXRr
|
||||||
|
VTF6QVk2WUZlTXpZMVNLMlpBOFc3M1o5WjZzCs9xbPlIX+u5vRSQ/z9utu+I9S2c
|
||||||
|
02DOsIb1kzxzb1OK91b8Kh4JucQSq3qkyEvRucsNn5QW8hIHDnRuND6EbPyN7p4S
|
||||||
|
YB/F0dxSqgnq
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
@@ -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