Creating Linux Desktop Shortcuts

In the previous post about how to hibernate your Ubuntu machine I touched on the concept of creating a desktop shortcut for the hibernate command to make it easy to run the command. That post can be found here. But since then I have been playing with desktop shortcuts some more and so in this post I go into some detail and outline how to create a shortcut icon with content menus too.

The basic concepts with examples…

The basic concept is to create the shortcut as a text file with the “.desktop” file extenstion and in it we define what we want to launch together with some other basic details about the application or script/command, such as icon, name, and whether it needs to run in the terminal etc. Below is an example “.desktop” file, saved to my desktop as “HibernateNow.desktop”. It is running a bash script via the terminal (/

 [Desktop Entry]
Exec=gnome-terminal -e "bash -c './;$SHELL'"

From ubuntu 20.04 onwards you may need to right click on the file after creation and choose “Allow Launching”, which is a one time operation (see screenshot).

But lets say that we want to create a shortcut for an application instead of a script. Its the same concept except the Exec path would be the file path to the executable application instead of a script and it would be “terminal=false” as we don’t need to launch the command in the terminal.

In the below example we are launching the Visual Studio Code application which is executed from /usr/share/code/code.

Just save this file on your desktop with a name “.desktop” extension, eg. VSCode.desktop.

[Desktop Entry]

In a nutshell that’s it for creating application shortcuts in Ubuntu (and many other Linux distros as this is a shared standard). Just create the file and amend the Exec path to be the application you want to launch, then change the name and optionally the icon etc. The category property is for you to optionally choose which group of application types it sits with in the menus.

Taking it further…

But what else can we do with these “.desktop” files? The specification for the files can be found here. As well as the Type=Application option there is also Type=Link for web/document links that can be used with a URL property like this….

[Desktop Entry]

But this doesnt work for me in Ubuntu 20.10 and it seems this has been removed from Gnome as per the discussion on this GitHub issue. If you want to add a web URL then its possible to use the Type=Application and point to your browser of choice (e.g. Firefox) and pass the URL as a parameter as per below:

[Desktop Entry]
Exec=firefox -new-window

Notice that the Icon property has been updated to be Icon=text-html so show its a web link. The icons spec can be found here . A good place to find new icons is to poke around in the “.Desktop” files already on your system. On Ubuntu checkout here: /usr/share/applications for a list of your shared system applications shortcuts or /home/.local/share/applications for your users application shortcuts list. If you add your custom “.desktop” file to one of the above file paths then you can see them in your applications menu, and then you can go further by adding it to your Favourites list (right click icon > Add to Favorties), thus making it appear in your launcher (depending on your distro’s launcher toolbar settings).

Adding Context Menu Actions to the shortcuts…

Check out this example below for a shortcut named Test that launches an application (VS Code in this case). Notice the Actions property and associated “Desktop Action” entry
which provides an additional menu item for action within the shortcut (in this case it uses Firefox to navigate to Google). If we create the textfile with the below contents and call it “test.Desktop”, then add it to the /home/.local/share/applications folder, it will appear in the Applications list and also now has a right click context menu which includes “Navigate to Google” (as per the screenshot).

[Desktop Entry]

[Desktop Action shortcut-action-here]
Name=Navigate to Google
Exec=firefox -new-window

And if I add it to my Dock Toolbar then I get the context menu there too.

A Useful GitHub Shortcut Example…

A better fleshed out and usable example is below where the shortcut is to GitHub (via firefox) and there are multiple actions for the context menu options for viewing Profile, Issues and Pull Requests.

[Desktop Entry]

[Desktop Action Profile]

[Desktop Action Issues]

[Desktop Action Pull-Requests]
Name=Pull Requests

So as you can see there is quite a lot of useful functionality in the desktop shortcuts on Linux.

Enabling Hibernate on Ubuntu

Personally I prefer to hibernate all my machines instead of shut them down as I find it more efficient being able to carry on from where I left off than to start a fresh. One annoyance with my Ubuntu installation is that Hibernate is not a first class function and needs some tweaking to get it to work. For my own record this post records what I have done to be able to Hibernate my Ubuntu 20.04 install. All credit to the original post on

For the actual steps checkout the AskUbuntu post but essentially you need to find the Swap partition (assuming you have one), grabs it UUID and then edit the grub file to update the GRUB_CMDLINE_LINUX_DEFAULT entry to add the resume=UUID=XXXXX-XXX-XXXX-XXXX-YYYYYYYYYY value. Finally update the grub file with “sudo update-grub”.

Once setup you can enter hibernate from the terminal with:

sudo systemctl hibernate

Now you may want to add a shortcut to your desktop or to a hot key to run this command without entering the terminal.

For a desktop shortcut check out this post, where it explains how to create a *.desktop file that will launch the script. Create a text file named e.g. HibernateNow.desktop and then add the content of the file like below, assuming that you have created a bash script with the above “sudo systemctl hibernate” command in it called “” :

[Desktop Entry]
Exec=gnome-terminal -e "bash -c './;$SHELL'"

Then you can double click the HibernateNow.desktop file and hibernate the machine. Or setup a hotkey for this instead.

Happy hibernating.

Ubuntu Intermittent Freezing Fixed with Swappiness

Having run Ubuntu on my Dell XPS 14z for years I have been increasingly plagued by an intermittent freezing problem which causes the UI to freeze (mouse still movable) for anything from 5 to 30 seconds. I’m not sure when this started (maybe Ubuntu 19.04 time) but it has gotten worse with each subsequent Ubuntu release to the point that Ubuntu 20.04 was almost unusable which prompted me to search harder for a solution. The solution I found resolved the problem completely – Swappiness.

Mine is capable but aging hardware but it appears that the OS is Swapping memory to disk too agressively for my system which is what is causing the temporary freezing to occur.

Photo by Michael Dziedzic on Unsplash

The Linux Swappiness setting is an itensity setting on how aggressive the OS should swap memory to disk. Here is the offical definition:

“This control is used to define how aggressive (sic) the kernel will swap memory pages. Higher values will increase aggressiveness, lower values decrease the amount of swap. A value of 0 instructs the kernel not to initiate swap until the amount of free and file-backed pages is less than the high water mark in a zone. The default value is 60.”

Linux documentation on GitHub

For a great explanation checkout this great HowToGeek article.

Whilst the default is 60 there are differing opinions on what to set it to for certain types of hardware and OS usage but for me I went with a value of “20” and its been great. No more freezing so far.

Find your systems current setting with this command:

cat /proc/sys/vm/swappiness

Then update it with this:

sudo sysctl vm.swappiness=20

No reboot required for testing, and when you have decided on the final value to use you need to persist it via updating the sysctl.conf file, e.g:

sudo nano /etc/sysctl.conf

and set the vm.swappiness=20 setting in the file.

This solution worked for me and Ubuntu 20.04 is now running really well.

Java keystore certificate missing after Jenkins upgrade

Following a tricky upgrade to a Jenkins server it was found that the server was no longer able to communicate with the Git server, although SSH access with private keys was stil working correctly. On invrestigating the Jenkins logs (found at Logs at: http://YOUR-JENKINS-SERVER-URL/log/all) this error was found to be the problem:

Failed to login with creds MYCREDENTIALNAMEHERE unable to find valid certification path to requested target
at Source)
at Source)
at Source)
Caused: PKIX path building failed
at Source)
at Source)
at Source)
at Source)
at Source)
at Source)

The problem here is that the Java runtime is not able to validate the connection as it doesnt have the relevant SSL certificate. To resolve I needed to download the certificate from the site and add it to the Java Keystore.

Photo by Chunlea Ju on Unsplash

On the server download the relevant web certificate for connecting to the relevant site (a GitHub server in my instance) that you are trying to access. Next find which Java JRE your Jenkins was using. This can be found in your Jenkins.xml file under the executable element. For example %BASE%\jre\bin\java means c:\Jenkins\JRE\bin\java if you have installed Jenkins to C:\Jenkins on Windows. Now find the cacerts file inside that Java runtime that it was using (for example C:\Jenkins\jre\lib\security\cacerts) where you will need to install the Certificate. To add the cert to the Java Keystore for that Java install run the below in a terminal:

keytool -import -alias INSERT_ALIAS_NAME_HERE -keystore PATH_TO_JRE_HERE\security\cacerts -file CERTIFICATE_FILE_NAME

for example…

keytool -import -alias ExampleName -keystore C:\Jenkins\jre\lib\security\cacerts -file exampleCertFile.cer

If you are asked for a password then it will be ‘changeit‘ by default.

Now the JRE Java runtime on the box that Jenkins is now using has the Certificate installed it will be able to make a SSL connection.

Free SSL encryption on Azure with Cloudflare

I have a small Web Application site (running Core) hosted on Microsoft Azure under a shared plan. Azure shared plans are budget friendly whilst providing features like custom domain names. Until recently the site was HTTP only which was initially fine for my use case but as HTTPS is becoming increasingly a minimum standard on most sites and even browsers are now warning users when navigating to unsecure sites, it was time to move to HTTPS.

Photo by James Sutton on Unsplash

The Problem

Whilst setting up HTTPs certificates has got easier and cheaper there is still usually a trade off between effort and cost. I could have added SSL to my Azure subscription but I couldn’t justify that cost for the site in question. So I needed an easy and cheap solution – and I definitely found it with Cloudflare!

The Solution

I am amazed how easy it was to set up SSL fronting of my existing site using Cloudflare’s SSL.

  1. Create an account at
  2. Enter your domain name where the site is hosted.
  3. Confirm the pricing plan (choose FREE)
  4. Cloudflare scans the domain’s DNS entries and asks you to confirm which entries you want proxying. Once done you’ll be given the new NameServers which you’ll need to update on your domain registar’s site.
  5. Once the NameServers have synced (could take minutes to 48 hours) you are done!

There are a few configuration modes for their SSL offering, e.g. full SSL (i.e. SSL from end users to Cloudflare to origin server) or Flexible (i.e. where the SSL stops at Cloudflare and traffic is not encrypted from your origin server to Cloudflare). The options you choose will depend on your setup and your requirements. As my site is hosted on Azure I got Full SSL encryption by default (using Azure’s SSL keys to encrypt traffic from my web server to Cloudflare).

You don’t need an Azure hosted site for this SSL goodness to work as they will front your service wherever its hosted.

This process was so easy I should have done it months ago. For more info checkout these resources:

RunAs Issue? Check Secondary Logon Service.

On Windows if you are having problems trying to perform an action as a different user via the RunAs command then it might be due to the ‘Secondary Logon Service’ not running. I recently had this problem on Windows Server and after some investigations found that the ‘Secondary Logon Service’ had been disabled, starting the service resolved the issue. By default it is set to ‘Manual’.

The error you get from the RunAs command may vary depending on OS version but will report a problem running a process or service. This is the error I get on Windows 10:

1058: The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.

Linux Home Server Build

On this blog I have posted many times about my home server configuration and seeing as I’ve recently updated it I thought I’d give a quick overview of the changes made and provide some tips for setting up a Linux home server.

My home server (an HP MicroServer) is used for NAS file storage, running Plex Media server and a few other ativites including client backups. Previously my server was running Windows Home Server 2011 which was an excellent Home Server OS from Microsoft based on Windows Server 2008 R2. In additon to file sharing it also allowed for easy server administration and client PC backups. Client PCs would backup images to the server allowing for client files or whole systems to be restored. Unfortunately Microsoft discontinued Windows Home Server and it is no longer supportrd and Windows Server 2008 R2 updates will stop in July 2019. In terms of replacement options there were several, whilst all Windows offerings are too expensive and seem overkill for a home server, serious Linux and BSD options include Free NAS, Amahi, Ubuntu Server and numerous Linux desktop distros. I would also recommend looking at a Synology if you have the budget.

In the end I chose Lubuntu 18.04 (LTS) desktop distro for my needs. Why a desktop distro for a server? Well I dont need to squeeze every onunce of performance from the server and the Lubuntu desktop is so lightweight and efficient I can have a graphcial desktop enviroment as well as great server performance. It is handy to have the option to be able to RDP into the box and use the Lubuntu desktop as an alternative to SSH when required.

I installed the OS, and checked for updates:

sudo apt-get update
sudo apt-get dist-upgrade

After installing the OS I inserted the data drives and mounted them under a /mydata mount point so that I can easily access all the files on those drives. To make these mount points persistent I edited /etc/fstab to add each one using the UUID of the partition (which is found in Disks app or the GParted app)

sudo nano /etc/fstab

Then add an entry for each parition to mount …

 UUID=YOUR_OWN_PARTITION_UUID /mydata/d1/ ext4 defaults 0 0
UUID=YOUR_OWN_PARTITION_UUID /mydata/d2/ ext4 defaults 0 0

Configure The FireWall

The ufw (uncomplicated firewall) firewall is installed on Lubuntu by default but is turned off so turn it on and check its status:

sudo ufw status 

If inactive then activate it with:

sudo ufw enable

To see its status and current rules:

sudo ufw status verbose

Add new rules with:

sudo ufw allow PORTNUMBERHERE 

Install XRDP Remote Desktop Service

Next I set up XRDP for remote access to this headless server.

sudo apt-get -y install xrdp
sudo ufw allow 3389/tcp
sudo systemctl enable xrdp
sudo systemctl restart xrdp

At this point I hit may issues but this hack below seemed to be the one that led to a working XRDP session but using this command to create a .xsession in home directory of connecting user:

 echo "lxsession -s Lubuntu -e LXDE" > ~/.xsession 

For more information see this article.

Setup Cockpit Web Interface

For more remote administration and monitoring goodness I installed Cockpit which is a web based interface for servers with lots of useful features.

sudo apt-get install cockpit
sudo ufw allow 9090

Then browse to https://yourserverip:9090

For a useful Cockpit install guide check out this link.

Setup Samba for file sharing

The whole point of a file server is to share files and in order to support file sharing with Windows devices on the network you’ll need to setup Samba. A good link for setting up Samba can be found here.

sudo apt-get install samba

Set a password for your user in Samba.

sudo smbpasswd -a        

All the folder shares and their configuration are stored in the smb.conf file which can be edited by opening it up in a text editor like nano.

 sudo nano /etc/samba/smb.conf 

In the smb.conf file you may want to change the workgroup name to the same as that used by your window PCs and then add each of your folder shares.

    path = /folder/path
    valid users = <user_name>
    read only = no

Once you have made the required changed restart the smb daemon service

sudo service smbd restart

You’ll also likely need to punch a hole in the ufw firewall for samba

sudo ufw allow Samba

Once Samba has restarted, use this command to check your smb.conf for any syntax errors with testparm


For a good guide on more complex permissions check out this guide here.

It’s worth noting that users need to have Unix perms on the underlying folders in order to be able to access them. Amend Linux file permissions as required.

Scheduled Tasks with Cron

For scheduled tasks (backup jobs etc) I have configured Cron jobs to run bash scripts (although I could have kept my existing PowerShell scripts as PowerShell now runs on Linux too) but they needed a rewrite anyway.

Open your cron job file with…

sudo crontab -e 

then add entries like this example:

# run test job at 11:15 every day 
15 11 * * * . /etc/profile; /bin/bash /home/me/ > /tmp/cron.out

For more info on Cron check out this guide and for an awesome helper tool for building the Cron schedule times check out


So I’ve covered the basics of how I’ve set up my Home Server using Lubuntu which others may find useful. I’ve been running this setup for a few months and so far I am very pleased with its performance and stability.

Future steps are to install Plex Media Server and configure client PC backups. As I want to use the Snaps for Plex I am waiting for the offical Plex Snap Package to come out of BETA as I’m not in a rush. Alternatively I may use Docker to run Plex. To replace the client PC backup feature I previously had with Windows Home Server I will soon be moving to a client imaging tool such as CloneZilla, Acronis or Windows Backup and then copying the images to the server.

Vertical Monitors

Whilst I’ve been using a multiple monitor setup at home and work for many years only for the past year have I been using one of the two in vertical/portrait mode, and I’m hooked.

The benefits for using multiple displays over a single display has been researched numerous times over the years. Estimates on the amount of productivity gain that can be made vary from 20% to 42% in the research I have seen, but even at 20% the second monitor soon pays for itself. Jon Peddie Research (JPR) in their 2017 research found a 42% gain in productivity based on the increased number of pixels available via multiple screens. And whilst some of this gain can be made from just larger screens as opposed to more screens there are certainly ease of use advatanges to multiple screens and several studies sponsored by Dell have found the user experience to be more pleasureable with multiple screens. I find using several screens an easier way of arranging windows than trying to arrange them on one large monitor.

“We found that users of multiple monitors have an average expected productivity increase of 42%,” said Dr. Jon Peddie, President of Jon Peddie Research.

University of Utah study showed that a second monitor can save an employee 2.5 hours a day if they use it all day for data entry.

“The more you can see, the more you can do.” Jon Peddie, 1998

But what about having monitors in portrait mode, well the Jon Peddie research also stated that additional benefit could be had by reducing scrolling for information.

“Having one of the monitors in portrait mode adds to productivity by eliminating the need to scroll.”

After taking a week or so to get used to the portrait mode I quickly found its benefits. It’s ideal for viewing anything that requires vertical scrolling, e.g. web pages, code, log files, Jira backlogs etc. In a quick test of a code file in VSCode I could see 62 lines of code on my 24inch hortizontal monitor, but 120 lines when the file was moved to the vertical monitor. Not only do you reduce scrolling but there are advantages in being able to see more of a document in one go, helping you visualise the problem.

On a side note the Xerox Alto, which was the first computer designed to support a GUI based OS, had a vertical screen to represent a document layout.


Over the past decade or more displays have moved to widescreen format and many applications have tailored their UIs to fit this trend. This means that having all portrait monitors can quickly lead to some frustrations and the need to horizontally scroll, thus reducing the additional productivity gains. This is why I have found that (for me) the ideal setup is one landscape display and one portrait display (as in the image above).

With this formation you can use the display that is best suited to the task at hand, and so you have the best of both worlds. Combine this with a few simple keyboard shortcuts to move things between monitors and you’ll find soon be loving the layout. In Windows using the Windows key and the cursor keys together can quickly move and dock windows. Linux distros vary.

Since I made the switch to one vertical at work I have had numerous colleagues see the benefits and be converted to this layout, so if you have a monitor that is capable of being turned vertically then I recommend you give it a go and see how you get on. You might get hooked!


Calculate a file hash without 3rd party tools on Windows & Linux.

If you need to generate a hash of a file (e.g. MD5, SHA256 etc) then there are numerous 3rd party tools that you can download but if you are restricted to only built in tools or don’t need to do this often enough to install something then there are built in OS tools for Windows and Linux that can be used.


For Windows there is “certUtil” which can be used from the command prompt console with  the “-hashfile” option to generate a hash for a supplied file:

CertUtil [Options] -hashfile filePath [HashAlgorithm]

The [HashAlgorithm] options are MD2, MD4, MD5, SHA1 (default), SHA256, SHA384 and SHA512.

For example to get an MD5 hash of a file use:

CertUtil -hashfile C:\ExampleFile1.txt MD5

More documentation for CertUtil can be seen here.

For those with access to PowerShell v4  and above (Windows 8.1 & Win Server 2012 R2) you can use the built in commandlet called get-filehash like this:

Get-FileHash C:\ExampleFile1.txt  -Algorithm MD5 | Format-List

The algorithms supported are SHA1, SHA256 (default), SHA384, SHA512, MACTripleDES, MD5 & RIPEMD160.

For Powershell versions prior to V4 there are numerous scripts available on the web that will work out the hash for you using various methods.


For Linux use the correct  hashalgorithmSUM command in the terminal for the algorithm you are looking for, i.e. for an MD5 hash use md5sum or for SHA512 hash use sha512sum.

For example:

md5sum /home/rich/Documents/ExampleFile1.txt 
sha1sum /home/rich/Documents/ExampleFile1.txt
sha512sum /home/rich/Documents/ExampleFile1.txt



Building a Python Flask Web UI For Raspberry Pi Sure Elec LCD

In an earlier post I outlined how I setup a Sure Electronics LCD screen with my Raspberry Pi 3 using a Python driver. Whilst updating the LCD via command line is immensely useful I decided to build a UI to control the LCD send messages too it. By using a browser based UI I could update the LCD screen from anywhere. Essentially this was a chance to play with a Python web framework and write some code!


I’ve passed the UI’s URL round my family’s devices at home and they now send me messages whilst I’m in my study working/playing.

The end result can be found in my GitHub repo.

As my driver was in Python and I’m enjoying coding in Python at the moment I decided to use a Python Web framework to serve the HTML/JavaScript UI and host RESTful services on the server side to accept LCD commands. After some reading I went with Flask which  seemed perfect for my needs. I could have gone with Django but Flask seemed for appropriate for my needs. For a good comparison see this post. For a great tutorial on Flask checkout this series by Miguel Grinberg and this great post by  

Building the server side web framework was easy and logical in Flask and I was able to get something setup in one file which served my needs. However after reading some Flask best practices I spread my solution out into a more appropriate structure. Flask will seem familiar to web developers with experience of MVC, Web API, Node/Express etc. You define routes to handle incoming requests. The key aspects my solution are outlined below. I am running the Flask server directly on my Raspberry Pi and using it to serve the pages and host the services for commanding the LCD screen.

To install Flask (on a Pi) first install Python Pip (a popular Python Package Manager) via “apt-get install python-pip” or “apt-get install python3-pip” (for a Python v3 specific Pip) and then install Flask via “pip install flask”.

Flask comes with a small lightweight development server which runs your app in Dev mode and also auto restarts after code changes. I found this fast and robust enough for my needs. 

Lets check out the main parts of the code:  This is the entry point for the app. When run it calls run in the app file and here I have optionally passed IP/Port I want the app to run on which enables the app to be exposed to the internal network so I can connect from other machines on the network. 

from app import app 
if __name__ == '__main__':"", port=5000)

app/ & This is the app initialisation code and where it points to the file where config settings can be set for the app.

app/ This is the heart of the app. After importing the relevant python components and instantiating the Smartie LCD driver (from previous post), the routes for the app are defined.

def show_homepage():
    return "Home Page!"

def show_lcdpage():
    return render_template("lcd.html", name=name)

The route for root will just return the text “Home Page” whereas the route for /lcd will call render_template to return a templated HTML page (lcd.html) and passes any relevant data (e.g. “Jeff” which is irrelevant in this example”). Templates will be covered shortly below.

@app.route("/lcd/clear", methods=["POST","GET"])
def display_clear():
    return "Success"

@app.route("/lcd/displaymessage", methods=["POST"])
def display_message():
    if not request.json:
    return "Success" 

Any POST or GET on http://SERVERADDRESS:PORT/lcd/clear will result in the smartie drivers clear screen method being called. A POST to “/lcd/displaymessage” will be validated to ensure that the request contains JSON data and then the data will be passed to the driver for display.

/app/templates/lcd.html: This is the main HTML page that enables the user to type the messages to display.


The CSS and JavaScript used by this page is found in the static folder and referenced in the usual way………….

<!-- CSS for our app -->         
 <link rel="stylesheet" href="/static/lcd.css"/>

<!-- JS for our app --> 
<script type="text/javascript" src="/static/lcd.js" charset="utf-8"></script>

So we need to ensure that the flask server returns these static files, but we don’t want to have to define  a specific app.route for each one so instead we use this one in our :

def send_file(filename):  
      return send_from_directory('/static', filename)

This basically states that any requests for a file path are sourced from the /static folder directly. So we can just place any files in the static folder that we want to be served directly (the CSS and JavaScript files in our case).

/app/static/lcd.js:  From this JavaScript code we can consume the services hosted by Flask for our application. It’s using the XMLHttpRequest object to make AJAX requests to the Flask server. The SendCommand function takes callback methods which will be called on success or error.

function SendCommand(url, httpVerb, data, successCallback, errorCallback){
  var dataToSend;
      var dataToSend = JSON.stringify(data);          
   var request = new XMLHttpRequest();, url, true);
  request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
   request.onload = function() {
      if(this.status >= 200 && this.status < 400){
          // success here
          var returnedData; 
          if (this.response != null){
              successCallback(returnedData, this.status);
          //error returned from server
          errorCallback("Error response returned from server", this.status);
   request.onerror = function() {
          errorCallback("Error contacting server", this.status);

  if (dataToSend != null){

That’s mostly it. Run the app by running the module (e.g in the Python IDLE or terminal) and direct your browser to http://SERVERADDRESS:5000/lcd.

The code for my Python driver and this web app is available on GitHub here and