In a previous post, I covered storing WordPress content in an NFS and mounting that share to each instance of your WordPress site. Since I was running WordPress in Azure Kubernetes Service cluster, I went over how to create and upload all your WordPress content to Azure File share and then followed up with how to mount that file share to each replica of your WordPress deployment.
In this post, I will go over how to solve the 2nd problem around horizontally scaling WordPress identified in this post: setting authentication keys and salts to the same values.
What are Authentication Keys and Salts
Whenever anyone tries to access the WordPress Admin Portal, they are immediately asked to login using their account credentials. Once they enter their credentials and press the login button, WordPress validates their credentials. If the credentials are wrong, the user receives an error, otherwise, WordPress loads the WordPress Admin Portal page that the user was trying to access. This process is known as authentication.
Behind the scenes, once the credentials are validated, a cookie is created containing information such as who the user is, how long is the cookie valid for, etc. This cookie is then sent to the user in the same response as the WordPress Admin Portal page that the user was trying to access before being asked to log in. This cookie will automatically be included in every request sent to the WordPress site. When the user tries to access another WordPress Portal page, instead of being asked to re-enter their credentials, the WordPress site checks the information in the cookie to determine who is the user requesting it. So the cookie plays a critical role in the security of the site.
In order to prevent users from tampering with the contents of the cookie (such as the user information, etc.), when the cookie is being created, it is signed with a key that only the site knows. Whenever the site receives a new request, it checks if the signature of the cookie matches with other contents of the cookie. If the contents of the cookie were modified, then this validation will fail. Whenever this happens, users are asked to re-authenticate themselves (i.e. go through log in process again).
Why do authentication keys and salts need to be the same for all replicas?
The configuration values specified in the authentication keys and salts section of wp-config.php are used for maintaining the security of the WordPress site. If each replica of the WordPress deployment has a different value for these settings, then authentication will keep failing and users will be asked to re-authenticate themselves endlessly.
How to generate and set authentication keys and salts to the same values?
There are several ways to generate values for authentication keys and salts. One of the easiest ones is to go to WordPress Security Generator (https://api.wordpress.org/secret-key/1.1/salt/). When you go to this site, you will see values generated for all of the following parameters:
Once you have these values, you will have to modify your wordpress deployment to the following.
apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: selector: matchLabels: app: wordpress strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 1 replicas: 3 template: metadata: labels: app: wordpress spec: containers: - name: wordpress image: wordpress:5.5.1-php7.4-apache env: - name: WORDPRESS_AUTH_KEY value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_SECURE_AUTH_KEY value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_LOGGED_IN_KEY value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_NONCE_KEY value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_AUTH_SALT value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_SECURE_AUTH_SALT value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_LOGGED_IN_SALT value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_NONCE_SALT value: "<enter value>" # TODO: fill in this value - name: WORDPRESS_DB_HOST value: "<your host>" # TODO: fill in this value - name: WORDPRESS_DB_NAME value: "<your DB>" # TODO: fill in this value - name: WORDPRESS_DB_USER value: "<your user>" # TODO: fill in this value - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: "<your DB password secret>" # TODO: fill in this value key: "<your DB password key>" # TODO: fill in this value ports: - containerPort: 80 volumeMounts: - name: azurefile mountPath: /var/www/html/wp-content volumes: - name: azurefile persistentVolumeClaim: claimName: azurefile