# AIM Installation Guide This guide installs AIM with `/etc/ansible/scripts` as the project root. ## Layout ``` text /etc/ansible/scripts/ ├── pyproject.toml └── src/ └── aim/ /etc/ansible/.venv/ /usr/local/bin/aim -> /etc/ansible/.venv/bin/aim ``` The virtual environment is intentionally not stored in Git. ## 1. Prerequisites On Debian/Ubuntu: ``` bash sudo apt update sudo apt install -y python3 python3-venv python3-pip ``` ## 2. Rebuild the virtual environment ``` bash sudo rm -rf /etc/ansible/.venv sudo python3 -m venv /etc/ansible/.venv sudo /etc/ansible/.venv/bin/python -m pip install --upgrade pip setuptools wheel ``` ## 3. Install AIM ``` bash sudo /etc/ansible/.venv/bin/python -m pip install -e /etc/ansible/scripts ``` Verify: ``` bash ls -l /etc/ansible/.venv/bin/aim /etc/ansible/.venv/bin/python -m pip check ``` ## 4. Restore the system-wide command ``` bash sudo ln -sfn /etc/ansible/.venv/bin/aim /usr/local/bin/aim ``` Verify: ``` bash ls -l /usr/local/bin/aim aim --version ``` ## 5. Authorization group / using another GID AIM authorization is group-based rather than root-based. The default required group is: ``` text srv_debsansible01_admins@bitformer.lan ``` AIM resolves the configured **group name** through the operating system's NSS layer (for example local groups, SSSD or winbind). The operator must have that group active as a primary or supplementary group. Do not hard-code a numeric GID into AIM merely because a particular server uses a different GID. Numeric GIDs can differ between systems; configure the appropriate group name and let NSS resolve its GID. Inspect the default group and its resolved GID: ``` bash getent group 'srv_debsansible01_admins@bitformer.lan' ``` Check the current user's active groups/GIDs: ``` bash id id -G id -Gn ``` If another authorization group should be used, change AIM's **Required Group** through: ``` text Global Config └── Required Group ``` For example, if the local/AD-backed group is: ``` text ansible_operators ``` verify it first: ``` bash getent group ansible_operators ``` Then configure `ansible_operators` as AIM's Required Group. AIM will use the GID returned by NSS for that group. After adding a user to a group, the login session may need to be renewed before the supplementary group becomes active. Verify with `id` before troubleshooting AIM authorization. ### Same group name, different GID This is supported. For example, one server may resolve: ``` text ansible_operators:x:1200:... ``` and another may resolve: ``` text ansible_operators:x:48001:... ``` AIM should be configured with `ansible_operators`, not `1200` or `48001`. ### Different group name Configure the alternative group name in AIM Global Config and confirm: ``` bash getent group '' id ``` If `getent` cannot resolve the group, fix NSS/SSSD/winbind/local group resolution first. ## 6. Git-ignored runtime data Important ignored data includes: ``` gitignore .vscode/* .venv/* .ansible/* secure/* secure/keys/* vault.yml .ssh *.msi *.deb *.rpm **/.hosts.tsv **/hosts.yml.aim-session.bak **/hosts.aim-session.bak.yml *.bak ``` For AIM inventory recovery, the critical persistent data is `vault.yml` and inventory `.ssh/` content. Do not restore `.venv`; rebuild it. ## 7. Recover missing Vaults and SSH keys Example restored backup: ``` text /etc/ansible/inventories_RESTORED_20260915_152127 ``` Active inventories: ``` text /etc/ansible/inventories ``` ### Dry run ``` bash BACKUP="/etc/ansible/inventories_RESTORED_20260915_152127" TARGET="/etc/ansible/inventories" echo "=== vault.yml ===" sudo find "$BACKUP" -type f -name 'vault.yml' -print0 | while IFS= read -r -d '' src; do rel="${src#"$BACKUP"/}" dst="$TARGET/$rel" if [ -e "$dst" ]; then echo "KEEP $dst" else echo "RESTORE $src -> $dst" fi done echo echo "=== .ssh files ===" sudo find "$BACKUP" -path '*/.ssh/*' -type f -print0 | while IFS= read -r -d '' src; do rel="${src#"$BACKUP"/}" dst="$TARGET/$rel" if [ -e "$dst" ]; then echo "KEEP $dst" else echo "RESTORE $src -> $dst" fi done ``` ### Restore ``` bash BACKUP="/etc/ansible/inventories_RESTORED_20260915_152127" TARGET="/etc/ansible/inventories" sudo find "$BACKUP" -type f -name 'vault.yml' -print0 | while IFS= read -r -d '' src; do rel="${src#"$BACKUP"/}" dst="$TARGET/$rel" if [ -e "$dst" ]; then echo "KEEP $dst" continue fi sudo mkdir -p "$(dirname "$dst")" sudo cp -a "$src" "$dst" echo "RESTORED $dst" done sudo find "$BACKUP" -path '*/.ssh/*' -type f -print0 | while IFS= read -r -d '' src; do rel="${src#"$BACKUP"/}" dst="$TARGET/$rel" if [ -e "$dst" ]; then echo "KEEP $dst" continue fi sudo mkdir -p "$(dirname "$dst")" sudo cp -a "$src" "$dst" echo "RESTORED $dst" done ``` `cp -a` preserves ownership, permissions and timestamps. Existing active files are never overwritten. Verify: ``` bash sudo find /etc/ansible/inventories -type f -name 'vault.yml' -print | sort sudo find /etc/ansible/inventories -path '*/.ssh/*' -type f -print | sort sudo find /etc/ansible/inventories -path '*/.ssh/*' -type f -exec ls -l {} \; ``` Keep the restored backup until Vault and SSH access have been tested. ## 8. Final verification ``` bash aim --version /etc/ansible/.venv/bin/python -m pip check aim ``` ## Updating AIM AIM is installed editable from `/etc/ansible/scripts`. If its entry point needs recreation: ``` bash sudo /etc/ansible/.venv/bin/python -m pip install -e /etc/ansible/scripts sudo ln -sfn /etc/ansible/.venv/bin/aim /usr/local/bin/aim ``` Customer data under `/etc/ansible/inventories` is separate from the AIM source installation.