Mostly about my amusement

Category: Geek (page 3 of 36)

How to use UpdraftPlus when The Bad Thing™ happens

I am in the process of handing over a site to someone who's not used WordPress before and doesn't necessarily know where what lives and how. I thought it would be a good idea for me to document how to use the free UpdraftPlus plugin.

I use the commercial version of this plugin because it is fire-and-forget for my multisite installation. But if you are running a standalone installation of WordPress then the free version is a good suitable option.

Read more

Did I mention I like WP-CLI?

I’ve written praise for wp-cli before but it’s a toy that will never get old for me.

I was working on this problem for a friend and I needed to create a test multisite installation. I have a domain I can use aside from my main one so I setup another nginx virtual host, setup the DNS entries and used Let’s Encrypt to obtain legitimate X.509 certificates.

For creating the DB and WordPress config I used CLI commands.

$ mysql -u root -p

create database leeloodallas;
grant all privileges on leeloodallas.* to 
"brucewillis"@"loc1alhost" identified by "5oM3U36ul$tringH3re";
flush privileges;
exit;

$ wp core download

$ wp core config --dbname=leeloodallas \
--dbuser=brucewillis \
--dbpass=5oM3U36ul$tringH3re \
--extra-php <<PHP
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
PHP

$ wp core install --admin_user=yourlogin \
--admin_password=Y3a2n0tHaP3n1ng \
--admin_email=you@example.com \
--url=blog.dn7.me \
--title="Leeloo Dallas Multisite"

$ wp core multisite-convert --subdomains

Yes, all the passwords and IDs are changed.

When I get into deep water (and I did) I just rm * -rf in the virtual host’s directory and in mysql drop database leeloodallas; and do it all over again.

The only thing different from other times is the wp core multisite-convert --subdomains command. I already have cookie cutter nginx configs and DNS is fire and forget. Once I had the vhost setup the Let’s Encrypt commands (also scriptable) was trivial.

WP-CLI is cool and scripting this is such a time saver.

Let’s Encrypt is all kinds of awesome

I had some time and did a git pull on the Let’s Encrypt github page. This is a project that makes it easy to install and maintain free X.509 certificates for web servers. The certificates are in PEM format and can be easily used for any server app but usually it’s just for HTTPS on web servers.

Requesting your own certs

The first time I ran the ./letsencrypt-auto command it used apt-get to download its dependencies. The integration with Ubuntu is nice and works well. A few minutes later of some prodding and poking, meaning I read the Let’s Encrypt User Guide, I gave it a shot.

On my VPS I selected blog.epyon-1.com and ran the following command as root.

./letsencrypt-auto certonly --webroot -w /var/www/vhosts/dembowski.net/ -m not@my-email.btw -d blog.epyon-1.com

The site blog.epyon-1.com is on my WordPress network so the directory is the same. The end result of that was to politely create and place these symlinked files.

/etc/letsencrypt/live/blog.epyon-1.com/cert.pem
/etc/letsencrypt/live/blog.epyon-1.com/fullchain.pem
/etc/letsencrypt/live/blog.epyon-1.com/privkey.pem

A quick update to my nginx config for

ssl_certificate /etc/letsencrypt/live/blog.epyon-1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.epyon-1.com/privkey.pem;

I checked with “nginx -t” and “service nginx restart” and that was it.

Encryption has never been this easy

The certificate is valid for 90 days and is recognized by all browsers.

lets-encrypt-epyon-1.com

To renew it I’ve created a cron job for the first of every month to run this command.

./letsencrypt-auto certonly --webroot -w /var/www/vhosts/dembowski.net/ -m not@my-email.btw -d blog.epyon-1.com -d epyon-1.com --renew

Which is the same command with just --renew added to it. Easy. If you don’t renew the CA will send you a reminder at the email you specified via the “-m not@my-email.btw” command line argument.

I’m not directing the output to /dev/null because if that cronjob works or not I want to see that output. If the cronjob fails then I can always run the command by hand.

Will I switch all my domains to Let’s Encrypt?

Why not? The project is currently in a public beta and the Let’s Encrypt tools will change and continue to be developed. But for the next 90 days the certificate I obtained will work fine. Even better if they automatically renew.

What I am looking for is a reasonable expectation of privacy between my web server and my visitors. I do not use TLS for authentication and the Let’s Encrypt certificates work fine.

If I had an online store then I might consider getting an Extended Validation Certificate but that would be only to reassure visitors when they are making a purchase. EV certs are not cheap. Let’s Encrypt is free so it’s not a hard decision for me to make.

This helps protect the traffic from casual snoopers between my server and your browser. It’s not a magic bullet for security but the wide spread adoption of encryption will help promote privacy.

My oEmbed discovery links work (It was me)

I thought I broke my oEmbed discovery links but I had a more fundamental problem. I had broken fancy permalinks on my nginx configuration for a while and didn’t realize it.

I revisited the Nginx Codex page and did a stare and compare of my configuration and the examples there. I am sure I read that page in the past and my mistake was the “try_files” line.

Here’s what I had for try_files.

location / {
	try_files $uri $uri/ /index.php;
}

Here’s what that line should have read.

location / {
	try_files $uri $uri/ /index.php?$args;
}

See the “?$args” part? With that in place the non-post URLs work. The permalinks worked fine but things that were not to a post or page didn’t. Due to my fancy permalink settings my oEmbed discovery links had this format.

https://blog.dembowski.net/wp-json/oembed/1.0/embed?url=urlencoded-data-here and that wasn’t being handled by my nginx configuration.

My plugin worked because I was replacing the fancy URLs with the regular non-fancy “?rest_route” version which nginx passed along to my WordPress installation just fine.

https://blog.dembowski.net/?rest_route=%2Foembed%2F1.0%2Fembed&url=urlencoded-data-here

This may have also broken other features as well. I wonder what else I’m missing? I should check all the things. 😉

oEmbed not working (I’m convinced it’s me)

One of the new WordPress 4.4 features is the ability for your installation to become an oEmbed provider. In plain English you can paste your post URL and get a result as if you were embedding a YouTube URL.

I could not get it to work for me. No way, no how. The json and XML discovery links were there in the post HTML but those links came back with “What? What? No. Go away, you’re bothering kid.”

It should have come back with a valid output and it did. It was a result, just not a functioning one.

For example, this post (which I’m not embedding) should provide via this link usable information. It doesn’t. I get this.

<link rel="alternate" type="application/json+oembed" href="https://blog.dembowski.net/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fblog.dembowski.net%2F2015%2Fserver-admins-love-wp-cli%2F" />

That link results in this.

{"code":"rest_missing_callback_param","message":"Missing parameter(s): url","data":{"status":400,"params":["url"]}}

It doesn’t contain any useful data except to reply with “What? What? What?”

It should output this.

{"version":"1.0","provider_name":"Mostly Harmless","provider_url":"https:\/\/blog.dembowski.net","author_name":"Jan Dembowski","author_url":"https:\/\/blog.dembowski.net\/author\/jan\/","title":"Server admins love WP-CLI","type":"rich","width":600,"height":338,"html":"</pre>
<blockquote class="\&quot;wp-embedded-content\&quot;">
<a href="\&quot;https:\/\/blog.dembowski.net\/2015\/server-admins-love-wp-cli\/\&quot;">Server admins love WP-CLI<\/a><\/blockquote>\n<script type="text\/javascript">// <![CDATA[
\n<!--\/\/--><![CDATA[\/\/><!--\n\t\t!function(a,b){\"use strict\";function c(){if(!e){e=!0;var a,c,d,f,g=-1!==navigator.appVersion.indexOf(\"MSIE 10\"),h=!!navigator.userAgent.match(\/Trident.*rv:11\\.\/),i=b.querySelectorAll(\"iframe.wp-embedded-content\"),j=b.querySelectorAll(\"blockquote.wp-embedded-content\");for(c=0;c<j.length;c++)j[c].style.display=\"none\";for(c=0;c<i.length;c++)if(d=i[c],d.style.display=\"\",!d.getAttribute(\"data-secret\")){if(f=Math.random().toString(36).substr(2,10),d.src+=\"#?secret=\"+f,d.setAttribute(\"data-secret\",f),g||h)a=d.cloneNode(!0),a.removeAttribute(\"security\"),d.parentNode.replaceChild(a,d)}else;}}var d=!1,e=!1;if(b.querySelector)if(a.addEventListener)d=!0;if(a.wp=a.wp||{},!a.wp.receiveEmbedMessage)if(a.wp.receiveEmbedMessage=function(c){var d=c.data;if(d.secret||d.message||d.value)if(!\/[^a-zA-Z0-9]\/.test(d.secret)){var e,f,g,h,i,j=b.querySelectorAll('iframe[data-secret=\"'+d.secret+'\"]'),k=b.querySelectorAll('blockquote[data-secret=\"'+d.secret+'\"]');for(e=0;e<k.length;e++)k[e].style.display=\"none\";for(e=0;e<j.length;e++)if(f=j[e],c.source===f.contentWindow){if(f.style.display=\"\",\"height\"===d.message){if(g=parseInt(d.value,10),g>1e3)g=1e3;else if(200>~~g)g=200;f.height=g}if(\"link\"===d.message)if(h=b.createElement(\"a\"),i=b.createElement(\"a\"),h.href=f.getAttribute(\"src\"),i.href=d.value,i.host===h.host)if(b.activeElement===f)a.top.location.href=d.value}else;}},d)a.addEventListener(\"message\",a.wp.receiveEmbedMessage,!1),b.addEventListener(\"DOMContentLoaded\",c,!1),a.addEventListener(\"load\",c,!1)}(window,document);\n\/\/--><!]]>\n<\/script><iframe sandbox=\"allow-scripts\" security=\"restricted\" src=\"https:\/\/blog.dembowski.net\/2015\/server-admins-love-wp-cli\/embed\/\" width=\"600\" height=\"338\" title=\"Embedded WordPress Post\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\" class=\"wp-embedded-content\"><\/iframe>","thumbnail_url":"https:\/\/blog.dembowski.net\/wp-content\/uploads\/sites\/2\/2015\/12\/wp-cli-rocks.png","thumbnail_width":600,"thumbnail_height":135}

Which is unreadable to you and I but to something looking to oEmbed your post it will look like this.

Server admins love WP-CLI

Nice huh? All neat in an iframe and easily embeddable. The output is customizable too and I plan to do that on my photo blog.

The oEmbed discovery links should just work but on my installations it doesn’t. I tried Apache2, nginx, clean installation with zero plugins and the Twenty Fifteen theme. Different servers too. I always got the wrong output and could not get oEmbed working.

During my troubleshooting I found a different URL that worked consistently for me. It’s the same information but with a filter I replaced the default output with one that worked for me.

Here’s the plugin code I used. The oembed_discovery_links is filterable (filters are cool) and I toss out the old links and replace them with my own.

This works for me but I do not like this solution.

The problem I have is that the normal links are not being replied to correctly via my WordPress installation. I don’t know why the default discovery links are not working. It bothers me, it really does. 😉

I’m convinced that there is something I’m doing wrong in my setup. Once I figure it out I’ll I can remove this plugin and I’ll post what I was missing.

Server admins love WP-CLI

I’m more of a Network Monkey, but whenever I can provision something just using an ssh session I smile. Many hosts use WP-CLI already and I’ve installed it on my VPS too.

This morning I wrote up a small script to go to my test vhost directory and did the following.

  • Install a blank WordPress site
  • Update some settings
  • Fix my user display name
  • Make sure the plugins and themes are up to date (Akismet needed an update)
  • Delete the default post and page
  • Install, activate and configure the Wapuuvatar plugin
  • Install and activate the Baskerville theme
  • Imported the Theme Unit Test data
  • Cleaned up after the import
  • Used search and replace to make all my http URLs into https

All this was performed without using a mouse or web GUI. (Okay, I checked the avatar setting via /options.php, but I didn’t have to.)

Here’s the script with sensitive details changed.

#!/bin/bash
cd /my/notsecret/www/vhosts/bang.dn7.me

# Setup a new WordPress installation

wp core download

wp core config --dbname=tothemoon \
--dbuser=testuser \
--dbpass=3c962761afbf9ab40a2e75346809c8cf

wp core install --admin_user=jan \
--admin_password=Rea11y*ot7y^assWiRd \
--admin_email=example@example.com \
--url=bang.dn7.me \
--title="Bang! Boom! Pow!"

# Update some options and my account info

wp option update blogdescription \
"What could possibly go wrong?"
wp option update comment_moderation 1
wp option update comments_notify 0
wp option update moderation_notify 0
wp option update comment_whitelist 0
wp user update 1 --first_name="Jan" \
--last_name="Dembowski" \
--display_name="Jan Dembowski"

# Make sure plugins and themes are all up to date

wp plugin update --all
wp theme update --all

# Clean up the default post and page

wp post delete 1 --force
wp post delete 2 --force

# Wapuuvatar is cool. Install, activate
# and set to the default avatar

wp plugin install wapuuvatar --activate
wp option update avatar_default dwapuuvatar

# Let's play with the Baskerville theme

wp theme install baskerville --activate

# Now to import the theme unit test data

wp plugin install wordpress-importer --activate

curl -O https://wpcom-themes.svn.automattic.com/demo/theme-unit-test-data.xml

wp import theme-unit-test-data.xml --authors=create

# Clean up in aisle seven

wp plugin deactivate wordpress-importer
wp plugin delete wordpress-importer
rm theme-unit-test-data.xml

# My test site is also TLS so I'll fix 
# all the things to point to the encrypted URL

wp search-replace http://bang.dn7.me https://bang.dn7.me

# All done

I previously dropped the test installation’s database and created a new empty one. A quick “rm -rf *” (which wise people never do) in the right vhost directory and I ran “bash install-bang.sh”.

It works like a charm. Smart web hosts can and do tie WP-CLI into their provisioning setup. I happened to setup my vhost with TLS and mysql in advance but with a little backend work this can be easily automated.

If you have a test server to play with then give WP-CLI a try. You’ll get a better understanding of both WordPress and the command line.

I can’t really get angry at him for solving a problem

Friday afternoon I called the house and got my then 13 year old son. He turned 14 a few days later.

Dad, the WiFi sucks. I'm trying to download an update to War Thunder and it's taking almost an hour.

He was right, the WiFi adapter on his PC is garbage. The access point is in the same room less than 10 feet away. There's no reason for wireless to suck.

I told him that I'll get an Ethernet cable and hardwire him into the FIOS router. That will give him all the bandwidth he could ever use. I didn't think much about it after that till I got home.

He really wanted that update to War Thunder.

He gave it some thought and enabled tethering on his iPhone. Via WiFi he connected his PC to the iPhone and began to download the update. In less than 2 hours he ate almost 3 GB out of my monthly 10 GB allotment.

This did not make Lily and I very happy. She got a text message saying we'd crossed 75% of usage. She asked him and he suddenly remembered what he'd done and quietly disabled tethering without 'fessing up. Lily pulled up a pie chart of the usage and his phone was right behind mine.

I got home and it took me 0.0035 seconds to figure out what he did. I was angry and let him know that he was being selfish. He should have told his mother what he'd done. And yet… I like how he figured out another way to connect to the Internet. He had a problem and quickly came up with an alternative to fix it.

He lost cellular data for the week and may lose it for the rest of December. I also deleted his games and YouTube app from his phone; enough already. But I'm glad he thinks to solve problems and I can't be mad at him for that. Later on I told him I like that part of what he did.

If he does it again though, that phone is mine. 😉