Install the collection from GitHub Release:
# Option 1: Direct from GitHub Release URL
ansible-galaxy collection install \
https://github.com/RedHatOfficial/aap-containerized-add-node/releases/download/v1.0.0/redhat_official-aap_containerized_add_node-1.0.0.tar.gz
# Option 2: Download then install
curl -LO https://github.com/RedHatOfficial/aap-containerized-add-node/releases/download/v1.0.0/redhat_official-aap_containerized_add_node-1.0.0.tar.gz
ansible-galaxy collection install redhat_official-aap_containerized_add_node-1.0.0.tar.gzReplace v1.0.0 with the latest release from Releases.
Two installation methods available. Pick based on your network access:
| Method | Use When | Control Host Needs |
|---|---|---|
| Online | SSH access from control host to target nodes | SSH to controller + SSH to ENs |
| Online + ProxyJump | SSH via bastion/jumpbox | SSH to jumpbox (routes to targets) |
| Offline | No SSH to target nodes (air-gap, policy, hybrid cloud) | SSH to controller only |
Scope note: This collection targets containerized installer workflows. For OpenShift/operator-based execution node setup, use native AAP UI docs: AAP 2.6, AAP 2.7.
Control host runs playbook that SSHes to both controller and execution nodes.
Control Host ──SSH──► Controller
──SSH──► Execution Node
Can your EN reach the Controller directly?
│
├─ YES → Do you need one EN or multiple?
│ │
│ ├─ One EN → Single EN
│ └─ Multiple → Parallel ENs
│
└─ NO → Is there a hop node between EN and Controller?
│
├─ One hop → EN via Hop
├─ Multiple ENs behind hop → Fan-out behind Hop
└─ Multiple hops (DMZ layers) → Multi-hop Chain
Controller ◄── outbound dial ── Execution Node
ansible-playbook playbooks/add_node.yml \
-i examples/inventory-single-en.yml \
-e aap_setup_dir=/path/to/setupController ◄── outbound dial ── EN1
◄── outbound dial ── EN2
◄── outbound dial ── EN3
ansible-playbook playbooks/add_node.yml \
-i examples/inventory-parallel-ens.yml \
-e aap_setup_dir=/path/to/setupController ◄── outbound dial ── Hop ◄── outbound dial ── EN
ansible-playbook playbooks/add_node.yml \
-i examples/inventory-en-via-hn.yml \
-e aap_setup_dir=/path/to/setupController ◄── Hop ◄── EN1
▲
└───── EN2
See examples/inventory-fanout-behind-hop.yml.
Controller ◄── Hop1 ◄── Hop2 ◄── EN
See examples/inventory-multi-hop-chain.yml.
Control host cannot SSH directly — routes through jumpbox:
Control Host ──SSH──► Jumpbox ──SSH──► Controller
──SSH──► Execution Node
ansible-playbook playbooks/add_node.yml \
-i examples/inventory-proxyjump.yml \
-e aap_setup_dir=/path/to/setupSee examples/inventory-proxyjump.yml.
Note: SSH routes via jumpbox; receptor mesh (27199) is direct between EN and controller.
Control host cannot SSH directly — routes through jumpbox:
Control Host ──SSH──► Jumpbox ──SSH──► Controller
──SSH──► Execution Node
ansible-playbook playbooks/add_node.yml \
-i examples/inventory-proxyjump.yml \
-e aap_setup_dir=/path/to/setupSee examples/inventory-proxyjump.yml.
Note: SSH routes via jumpbox; receptor mesh (27199) is direct between EN and controller.
Control host generates a bundle, you transfer it manually, then run locally on target.
Control Host ──SSH──► Controller
│
[Generate Bundle]
│
▼
offline-bundle-exec1.tar.gz
│
[Transfer: USB, SFTP, etc.]
│
▼
Execution Node (local install)
- No SSH from control host to execution nodes
- Air-gapped networks
- Hybrid cloud (controller in cloud, ENs on-prem)
- Strict security policies prevent direct access
ansible-playbook playbooks/generate_bundle.yml \
-i inventory.yml \
-e aap_setup_dir=/path/to/setup \
-e _target_hostname=exec1.example.com \
-e _receptor_peers='["controller.example.com"]'Output: offline-bundles/offline-bundle-exec1.example.com-YYYY-MM-DD.tar.gz
Transfer via approved secure channel (USB, SFTP, jump host, etc.).
Security: Bundle contains TLS private keys. Delete after installation.
# On the execution node
tar -xzf offline-bundle-exec1.example.com-YYYY-MM-DD.tar.gz
cd offline-bundle-exec1.example.com-YYYY-MM-DD
sudo ansible-playbook -c local install.yml- RHEL 9 or 10 with valid subscription
podmaninstalledansible-coreinstalled- Receptor image pre-pulled:
podman pull registry.redhat.io/ansible-automation-platform-26/receptor-rhel9:latest
For fully air-gapped environments, include the receptor image in the bundle:
ansible-playbook playbooks/generate_bundle.yml \
-i inventory.yml \
-e aap_setup_dir=/path/to/setup \
-e _target_hostname=exec1.example.com \
-e _receptor_peers='["controller.example.com"]' \
-e aap_add_node_bundle_include_images=trueBundle size increases from ~50KB to ~500MB.
See OFFLINE.md for complete documentation.
- Wait 1-2 minutes for heartbeat
- Verify on controller:
ssh controller "podman exec automation-controller-task awx-manage list_instances" - Check Controller UI → Administration → Topology
# On execution node
systemctl status receptor
journalctl -u receptor -f
podman logs receptorNode should show green with capacity=16 and recent heartbeat timestamp.
| Symptom | Check |
|---|---|
| No heartbeat | systemctl status receptor, podman logs receptor |
| Connection refused | Firewall allows 27199/TCP |
| Certificate error | routable_hostname matches certificate SAN |
| capacity=0 | Check receptor logs for permission errors |
See TROUBLESHOOTING.md for detailed diagnostics.
- TOPOLOGY.md — Peer direction, firewall matrix, topology patterns
- OFFLINE.md — Complete offline bundle documentation
- CONVENTIONS.md — Variable naming and collection structure