How To Install Ansible AWX on Ubuntu 20.04|18.04

Posted on 236 views

Welcome to today’s guide on how to install Ansible AWX on Ubuntu 20.04|18.04 with Nginx Reverse Proxy and optional Let’s Encrypt SSL Certificate. Ansible AWX is an open source tool which provides a web-based user interface, REST API, and task engine for easy and collaborative management of Ansible Playbooks and Inventories.

AWX allows you to centrally manage Ansible playbooks, inventories, Secrets, and scheduled jobs from a web interface. It is easy to install AWX on Ubuntu 20.04|18.04 (Bionic Beaver) Linux system. Use the steps shared below to install and configure Ansible AWX on Ubuntu 20.04|18.04 Linux server.

Starting in version 18.0 of AWX, the recommended installation method is via AWX Operator. As the operator installation method requires a Kubernetes Cluster, we will perform a single node Kubernetes installation on Ubuntu Linux using k3s.

Setup minimum requirements

  • Ubuntu 20.04|18.04 LTS Server
  • At least 8GB of RAM – More is better
  • 4vcpus – Pump more if you have
  • 10GB free disk storage
  • root or user with sudo for ssh

Step 1: Update Ubuntu system

Update and upgrade your system

sudo apt update && sudo apt -y upgrade
[ -f /var/run/reboot-required ] && sudo reboot -f

Step 2: Install Single Node k3s Kubernetes

We will deploy a single node kubernetes using k3s lightweight tool. K3s is a certified Kubernetes distribution designed for production workloads in unattended, resource-constrained environments. The good thing with k3s is that you can add more Worker nodes at later stage if need arises.

K3s provides an installation script that is a convenient way to install it as a service on systemd or openrc based systems

Let’s run the following command to install K3s on our Ubuntu system:

curl -sfL | sudo bash -
sudo chmod 644 /etc/rancher/k3s/k3s.yaml

Installation process output:

[INFO]  Finding release for channel stable
[INFO]  Using v1.22.7+k3s1 as release
[INFO]  Downloading hash
[INFO]  Downloading binary
[INFO]  Verifying binary download
[INFO]  Installing k3s to /usr/local/bin/k3s
[INFO]  Skipping installation of SELinux RPM
[INFO]  Creating /usr/local/bin/kubectl symlink to k3s
[INFO]  Creating /usr/local/bin/crictl symlink to k3s
[INFO]  Creating /usr/local/bin/ctr symlink to k3s
[INFO]  Creating killall script /usr/local/bin/
[INFO]  Creating uninstall script /usr/local/bin/
[INFO]  env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s.service
[INFO]  systemd: Enabling k3s unit
Created symlink /etc/systemd/system/ → /etc/systemd/system/k3s.service.
[INFO]  systemd: Starting k3s

Validate K3s installation:

The next step is to validate our installation of K3s using kubectl command which was installed and configured by installer script.

$ kubectl get nodes
NAME        STATUS   ROLES                  AGE   VERSION
ubuntu-01   Ready    control-plane,master   2m53s   v1.22.7+k3s1

You can also confirm Kubernetes version deployed using the following command:

$ kubectl version --short
Client Version: v1.22.7+k3s1
Server Version: v1.22.7+k3s1

The K3s service will be configured to automatically restart after node reboots or if the process crashes or is killed.

Step 3: Deploy AWX Operator on Kubernetes

This Kubernetes Operator has to be deployed in your Kubernetes cluster, which in our case is powered by K3s. The operator we’ll deploy can manage one or more AWX instances in any namespace.

Install git and make tools:

sudo apt update
sudo apt install git build-essential

Clone operator deployment code:

$ git clone
Cloning into 'awx-operator'...
remote: Enumerating objects: 6306, done.
remote: Counting objects: 100% (315/315), done.
remote: Compressing objects: 100% (189/189), done.
remote: Total 6306 (delta 160), reused 236 (delta 115), pack-reused 5991
Receiving objects: 100% (6306/6306), 1.54 MiB | 19.74 MiB/s, done.
Resolving deltas: 100% (3598/3598), done.

Create namespace where operator will be deployed. I’ll name mine awx:

export NAMESPACE=awx
kubectl create ns $NAMESPACE

Set current context to value set in NAMESPACE variable:

# kubectl config set-context --current --namespace=$NAMESPACE 
Context "default" modified.

Switch to awx-operator directory:

cd awx-operator/

Save the latest version from AWX Operator releases as RELEASE_TAG variable then checkout to the branch using git.

sudo apt install curl jq
RELEASE_TAG=`curl -s | grep tag_name | cut -d '"' -f 4`
git checkout $RELEASE_TAG

Deploy AWX Operator into your cluster:

export NAMESPACE=awx
make deploy

Command output:

namespace/awx configured created created created
serviceaccount/awx-operator-controller-manager created created created created created created created created
configmap/awx-operator-awx-manager-config created
service/awx-operator-controller-manager-metrics-service created
deployment.apps/awx-operator-controller-manager created

Wait a few minutes and awx-operator should be running:

# kubectl get pods
NAME                                               READY   STATUS    RESTARTS   AGE
awx-operator-controller-manager-68d787cfbd-z75n4   2/2     Running   0          40s

How To Uninstall AWX Operator (Don’t run this unless you’re sure it uninstalls!

You can always remove the operator and all associated CRDs by running the command below:

# export NAMESPACE=awx
# make undeploy
/root/awx-operator/bin/kustomize build config/default | kubectl delete -f -
namespace "awx" deleted "" deleted "" deleted "" deleted
serviceaccount "awx-operator-controller-manager" deleted "awx-operator-leader-election-role" deleted "awx-operator-manager-role" deleted "awx-operator-metrics-reader" deleted "awx-operator-proxy-role" deleted "awx-operator-leader-election-rolebinding" deleted "awx-operator-manager-rolebinding" deleted "awx-operator-proxy-rolebinding" deleted
configmap "awx-operator-manager-config" deleted
service "awx-operator-controller-manager-metrics-service" deleted
deployment.apps "awx-operator-controller-manager" deleted

Step 4: Install Ansible AWX on Ubuntu 20.04/18.04 using Operator

Create Static data PVC – Ref AWX data persistence:

cat <

PVC won’t be bound until the pod that uses it is created.

# kubectl get pvc -n awx
static-data-pvc          Pending                                      local-path     43s

Let’s now create AWX deployment file with basic information about what is installed:

vim awx-deploy.yml

Paste below contents into the file:

kind: AWX
  name: awx
  service_type: nodeport
  projects_persistence: true
  projects_storage_access_mode: ReadWriteOnce
  web_extra_volume_mounts: |
    - name: static-data
      mountPath: /var/lib/projects
  extra_volumes: |
    - name: static-data
        claimName: static-data-pvc

We have defined resource name as awx and service type as nodeport to enable us access AWX from the Node IP address and given port. We also added extra PV mount on the web server pod.

Apply configuration manifest file:

$ kubectl apply -f awx-deploy.yml created

Wait a few minutes then check AWX instance deployed:

$ watch kubectl get pods -l ""
NAME                   READY   STATUS    RESTARTS   AGE
awx-postgres-0         1/1     Running   0          75s
awx-7c5d846c88-mjlvm   4/4     Running   0          64s

You can track the installation process at the operator pod logs:

kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager

Fixing Postgres Pod in CrashLoopBackOff state (Skip if you don’t have this error message)

Check status of PostgreSQL Pod:

$ kubectl get pods -l ""
NAME                   READY   STATUS             RESTARTS   AGE
awx-postgres-0         0/1     CrashLoopBackOff   4          2m38s
awx-66c64f8d67-qvfk9   3/4     ImagePullBackOff   0          2m27s

Check logs of the Pod:

$ kubectl logs awx-postgres-0
mkdir: cannot create directory ‘/var/lib/postgresql/data’: Permission denied

It means the Postgres pod cannot write to the persistent volume directory inside /var/lib/rancher/k3s/storage/:

# ls -lh /var/lib/rancher/k3s/storage/ | grep awx-postgres-0
total 0
drwx------ 3 root root 4.0K Aug 24 09:18 pvc-b2acb2d0-6d2f-457b-a40c-390cff5ec6d2_default_postgres-awx-postgres-0

Try setting the directory mode to 777

# chmod -R 777  /var/lib/rancher/k3s/storage/*
# kubectl delete pods -l ""
pod "awx-66c64f8d67-qvfk9" deleted
pod "awx-postgres-0" deleted

The Postgres container pod should come up in few seconds:

# kubectl get pods -l ""
NAME                   READY   STATUS             RESTARTS   AGE
awx-postgres-0         1/1     Running            0          42s
awx-66c64f8d67-4qmh5   4/4     Running            0          42s

If you experience any issues with the Pods starting check deployment logs:

kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager

Data Persistence

The database data will be persistent as they are stored in a persistent volume:

$ kubectl get pvc
NAME                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
postgres-awx-postgres-0   Bound    pvc-c0149545-8631-4aa1-a03f-2134a7f42aa6   8Gi        RWO            local-path     84s
static-data-pvc           Bound    pvc-6b6005de-0888-4634-b0a2-d5cc92eb85cc   1Gi        RWO            local-path     2m10s
awx-projects-claim        Bound    pvc-91e751e9-0e8e-40c8-9953-f8d9db5f612b   8Gi        RWO            local-path     77s

Volumes are created using local-path-provisioner and host path

$ ls /var/lib/rancher/k3s/storage/

Checking AWX Container’s logs

The awx-xxx-yyy pod will have four containers, namely:

  • redis
  • awx-web
  • awx-task
  • awx-ee

As can be seen from below command output:

# kubectl -n awx  logs deploy/awx
error: a container name must be specified for pod awx-75698588d6-r7bxl, choose one of: [redis awx-web awx-task awx-ee]

You’ll need to provide container name after the pod:

kubectl -n awx  logs deploy/awx -c redis
kubectl -n awx  logs deploy/awx -c awx-web
kubectl -n awx  logs deploy/awx -c awx-task
kubectl -n awx  logs deploy/awx -c awx-ee

Access AWX Container’s Shell

Here is how to access each container’s shell:

kubectl exec -ti deploy/awx  -c  awx-task -- /bin/bash
kubectl exec -ti deploy/awx  -c  awx-web -- /bin/bash
kubectl exec -ti deploy/awx  -c  awx-ee -- /bin/bash
kubectl exec -ti deploy/awx  -c  redis -- /bin/bash

Upgrading AWX Operator and instance

We have created a dedicated guide for upgrading the Operator and AWX instance:

Step 5: Access Ansible AWX Dashboard

List all available services and check awx-service Nodeport

$ kubectl get svc -l ""
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
awx-postgres   ClusterIP   None                   5432/TCP       2m5s
awx-service    NodePort           80:30922/TCP   94s

We can see the service type is set to NodePort. To access our service from outside Kubernetes cluster using k3s node IP address and give node port


You can edit the Node Port and set to figure of your preference, but it has to be in the range of 30000-32768

On accessing AWX web portal you are presented with the welcome dashboard similar to one below.


The login username is admin

Obtain admin user password by decoding the secret with the password value:

kubectl get secret awx-admin-password -o jsonpath=".data.password" | base64 --decode

Better output format:

kubectl get secret awx-admin-password -o go-template='range $k,$v := .dataprintf "%s: " $kif not $v$velse base64decodeend"\n"end'

Login with admin username and decoded password:


The new AWX interface is beautifully designed with Love. It is a serious redesign with good polishing.


In the articles to follow we will explore Ansible AWX administration and usage in automation Infrastructure repetitive tasks.

Review Kubernetes Node resources to ensure they are enough to run AWX:

$ kubectl top nodes --use-protocol-buffers
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
ubuntu   102m         1%     2534Mi          15%

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.