Ansible Tower has been rebranded. The open-source upstream project is now called AWX, while Red Hat offers Ansible Automation Platform as the enterprise product. AWX provides a web-based UI, REST API, and role-based access control for managing Ansible playbooks at scale. The big architectural change: AWX now runs on Kubernetes, deployed via the AWX Operator.
This guide walks you through installing AWX on RHEL 10, Rocky Linux 10, or AlmaLinux 10 using K3s as the lightweight Kubernetes backend and the AWX Operator for deployment.
Prerequisites
Before you begin, make sure you have:
- A server running RHEL 10, Rocky Linux 10, or AlmaLinux 10 (minimum 4 GB RAM, 2 CPUs, 20 GB disk)
- Root or sudo access
- A working internet connection
- A fully qualified domain name (optional, but recommended for production)
AWX runs on Kubernetes, so you need a Kubernetes cluster. For a single-node setup, K3s is the simplest option. Alternatives include Minikube or a full K8s cluster, but K3s is production-ready and lightweight.
Step 1 – Update the System
Start by updating all packages on your server:
sudo dnf update -y
Install a few basic tools you will need:
sudo dnf install -y curl git vim
Verify your OS release:
cat /etc/redhat-release
You should see output like Rocky Linux release 10.0, AlmaLinux release 10.0, or Red Hat Enterprise Linux release 10.0.
Step 2 – Disable Firewall or Open Required Ports
K3s and AWX need several ports. For a lab setup, you can disable firewalld temporarily:
sudo systemctl disable --now firewalld
For production, open these ports instead:
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=10250/tcp
sudo firewall-cmd --reload
Verify the firewall rules:
sudo firewall-cmd --list-all
Step 3 – Install K3s (Lightweight Kubernetes)
Install K3s using the official install script. This gives you a single-node Kubernetes cluster in about 30 seconds:
curl -sfL https://get.k3s.io | sh -
Wait for K3s to start, then verify it is running:
sudo systemctl status k3s
Check that the node is ready:
sudo kubectl get nodes
Expected output:
NAME STATUS ROLES AGE VERSION
your-host Ready control-plane,master 30s v1.31.x+k3s1
Set up kubectl for your user so you do not need sudo every time:
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config
echo 'export KUBECONFIG=~/.kube/config' >> ~/.bashrc
Verify kubectl works without sudo:
kubectl get nodes
Step 4 – Install AWX Operator Using Kustomize
The AWX Operator is the official way to deploy AWX on Kubernetes. We will use Kustomize (built into kubectl) for this deployment.
First, create a working directory:
mkdir -p ~/awx-deploy
cd ~/awx-deploy
Check the latest AWX Operator release version on the AWX Operator GitHub releases page. At the time of writing, the latest version is 2.19.1. Set the version variable:
AWX_OPERATOR_VERSION=2.19.1
Create the kustomization.yaml file:
cat <<EOF > kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/ansible/awx-operator/config/default?ref=${AWX_OPERATOR_VERSION}
images:
- name: quay.io/ansible/awx-operator
newTag: ${AWX_OPERATOR_VERSION}
namespace: awx
EOF
Create the namespace and deploy the AWX Operator:
kubectl create namespace awx
kubectl apply -k ~/awx-deploy
Wait for the operator pod to become ready:
kubectl -n awx get pods -w
You should eventually see the operator pod in Running state:
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-xxxxxxxxxx-xxxxx 2/2 Running 0 60s
Press Ctrl+C once the pod is running.
Step 5 – Deploy the AWX Instance
Now that the operator is running, create an AWX custom resource to deploy the actual AWX application.
Create the AWX resource file:
cat <<EOF > ~/awx-deploy/awx-instance.yaml
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
namespace: awx
spec:
service_type: NodePort
nodeport_port: 30080
EOF
Update the kustomization.yaml to include the AWX instance:
cat <<EOF > ~/awx-deploy/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/ansible/awx-operator/config/default?ref=${AWX_OPERATOR_VERSION}
- awx-instance.yaml
images:
- name: quay.io/ansible/awx-operator
newTag: ${AWX_OPERATOR_VERSION}
namespace: awx
EOF
Apply the updated configuration:
kubectl apply -k ~/awx-deploy
This triggers the operator to create all required AWX pods, services, and persistent volumes. The deployment takes 3 to 10 minutes depending on your internet speed and hardware.
Monitor the deployment progress:
kubectl -n awx get pods -w
Wait until all pods show Running status. You should see pods like:
NAME READY STATUS RESTARTS AGE
awx-operator-controller-manager-xxxxxxxxxx-xxxxx 2/2 Running 0 5m
awx-postgres-15-0 1/1 Running 0 3m
awx-task-xxxxxxxxxx-xxxxx 4/4 Running 0 2m
awx-web-xxxxxxxxxx-xxxxx 3/3 Running 0 2m
Verify the AWX deployment is fully up:
kubectl -n awx get awx
kubectl -n awx get svc
Step 6 – Retrieve the Admin Password
The AWX Operator automatically generates an admin password and stores it in a Kubernetes secret. Retrieve it with:
kubectl -n awx get secret awx-admin-password -o jsonpath='{.data.password}' | base64 --decode; echo
Save this password somewhere safe. The default username is admin.
Step 7 – Access the AWX Web UI
Since we configured the service as NodePort on port 30080, open your browser and go to:
http://YOUR_SERVER_IP:30080
Log in with:
- Username: admin
- Password: the password retrieved in Step 6
You should see the AWX dashboard. If the page does not load, check that the pods are all running and that your firewall allows port 30080.
Verify the service is exposed correctly:
kubectl -n awx get svc awx-service
Step 8 – Configure Inventories
Inventories define the hosts AWX will manage. To create one:
- In the AWX web UI, navigate to Resources – Inventories
- Click Add – Add inventory
- Enter a name (e.g., “Production Servers”) and click Save
- Go to the Hosts tab and click Add
- Enter the hostname or IP address of a target machine and click Save
Repeat for each host you want to manage.
Step 9 – Configure Credentials
Credentials store authentication details for connecting to managed hosts and source control.
- Navigate to Resources – Credentials
- Click Add
- Enter a name (e.g., “SSH Key – Production”)
- Select Credential Type as “Machine”
- Enter the SSH username and paste your private key or password
- Click Save
For Git-based projects, also create a “Source Control” credential with your repository access token or SSH key.
Step 10 – Create a Project
Projects link AWX to a Git repository containing your Ansible playbooks.
- Navigate to Resources – Projects
- Click Add
- Enter a name (e.g., “My Playbooks”)
- Set Source Control Type to “Git”
- Enter the Source Control URL (your Git repo URL)
- Select the source control credential if the repo is private
- Click Save
AWX will sync the project automatically. Check the status icon turns green.
Step 11 – Create a Job Template and Run Your First Playbook
Job templates tie together an inventory, credentials, and a playbook from a project.
- Navigate to Resources – Templates
- Click Add – Add job template
- Enter a name (e.g., “Ping All Servers”)
- Select the Inventory you created in Step 8
- Select the Project you created in Step 10
- Choose the Playbook from the dropdown (e.g.,
ping.yml) - Select the Credentials you created in Step 9
- Click Save
Now launch the job:
- Click the rocket icon next to your template, or click Launch
- Watch the output in real time as AWX connects to your hosts and runs the playbook
A successful ping playbook run confirms that AWX can reach your managed hosts and execute tasks.
Alternative: Deploying AWX with Helm
If you prefer Helm over Kustomize, you can install the AWX Operator this way:
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add awx-operator https://ansible-community.github.io/awx-operator-helm/
helm repo update
helm install awx-operator awx-operator/awx-operator \
-n awx --create-namespace \
--set AWX.enabled=true \
--set AWX.spec.service_type=NodePort \
--set AWX.spec.nodeport_port=30080
Verify the Helm deployment:
helm list -n awx
kubectl -n awx get pods
The rest of the steps (retrieving the password, accessing the UI, configuring inventories) remain the same.
Ansible Automation Platform (Enterprise Alternative)
If you need enterprise support, certified content, and a subscription-backed product, Red Hat offers Ansible Automation Platform (AAP). AAP includes the automation controller (the commercial version of AWX), automation hub for curated collections, and Event-Driven Ansible.
AAP requires a Red Hat subscription and is available through the Red Hat Customer Portal. It is the right choice for organizations that need vendor support, SLA guarantees, and FIPS-validated deployments. For labs, development, and smaller teams, AWX is the way to go.
Troubleshooting
Pods stuck in Pending or CrashLoopBackOff
Check the pod logs and events:
kubectl -n awx describe pod <pod-name>
kubectl -n awx logs <pod-name> --all-containers
Common causes: insufficient memory (AWX needs at least 4 GB RAM), storage provisioner issues, or image pull failures.
Cannot access the web UI
Verify the service and check which port is exposed:
kubectl -n awx get svc awx-service -o wide
Make sure your firewall allows the NodePort (30080) and that you are using the correct server IP.
Database migration errors
If the AWX task pod keeps restarting due to migration failures, check the task container logs:
kubectl -n awx logs deployment/awx-task -c awx-task
This usually indicates a storage issue or an interrupted previous deployment. Delete the AWX instance and redeploy:
kubectl -n awx delete awx awx
kubectl -n awx delete pvc --all
kubectl apply -k ~/awx-deploy
K3s fails to start
Check the K3s service logs:
sudo journalctl -u k3s -f
On RHEL 10 with SELinux enforcing, you may need the K3s SELinux policy package:
sudo dnf install -y container-selinux
curl -sfL https://get.k3s.io | INSTALL_K3S_SELINUX_WARN=true sh -
Resetting the admin password
If you lost the admin password, reset it by exec-ing into the web pod:
kubectl -n awx exec -it deployment/awx-web -c awx-web -- awx-manage changepassword admin
Checking AWX Operator logs
The operator logs show what it is doing during deployment:
kubectl -n awx logs deployment/awx-operator-controller-manager -c awx-manager -f
Uninstalling AWX
To remove AWX completely:
kubectl -n awx delete awx awx
kubectl delete namespace awx
To also remove K3s:
/usr/local/bin/k3s-uninstall.sh
Conclusion
You now have AWX running on your RHEL 10 / Rocky Linux 10 / AlmaLinux 10 server. The deployment uses K3s as a lightweight Kubernetes layer and the AWX Operator to manage the application lifecycle. From here, you can create inventories, set up credentials, build job templates, and schedule playbook runs – all from the web UI.
For teams that need enterprise support, look into Ansible Automation Platform from Red Hat. For everyone else, AWX delivers the same core functionality at zero cost.
































































Helpful article, thanks!
Hi,
Glad to see these write ups.
> “We will use the Web UI since this is the most preferred method by most new Ansible Tower users”
No, CLI is the preferred way by everybody that I know who was new to Tower. Myself included.
Best not to presume that the reader is retarded.
I should be very grateful if you wrote a version of your article that did the configuration via a shell. I stopped reading as soon as I saw a GUI.
Regards, S.