- dark2devil (UID 1002) aus der gesamten deklarierten State entfernt: derselbe Benutzer wie debugofen (Betreiberklärung 2026-10-28); GNAI-019 Entscheidung 11 revidiert, gn-media-Mitgliedschaft nur ghost - Share-ACLs im Inventar an die live smb.conf angeglichen (GNAI-018 R4): admin users auf elf Shares ergänzt, write list Dokumente/Extern ergänzt, Serien2 ohne force user/group; Template [printers] um browseable=no ergänzt - passdb-Asserts und Audit-Loops auf die drei deklarierten Medien-User umgestellt; Platzhalterzahl 11; provision-Script-Hash aktualisiert - AGENTS.md (Repo-Root) um Grundwissen für Agenten ergänzt: ghost-agent-Convention, Account-Landscape/Inventory-Pfade, Operator-Run-Steps, LXC-Konventionen, Repo-Konventionen Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
6.0 KiB
Ghostnet.AI project context
Before infrastructure work, read .codex/LOCAL_MEMORY.md if it exists. It contains dated local observations and access hints; verify live state before making system changes. Keep secrets and private key material out of that file.
For read-only access to the KI server, use the tested SSH profile ghostnet-ai-agent, which logs in as the unprivileged account ghost-agent on 10.0.0.90. On this workstation, invoke it as ssh -F ~/.ssh/config ghostnet-ai-agent because the system-wide SSH client configuration currently has an ownership/permissions error. Do not assume sudo access or make server changes without an explicit user request.
The KI server at 10.0.0.90 is deliberately a fresh base system. The operator plans to install the LLM application stack in a later Ansible sprint. Do not install applications or change server configuration as part of documentation review or access checks unless the operator explicitly requests that work.
Agent access convention: ghost-agent
ghost-agent is the standard unprivileged account for the AI agent on the
Proxmox LXCs and the KI server (operator-confirmed 2026-10-28: "on the KI
server and many other Proxmox LXCs"). It is a convention, not a per-host
exception.
-
Login is key-based with a passphrase-less Ed25519 key kept in the operator's
~/.ssh(id_ed25519_ghostnet_<host>_agent);~/.ssh/configcarries the matchingghostnet-<host>-agentaliases, which also work withssh -o BatchMode=yes. Private keys never enter the repository. -
ghost-agenthas no sudo (verified on CT 100, CT 101, CT 103 and ghostnet-ki): treat every agent session as read-only unless the operator explicitly authorizes a change. -
Known aliases (verify live state before use; the WireGuard LXC has no
ghost-agentalias and uses the legacyadminaccount via aliaslxc):Alias System IP ghostnet-ct100-agentCT 100, Pi-hole/Split-DNS dns10.0.0.14 ghostnet-ct101-agentCT 101, Samba file server 10.0.0.9 ghostnet-ct102-agentCT 102, Keycloak 10.0.0.4 ghostnet-ct103-agentCT 103, reverse proxy (NPM) 10.0.0.10 ghostnet-ct104-agentCT 104, Keycloak 10.0.0.16 ghostnet-ai-agentghostnet-ki, LLM/AI server 10.0.0.90 -
Invoke ssh as
ssh -F ~/.ssh/config <alias>: a baresshcurrently rejects/etc/ssh/ssh_config.d/20-systemd-ssh-proxy.confbecause of its ownership/permissions;-Fdeliberately uses the local profile without loading that broken system configuration. -
Dated per-host observations (host-key fingerprints, verified identities, account details) live in
.codex/LOCAL_MEMORY.md, not here.
Account landscape and Ansible inventory paths
| Account | Role | Key (operator ~/.ssh) |
sudo |
|---|---|---|---|
ghost-agent |
AI agent, read-only | id_ed25519_ghostnet_<host>_agent (no passphrase) |
no |
ghost |
human operator/admin | id_ed25519_ghostnet_<host>_ghost (passphrase-protected) |
yes, password-gated |
ansible-deploy |
Ansible deployment; created by the project's access role during adoption | id_ed25519_ghostnet_<host>_ansible_deploy (no passphrase) |
NOPASSWD: ALL (treat the key as root-equivalent) |
Each Ansible LXC project (proxmox/lxc/<ct>/ansible/) maps these accounts to
three inventories: agent (ghost-agent, read-only preflight), bootstrap
(ghost, --ask-become-pass), production (ansible-deploy, NOPASSWD).
Legacy exceptions exist (CT 103 is root-only and bootstrapped via the Proxmox
console; the WireGuard LXC uses admin) — see .codex/LOCAL_MEMORY.md.
Operator-run steps
- The workstation has no Proxmox host access (no
pct): PVE-side commands (pct exec,pct reboot,vzdump, editing/etc/pve/lxc/*.conf) are run by the operator as root@pve. The agent prepares exact commands and reviews the pasted output. - Interactive secret steps are operator-run:
passwd,smbpasswd -a, playbook runs with--ask-become-pass, and key passphrase prompts. The agent hands over copy-paste commands; the operator executes them. - Secrets never enter the repository, inventories, playbooks or logs: SMB
passwords, the Samba passdb, the
ghostpassword, private SSH keys, Podman secrets. Only public keys belong in the repo (ansible/files/ssh/).
LXC / Proxmox conventions
- Reboot caveat (GNAI-016 section 7): in LXC,
/proc/sys/kernel/random/boot_idbelongs to the PVE host and does not change on a guest reboot — never use boot_id-based waiters; reboot via PVE and verify independently over SSH. - Unprivileged LXCs: keep the empty
lxc.seccomp.profile:line (rootful Podman/Ganesha containers needopen_by_handle_at), masksys-kernel-config.mount(configfs is unavailable), and expectuid_map 0 100000 65536— host UIDs appear as 65534 (nobody) inside the guest. - In-place dist-upgrades: take a
vzdumpsafety net first and use--force-confoldso productive configuration files survive.
Repository conventions
- Documentation:
docs/platform/proxmox-server/lxc/<ct>/GNAI-*.md(German; decisions carry operator/date stamps, findings are lettered a), b), …). Ansible project READMEs are English. The central index isdocs/GNAI-000-DOC_Index.md. - Ansible projects are self-contained under
proxmox/lxc/<ct>/ansible/(ansible.cfg,inventories/{agent,bootstrap,production},playbooks/,roles/,files/ssh/), use the repository-wide control venv (.venv, built fromshared/ansible/requirements-control.txt) and the shared roles inshared/ansible/roles/. - Change discipline: productive changes only with explicit operator go; preview
with
--check --difffirst; convergence must be idempotent (a second run reportschanged=0); commit only when the operator asks. - Communicate with the operator in German.
- Verify account/identity assumptions with the operator before declaring them
(CT 101 example:
dark2devilturned out to be the same person asdebugofen; GNAI-019 decision 11 was revised accordingly).