diff --git a/AGENTS.md b/AGENTS.md index 05c0c99..d7ef707 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,151 +1,168 @@ # AGENTS.md +Guidance for agentic coding tools working in this repository. +Project type: Ansible-based infrastructure plus managed dotfiles. -Guidance for coding agents working in this repository. -Project type: Ansible infrastructure + managed dotfiles. - -## Repository scope and layout +## Repository snapshot - Entry playbook: `ansible/site.yml` +- Ansible config: `ansible.cfg` - Inventory: `ansible/inventory/hosts.yml` - Group vars: `ansible/inventory/group_vars/*.yml` - Host vars: `ansible/inventory/host_vars/*.yml` - Roles: `ansible/roles/*/tasks/main.yml` - Dotfiles source of truth: `dotfiles/` -- Ansible config file: `ansible.cfg` +- Scripts: `scripts/` +- Sensitive local material/examples: `secrets/` +- Active orchestration: `all -> dotfiles_common`; `void -> packages_void, services_runit, profile_desktop_i3` +- Roles present but not currently wired into `ansible/site.yml`: `base`, `dotfiles`, `packages_ubuntu`, `services_systemd`, `profile_workstation_gnome`, `profile_server` -Current `ansible.cfg` defaults: -- `inventory = ansible/inventory/hosts.yml` -- `roles_path = ansible/roles` -- `host_key_checking = False` -- `retry_files_enabled = False` - -## Local instruction files (Cursor/Copilot) -Checked in this repository: +## Local instruction files +Checked in this repository when this file was written: - `.cursorrules`: not present - `.cursor/rules/`: not present - `.github/copilot-instructions.md`: not present +If any of these appear later, treat them as higher-priority local instructions. -If any of the files above appear later, treat them as higher-priority local instructions. +## Working assumptions +- Favor idempotent, host-safe changes over cleverness. +- Preserve the intended layering: `all -> OS -> profile -> host`. +- Validate on one host before broad rollout. +- The repo contains both first-party dotfiles and vendored third-party plugin code. ## Build, lint, and test commands -There is no compile/build step in this repo. -Validation is Ansible syntax checks, dry-runs, inventory checks, and linting. - -Core apply run: +There is no compile/build step. Validation is Ansible syntax checks, inventory inspection, dry-runs, and linting. +Install base tooling if needed: +```bash +python3 -m pip install ansible +``` +Core commands: ```bash ansible-playbook ansible/site.yml -``` - -Safe dry-run with changes preview: -```bash ansible-playbook ansible/site.yml --check --diff -``` - -Target a single host (useful for SSH-first rollout): -```bash ansible-playbook ansible/site.yml --limit ikaros +ansible-playbook ansible/site.yml --limit nymph +ansible-playbook ansible/site.yml --syntax-check +ansible-inventory --graph +ansible-inventory --host ikaros ``` - -Linting (if installed locally): +Linting if available locally: ```bash ansible-lint ansible/site.yml ansible-lint ansible/roles yamllint ansible/ ``` -## Single-test equivalents (important) -There is no Molecule/pytest suite. -Use one of these as a "single test" workflow. - -Fast syntax-only validation: +## Single-test equivalents +There is no Molecule, pytest, or dedicated unit-test suite. Use these as the closest equivalent to a single targeted test. +Fastest confidence check: ```bash ansible-playbook ansible/site.yml --syntax-check ``` - -Best default single-host safety check: +Best default host-scoped safety check: ```bash -ansible-playbook ansible/site.yml --limit nymph --check --diff +ansible-playbook ansible/site.yml --limit ikaros --check --diff ``` - -Single-role smoke test using `--start-at-task` (dotfiles path): +Start from one task when validating a narrow change: ```bash ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy common dotfiles" --check --diff -``` - -Single-role smoke test using `--start-at-task` (Void packages path): -```bash ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff +ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy desktop dotfiles" --check --diff +``` +Inventory-only resolution for one machine: +```bash +ansible-inventory --host ikaros ``` - Notes: -- Current active stack in `ansible/site.yml`: `dotfiles_common`, `packages_void`, `services_runit`, `profile_desktop_i3`. -- Ubuntu/systemd/workstation/server roles exist in the repo but are not currently included by `ansible/site.yml`. -- Minimum dependencies: Python 3, Ansible, target host access (local or SSH). Setup: `python3 -m pip install ansible`. +- Keep task names stable and unique enough for `--start-at-task`. +- Prefer `--check --diff` before package, service, PAM, or session changes. +- Use `--limit` aggressively to avoid accidental multi-host rollout. ## Code style guidelines +### General principles +- Prefer minimal, scoped changes that match the existing layout. +- Preserve idempotency and avoid hidden mutable state. +- Prefer declarative modules over imperative commands. +- Keep orchestration in playbooks and implementation in roles. +- Avoid unrelated refactors while solving a targeted task. -### Core principles -- Prefer declarative, idempotent, host-safe automation. -- Keep layering explicit: `all -> OS -> profile -> host`. -- Keep changes minimal, scoped, and reversible. -- Avoid speculative refactors unrelated to the requested task. +### Ansible modules and task structure +- Use FQCN module names such as `ansible.builtin.copy` and `community.general.xbps`. +- Prefer purpose-built modules over `ansible.builtin.command` or `ansible.builtin.shell`. +- Use `command` only when no good module exists. +- Use `shell` only when shell features are genuinely required. +- When using `command` or `shell`, set `changed_when` and `failed_when` when defaults are misleading. +- Keep task names imperative, outcome-based, and unique enough to support `--start-at-task`. - -### Modules, imports, and task structure -- Use FQCN modules (`ansible.builtin.copy`, `community.general.xbps`). -- Prefer dedicated modules over `ansible.builtin.command` and `ansible.builtin.shell`. -- Use `command`/`shell` only when no module exists; explain intent in task name. -- For `command`/`shell`, define `changed_when` and `failed_when` when defaults are unsafe. -- Keep `ansible/site.yml` orchestration-only; place implementation details in roles. -- Keep roles domain-focused (packages, services, profiles, dotfiles). - - -### YAML formatting and file hygiene -- Start YAML documents with `---`. -- Use 2-space indentation; never tabs. -- Keep key ordering stable and meaningful. -- Quote file modes as strings (`"0644"`, `"0755"`, `"0600"`, `"0700"`). -- Use multiline Jinja for long expressions. -- Avoid trailing whitespace and formatting-only churn. +### YAML formatting +- Start YAML files with `---`. +- Use 2-space indentation; do not use tabs. +- Keep lists and maps in stable, readable order. +- Quote file modes as strings: `"0644"`, `"0755"`, `"0600"`, `"0700"`. +- Prefer multiline Jinja when a one-line expression becomes hard to read. +- Avoid formatting-only churn in untouched sections. ### Variables, types, and templating -- Use `snake_case` names for variables. -- Use semantically scoped names (`common_packages`, `void_packages_base`, `profile_packages`, `host_packages`). -- Keep booleans as booleans (`true`/`false`), not quoted strings. -- Keep lists/maps as YAML collections, not comma-separated strings. -- Guard optional values with `default([])` and `default({})`. -- Build home-relative paths from `{{ user_home }}` consistently. - +- Use `snake_case` consistently. +- Follow existing naming families like `common_packages`, `profile_packages`, and `host_packages`. +- Keep booleans as booleans, not quoted strings. +- Keep structured data as YAML collections, not comma-separated strings. +- Guard optional values with `default([])`, `default({})`, or `default('')` as appropriate. +- Build user paths from `{{ user_home }}` instead of hardcoding home directories. ### Naming conventions -- Role directory names: lowercase with underscores. -- Task names: imperative, outcome-based, and unique enough for `--start-at-task`. -- Keep inventory group names aligned with related var files. - +- Role names stay lowercase with underscores. +- Inventory groups and matching var files should stay semantically aligned. +- New variables should fit existing patterns instead of inventing one-off names. ### Error handling and safety -- Guard OS/profile-specific behavior with `when` clauses. -- Prefer explicit loop inputs over implicit assumptions. -- Do not suppress failures unless there is a clear operational reason. -- Validate risky changes with `--check --diff` before full apply. -- Avoid destructive operations in user homes unless explicitly required. +- Guard OS-specific or profile-specific behavior with `when` clauses. +- Prefer explicit loops and inputs over assumptions. +- Do not suppress failures without a clear operational reason. +- Use `failed_when: false` only for intentional state probes. - Keep tasks non-interactive and automation-safe. +- Avoid destructive operations in user homes unless the request clearly requires them. -### Dotfiles and shell script style -- Prefer POSIX `sh`; use Bash only when Bash features are required. -- Bash scripts must use `#!/usr/bin/env bash`. -- Quote expansions (`"$var"`) unless intentional word splitting is required. -- Preserve executable bits for copied scripts (`mode: preserve` where appropriate). +### Dotfiles and script conventions +- Prefer POSIX `sh` for simple login/session scripts. +- Use Bash only when Bash features are required; then use `#!/usr/bin/env bash`. +- Quote variable expansions unless intentional word splitting is required. +- Preserve executable bits for deployed scripts where appropriate. +- Keep session-start changes conservative; verify startup paths and environment assumptions. + +### Imports and external code +- There are no Python import conventions to optimize for here; most changes are YAML and shell. +- Treat `dotfiles/common/.tmux/plugins/` as vendored upstream code unless the task explicitly targets it. +- Prefer changing first-party wrapper/config files before patching vendored plugin internals. + +## Editing guidance by area +- `ansible/site.yml`: keep it small and orchestration-focused. +- `ansible/inventory/group_vars/*.yml`: shared defaults by layer. +- `ansible/inventory/host_vars/*.yml`: host-specific overrides only. +- `ansible/roles/*/tasks/main.yml`: role implementation details. +- `dotfiles/`: user-facing config and session scripts deployed by roles. +- `secrets/vault.yml`: treat as sensitive; do not expose values in tracked plain text. + +## Validation expectations before finishing +Run the narrowest useful checks for the area you changed. +Default minimum: +```bash +ansible-playbook ansible/site.yml --syntax-check +``` +Preferred for role or vars changes: +```bash +ansible-playbook ansible/site.yml --limit --check --diff +``` +Useful supporting checks: +```bash +ansible-inventory --graph +ansible-inventory --host +ansible-lint ansible/site.yml +yamllint ansible/ +``` ## Agent workflow expectations -- Do not modify unrelated files. -- Read inventory, vars, and relevant roles before editing. -- Keep AGENTS and README aligned when workflows/commands change. -- When adding roles or domains, also add validation and targeting guidance. -- Prefer `--limit ` validation before broader runs. - -## Pre-merge checklist -Run before proposing/finalizing changes: -- `ansible-playbook ansible/site.yml --syntax-check` -- `ansible-playbook ansible/site.yml --check --diff --limit ` -- `ansible-inventory --graph` -- If available: `ansible-lint ansible/site.yml` and `yamllint ansible/` +- Read the relevant inventory, vars, role tasks, and deployed dotfiles before editing. +- Do not change unrelated files to "clean things up". +- Keep README and AGENTS aligned when workflows materially change. +- If you add a new operational area, also add the validation command agents should run. +- Prefer host-limited validation before broad apply. +- Call out any verification you could not run. diff --git a/README.md b/README.md index 7536bf5..4245b5d 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,14 @@ Il repository è diviso in due componenti principali: --- -# Macchine gestite - -Il sistema attualmente gestisce tre tipologie di profilo. +# Macchine gestite + +Il repository modella attualmente tre tipologie di profilo. + +Nota sullo stato attuale del playbook principale: + +- `ansible/site.yml` applica oggi in automatico il profilo desktop su host Void Linux +- i profili workstation e server sono gia presenti in inventory e nei ruoli, ma non sono ancora inclusi nel playbook principale ## Desktop @@ -66,7 +71,15 @@ Macchine: - `ikaros` - `nymph` -Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible. +Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible. + +Lo stato attuale del profilo desktop include, tra le altre cose: + +- dotfiles comuni e desktop +- sessione i3 e servizi desktop correlati +- pacchetti Void Linux e servizi runit +- Flatpak con remoto Flathub +- GNOME Keyring e bootstrap della posta via script dedicato --- @@ -84,7 +97,9 @@ Macchina: - `deadalus` -Questo profilo è pensato per sviluppo e lavoro. +Questo profilo è pensato per sviluppo e lavoro. + +Il modello e la struttura dei ruoli sono presenti, ma l'orchestrazione automatica tramite `ansible/site.yml` verra completata in una fase successiva. --- @@ -102,7 +117,9 @@ Macchina: - `prometheus` -Profilo minimale orientato a servizi server. +Profilo minimale orientato a servizi server. + +Anche questo profilo e gia rappresentato in inventory e nei ruoli, ma non e ancora agganciato al playbook principale. --- @@ -139,23 +156,38 @@ Questo approccio consente di: # Ruoli Ansible -I principali ruoli attualmente presenti sono: +I principali ruoli attualmente presenti sono: | Role | Descrizione | | ------------------------- | ----------------------------------- | | base | configurazione base comune | -| packages_void | installazione pacchetti su Void | -| packages_ubuntu | installazione pacchetti su Ubuntu | -| services_runit | gestione servizi runit | -| services_systemd | gestione servizi systemd | -| profile_desktop_i3 | configurazione desktop i3 | -| profile_workstation_gnome | configurazione workstation GNOME | -| profile_server | configurazione server | -| dotfiles | distribuzione configurazioni utente | - ---- - -# Dotfiles +| packages_void | installazione pacchetti su Void | +| packages_ubuntu | installazione pacchetti su Ubuntu | +| services_runit | gestione servizi runit | +| services_systemd | gestione servizi systemd | +| profile_desktop_i3 | configurazione desktop i3 | +| profile_workstation_gnome | configurazione workstation GNOME | +| profile_server | configurazione server | +| dotfiles_common | distribuzione dotfiles comuni | +| dotfiles | distribuzione configurazioni utente | + +--- + +# Stato attuale del playbook principale + +Il playbook `ansible/site.yml` e attualmente composto da due blocchi: + +```text +all -> dotfiles_common +void -> packages_void + services_runit + profile_desktop_i3 +``` + +Questo significa che, allo stato attuale: + +- i desktop Void (`ikaros`, `nymph`) sono il target operativo principale +- inventory, gruppi e ruoli per workstation Ubuntu e server Ubuntu restano nel repository come base per l'estensione futura + +# Dotfiles La directory `dotfiles/` contiene le configurazioni utente versionate. @@ -180,48 +212,71 @@ Le configurazioni sono applicate tramite Ansible e organizzate per livelli: # Requisiti -Per utilizzare il repository sono necessari: - -- Python 3 -- Ansible -- accesso SSH alle macchine target - -Installazione Ansible: - -```bash -pip install ansible -``` +Per utilizzare il repository sono necessari: + +- Python 3 +- Ansible +- collection `community.general` +- accesso locale o SSH alle macchine target, in base a come e definito l'inventory + +Installazione base: + +```bash +pip install ansible +ansible-galaxy collection install community.general +``` + +Gestione segreti: + +- il repository supporta il caricamento opzionale di `secrets/vault.yml` +- `secrets/vault.yml.example` funge da template/esempio +- se `secrets/vault.yml` non e presente, il playbook continua comunque senza caricare variabili locali opzionali --- # Utilizzo -Eseguire il playbook principale: - -```bash -ansible-playbook ansible/site.yml -``` - -Questo comando: - -- installa i pacchetti richiesti -- configura i servizi -- applica il profilo macchina -- distribuisce i dotfiles +Eseguire il playbook principale: + +```bash +ansible-playbook ansible/site.yml +``` + +Allo stato attuale questo comando: + +- distribuisce i dotfiles comuni a tutti gli host +- per gli host Void applica pacchetti, servizi runit e profilo desktop i3 +- carica `secrets/vault.yml` solo se presente + +Per validare prima di applicare: + +```bash +ansible-playbook ansible/site.yml --syntax-check +ansible-playbook ansible/site.yml --limit ikaros --check --diff +``` --- # Bootstrap di una nuova macchina -Una nuova macchina può essere inizializzata con i seguenti passaggi: - -```bash -git clone -cd infra -ansible-playbook ansible/site.yml -``` - -Dopo l'esecuzione del playbook la macchina verrà configurata secondo il profilo definito. +Una nuova macchina può essere inizializzata con i seguenti passaggi: + +```bash +git clone +cd infra +ansible-galaxy collection install community.general +ansible-playbook ansible/site.yml +``` + +Dopo l'esecuzione del playbook la macchina verra configurata secondo il profilo definito e i ruoli attualmente orchestrati. + +Per il flusso mail desktop esiste inoltre uno script dedicato: + +```bash +scripts/bootstrap_mail.sh +``` + +Lo script si occupa del bootstrap dei secret nel keyring, del primo sync con `mbsync` e dell'inizializzazione di `mu` usando la configurazione mail generata dai template. --- @@ -241,14 +296,14 @@ Questo consente di ricreare qualsiasi macchina partendo esclusivamente dal repos # Roadmap -Possibili evoluzioni future: - -- gestione segreti con `ansible-vault` -- hardening sicurezza server -- configurazione backup -- testing automatico playbook -- integrazione CI -- supporto ad altre distribuzioni Linux +Possibili evoluzioni future: + +- completamento dell'orchestrazione per workstation Ubuntu e server Ubuntu +- hardening sicurezza server +- configurazione backup +- testing automatico playbook +- integrazione CI +- supporto ad altre distribuzioni Linux ---