# 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__agent`); `~/.ssh/config` carries the matching `ghostnet--agent` aliases, which also work with `ssh -o BatchMode=yes`. Private keys never enter the repository. - `ghost-agent` has **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-agent` alias and uses the legacy `admin` account via alias `lxc`): | Alias | System | IP | | --- | --- | --- | | `ghostnet-ct100-agent` | CT 100, Pi-hole/Split-DNS `dns` | 10.0.0.14 | | `ghostnet-ct101-agent` | CT 101, Samba file server | 10.0.0.9 | | `ghostnet-ct102-agent` | CT 102, Keycloak | 10.0.0.4 | | `ghostnet-ct103-agent` | CT 103, reverse proxy (NPM) | 10.0.0.10 | | `ghostnet-ct104-agent` | CT 104, Keycloak | 10.0.0.16 | | `ghostnet-ai-agent` | ghostnet-ki, LLM/AI server | 10.0.0.90 | - Invoke ssh as `ssh -F ~/.ssh/config `: a bare `ssh` currently rejects `/etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf` because of its ownership/permissions; `-F` deliberately 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__agent` (no passphrase) | no | | `ghost` | human operator/admin | `id_ed25519_ghostnet__ghost` (passphrase-protected) | yes, password-gated | | `ansible-deploy` | Ansible deployment; created by the project's access role during adoption | `id_ed25519_ghostnet__ansible_deploy` (no passphrase) | `NOPASSWD: ALL` (treat the key as root-equivalent) | Each Ansible LXC project (`proxmox/lxc//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 `ghost` password, 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_id` belongs 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: mask `sys-kernel-config.mount` (configfs is unavailable) and expect `uid_map 0 100000 65536` — host UIDs outside 100000–165535 appear as 65534 (nobody) inside the guest, so guest root cannot write to files owned by such UIDs without world-write bits. (The former empty `lxc.seccomp.profile:` line was a Ganesha-era exception and was removed on 2026-10-30 when the NFS export moved to the PVE host; GNAI-019 decision 2.) - In-place dist-upgrades: take a `vzdump` safety net first and use `--force-confold` so productive configuration files survive. ## Repository conventions - Documentation: `docs/platform/proxmox-server/lxc//GNAI-*.md` (German; decisions carry operator/date stamps, findings are lettered a), b), …). Ansible project READMEs are English. The central index is `docs/GNAI-000-DOC_Index.md`. - Ansible projects are self-contained under `proxmox/lxc//ansible/` (`ansible.cfg`, `inventories/{agent,bootstrap,production}`, `playbooks/`, `roles/`, `files/ssh/`), use the repository-wide control venv (`.venv`, built from `shared/ansible/requirements-control.txt`) and the shared roles in `shared/ansible/roles/`. - Change discipline: productive changes only with explicit operator go; preview with `--check --diff` first; convergence must be idempotent (a second run reports `changed=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: `dark2devil` turned out to be the same person as `debugofen`; GNAI-019 decision 11 was revised accordingly).