↓ Archives ↓

Affordable* Self-Updating WordPress Installs in 5 Minutes

* Cost is as-much-as-you-want with a mininum of €1. Please read my last paragraph about pricing.

I just counted: As it turns out, I am the proud maintainer of 19 different WordPress installations. How did I get here? I have no idea. It probably has to do with some bad life choices. “Let’s just spin up a WordPress for this!” sounded totally doable at the time. But then what?

“Maintaining WordPress installations is educational, fun, and quite easy.”
— said noone ever.

WordPress is brittle. WordPress plugins and themes are often created by folks who are just learning how to code. What you want to do is update WordPress and all plugins and themes *all* *the* *time*. Otherwise, very bad things happen sooner than you may think. Trust me, been there, done that.

The wish list

After a few WordPress installs I had hosted for a friend who promised to “make all updates all the time, of course” got hacked, I started looking for a way to solve this problem once and (hopefully) for all. This is the wishlist I started out with:

  • It should be quick and easy to “spin up a new WordPress”.
  • WordPress installs (including plugins, themes) should update automatically.
  • Sites should be backed up automatically.
  • All plugins and themes should be under version control.
  • Sites should use SSL and I don’t want to be bothered with certificate renewals.
  • It should be affordable – most of the WordPress sites I run are just-for-fun projects that don’t make any money.
  • Nice to have: Easily install plugins on all WordPress installs at once

The solution involves Uberspace, Ansible, Let’s Encrypt, Composer, and Bedrock — a most awesome combination as it turns out.

Here it goes:

1. Get an Uberspace (23 seconds)

This is easy, head to uberspace.de and sign up for an Uberspace.

Uberspace is an awesome command-line powered hosting provider with great features and support which lets you pay what you want (with a minimum of 1 Euro per month).

2. Configure your DNS (49 seconds)

Make note of your IP address(es) within the Uberspace dashboard and edit your DNS records so that your domains point to your Uberspace. Since Uberspace is fully IPv6 ready, you might want to set up both A and AAAA records.

3. Create your Bedrock fork (14 seconds)

Go to my fork of the Bedrock repo on GitHub and fork it yourself.

Bedrock is a Composer-powered WordPress boilerplate. The idea is that you keep your plugins and themes in a Git repo and reference publicly available third party themes and plugins using Composer, a dependency manager for PHP. For every WordPress site, you’ll create a fork of Bedrock. Read this handy guide to learn how to add themes and plugins to your Bedrock WordPress.

4. Install Ansible (42 seconds)

On the Mac with Homebrew, a simple brew install ansible will do. For more ways to install Ansible, see the docs.

Ansible is an IT automation engine (their words, not mine) which is basically scripted multi-server SSH on steroids. In Ansible, you create “playbooks” which are scripts that run stuff on servers.

5. Clone the Uberspace Playbook (13 seconds)

Simply run git clone git@github.com:yeah/ansible-uberspace.git to get the latest and greatest version of my Uberspace Playbook.

This is where the magic happens. The Uberspace Playbook contains all the configurations necessary to set up awesome WordPress hosting on Uberspace.

6. Add your Uberspace as Ansible inventory (2 minutes)

Within your copy of the Uberspace Playbook, copy uberspaces.example to uberspaces and add your Uberspace host and username. You can add as many Uberspaces here as you want. Ansible will install them all together.

Next, copy host_vars/UBERSPACE_NAME.UBERSPACE_HOST.uberspace.de.example to a new file named without the .example suffix and replace UBERSPACE_NAME with your username and UBERSPACE_HOST with your Uberspace host.

Now, edit the file you just created and add the domains you set up previously. Choose an internal name for your WordPress install, modify bedrock_repo to point to your Bedrock fork, and specify the domains (again). If you want to use your Uberspace for other things besides WordPress, add all domains you’re using to the domains section at the beginning and only those which should point to a WordPress instance to the respective domains within wordpress_instances. You can of course have as many domains and subdomains as you want and you can run as many WordPress instances as you want.

7. Run Ansible! (39 seconds)

Within your copy of the Uberspace Playbook, run ansible-playbook --ask-pass site.yml.

That’s it. You’re done. Enjoy your fresh new auto-updating, SSL-encrypted and backed up WordPress by navigating to https://yourdomain.com/wp/wp-admin.

Be sure to check out the Uberspace Playbook’s source code to learn what actually happens in the background.

If you need to add themes or plugins, simply update, commit and push your Bedrock fork and run the playbook again.

8. Hold on a minute and think about pricing

While the kind folks at Uberspace do allow you to pay as little as €1 for an account, a generous offer like that is not sustainable. Uberspace recommends that you pay between €5 and €10 per month which is still a great deal given the flexibility and support you’re getting.

If you’re making money from the sites you’re hosting, you may consider paying more than that and therefore help keep Uberspace a place that’s affordable for everyone. If you can’t afford more than €1, that’s fine, too.

Just be sure to play fair and pay what you think is right.


  • May 30th 201619:05
    by ThorstenS

    yeah! Thanks, very clever playbooks 🙂

  • Jun 16th 201618:06
    by Nils

    I get an “wordpress_instances’ is undefined.” error within the task of cloning a fresh bedrock. what do i miss ?

  • Jul 7th 201600:07
    by Jan Schulz-Hofen

    Nils, you probably didn’t define wordpress_instances in your host_vars file. Even if you don’t care about WordPress, define it as an empty array. Here’s the example: https://github.com/yeah/ansible-uberspace/blob/master/host_vars/UBERSPACE_NAME.UBERSPACE_HOST.uberspace.de.example

  • Aug 23rd 201609:08
    by Richard

    When I run the playbook, I get the following error at step “Create .env template with salts”:

    PHP Catchable fatal error: Argument 2 passed to WP_CLI_Dotenv\Dotenv\FileLines::WP_CLI_Dotenv\Dotenv\{closure}() must implement interface WP_CLI_Dotenv\Dotenv\LineInterface, integer given in /home/epc/.wp-cli/packages/vendor/aaemnnosttv/wp-cli-dotenv-command/src/Dotenv/FileLines.php on line 99

  • Aug 24th 201607:08
    by Jan Schulz-Hofen

    Richard: Thanks for the feedback. A newer version of wp-cli-dotenv-command seems to break things for us. I’ve pinned the version to the previous 0.2 which works as advertised. Please update your copy of the Playbook and try again.

  • Aug 25th 201608:08
    by Richard

    It works. Thanks!

  • Sep 7th 201610:09
    by Richard

    Could it be that the Ansible script doesn’t set the WP_SITEURL in .env correctly? My WordPress had been working fine until I installed Jetpack, which stubbornly stayed in development mode, even though it is in the production environment. The reason for this is that WP_SITE_URL was “/wp”. Looking at the recipe, I guess that WP_HOME is undefined when it’s setting WP_SITE_URL.

  • Dec 7th 201601:12
    by Anton

    Is it possible to use an already existing uberspace with multiple domain and just use the playbook for just one domain?

  • Dec 27th 201610:12
    by Jan Schulz-Hofen

    @Richard: WP_SITEURL gets set to /wp intentionally by bedrock (https://roots.io/bedrock/). Works for me.

    @Anton: Should work, but make a backup first!

  • Leave a Reply