Moving Blog from CentOS 7 to Ubuntu 19.04

With WordPress 5.2 I decided to leave my CentOS 7 installation as it required PHP 5.6.20 or higher and my CentOS only had 5.4.16. Yes, I could have manually upgraded PHP from alternative CentOS repositories but I decided not to. While CentOS has been stable for me and I had pretty much no issues with it, that stability came at the cost of slow or non-existent new features. Biggest example being stuck in pre-HTTP2 times.

It took me a while to decide which distribution to use as a replacement, the final candidates being Debian and Ubuntu. While I was really tempted to go with Debian due to its reputation, I decided to go with Ubuntu at the end. It was due to frequency of updates more than anything else. After sticking with CentOS for so long, I wanted something more dynamic.

Most of my setup scripts needed just a simple replacement of yum with apt-get, the only major hurdle presented switching from CentOS Apache (httpd) to Ubuntu’s Apache (apache2). Despite both being 2.4, differences were significant enough that I couldn’t just move my config files. So I went with true and tested way of gradually modifying my config file until I could actually start Apache.

The first hurdle was how to install it. My CentOS installation used httpd mod_ssl php php-mysql, and php-gd packages. The equivalent Ubuntu setup consisted of apache2 php php-mysql php-gd. Essentially only the SSL package was missing from list and only because Apache2 already contained it.

The first error appeared with User and Group setting. While CentOS uses apache, the Ubuntu needs www-data. Remember that you need to change this not only in config file but that a chown or two might be needed.

The biggest issue were includes. On CentOS I used the following collections:

Include conf.modules.d/00-base.conf
Include conf.modules.d/00-mpm.conf
Include conf.modules.d/00-ssl.conf
Include conf.modules.d/00-systemd.conf
Include conf.modules.d/10-php.conf

On Ubuntu there is no equivalent. One has to either use wildcards to load all or list each include separately. Since list of enabled modules is rather conservative, I decided to use wildcards:

Include mods-enabled/*.load
Include mods-enabled/*.conf
Include conf-enabled/*.conf

Due to aforementioned conservative list of enabled modules, I had to enable a few more:

a2enmod autoindex
a2enmod expires
a2enmod headers
a2enmod rewrite
a2enmod ssl
a2enmod socache_shmcb
a2enmod php7.2

And yes, this is not strictly speaking equivalent of CentOS configuration but it’s close enough for my WordPress installation. Depending on your exact setup, you might need to enable a few more (or choose to skip some).

The last change I had to do was for firewall. As Ubuntu uses ufw, the following commands were needed to allow traffic through:

ufw allow 'Apache'
ufw allow 'Apache Secure'
sudo ufw reload

And now my WordPress runs on Ubuntu. :)

Remembering the Last Grub OS

If you are dual booting Linux and Windows, you might want to have Grub automatically select the last booted OS instead of just going with the default. The whole trick rests on adding just two lines to /etc/default/grub:

GRUB\_DEFAULT=saved GRUB\_SAVEDEFAULT=true

Of course that has to be followed by update-grub:

sudo update-grub

Now Grub will track which OS you booted last and preselect that menu entry.

PS: If you have custom menu entries, do not forget that you need to have savedefault option present.

Adding UEFI Windows 10 Menu Entry to Grub

If you install Ubuntu first and Windows later, you’ll notice that it’s not possible to boot into Linux anymore. As Windows boot loader doesn’t really handle Linux, you’ll need to tell Windows to use Grub.

Once you’re in command prompt with administrative privileges, you can execute:

BCDEDIT /set {bootmgr} path \EFI\Ubuntu\grubx64.efi

After reboot Grub will show it’s ugly face and you’ll have another problem - there are no Windows entries.

To get them into Grub menu, one can simply update grub:

sudo update-grub

On most Linux distributions this will trigger OS Prober and Windows Boot Manager entry will magically appear. However, if you have OS Prober disabled or you want to disable it in future for some reason, you can add manual entry too:

cat << EOF | sudo tee /etc/grub.d/25_windows
#!/bin/sh
exec tail -n +3 \$0
menuentry 'Windows 10' {
  savedefault
  search --no-floppy --set=root --file /EFI/Microsoft/Boot/bootmgfw.efi
  chainloader (\${root})/EFI/Microsoft/Boot/bootmgfw.efi
}
EOF

sudo chmod +x /etc/grub.d/25_windows

sudo update-grub

In either case, boot menu should now offer you option to get into Windows.

Symbolic Links on VirtualBox Share

If you are running VirtualBox with Linux guest under a Linux host, you will definitely need symbolic links at one point in time. And, while you can do links toward shared folders, you cannot create a link on shared folder itself. You will get something like:

ln -s /something /somethingelse
 ln: failed to create symbolic link '/somethingElse': Read-only file system

Well, fortunately it’s easy to enable connection on per share basis. Just run the following command on your host (replacing GuestName and ShareName with correct information):

VBoxManage setextradata '^^GuestName^^' VBoxInternal2/SharedFoldersEnableSymlinksCreate/^^ShareName^^ 1

If your machine is running, you will need to fully shut it down (no, restart doesn’t help) and you get to enjoy the full symbolic link glory.

Detecting Status Bar Double-Click in VSCode Extension

If you’re developing Visual Studio Code extension that deals with statusbar, you might have noticed that it’s activated with a single click. Yes, there is no way to specify double-click behavior. But what if you really, really, want that double-click? Well, you can use trickery.

For example, you can use a timer to help you out:

var doubleClickTimerId

vscode.commands.registerTextEditorCommand("statusbar.command", () => {
  if (!doubleClickTimerId) { //if timer still exists, it's a double-click
    doubleClickTimerId = setTimeout(singleClick, 250); //do single-click once timer has elapsed
  } else {
    clearTimeout(doubleClickTimerId) //cancel timer
    doubleClickTimerId = undefined

    //code for double-click
  }
})

function singleClick() {
  clearTimeout(doubleClickTimerId) //cancel timer
  doubleClickTimerId = undefined

    //code for single click
}

On first click this code will setup a callback to be executed in 250 ms. If nothing else happens, after timer has elapsed, function singleClick will be called and your single-click code will be executed.

However, if another click happens before timer elapses, statusbar command will cancel the timer and execute the double-click code.

Final effect is that any clicks slower than 250 ms get detected as independent while all faster clicks get a double-click treatment - exactly what we wanted.

PS: If you’re wondering why I needed this, it was for my Code Point extension. Single click changes between display style for Unicode character while double click sends you to a web page with much more information.