The landscape of enterprise automation often creates a friction point between modern software delivery patterns and traditional infrastructure policies. Ansible AWX, the open-source upstream project for the Red Hat Ansible Automation Platform, provides a sophisticated web-based user interface, a robust REST API, and a powerful task engine built atop the Ansible core. While AWX is designed to empower users to control Ansible usage within large-scale IT environments, it is equally beneficial for smaller deployments seeking a centralized management plane. However, a significant architectural shift occurred with the release of version 18.0.0, where the official support for single-host, non-containerized installations was deprecated in favor of the AWX Operator on Kubernetes. This transition has left a gap for engineers operating in environments where Kubernetes is either too resource-heavy or explicitly forbidden by corporate policy, leading to a demand for alternative deployment methodologies.
The Architectural Divergence: Kubernetes versus Docker
The primary conflict in deploying AWX centers on the distinction between the officially supported production path and the community-supported development path. The AWX Operator is the gold standard for production deployments, leveraging Kubernetes to manage the lifecycle of the AWX instance, including scaling and updates. Conversely, Docker-based installations exist but are explicitly categorized as tools for development and testing.
The technical implications of this divide are significant. A Kubernetes deployment utilizes the AWX Operator to maintain the desired state of the application, whereas a Docker Compose setup requires manual orchestration of the containers. For those attempting to run AWX in production via Docker, the risks include a lack of official published releases for that specific path and a diminished level of support from the core development community.
The following table delineates the core differences between these two primary deployment modalities:
| Feature | AWX Operator (Kubernetes) | Docker / Docker Compose |
|---|---|---|
| Support Status | Official Production Standard | Development/Test Only |
| Orchestration | Automated via Operator | Manual via Compose/Systemd |
| Scaling | Native via Pod Replicas | Manual container scaling |
| Update Path | Managed by Operator | Manual image pull and rebuild |
| Community Support | High (Devs and Community) | Low (Self-managed) |
Non-Kubernetes Implementation on Ubuntu 20.04
Despite the official shift toward Kubernetes, it remains possible to implement AWX on a single host using Docker Compose, particularly for smaller setups that cannot justify the overhead of a K8s cluster. This approach is viable on Ubuntu 20.04 and similar distributions, provided the hardware meets the baseline specifications derived from the Ansible Tower Installation and Reference Guide.
The hardware requirements are precise and non-negotiable for stable operation:
- 2 CPU cores
- 4 GB RAM
- 20 GB storage
In a cloud environment, such as Hetzner, a CX23 server instance aligns perfectly with these specifications, offering sufficient compute and memory while exceeding the minimum storage requirements. To ensure a successful deployment, the administrator must possess root access to the server and a valid domain name mapped to the server's IP address for web access.
Technical Execution of the Docker-Based Setup
The process of deploying AWX without Kubernetes involves a series of manual build and configuration steps. This method bypasses the Operator entirely and relies on the make utility to orchestrate the container environment.
The initial phase requires building the Docker image. This is achieved by executing the following command:
make docker-compose-build
Once the image is built, the Docker Compose manifest must be rendered to define the project sources. This is performed using:
make awx/projects docker-compose-sources
A critical technical detail in this process is that source deployments of AWX do not include pre-built UI files. These must be generated manually, which is a time-consuming process depending on the hardware's performance. The UI files are built by running the following command:
docker compose -f tools/docker-compose/_sources/docker-compose.yml run --rm awx_1 make clean-ui ui-devel
After the UI build is complete, the service is managed via systemd:
systemctl start awx
During the initial boot sequence, AWX performs essential database migrations. The progress of these migrations can be monitored in real-time through the system logs:
journalctl -f -u awx
Troubleshooting and Post-Installation Configuration
A common failure point during the initial launch of AWX involves the Linux kernel's inotify limits. When the system reaches the upper limit of inotify watches, the logs will report an error stating that the limit has been reached for /awx_devel/awx. This is a critical failure that prevents the application from monitoring file changes.
To resolve this, the administrator must increase the max_user_watches value by creating a configuration file in the sysctl directory:
echo 'fs.inotify.max_user_watches=524288' > /etc/sysctl.d/99-awx.conf
Following the creation of the file, the changes must be applied to the active kernel session:
sysctl -p /etc/sysctl.d/99-awx.conf
Once the system is stable and the services are running, the final security step is to change the default administrative password. This is done by executing a command inside the running container:
docker exec -ti tools_awx_1 awx-manage changepassword admin
Advanced Scaling: Control and Execution Nodes
A common requirement for production-grade environments is the ability to separate the control plane from the execution plane. In a Kubernetes environment, this is handled through task_replicas to scale the web and task pods independently. However, in non-Kubernetes environments, the approach differs.
Execution Nodes are defined as instances that run standalone, independent of a Kubernetes cluster. These nodes can be added via the AWX Graphical User Interface (GUI), and the necessary installation bundles are available through the official documentation at awx/docs/execution_nodes.md. This allows an organization to maintain a central AWX control node while distributing the actual task execution across multiple remote servers.
For those utilizing Kubernetes but seeking to constrain execution, Container Groups provide a mechanism to use customized pod specifications with nodeAffinity. This ensures that specific jobs are routed to specific physical or virtual nodes within the cluster. Container Groups can even be configured to run jobs on a completely different Kubernetes cluster than the one hosting the primary AWX instance.
The Constraint of "No-Container" Policies
There exists a significant segment of the enterprise market, particularly those utilizing traditional virtual infrastructure such as KVM and VMware, where corporate policy strictly forbids the use of containers in production. This creates a fundamental conflict with the current trajectory of AWX development.
The requirement for a "traditional" installation—where AWX is installed directly on a host as a web application without any containerization—is a documented request in the community. Such environments often require:
- Direct host installation on CentOS/RHEL.
- No downloading or building of container images.
- External database installation on a separate, dedicated host.
As of the current architectural state, there is no officially supported, non-containerized installation path for AWX. While users have requested an Ansible playbook to automate a bare-metal installation, the project has moved entirely toward a container-centric model (Docker for dev, K8s for prod). Consequently, those with strict no-container policies are faced with a choice: adopt container technology, use the Red Hat Ansible Automation Platform (which provides supported enterprise deployment paths), or attempt unsupported community modifications.
Data Management and Git Integration
A recurring technical challenge in AWX deployments is the management of Ansible project code. Some users attempt to manually copy project code into the web-task pod at /var/lib/awx/projects. This is widely regarded as an inefficient and cumbersome practice.
The architecturally sound method for managing project code is the use of Git repositories. AWX is designed to pull playbooks and roles directly from a Git provider. This ensures:
- Version control of all automation assets.
- Seamless updates across multiple execution nodes.
- Elimination of the need to manually mount volumes or copy files into containers.
In scenarios where network restrictions prevent the use of Git, some users seek to manually manipulate the pod YAML files to mount local directories. However, this is discouraged by experts as it introduces instability and complicates the upgrade path.
Conclusion: Strategic Analysis of Deployment Choices
The decision to deploy AWX without Kubernetes is a trade-off between operational simplicity and long-term stability. Using Docker Compose on a single host (such as Ubuntu 20.04) significantly reduces the initial complexity and resource overhead, making it an attractive option for small-scale environments or rapid prototyping. However, this path removes the user from the "supported" ecosystem, meaning that updates and troubleshooting must be handled independently.
For production environments, the evidence strongly suggests that the AWX Operator on Kubernetes is the only viable path for scalability and reliability. The ability to scale control nodes via task_replicas and the flexibility of Execution Nodes for remote task processing provide a level of robustness that Docker Compose cannot match.
Ultimately, the tension between modern container-driven development and traditional "bare-metal" policies remains unresolved in the open-source version of AWX. Organizations bound by strict non-container policies must either advocate for a policy shift to accommodate the containerized nature of modern automation tools or transition to the commercial Red Hat ecosystem to obtain the necessary support for their specific infrastructure constraints.