Skip to content

Making Lando work inside WSL2

Dear Reader,

About five months ago I started using Lando. I have never been a Docker fan. I know Docker is useful, but for most things I work on it just seemed to be one additional layer on top of everything else I’ve got to build. Then a friend I was working with at the time introduced me to Lando. Lando seemed almost perfect.

  • It was easy to spin up and down
  • It supported PHP, WordPress, Drupal, and Composer out of the box
  • It was easily extensible

Honestly, the only downside was that on Windows 10, it ran in Windows, not in WSL. On Windows all my development takes place inside WSL. Until  I started working a contract that required it, I didn’t even have Git or PHP installed on Windows, only in WSL.

Then WSL2 hit and everything changed. Docker released a new version that would run inside of WSL2 and would take advantage of the WSL2 Linux kernel when running in Windows. I was beginning to see the light at the end of the tunnel.

Still, as with everything in tech, there were hurdles to overcome. This blog post does not delve into the WHY things work the way they do; honestly, in some cases, I do not know. This is designed to be a step-by-step guide to getting Lando and Docker up and running.

Also, where applicable, I have linked to the original posts where I got the information. Most of this info was borrowed from other sites but I had to piece things together to get everything working.

Step, the first: Install Docker

I am going to assume you already have already upgraded Windows 10 and have WSL2 installed and operational. You will need a Linux distribution. I chose Ubuntu because Cent OS isn’t available (grumble).


If you have Docker Desktop installed on Windows 10, check the settings. If you have enabled WSL integration make SURE – I mean absolutely, positively SURE – that you do not integrate it with the distro you are going to be using Lando with. If that’s your default Distro then don’t check the “Enable integration with my default WSL distro” checkbox. Make sure the slider is not lit for the distro you will be using Lando with. Failure to do this will lead to hours of heartache and head-banging until you come back to this post, read it again from the top, and see this warning.

Ok, now that you either understood and heeded the warning above, or you ignored it thinking it doesn’t really apply to you, follow the instructions from to get Docker up and running on your WSL2 distro.

For me, these were the commands I executed. Feel free to copy and paste them one command at a time. (They are the same ones from the blog post but without the comments.)

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common libssl-dev libffi-dev git wget nano
sudo groupadd docker
sudo usermod -aG docker ${USER}
curl -fsSL | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] $(lsb_release -cs) stable"
curl -s | sudo apt-key add -
echo "deb kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get autoremove -y
sudo apt-get install -y docker-ce
sudo apt-get install -y kubectl
sudo curl -sSL`curl -s | \
grep "compose/releases/tag" | sed -r 's|.*([0-9]+\.[0-9]+\.[0-9]+).*|\1|p' | head -n 1`/docker-compose-`uname -s`-`uname -m` \
-o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose

That got me almost there. right now, if you can run the following command and it works then you are golden.

docker run hello-world

If that worked, you can proceed to Step, the Second.

However, if you get this error:

docker: Error response from daemon: cgroups: cannot found cgroup mount destination: unknown.

Then you need one more step. Reading the thread, I found that Dinar-Dalvi posted this “temporary” fix. Execute these two commands in your WSL2 terminal.

sudo mkdir /sys/fs/cgroup/systemd
sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

Now try Docker run hello-world again. It should work. If you’ve gotten this far, you are home free. The rest is pretty easy.

Step, the second: Install Lando

Ok, Lando’s install instructions are pretty dang simple. Go to the Lando Releases Page and grab the package for your distro from the latest version. Since I am using Ubuntu, I grabbed the .deb package. Then, following the instructions on the Lando Install Page I executed:

sudo dpkg -i lando-WHATEVER_I_DOWNLOADED.deb

Yup, it’s that easy.

Step, the third: Spin up your first Lando

I work with WordPress a lot so my Lando Hello World was spinning up a WordPress site. The very easy to use Lando manual has a page for WordPress and to init a container for Lando with WordPress, all I need to do is follow these instructions.

$ lando init \
--source remote \
--remote-url \
--recipe wordpress \
--webroot wordpress \
--name my-first-wordpress-app
$ lando start


Two minutes later I have a working WordPress site ready for my “Five Minute Install.”

Before you start the final WordPress install step, make sure you execute:

lando info

Lando has already installed a DB for you and created a user. lando info will give you the info you need to finish up the install and start developing your next great idea with Lando.

Step, the last: Wrap-up

If you are already a Docker aficionado and conversant with how to setup and maintain Docker containers, Lando, will be of little interest to you. However, if you are a developer who just wants to get a container spun up so they can work on a website (WordPress, Drupal, Laravel, whatever) it is a great tool and will fast become one of your regulars.

Until next time,
I <3 |<

The VS Code extensions I use for PHP development in 2019

Dear Reader,

I hate IDEs. I always have, I probably always will. I don’t always want to edit a file that is in a project and I don’t like any of the ‘project-less’ kludges that are out there.  So for the majority of my programming career, I’ve used “program editors”.  Programs just smart enough to know that I’m working in code and give me tools to do that properly, but not so smart that they get in my way. For the last few years I’ve been a huge fan of “Sublime Text”. I’ve owned a license at the last three places I’ve worked and even maintained my own personal license.  All that changed last year when I became one of the last developers on earth to notice VS Code by Microsoft.

Back in April, since I found myself with some time on my hands, I decided I would spend a day actually learning how to use VS Code. Maybe if I had bothered to do that with Sublime Text, I’d still be using it. but that’s a discussion for another day.

Once I got the basics setup, I started exploring Extensions. I’ve loaded more than 40 of them now at one time or another but I’ve paired my list down to my “Essential 12”. Here they are for you.

WAIT! Before we get started though, let me describe my setup.

I use Windows 10, but I use the Windows Subsystem for Linux (WSL) for all of my development. My production servers are all Linux (CentOS if you MUST know) All of my projects are stored on either GitLab or GitHub.  You may be using MacOS or Linux, but since all my development is Linux, almost everything I talk about here will apply.

“Absolutely must have or it’s not worth using” extensions

Visual Studio Code Remote Development Extension Pack

This is the grandaddy of all the extensions. This is what made VSC actually useful to me on a day to day basis. It was only released in May, so I have the least amount of experience with this one but trust me, this is the ONE you have to install if you don’t install anything else.

This is actually an extension pack, not a single extension.

  • Remote – WSL
  • Remote – Containers
  • Remote – SSH: Explorer
  • Remote – SSH: Editing Configuration Files

The first three are the secret sauce. They allow you to edit files natively inside of the WSL, inside of running Docker containers, or on any machine that you can ssh into.

From a command prompt inside the WSL (I use bash so I’m going to say bash prompt form now on. You can translate into your favorite command prompt) developers can open a single file  or a directory by simply typing code.


code .

This will open VCS, instantiate a running instance of it’s server piece inside the WSL, and open the current directory ready for us to begin working.

It’s that middle task that makes the magic happen. VSC Remote Development Extension Pack actually has a server piece that it runs in Containers, WSL, and over SSH to allow it to seamlessly manipulate files and directories.

This group of extensions also integrate the remote file system into VSC so you can use File->New/Save/SaveAs/Delete etc on remote systems, WSL, and inside containers. That did away with the need for an extension solely for that purpose.

The fourth item on the list above is a convenience extension that makes editing remote ssh config files easier by giving keyword intellisense and syntax coloring.

BONUS: When you open the terminal window while connected to WSL, a container, or SSH, you get a command prompt in that environment. This means a bash shell in WSL for me, not the PowerShell. (which I still hate) The shell it presents is better and more compatible than any shell I’ve used in Windows so far. If you want, you can even setup forwarders. This could be your complete ssh solution if you so desired.

If you don’t have this extension, you are missing the power of VSC, especially if you work in Win/WSL.

PHP IntelliSense

Since the vast majority of my work in VSC is PHP code, I wanted more than the basic intellisense that is built into VSC. (It is actually recommended that when you install this extension, you turn off the native PHP intellisense) There are a couple of Extensions that do this, I tried them all and this is by far the best and least intrusive.

At least one of them tried to format things as I pasted them in. This caused me to have to do a lot of correcting, removing spaces, and reformatting before I could use the code I just pasted in. This plugin does not do anything too wild. It gives you basic keyword intellisense, tab completion, advanced searching, etc. One of my favorite things about this extension is that if you click on a use statement, it will locate the file that class is defined in and open it for you.

As I said, this plugin does not attempt to format your code for you. It recommends that you use the PHPCS extension for that. (Another reason I love it)

“Sugar coating that make the tool very nice to use” Extensions


This one really should be in a category all it’s own called “This is so cool” Extensions. Polacode allows you to create “snapshots” of your code. You activate it, you highlight the code you want snapshoted, and you click the shutter button. BOOK, you’ve got a png of your code ready to share on social media or incorporate into your next slide presentation. It really is that simple. (Well, when you click the button, it asks you where to save it and what to name it. Other than that it’s that simple.)

Outside of the Remote Development Extension Pack, this is probably the coolest extension I use.


If you do want your code auto-formatted, this is the extension to use. You have complete control over which standards to implement and those can even change on a project by project basis. If you use phpcs in your development process this is a must-have extension. If you install it though, take the time necessary to configure it properly for your base configuration and then modify that as needed on a per-project basis. Since I work in several communities, this allows me to say that my base config is PSR1/1, but my WordPress plugins adhere to the WordPress coding standards. (Mostly) The investment of 30 minutes to get everything setup and configured is time well spent.

Twig Language 2

Some of the work I do requires views and when I use a view, I always use Twig as my templating engine. This extension provides syntax highlighting and hovers for my twig templates. Syntax highlighting might not sound important but once you get used to it, and then you open a file that does not have it, you begin to wonder if your program is broke or if you’ve suddenly been transported into a black & white movie.

Code Spell Checker

Anyone who has ever received an email from me (or read one of my blog posts that pre-dates spellcheckers built into browsers) knows that I seriously suck at spelling. Even when I do have spell checkers they rarely work in code because $somethingImportant will never pass a spell checker. So I have this plugin. This one is hit or miss. It almost always identifies misspelled words in strings or comments (YEA COMMENTS!) but it used to be that I could have it fix them. That stopped working in the latest update. Hopefully they get that fixed soon.

Bracket Pair Colorizer

First, you should not have a lot of nested IF and FOR statements. Down that road is madness. However there are a lot of times where we have function calls nested inside other function calls, nested inside an IF. When you do find yourself in that situation, you want this plugin. This plugin assigns a color to each pair of brackets, braces, and parentheses.  This makes tracing down missing ones trivial and helps you understand the actual nesting of your code.


“You may not needs these but I sure do” Extensions


I write a lot. Of late I’ve been writing two books “Using the WordPress REST API” and “Extending the WordPress REST API”. These books are written in MarkDown and stored in private repos on github. (Leanpub refuses to support GitLab, my preferred site. ) Most of the time, MarkDown is easy to do, however, there are some rules that have to be followed. This plugin keeps all of my markdown clean and parse-able.

Prettify JSON

JSON is the lingua franca of APIs. It is heads and shoulders better than XML in every respect except one, readability. XML is human readable. This plugin basically does what PHP’s json_encode($payload, JSON_PRETTY_PRINT) does. It puts linefeeds where we need them and indents where we need them. It also does syntax highlighting and linting for JSON. If you find yourself pasting JSON into a text editor and making it readable by hand, you want this extension.  If on the other hand, you prefer XML, well, you have problems beyond the scope of this article. :)

Word Count

Again, another writing tool. Not even a tool, just a simple little plugin that tells me how many words are in a given MarkDown file. It is not important if you don’t do a lot of writing, but without it I couldn’t tweet out my “how many words I wrote today” tweets.

“I’m keeping an eye on this” Extensions


I’m an old database programmer. I still hand code every line of SQL I write. So I am always looking for new ways to access and manipulate data. I had high hopes for this extension because it looked like it would give me a powerful command line to access my database. To date I’ve not been able to do anything other than get a list of tables on a server.

Still, I have not uninstalled it. Every time there is an update, I try again to see if it is working better.



That’s it, that’s my current extension list. I hope I’ve introduced you to a new friend or two. If you are new to VS Code, I hope I’ve given you a few new toys to play with.

Until next time,
I <3 |<

Thank you Derick Rethans for 15 years of XDebug

Dear Reader,

There are a handful of tools that have actually changed how many of us code PHP. XDebug is one of those tools[1]. There is no doubt of the impact that XDebug has has on PHP developers and PHP projects.

Recently, XDebug turned 15. (If you don’t know what XDebug is, start with this SitePoint article about Xdebug) This means that the man responsible for XDebug, Derick Rethans, has been supporting XDebug for 15 years, for free. XDebug is open source. Derick maintains it, answers questions about it, spoke at conference about it, and generally done everything he can to help anyone who is having an issue with it.


Thank about that. How much code do you have that has lasted fifteen years?

So on this the (close to) anniversary of this product, many of us in the PHP community decided to do something to show Derick how much we appreciate it. Those that know him know that Derick loves a good Scotch. So we decided to buy him some. Originally, I was just going to buy him the most expensive bottle I could find and be done with it. However, my friend James Titcumb stepped in. He knew the owner of the shop that Derick buys his Scotch. He contacted the owner and we gt a quick education in Scotch. tl;dr, expensive doesn’t always mean good. He picked out a selection of bottles that he knew met Derick’s high standards.

On April 26th, 2017, James met Derick at the retailer and here is the video.

Thank you!

  • First and foremost, thank you Derick.
  • Second, thank you James Titcumb for going above and beyond on this project. Y’all really have no idea what he did to make this happen.
  • Third, I gotta say it. Thank you to the lovely and talented Kathy. It is hard to describe how difficult it is to live with someone like me who randomly sit up and shouts “I HAVE AN IDEA”. Yes, sometimes, she buries her face in her hands and weeps. Most of the time though, she supports me, she encourages me, and she helps me. This time, she worked with James to get the Scotch paid for. (Moving that amount of money across the pond is not as easy as you might think it would be.)
  • Finally, but not nearly the least important, thank you to the entire PHP community. When I setup the GoFundMe, I never expected to actually hit the $5,000. I would have been happy with hitting $1,500. As of right now we have hit $5,100! (I’m trying to figure out how to close the GoFundMe!) :)

    Part of the deal I offered companies was that if anyone donated at least $100, I would list their logo and link in this blog post. Here are the people and companies that rose to that level.

    Make sure you say thank you to these individuals and companies.[2]

All told, 151 people donated to make this happen!

So that’s it. We had some fun, we raised some money, we said thank you to someone who has given so much to all of us. Once again, thanks Derick. :)

Until next time,
I <3 |<

p.s. I will provide a full accounting of all funds raised when I get home from traveling.

[1] The other two, IMHO, are PHPUnit and Composer.
[2] If you are on this list, you probably noticed there re no logos. This is my fault, not yours. Basically, I lost them in all my recent travels. PLEASE send to me again via email and I will update your entry.

When Giants Battle. Google, Twitter, Apple, and encrypting the web. A podcaster’s story

Dear Reader,

This is a story about my fight to change the feed on my little podcast, Voices of the ElePHPant.



Google's attitude towards encryption on the web


Twitter's attitude towards encryption on the web


Apple's attitude towards encryption on the web

As a podcaster, I’m in a quandary. I know that encrypting the web is a good thing. Most of my sites now sport a Let’s Encrypt cert. (See this post for how I automated let’s Encrypt on CentOS) However, several giants of the web have different views on encryption.

  • Google – Encrypt everything.
    That’s good, right? I mean encryption is good and Google will reward encrypted sites with better ranking.
  • Twitter – Encrypt Player-cards and all the assets.
    Ok, Since I’m encrypting everything, encrypting my player cards and all their assets are encrypted. I even wrote a plugin to do thePlayer-cards and part of it makes sure that everything is served over https.
  • Apple – Don’t encrypt your feed or anything in it.
    Ok, Apple doesn’t come right out and say this, they simply give you a “Can’t read your feed” error if you submit a https URL and you are left to try and figure out why. Turns out that with a little experimentation you will find that not only that your feed can’t be encrypted, nothing in your feed can be encrypted.

Welcome to the modern web.

Trying to play nice

iTunes is still the most popular destination for podcast discovery. So you’ve got to have your feed there. iTunes has a lot of rules though. Early on, we had tools like FeedBurner that would “wash” our feeds and make them iTunes friendly. Feedburner WOULD accept an encrypted URL and spit out unencrypted.

As with all free services on the web, priorities change and services die. FeedBurner hasn’t had an update in many years and if you listen closely, you can hear the rumblings about Google shuttering it soon. That’s fine, long ago, I moved my entire podcast infrastructure to using the Bluberry Powerpress plugin for WordPress and it puts out an iTunes friendly feed by itself. So you would think that it’s just a matter of telling iTunes you have a new feed right? Well, um…no.

The Fix

The problem is that all three of these giants, Google, Twitter, and Apple, have influence over my little podcast.  After hours of searching for a solution, and switching to a paid cert simply because someone suggested that Apple simply didn’t like Lets Encrypt (not true) I finally decided to try an unencrypted feed. I turned off the automatic redirect to https that I had in my Apache configuration file for my podcast site. This almost worked.

I resubmitted the regular HTTP URL.  I could see from tailing my log files that iTunes accepted it and actually read it this time. I was elated for about half a second until Apple came back with an error message telling me that the podcast image couldn’t be encrypted either. <sad trombone />

Making Progress

Ok, I was making progress. This was further than I had gotten in several weeks of research. I jumped to the conclusion that Apple didn’t want to see any https inside the feed. This presented an interesting challenge because of the way that WordPress and thus PowerPress handle feeds.

The feed is generated in feed-podcast.php inside the PowerPress plugin directory. Looking it over, this is just a big while loop that pulls in the necessary information and then echoes out XML, one post at a time. Since it uses WordPress’s native functions to get urls and such, everything says https. I didn’t want to change WordPress because then my entire site would be back to unencrypted. I also didn’t want to check each echo statement for https and remove the s if it was found. This could get messy in a hurry.

It became obvious that I needed to grep the entire feed and replace https with HTTP. I’m a programmer, this should be easy. Except that there is no point in the WordPress flow where I can intercept the entire feed before it is sent out. WordPress has a complex system of hooks and filters but none of them were “RSS_FEED_BEFORE_IT_IS_SENT_OUT”. <sad trombone />

Since WordPress doesn’t gather the entire feed into a variable and then spit it out, a different solution is needed. WordPress treats the feed like any other page, it has a template that is executed that directly outputs XML. This was the absolute worst case scenario. Since Powerpress controlled the feed for my podcast, it looked like I was going to have to hack the core of the PowerPress plugin itself.

Old-School PHP to the rescue

Digging around for solutions, I came across a snippet of code that suggested using PHP’s Output buffer. Something I’ve not done in a very long time. The code in the snippet was not helpful, but the idea it sparked was what worked.

function my_callback($buffer) 
    return str_replace('https://','http://',$buffer);

The heart of the solution is the function my_callback. In it, I simply replace HTTPS:// with HTTP://. Not terribly difficult to do in PHP. If I wanted to get fancy, I could probably have used an anonymous function int he ob_start() command, this solution is easier to read.

Next, we put in the ob_start(). In it we put the optional callback parameter and specify the name of the function we created just above it. For those not familiar with the callback parameter, here is an excerpt from the manual.

An optional output_callback function may be specified. This function takes a string as a parameter and should return a string. The function will be called when the output buffer is flushed (sent) or cleaned (with ob_flush(), ob_clean() or similar function) or when the output buffer is flushed to the browser at the end of the request. When output_callback is called, it will receive the contents of the output buffer as its parameter and is expected to return a new output buffer as a result, which will be sent to the browser. If the output_callback is not a callable function, this function will return FALSE.

tl;dr my_callback is called and passed everything that output buffering collected. I can make any modifications to it and whatever I return is what is actually sent out. That is exactly what I did.

At the bottom of the feed template, I simply put

<?php ob_end_flush(); ?>

This triggers the callback that is the secret sauce to the solution.

That’s all it took. I was able to exactly what I needed to do by going old-school on it’s butt and using output buffering. This gathered everything into a single variable that I was able to wash before outputting.

Once this was in place, I resubmitted the newly cleansed feed to Apple and not only did it accept it, the change was completed and visible in iTunes within about 30 minutes. (See the pretty new logo that the lovely and talented Kathy did for us two years ago? Until yesterday we still had our old logo there)


Screen Shot 2016-04-09 at 12.01.09 PM


This blog post is not about the horrors of using a free service like FeedBurner. FeedBurner served me well for many years. It was my fault to begin with for submitting the FeedBurner url itself and not one hosted on my site as a 301 Redirect. The only lesson there is to make sure you own all the important pieces of your project, like feed URLs. :)

Here are the takeaways though.

  • iTunes does not hate Let’s Encrypt, iTunes hates encryption.
  • My site now runs both https and HTTP but I only advertise https
  • My feed is now exclusively HTTP, everything else on the site is HTTPS
  • I had to hack the core, which sucks but sometimes is necessary.

With regards to that last point. I believe that because PowerPress is awesome, there is a way to do this by specifying my own feed template. Reading the code, it looks like it is possible. I’ve written them to get clarification and will update this post when they get back to me.

Honestly, I don’t know how muggles deal with this. I was able to solve this because I am a programmer.

Until next time,
I <3 |<

Public Speaking for Developers II

Dear Reader,day camp 4 developers: Public Speaking for Developers II

It is that time again, time for the Day Camp 4 Developers December Edition. This year we are back with 5 great talks revolving around the topic of “Public Speaking for Developers II”.

We presented the first one back in 2013 and developers from around the world dialed in to improve their speaking ability and process.

Become better at public speaking!

In Day Camp 4 Developers: Public Speaking for Developers II we’ve got all new speakers and five great talks that we think are even better than the first one. (and 5 absolutely wonderful sponsors!)

So if you are a developer and you speak at conferences, get your ticket now for “Day Camp 4 Developers: Public Speaking for Developers II”.

If you want to get into speaking but don’t know where to start, get your ticket now for“Day Camp 4 Developers: Public Speaking for Developers II”.

If you manage a development team and want to build esprit de corp while improving the skills of your developers, get an Office Party ticket for“Day Camp 4 Developers: Public Speaking for Developers II”.

Managers, we want you too!

Directors of IT, Team Leads, Developer Managers, just because you are management don’t feel you are exempt from the learning. Block out some time and participate as well. Make sure you don’t miss our closing talk by Jon Shearer! He is a manager and he understands how important the skill of public speaking is to the developers on his team.

Join us for “Day Camp 4 Developers: Public Speaking for Developers II”. Invest a day in your career.

Until next time,
I <3 |<

p.s. If this event is interesting to you, make sure you also subscribe to our free service, The CFP Report. It’s everything you need to know about open CFPs all in one weekly email. Join today! Stay in the loop.