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:

  1. In the AWX web UI, navigate to ResourcesInventories
  2. Click AddAdd inventory
  3. Enter a name (e.g., “Production Servers”) and click Save
  4. Go to the Hosts tab and click Add
  5. 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.

  1. Navigate to ResourcesCredentials
  2. Click Add
  3. Enter a name (e.g., “SSH Key – Production”)
  4. Select Credential Type as “Machine”
  5. Enter the SSH username and paste your private key or password
  6. 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.

  1. Navigate to ResourcesProjects
  2. Click Add
  3. Enter a name (e.g., “My Playbooks”)
  4. Set Source Control Type to “Git”
  5. Enter the Source Control URL (your Git repo URL)
  6. Select the source control credential if the repo is private
  7. 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.

  1. Navigate to ResourcesTemplates
  2. Click AddAdd job template
  3. Enter a name (e.g., “Ping All Servers”)
  4. Select the Inventory you created in Step 8
  5. Select the Project you created in Step 10
  6. Choose the Playbook from the dropdown (e.g., ping.yml)
  7. Select the Credentials you created in Step 9
  8. Click Save

Now launch the job:

  1. Click the rocket icon next to your template, or click Launch
  2. 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.

2 COMMENTS

  1. 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.

LEAVE A REPLY

Please enter your comment!
Please enter your name here