Engineering

⌘K
  1. Home
  2. Docs
  3. Engineering
  4. WordPress
  5. WordOps

WordOps

We previously used WordOps to manage WordPress/WooCommerce installations. However, in 2021 we faced several issues:

  1. It is often down due to high CPU usage, then exhausted CPU burst capacity.
  2. It does not support AWS Graviton2 instances.

Now we are switching to RunCloud with OpenLiteSpeed. Hendy evaluated Webinoly and ServerPilot ($5/month + $0.5/app/month) and SpinupWP, RunCloud ($8-$15-$45/mo), Ploi, and GridPane.

Installation

Create and set up an Ubuntu VM.

  1. Create AWS Lightsail instance (1 GiB for one site, 2 GiB for two or more sites), using Ubuntu latest LTS version.
  2. Create static IP address, and assign to the Lightsail instance.
  3. Using AWS Lightsail Firewall, deny HTTP port 80 and allow HTTPS port 443.
  4. SSH to Ubuntu
  5. Enable Byobu: byobu-enable
  6. Install WordOps: wget -qO wo wops.cc && sudo bash wo

Preparing WordOps Configuration

WordOps configuration, include application level debugging, is available at /etc/wo/wo.conf.

The most important one is remote MySQL/MariaDB database configuration, as we are using AWS RDS MariaDB.

Install MySQL client (for AWS Graviton2, see #392): sudo wo stack install --mysqlclient

Edit MySQL client configuration at /etc/mysql/mariadb.conf.d/50-clients.cnf (new WordOps uses MariaDB), or previously /etc/mysql/conf.d/my.cnf: (change the host and password)

[client]
host = ***.ap-southeast-1.rds.amazonaws.com
user = root
password = your-very-strong-password

Edit /etc/wo/wo.conf. Edit the [mysql] section, set grant-host to %:

[mysql]

### MySQL database grant host name
grant-host = %

### Ask for MySQL db name while site creation
db-name = False

### Ask for MySQL user name while site creation
db-user = False

Edit the section and set version to latest stable PHP as follows:



### Default PHP version
version = 7.4

Creating A WordPress Site

Before you start, make sure you install acme.sh, then configure DNS verification, e.g. CloudFlare.

# Dedicated shell
sudo bash

# install acme.sh
curl https://get.acme.sh | sh -s email=YOUR_EMAIL
sudo -E acme.sh --register-account -m YOUR_EMAIL

export CF_Key="..."
export CF_Email="[email protected]"

# Now you can enable SSL cert

We’re using AWS RDS MariaDB, the GRANT patch was accepted.

Create the WordOps Dashboard site first: (AWS Graviton2 problem #393)

sudo -E wo stack install --dashboard
# FIXME: --netdata errors in AWS Graviton2
#sudo -E wo stack install --dashboard --netdata
sudo -E wo site create server-cname.domain.tld -le --dns=dns_cf

Trying to install –netdata will give error:

# sudo -E wo stack install --netdata
Downloading Netdata              [Done]
Installing Netdata              [OK]
Traceback (most recent call last):
  File "/usr/local/bin/wo", line 8, in <module>
    sys.exit(main())
  File "/opt/wo/lib/python3.8/site-packages/wo/cli/main.py", line 102, in main
    app.run()
  File "/opt/wo/lib/python3.8/site-packages/cement/core/foundation.py", line 882, in run
    return_val = self.controller._dispatch()
  File "/opt/wo/lib/python3.8/site-packages/cement/core/controller.py", line 471, in _dispatch
    return func()
  File "/opt/wo/lib/python3.8/site-packages/cement/core/controller.py", line 477, in _dispatch
    return func()
  File "/opt/wo/lib/python3.8/site-packages/wo/cli/plugins/stack.py", line 537, in install
    post_pref(self, [], packages)
  File "/opt/wo/lib/python3.8/site-packages/wo/cli/plugins/stack_pref.py", line 1414, in post_pref
    .format(wo_netdata),
UnboundLocalError: local variable 'wo_netdata' referenced before assignment

Then create a WordPress site:

sudo -E wo site create subdomain.lovia.life --wpredis --php74 --letsencrypt=on --dns=dns_cf --user sysadmin --email [email protected]

Crontab using WP-CLI cron

Edit the crontab for user www-data:

sudo crontab -e -u www-data
# Repeat for each website
*/5 * * * * cd /var/www/example.com/htdocs; wp cron event run --due-now > /dev/null 2>&1

Reference: https://easyengine.io/tutorials/wordpress/wp-cron-crontab/

Moving A WordOps Site to Another Server

  1. Backup using UpdraftPlus to AWS S3
  2. Install WordOps (as above)
  3. Prepare WordOps configuration (as above)
  4. Create the WordPress site with DNS verification and AWS RDS MariaDB GRANT patch (as above)
  5. Change the DNS record or CloudFront to point to new server

Option 1: rsync way (old database)

  1. On new server, using root, generate ssh-keygen
  2. Add key to old server’s authorized_keys
  3. In new server, sudo su, then rsync -va from old server:
    /etc/wo/*
    /var/lib/wo/*
    /etc/letsencrypt/live/*
    /var/www/*
  4. Remove key from old server’s authorized_keys
  5. Install wo on new server
  6. Install stack
    sudo -E wo stack install –nginx –php74 –wpcli –nginx –mysqlclient –dashboard –netdata
  7. rsync -va from old server:
    /etc/nginx/sites-available/*
# (Optional) Update LetsEncrypt certificates using Cloudflare:
#export CF_Key=....
#export CF_Email=....
#sudo -E wo site update -le wildcard --dns dns_cf yoursite.com

# What you must do is to enable each site one by one, for all sites
sudo -E wo site enable lovia.life

Enable HTTP/2 for health check: Edit /etc/nginx/sites-enabled/default.

  • Uncomment the listen part including snakeoil self-signed certificate
  • In the two listen lines, after “ssl” append “http2”

Snakeoil cert is:

  • /etc/ssl/certs/ssl-cert-snakeoil.pem
  • /etc/ssl/private/ssl-cert-snakeoil.key
sudo apt -y install ssl-cert
sudo make-ssl-cert generate-default-snakeoil

Make sure nginx default page works, at least for ALB health check:

# WordOps does not support HTTP/2 on port 80
curl -v --header 'Host: 10.0.0.1' http://172.26.10.83/
# This will be self signed cert
curl -v --http2 --insecure --header 'Host: 10.0.0.1' https://172.26.10.83/

Now we need to set up crontab, see Crontab section below.

Cleanup old server:

  1. Remove all WordPress files from old server: sudo wo site delete --files subdomain.example.com
  2. In MariaDB, drop the “new” (unused) WordPress database and user

Option 2: UpdraftPlus way (new database)

  1. Copy parts of the wp-config.php file (SES config, etc.)
  2. Sign in to new WordPress
  3. Install UpdraftPlus
  4. Link AWS S3
  5. Restore from AWS S3 backup
  6. Delete old site

Operations

Update WordOps

sudo -E wo update

Perform Maintenance

sudo -E wo maintenance

Upgrade Stack

This is needed to upgrade files like /etc/nginx/common/wpcommon-php74.conf and others.

sudo -E wo stack upgrade

Performance Best Practices

Although WordOps is good by default, Hendy found a few ways that can be optimized, with caveats.

Buffering access_log

By default all sites will write access_log all the time, even just for BetterUptime monitoring. So, edit /etc/nginx/sites-available/* and enable buffering, e.g.:

  access_log   /var/log/nginx/22222.access.log rt_cache buffer=32k;

How to Change WordPress Site URL using WP CLI

cd /var/www/anakalam.id/htdocs
sudo -u www-data wp search-replace 'https://anakalam.id' 'https://www.anakalam.id' --skip-columns=guid
sudo -u www-data wp cache flush

How can we help?