How (and why) to script the download and integration of the latest version of the yubioath-desktop app directly from Yubico without using your distro’s package manager
EDIT: 5 Nov 2023
1. I added these scripts to my GitHub for convenience. They don’t have dependency checks though. You’ll need to make sure you have the needed prereq packages: https://github.com/openaiken/yubioath-desktop-manual
2. Since writing this post, I moved off of Manjaro to vanilla Arch Linux, and I used this install script again. Works great!
This isn’t the “best” way to accomplish this task. As a matter of fact, it’s pretty close to the worst way to do this. Why am I doing it, then? I use Manjaro Linux for now (I have my reasons, in spite of its plentiful shortcomings and controversies) on my primary desktop, and for whatever reason, the Manjaro maintainers have not updated the version of the yubioath-desktop
package in the community
repository. At time of writing (2023/05/20) the version offered is 5.1.0 and the latest version offered from Yubico is 6.2.0. Recently the 5.1 version stopped communicating properly with my YubiKeys entirely, and will not detect the keys and display TOTP codes. I have taken matters into my own hands by using the application directly from Yubico’s website. I saw this recommendation from a reddit comment on r/yubikey.
In order to ensure I can easily update the app in the future, I scripted the installation steps (and an accompanying script for uninstallation in case I need to go back to a package manager based installation in the future). I wrote it pretty lazily, with no error handling, but I think it’s very simple to interpret visually and modify it to your needs.
Instructions
Prerequisites
First thing’s first: dependencies. If you already had yubioath-desktop
installed and are doing the same thing I did, you already have the dependencies, unless you uninstalled the package (which I do recommend before doing this…) and purged orphaned dependencies. I pulled up the dependency list with pamac
(Manjaro 22.1.2). Your command to list dependencies, and the names of those packages, will vary by distribution.
$ pamac info yubioath-desktop
Name : yubioath-desktop
Version : 5.1.0-3
Description : Yubico Authenticator for Desktop
URL : https://github.com/Yubico/yubioath-desktop
Licenses : BSD
Repository : community
Installed Size : 7.5 MB
Groups : --
Depends On : qt5-base qt5-declarative qt5-quickcontrols qt5-quickcontrols2 python-pyotherside qt5-graphicaleffects qt5-multimedia ccid pcsclite yubikey-manager
Optional Dependencies : --
Provides : --
Replaces : --
Conflicts With : --
Packager : Jan Alexander Steffens (heftig) <heftig@archlinux.org>
Build Date : Sat 05 Mar 2022 01:06:46 PM CST
Validated By : MD5 Sum SHA-256 Sum Signature
The “Depends On” line is the important part. What I chose to do is simply to mark them as “explicitly installed” instead of as “dependencies” in my package manager, so that if in the future I ever remove all orphaned packages, I don’t lose these by accident:
$ pamac install --as-explicit qt5-base qt5-declarative qt5-quickcontrols qt5-quickcontrols2 python-pyotherside qt5-graphicaleffects qt5-multimedia ccid pcsclite yubikey-manager
This, friends, is called “tech debt” (or configuration drift, depending on your perspective or intentions). I will NEVER go audit what packages are taking up space on my install, or why. I will now have these for as long as I’m on Manjaro. I have elected this sentence for my crimes. I built my own cage. But I accept it, and I try to take better care of my home servers.
Scripts
Basically, we need to:
- Download the latest tarball from Yubico
- Extract the contents
- Place a reference to the binary in the $PATH
- Integrate the program with the Desktop Environment
And do all of it in a clean fashion such that it is agnostic to the version number / filename, doesn’t create bloat, and is completely cleaned up with the uninstall script.
Pick an arbitrary directory (I’m using a folder in my Home dir that I use for screwing with random Open Source projects). You’ll need to create the script (e.g. $ touch install-yubioath.sh
) and make it executable (e.g. $chmod +x install-yubioath.sh
). Here are the contents:
#!/bin/bash
DIR="$HOME/opensource/yubico-authenticator"
URL=https://developers.yubico.com/yubioath-flutter/Releases/yubico-authenticator-latest-linux.tar.gz
FILENAME=yubico-auth-latest.tar.gz
OUTDIR=yubi-auth-files
curl -L $URL -o $DIR/$FILENAME
mkdir $DIR/$OUTDIR
tar --overwrite -xzf $DIR/$FILENAME -C $OUTDIR --strip-components 1
sudo chown root:root $DIR/$OUTDIR/authenticator
sudo chmod 555 $DIR/$OUTDIR/authenticator
sudo ln -s $DIR/$OUTDIR/authenticator /usr/bin/yubioath-desktop
bash $DIR/$OUTDIR/desktop_integration.sh -i
I’ll explain what’s going on here line by line.
- The first 4 lines are variables to make the script easier to customize for your system and to reduce copy-pasting a bunch.
DIR=
is the absolute path of the folder I’m running this script in. As stated before, I have an “opensource” directory for random projects, and a subdirectory for this application.URL=
is the address of the tarball of the latest release of the app. Fortunately for us, Yubico seems to simply redirect this filename to whatever the latest release is named.FILENAME=
is the name of the tarball file after downloading it. The reason we’re setting this is so that the filename is always the same. By default, the download will have a different filename when there is a new version.OUTDIR=
is the subdirectory ofDIR=
that we’ll extract the tarball into and run the application out of.
curl -L $URL -o $DIR/$FILENAME
will download (curl) the file ($URL), following redirects (-L), and output it (-o) to the specified location and static filename ($DIR/$FILENAME).mkdir $DIR/$OUTDIR
is there to ensure that when you run this for the first time, or if you ever delete the data directory (e.g. uninstalling), that your OUTDIR will exist [again].tar --overwrite -xzf $DIR/$FILENAME -C $OUTDIR --strip-components 1
extracts and decompresses (tar -xz) the contents of the download (-f $DIR/$FILENAME), explicitly overwriting any existing files from an older version (–overwrite), using the OUTDIR you specified instead of using the current directory (-C $OUTDIR), but removing the top-level folder from the extraction so that your OUTDIR actually contains the contents of the tarball itself instead of a nested folder (–strip-components 1). Cue XKCD 1168.- Next, we secure the application somewhat so that only root can “modify” the actual program instead of any non-privileged (i.e. user-owned) process having permissions over it. The kids call this “being extra”:
sudo chown root:root $DIR/$OUTDIR/authenticator
changes the user/group ownership (chown) of the actual yubico authenticator executable program ($DIR/$OUTDIR/authenticator) to root (root:root), as root (sudo).sudo chmod 555 $DIR/$OUTDIR/authenticator
changes the file modes/permissions (chmod) to only read+execute for the owners and all users (555) for the executable program ($DIR/$OUTDIR/authenticator), as root (sudo).
sudo ln -s $DIR/$OUTDIR/authenticator /usr/bin/yubioath-desktop
creates a soft link / symlink (ln -s) of the program ($DIR/$OUTDIR/authenticator) inside a directory in your $PATH with the official name of the application (/usr/bin/yubioath-desktop), as root (sudo).- Lastly,
bash $DIR/$OUTDIR/desktop_integration.sh -i
runs (bash) the Desktop Environment Integration script that Yubico provides ($DIR/$OUTDIR/desktop_integration.sh) in “install” mode (-i).- This makes the app show up in your app list, such as the app launcher in your DE’s start menu, or as an available Startup application (re: gnome-tweaks).
This is one of those Linux power-user tasks that there are a thousand ways to go about. Note that this script has no error checking or exception handling, doesn’t make use of much more efficient bash tools and variables such as setting the working directory or using an environment file, etc. Feel free to make this way more professional. My only goal was to script all the stuff I was going to have to do manually for every update since I’m not using my distro’s official package. Fortunately this script can be executed as many times as you need, as often as you need (be respectful, it actually pulls it from Yubico’s servers every time), and overwrites the existing data without creating any bloat.
I created an accompanying uninstall script, which is functionally the reverse of the install script. Again, you’ll need to create the file (e.g. uninstall-yubioath.sh) and make it executable. Here are the contents, which I’ll explain line by line:
#!/bin/bash
DIR="$HOME/opensource/yubico-authenticator"
URL=https://developers.yubico.com/yubioath-flutter/Releases/yubico-authenticator-latest-linux.tar.gz
FILENAME=yubico-auth-latest.tar.gz
OUTDIR=yubi-auth-files
sudo rm -f /usr/bin/yubioath-desktop
bash $DIR/$OUTDIR/desktop_integration.sh -u
sudo rm -rf $DIR/$OUTDIR
rm -f $DIR/$FILENAME
- All of the variables at the top are pasted from the install script. This could be simplified with a third “configuration” file that is included at the beginning of the script, if you’d like.
sudo rm -f /usr/bin/yubioath-desktop
removes (rm) without confirmation (-f) the soft link / symlink created in the the install script (/usr/bin/yubioath-desktop) as root (sudo).bash $DIR/$OUTDIR/desktop_integration.sh -u
runs (bash) the Desktop Environment Integration script that Yubico provides ($DIR/$OUTDIR/desktop_integration.sh) in “uninstall” mode (–u).sudo rm -rf $DIR/$OUTDIR
removes (rm) recursively and without confirmation (-rf) the working directory where you extracted the contents of the download from Yubico ($DIR/$OUTDIR) as root (sudo).rm -f $DIR/$FILENAME
removes (rm) without confirmation (-f) the original tarball that was downloaded from Yubico in the install script ($DIR/$FILENAME).
Running this script quite literally undoes every single task performed by the install script. It’s a comprehensive cleanup that will prevent interference with any future installation of the official package.
One final note: For your situational awareness, data created/stored by this program, such as saving a password to unlock the key for displaying your OATH codes, is stored in a local directory (or possibly your keyring, I’m not sure) on your profile, not in the directory where the application is stored. This is a good thing overall, for security reasons above all else, but it’s not accounted for by the uninstall script.
Problems with this approach
Any sufficiently snobby Linux nerd (such as myself) could easily rattle off a laundry list of fundamental issues with this approach itself, and inefficiencies with the actual solution I presented. Like this…
- This is not how you’re “supposed” to install software on Linux. This is a very “Windows” approach. There’s no dependency tracking (packages or required versions), the package manager doesn’t know that the files belong to the authenticator app, there’s no conflict avoidance if you install an incompatible package (such as the official one)…
- The scripts could be consolidated into a single script with 2 modes, toggled with a command-line argument.
- Especially with 2 scripts, there should be a configuration file.
- This should just be compiled into a new package, even if it’s not retrieved from a repository, in order to mitigate the above problems and avoid borrowing a directory in your home folder. This home folder is prone to accidental deletion and could thereafter result in the files created by the install script being orphaned (and useless!)
- There’s no condition checking, error checking, or exception handling.
- The package maintainer should just update the package.
- I should write an override in my pamac/pacman configuration to ignore the original package to avoid conflicts.
- I should stop using Manjaro because it kinda sucks.
- The dependencies marked as explicitly installed will never go away unless I audit my installations and remove them, and if I do so, the package manager won’t know that I’m breaking my Yubico Authenticator. If I don’t mark them as explicitly installed, I may delete them by accident.
- The package won’t be updated when you do your other system updates. You could mitigate this issue by creating a hook in your system upgrade process to run this, or by putting a link to the install script in a
cron
directory/job so that it’s always done automatically. - The install script downloads the package every time, instead of checking the latest version and skipping the download if you already have it. This is a waste of resources.
But… I have by TOTP codes on the desktop again! It’s a sufficient enough solution for me. Use at your own discretion.