Electricmonk

Ferry Boender

Programmer, DevOpper, Open Source enthusiast.

Blog

Tuxedo Computers TUXEDO Pulse 14 (Gen1) Review

Sunday, August 8th, 2021

Last Tuesday my new Tuxedo Computers Pulse 14 laptop arrived. I’ve been running it as my daily driver since then (6 days) and this is my review of it.

Background

First, some background about what I look for in a laptop and what my use-case is.

I’m a software developer and systems operator. While I don’t do any high-performance computing or heavy compiling, I do generally tend to run a lot of things in Virtual Machines and Docker stacks. My OS of choice is Xubuntu, which is a basic derivative of Ubuntu except it runs the XFCE desktop environment instead of Gnome.

I previously used a Dell XPS 15 with 8 Gb of memory and regularly ran out of memory on that machine, even without any VMs or Docker containers running. For example, starting a Google Meet while also having Slack and a few other browser windows open would generally OOM kill Slack or something else.

I used to game on Linux, which is why I previously went for the Dell XPS 15 with a dedicated NVIDIA Geforce card. However, I no longer game on Linux, so that’s not a requirement anymore. On a side-note, everybody seems really hyped for Proton, but I’ve had a terrible experience trying to run even the most basic non-native Linux games with Proton. Is it just me?

So what was I looking for in a laptop? First and foremost: excellent Linux support, preferably with Linux preinstalled. Second, memory and lots of it. It is by far the most limiting factor for me these days. 16 Gb was the absolute lowest limit for me. I don’t care too much about the CPU, but if I had to choose, I’d go for fast single core / thread performance. This is mostly because many programming language are still limited to a single core / thread. But honestly, it doesn’t matter that much. For a disk, SSD is the bare minimum. I value speed over storage space, although 256 Gb is the bare minimum.

I don’t require an ultra-mobile experience. I travel at most a few hours between locations where I can plug in the laptop so battery life isn’t especially important. I also don’t work extensively on the laptop itself, but generally plugin in an external monitor, keyboard and mouse. I also prefer a single external monitor with virtual desktops over multiple external monitors. That said, I do prefer smaller laptops over larger ones, so the Pulse’s 14″ display suited me just fine.

Configuration

This was the first time I’ve ever heard of, let alone ordered, a Tuxedo Computers product. That’s always a bit of a risk, but they presented enough technological information on their website to convince me that they knew what they were doing. Being a product from Germany (generally excellent engineering) with Ubuntu preinstalled (hardware compatibility with Xubuntu basically guaranteed), I decided to take the risk.

TUXEDO Pulse 14 – Gen1

I configured the following:

  • Memory: 64 Gb 3200MHz CL22 Samsung (2 x 32 Gb)
  • CPU: AMD Ryzen 7 4800H (8x 2.9-4.2GHz Eight-Core, 16 Threads, 12 MB Cache, 45 W TDP)
  • Disk: M.2 SSD: 2000 GB Samsung 970 EVO Plus (NVMe PCIe)

That’s a bit of an overspecced powerhouse for my needs, but Tuxedo Computers’s prices are so extremely competitive that I couldn’t even max out my budget. For comparison, the above configuration clocked in at € 1.377,-. A similar configuration of a Dell XPS 13 (with only 32 Gb of memory) meanwhile costs € 2.119,-. Prices don’t include VAT btw.

Ordering and delivery

While ordering the laptop, Tuxedo Computers were very clear about a delay of a few weeks (up to about 7 weeks) due to a shortage in parts. Given the current market, that’s to be expected. I was kept up to date constantly about the current status of my order. I was also pleasantly surprised when the parts came in much sooner than I was expecting and the laptop was assembled and shipped a few days after the components came in.

Shipping from Germany to the Netherlands was handled by UPS with, again, excellent status updates about the whereabouts of my purchase and delivery date and time.

The laptop arrived well packaged and undamaged. I would feel comfortable shipping this laptop over longer distances if I had to. It came with a few goodies such as Tuxedo Computers pens and a Tux Crystal 1st revision (as shown in the image) Mousepad.

Initial impressions

While the laptop was charging, I took a good look at the hardware. Given the low cost of only € 1.377, I was kind of expecting some… compromises on the quality of the laptop housing or something. I was pleasantly surprised to find a beautifully slim, sturdy laptop. The chassis has no noticeable flexibility. The screen opens easily, yet the hinge feels solid. There is no wobble on the screen whatsoever when typing; a problem I’ve seen with some other cheap(er) laptops.

All the ports on the laptop are spaced out perfectly, which prevents cables and dongles from getting in each other’s way – a problem I ran into with the Dell XPS 15. The screen bevels at the sides and top are thin, which gives the display an impression that it’s bigger than it actually is. The camera is situated at the top. It’s something I didn’t even really think about when ordering the laptop, but it’s so much better than the Dell XPS 15’s camera positioning at the bottom of the screen, a.k.a. “The Nose Cam”.

The trackpad is large, but feels slightly worse to the fingers than the XPS 15’s trackpad. The keyboard feels pretty good to the touch and has large keys with a moderate amount of spacing in between. The arrow keys are large enough to be comfortable to use, although I would have preferred the up and down arrow keys to be as large as the left and right keys. Like many laptops these days, it doesn’t come with dedicated Page Up/Down and Home / End keys. Given the large size of the keys, it feels like they could have easily made room for another column on the right to facilitate those keys.

Xubuntu installation

The Pulse 14 came with Ubuntu preinstalled, but I did not test-drive it other than testing a few small things. I made a copy of the /etc directory and some PCI and kernel module outputs and then plugged in a USB stick with the Xubuntu installer. Because I did not test-drive the preinstalled Ubuntu, there’s a chance that some of my findings in the rest of this review are a consequence of my Xubuntu installation rather an actual problem with the Pulse 14, so keep that in mind.

Like the previous three laptops I installed Xubuntu on, the installation worked flawlessly and almost everything was working out of the box. Wifi, sound, networking, bluetooth and all the other Usual Suspects when installing Linux all just worked. That’s not something new, as the same was true for the previous two off-the-shelve Windows laptops that I installed Xubuntu on in the last year. For some reason I still expect at least something to not work properly though, but that wasn’t the case. I did choose the wrong keyboard layout, which caused some of the symbol keys  such as “[” and “]” to output other characters, but a quick “dpkg-reconfigure keyboard” fixed that.

Tuxedo Computers offers some of their own software for Ubuntu such as the Tuxedo Control Center, which lets you easily change various hardware settings using profiles. These can automatically be applied when the power is plugged in or when you’re running on batteries. This is one of the few things I tried out while the original preinstalled Ubuntu was still on the laptop, and it seemed like a very nice addition to the usual power management options, so I decided to install it.

That’s also where my first critique of Tuxedo Computers comes in. The installation instructions for the Tuxedo Control Center were very unclear and even borked my apt configuration. That’s not a significant problem for me, because I know how apt works, so I could figure out what the instructions were actually trying to tell me. I assume that if you don’t have that knowledge, you’re also not very likely to install something other than the preinstalled Ubuntu, so I guess that’s not much of a problem.

And honestly, the fact that Tuxedo Computers bothers with writing such a tool at all is amazing. It’s what gave me the confidence to order this laptop in the first place.

The Tuxedo Control Center is really nice though. You can configure profiles to set the display brightness, number of CPU cores and their min / max performance, choose various settings for fan control from “Silent” (minimum fans) all the way up to “Freezy” (max fans). I recommend installing this piece of software.

Impressions after one week of daily usage

I’ve been using the Pulse 14 as a daily driver for a little under a week now. Obviously that’s too short to say much about long-term things such as hardware reliability and such, but so far I’ve been extremely impressed with this little power house. It’s basically everything I hoped it would be. There were a few issues I ran into in the first few hours of usage.

Keyboard layout issues

The first issue I ran into is the fact that the Insert and PrntScr keys are labelled wrong. The PrtScr button is actually the Insert key and the Insert key is actually the Delete key. This might be a keyboard layout configuration issue, but if it is, I’m actually glad things aren’t working properly, otherwise I would have no Delete key. It did cost me some time to figure out that pasting the primary clipboard buffer with Shift-Ins wasn’t working because the Insert key was actually the Delete key. It’s a minor thing and once you’ve figured this out, it’s not a problem at all.

Fans

The next thing I noticed are the fans. They were coming on even though I wasn’t even really doing anything remotely heavy. Just some light browsing and some “apt” install of a few tools such as Git. Now I’m kinda spoiled coming from the XPS 15 which had really quiet fans. Not so much with the Pulse 14. The fans are fairly loud and a little bit whiny. At low revs I also noticed a little bit of a “wobble” in the sound of the fan at one time, but I haven’t heard it since.

This had me a little bit worried because I really dislike fan noise. Even worse, there’s a tiny audible click when the fan goes from off to on at 20%. It sounds a lot like the click you’d hear from mechanical hard drives when they spun up from idle – just not as loud. Fortunately, I installed the Tuxedo Control Center, so I took a look at the current profile in use  (“Default”) and the fan was set to “Balanced”. I switched to the “Cool and breezy” profile, which had the fan setting at “Quiet” and the problem has since gone mostly away.

At normal usage the fan hasn’t audibly come on since and the CPU sits at a decent 50°c. It does seem that occasionally the fan comes on with that tiny audible click. There’s an even quieter fan mode called “Silent” but I’m a bit afraid to set the profile to that since it would cool the CPU and such less. In daily life the laptop sits a little bit away from me anyway, which means I don’t hear the click anyway.

Battery life

The battery life is advertised as:

Endurance for up to 12 hour. For mobile use […] practical operation (1080p video streaming at ~150 cd/m2) endurance for up to 7 hours. In the energy-saving idle state, […] up to 12 hours.

As is always the case with laptop manufacturers, I’ve found these claims to be a little exaggerated. In the “Powersave extreme” profile, while being basically idle, the laptop reports about 6h45m of battery life. I assume, though haven’t tested, that under fairly normal loads, the battery will last about 3 to 4 hours. Do note that I’m not running the preinstalled Ubuntu, which might make a bit of a difference.

Performance

To be honest, I can’t tell you much about the performance CPU-wise. Xubuntu is a very light desktop environment, and I haven’t noticed any change whatsoever in its performance since I first started using it about 10 years ago. It’s always been extremely snappy. I haven’t really cared about CPU performance for a long long time. I did notice a huge improvement in the startup of Gimp, but I’ve got no idea whether that’s due to changes in Gimp or the specs of the Pulse 14.

The biggest impact on performance for me has always been memory. Even the slightest amount of memory pressure on Linux means it’s going to free up buffered and cached content to make room for other programs, and that is generally noticeable in the performance. Once memory really runs out and linux starts to swap, it’s basically over for your performance until something gets OOM killed.

You can imagine that with 64 Gb of memory, I haven’t found any performance problems whatsoever.

With the “Cool and breezy” profile enabled, I performed various stress testing with “stress-ng” over a one-minute time period to see if it impacted performance at all:

$ stress-ng --cpu 4 --io 2 --vm 1 --vm-bytes 1G --timeout 60s
stress-ng: info: [44275] dispatching hogs: 4 cpu, 2 io, 1 vm
stress-ng: info: [44275] successful run completed in 60.08s (1 min, 0.08 secs)

During this minute of working I browsed some (heavy) websites while watching a video. I didn’t notice any degradation in the performance. The fan also didn’t come on and the CPU temperature reached 58°c, while the CPU topped out at 2.4 Ghz.

The same stress test with the “Default” profile (max performance basically)  took the CPU up to 3.3 Ghz, the CPU temperature to 75°c (with a tiny spike to 90°c before the fans kicked in fully) and the fan speed to about 60%.

I did some very basic benchmarking of the disk’s read / write speed:

fboender @ eek ~ $ sudo dd if=/dev/zero of=writetest bs=4096 count=5000000
5000000+0 records in
5000000+0 records out
20480000000 bytes (20 GB, 19 GiB) copied, 19.5588 s, 1.0 GB/s


fboender @ eek ~ $ sudo dd if=writetest of=/dev/null bs=4096 count=5000000
5000000+0 records in
5000000+0 records out
20480000000 bytes (20 GB, 19 GiB) copied, 3.75467 s, 5.5 GB/s

Obviously, dd is not a decent read / write performance test, but it’s good enough. 1 GB/s sustained write speed and 5.5 GB/s read speed. Not bad.

Touchpad

I’ve got little to complain about the touchpad, but mostly because I haven’t used it much. The hardware left and right click of the touchpad feel reasonable, but why would you use hardware clicking on a touchpad when you can tap for left click and two-finger tap for right click?

It suffers from the same problems as all touchpads under Linux though. They get in the way when you type and randomly warp the mouse cursor all over the place. This isn’t a problem with the touchpad hardware or anything. It’s just one of those quality-of-life things that just aren’t there in Linux on the desktop yet. I’ve gotten used to this and don’t even bother trying to tweak this anymore. Rather I just have a keybinding that turns the touchpad on and off manually using “xinput”. See this link for more info.

There are the usual tips for tweaking the touchpad on Tuxedo Computer’s website, but it’s the same stuff you already know probably. Disabling the Touchpad for a few moments after typing a key helps a little. I found 0.3 to be a reasonable compromise, but touchpad usage on Linux remains a problem and Tuxedo Computers did not manage to improve this unfortunately. Again, it’s possible this is an issue with Xubuntu though.

Keyboard

Now we come to the first and only real problem with this laptop: the keyboard. I don’t know whether this is a software or hardware problem, but I very strongly suspect it’s a hardware problem. The issue is that sometimes keys don’t register. This is mostly noticeable with keys further away from the center of the keyboard, such as ‘q’, ‘a’, ‘z’ and ‘p’ and such. It also happens very frequently when needing to type the same key twice, such as the ‘e’ in “needing”.

Now I regularly switch keyboards to prevent RSI and in the last year I’ve typed on at least four different laptop keyboards and three standalone keyboards and I’ve never had this problem before. Sure, sometimes you have to get a little used to a new keyboard and you might make some typo’s, but keys sometimes not registering is something I’ve simply never encountered before. It’s not that I’m not pressing the keys properly. I can feel the key going through the resistance just fine and it feels like I’ve typed the key, it just doesn’t register.

Over the course of a few days I’ve tested this a few times. I’d use the keyboard for a bit; say half an hour. Then I’d write a few paragraphs of the same text each time without looking at the output, to prevent my brain from automatically correcting typing mistakes. In each test I noticed the same pattern of missing characters as mentioned above.

This is a fairly major blemish on an otherwise fantastic product. It’s possible that this is a software problem, but I highly doubt it. I’ve tried the solution to “Keyboard not working properly” given on Tuxedo’s website, to no avail. A review on Reddit notices the same problem, but only with the Return key:

Feedback is good on the most part, the stroke is firm but not stiff, with quick return and quiet actuation. The only key I’ve had issues with so far is (maybe most unfortunately) the carriage return. I thought perhaps it was a matter of not hitting it square on, but I think it actually just feels like it’s bottoming out prematurely before registering the input.

This sounds exactly like my problem, except I have it with multiple keys.

Does this make the laptop entirely unusable? Well, not for me. I generally don’t like typing on laptop keyboards, and would rather use a standalone keyboard. I’ve got a compact Logitech K380 Bluetooth keyboard which I take with me when I know I’m going to need to type for longer periods. if, however, I was planning on using this laptop a lot on the go, it would certainly be a big disappointment.

TUXEDO Office Hub

Because I had some extra budget, I decided to get a TUXEDO Office Hub, which set me back €230. The store page looked promising with a good deal of USB ports, HDMI and DisplayPort outputs, headphone / microphone jacks, etc. It seemed to be compatible with the Pulse 14:

In general, all notebooks with USB ports are compatible with our Office Hub. The connection of the hub via USB-C is enabled by a so-called DisplayLink driver. It provides basic functions of image signals via USB. This is very suitable for working and surfing, but only conditionally for gaming and graphics-intensive applications.
Mice and keyboards connected via USB as well as Gigabit LAN and audio always work. The native HDMI port works as soon as your notebook includes USB-C with DisplayPort. Otherwise, you have to use the included DisplayPort to HDMI adapter.

The Pulse 14 has no support for DisplayPort over USB-C, but that didn’t seem to be a problem given that it says that: “Otherwise, you have to use the included DisplayPort to HDMI adapter”.

There was another compatibility issue mentioned:

Devices with AMD Ryzen CPU have the following restrictions due to the necessary DisplayLink driver:

  • Slight delays during movements, e.g. when moving windows
  • Monitors with 4K resolution cannot be addressed properly

Unfortunately, that “slight delay” means “utterly unusable screen lag of multiple seconds”. I’m not exaggerating when I say that this isn’t usable in any setting whatsoever. I have not been able to find any way of getting a monitor to work properly via the Office Hub. The DisplayPort to HDMI adapter suffers from exactly the same problems. There are plenty of bug reports on the internet about this problem, with all kinds of potential solutions, but the ones I’ve tried so far haven’t worked out.

This isn’t a huge problem for me personally. I only use one external screen, and that works fine with the native HDMI port on the laptop itself. However, if you want to attach multiple external monitors to the Pulse 14, you may be in for a disappointment. It’s possible that it can be fixed with one of the solutions on the internet, or perhaps AMD / DisplayLink or whoever will fix this problem in the future. Until then, I’d be very wary. I’ll update this page if I find a solution (but don’t count on it cause I don’t care that much).

It’s worth noting that I’ve had plenty of similar problems with DisplayLink on the Dell XPS 15. For me, it never worked. Some other people I know managed to get it to work properly. This isn’t a problem with the Pulse 14 really, nor is it the fault of Tuxedo Computers.

Anyway, for me right now it’s a glorified USB hub. Fortunately this purchase come out of the extra budget I had left due to the competitive price of the Pulse 14 itself, so it didn’t cost me anything extra. Otherwise, I would have been a bit more disappointed having bought a USB hub at €230.

Conclusion

The Pulse 14 is amazing bang for your buck. It’s very powerful, lightweight and looks fantastic. The build feels sturdy and of decent quality. It has better specs than a Dell XPS 13, but it’s €742 cheaper. I have no idea how Tuxedo Computers are managing that extremely competitive price-point, especially given the current chip shortages. This allowed me to max out the memory to 64 Gb, which is the most limiting factor in performance for me these days.

All the hardware works straight away on a clean install of Xubuntu. Once power management and fan control are configured properly using Tuxedo Control Center, the laptop is quiet and runs cooler than a Dell XPS 15. The performance feels amazing, but that’s normal for Xubuntu even on slower hardware. I don’t run many CPU or IO heavy workloads, so I can’t really comment too much on that otherwise. From some benchmarks I ran, everything looks fantastic, but that’s just theory.

The Pulse 14 suffers from the usual Linux-on-the-desktop problems. The touchpad seems fine hardware-wise, but gets in the way as is normal under Linux. DisplayLink is a drama – especially on AMD – which means the Office Hub is useless for attaching to external screens. I suspect the same is true for attaching an external screen over anything other than the built-in HDMI port. Beware if you want to hook up more than one monitor.

For me personally, the only real downside is the laptop’s keyboard. It regularly misses key presses and the characters just don’t show up. This has never happened to me before. I strongly suspect this is problem with the keyboard itself, and not some settings, configuration or me just needing to get used to it. It doesn’t make the keyboard entirely unusable, just frustrating. Again, this is not a deal breaker for me. I don’t like working on a laptop directly and prefer external screens, keyboards and mice.

All in all, I’m extremely impressed with the Pulse 14, as well as with Tuxedo Computers. It’s the first time I heard of them, the first time I’ve ever ordered one of their products and at the price-point of € 1.377,- I got much much more than I expected. Tuxedo Computers seems like a company that truly cares about Linux on the desktop. They got various support pages and github repositories for fixing hardware / software compatibility problems, but so far I haven’t needed them. The addition of the Tuxedo Control Center is a very nice touch.

I will definitively buy from then again. Most likely a new NUC-like media center or a new Gaming PC.

An Audio / Video profile switcher (and app launcher) script for Linux

Tuesday, April 13th, 2021

Since the start of Corona, my company has been mostly working remote. That means more video conference meetings. A lot more. So much in fact, that I decided to automate the process of setting everything up correctly for that and other audio video profiles.

For example, my webcam is in my laptop, whose screen I don’t normally use (because virtual desktops == infinite screens right in front of you). Since I’d like people to see me looking at them when we’re conferencing, I want Google Meet to be on the laptop screen. Also, I need to activate my headset.

Switching the internal screen on, switching to the headset, opening Google Meet, dragging it to the laptop’s screen and making the window sticky so it doesn’t disappear when I switch virtual desktops on my main screen… is a bit of a hassle. And since I’m lazy, I decided I need an Audio Video profile switcher.

No such thing existed, so I cobbled together a script, that you can find in a Gist on Github.

The script is reasonably documented I think. It relies heavily on xdotool, wmctrl and pacmd. At the top are some profile definitions for screen layouts, screen coordinates (to move a window to a different screen), and some sound output profiles:

# Use arandr to setup your displays and then export the profile
SCREEN_LAYOUTS[external_only]="
    --output HDMI-2 --off 
    --output DP-1 --off
    --output DP-2 --off
    --output eDP-1 --off
    --output HDMI-1 --primary --mode 1920x1080 --pos 0x0 --rotate normal
"
SCREEN_LAYOUTS[external_left]="
    --output HDMI-2 --off
    --output DP-1 --off
    --output DP-2 --off
    --output HDMI-1 --primary --mode 1920x1080 --pos 0x0 --rotate normal
    --output eDP-1 --mode 1920x1080 --pos 1920x0 --rotate normal
"

# Screen coordinates for moving windows to a different screen. These are
# coordinates on a virtual desktop that is stretched over all monitors; either
# vertically or horizontally, depending on the screen layout.
SCREEN_COORDS[laptop]="0,1920,0,500,500"
SCREEN_COORDS[external]="0,0,0,500,500"

# This requires a bit of a PhD in pulse audio. There has to be a better way
# Mike!
SOUND_OUTPUTS[headphones]="
    pacmd set-card-profile alsa_card.usb-Logitech_Logitech_USB_Headset-00 output:analog-stereo+input:analog-mono;
    pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo;
    pacmd set-default-sink alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo;
"
SOUND_OUTPUTS[external_monitor]="
    pacmd set-card-profile alsa_card.usb-Logitech_Logitech_USB_Headset-00 off;
    pacmd set-card-profile 0 output:hdmi-stereo;
    pacmd set-default-sink alsa_output.pci-0000_00_1f.3.hdmi-stereo;
"

Then there’s a bunch of helper functions to do various things such as:

  • Change the monitor layout
  • Change the audio output profile
  • Manipulate windows such as moving them around

Finally, the actual audio video profiles are defined in a big “if, then” statement. I also throw in the launching of some applications just to make things easier. For example, the forementioned “conference” profile:

elif [ "$PROFILE" = "conference" ]; then
   sound_output "headphones"
   screen_layout "external_left"
   firefox --new-window https://meet.google.com/landing?authuser=1
   sleep 1 # give firefox a moment
   win_to_screen "Google Meet" "laptop"
   win_sticky "Google Meet"
   win_focus "Google Meet"

I hook all of this up in my Lurch launcher, so that I can just hit Ctrl-alt-semicolon and type the partial name of a profile to switch to it:

I thought I’d share it, since it might be useful for other people. Note that the script may require tweaking to suit your needs, as it’s written for XFCE and other Window Manager might work slightly different.

Finding and removing packages installed from non-standard repos in Ubuntu

Saturday, April 10th, 2021

Update: Oh, look, right in the nick of time: “Valve Steam through 2021-04-10, when a Source engine game is installed, allows remote authenticated users to execute arbitrary code because of a buffer overflow that occurs for a Steam invite after one click

As part of my big spring cleaning, as well as given all the recent supply chain attacks, I’ve decided that I will no longer run any software from third-party repositories directly on my Linux desktop. The most pressing issues is with packages from PyPi, NPM, Docker Hub and other repositories that don’t support cryptographically signed packages. I now run those in Virtual Machines, but that’s a topic for another blog post.

I also wanted to get rid of all the cruft I’ve installed on my Linux desktop over the last years from third-party Ubuntu repositories. I often tend to try things out, but then forget to clean up after myself, which leaves quite a bit of software lingering around that I never use anyway:

root @ jib /etc/apt/sources.list.d $ ls
000-mailpile.list slack.list
000-mailpile.list.save slack.list.save
crystal.list spotify.list
crystal.list.save spotify.list.save
google-chrome.list steam.list
google-chrome.list.save steam.list.save
google-cloud-sdk.list taskcoach-developers-ubuntu-ppa-bionic.list
google-cloud-sdk.list.save taskcoach-developers-ubuntu-ppa-bionic.list.save
gregory-hainaut-ubuntu-pcsx2_official_ppa-bionic.list teams.list
gregory-hainaut-ubuntu-pcsx2_official_ppa-bionic.list.save teams.list.save
nodesource.list teamviewer.list.save
nodesource.list.save ultradvorka-ubuntu-productivity-bionic.list
peek-developers-ubuntu-stable-bionic.list ultradvorka-ubuntu-productivity-bionic.list.save
peek-developers-ubuntu-stable-bionic.list.save vscode.list
signal-xenial.list vscode.list.save

I mean, I don’t even know what some of that stuff is anymore. Time to clean things up!

First, how do I figure out which packages are in those repositories? The web gives us plenty of tips, but they seem to revolve mostly around aptitude, which I don’t have installed. And the whole idea is to clean things up, not install additional cruft!

Let’s look at /var/lib/apt/lists:

$ cd /var/lib/apt/lists
$ ls | head -n5
deb.nodesource.com_node%5f12.x_dists_bionic_InRelease
deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages
dist.crystal-lang.org_apt_dists_crystal_InRelease
dist.crystal-lang.org_apt_dists_crystal_main_binary-amd64_Packages
dist.crystal-lang.org_apt_dists_crystal_main_binary-i386_Packages

Okay, that looks promising..

$ cat deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages | head -n5
Package: nodejs
Version: 12.22.1-1nodesource1
Architecture: amd64
Maintainer: Ivan Iguaran <ivan@nodesource.com>
Installed-Size: 91389

Ah, just what we need. So we can get a list of all the packages in a repo using some grep magic. Note that these are not necessarily packages that have actually been installed, but rather they’re all the packages that are available in the repository.

$ grep '^Package:' deb.nodesource.com*
lists/deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages:Package: nodejs

For a repo with multiple packages, the output looks like this:

$ grep '^Package:' repository.spotify.com*
lists/repository.spotify.com_dists_stable_non-free_binary-amd64_Packages:Package: spotify-client
lists/repository.spotify.com_dists_stable_non-free_binary-amd64_Packages:Package: spotify-client-0.9.17
lists/repository.spotify.com_dists_stable_non-free_binary-amd64_Packages:Package: spotify-client-gnome-support
lists/repository.spotify.com_dists_stable_non-free_binary-amd64_Packages:Package: spotify-client-qt
lists/repository.spotify.com_dists_stable_non-free_binary-i386_Packages:Package: spotify-client
lists/repository.spotify.com_dists_stable_non-free_binary-i386_Packages:Package: spotify-client-gnome-support
lists/repository.spotify.com_dists_stable_non-free_binary-i386_Packages:Package: spotify-client-qt

Fix that output up a little bit so we only get the package name:

$ grep '^Package:' repository.spotify.com* | sed "s/.*Package: //" | sort | uniq
spotify-client
spotify-client-0.9.17
spotify-client-gnome-support
spotify-client-qt

There we go. We can now use apt to see if any of those packages are installed:

$ apt -qq list $(grep '^Package:' repository.spotify.com* | sed "s/.*Package: //" | sort | uniq) | grep installed
spotify-client/stable,now 1:1.1.55.498.gf9a83c60 amd64 [installed]

Okay, so Spotify has been installed with the spotify-client package. Now, we could purge that package manually, but for some of the repositories there are many installed packages. An easier (but slightly more dangerous) method is to just purge all of the packages mentioned in the repo, whether they’re installed or not:

$ apt purge $(grep '^Package:' repository.spotify.com* | sed "s/.*Package: //" | sort | uniq)
Package 'spotify-client-0.9.17' is not installed, so not removed
Package 'spotify-client-gnome-support' is not installed, so not removed
Package 'spotify-client-qt' is not installed, so not removed
The following packages will be REMOVED:
spotify-client*
0 upgraded, 0 newly installed, 1 to remove and 13 not upgraded.
After this operation, 305 MB disk space will be freed.
Do you want to continue? [Y/n]

Finally, we can remove the source list from our system:

$ rm /etc/apt/sources.list.d/spotify.list*

Rinse and repeat for the other repositories, and soon we’ll have rid our system of not just a bunch of cruft that increases our attack surface, but also of a bunch of closed source, proprietary garbage that I never used in the first place.

Update: Don’t forget to also remove any lingering configuration or data from your home directory or the system in general. How to go about doing that differs per application, so I can’t give any instructions for that. I just did a “find -type d” in my home dir, grepped out a bunch of irrelevant stuff and then went through the entire list and did a “rm -rf” on anything I didn’t think was worth keeping around. Freed up about 90 Gb of disk space too! (mostly due to steam). Make backups  before you do this!

Also, when you’re done removing the source lists, you can just wipe the entire contents of /var/lib/apt/lists. It’ll get rebuild when you do an apt update:

$ rm /var/lib/apt/lists/*
$ apt update

Now, I’m pretty sure that there is some arcane apt, dpkg, apt-get or add-apt-repository command to make this easier. The thing is that finding out which command does exactly what I wanted was taking up more time than just going ahead and cobble some shell oneliners myself.

Stay tuned for a blog post on how I use VirtualBox with linked clones and a little shell script wrapper to super easily spin up a sandboxes virtual machine for each of my development projects!

Shared folder on Virtualbox Ubuntu 20.04 guest fails with “No such device or address”

Friday, February 26th, 2021

In an Ubuntu 18.04 virtual machine in VirtualBox, I could define a Shared Folder like so:

And then mount it like this:

mount -t vboxsf Projects -o uid=1000,gid=1000 /home/fboender/Projects/

Or with the equivalent fstab entry like this:

Projects /home/fboender/Projects/ vboxsf defaults,uid=1000,gid=1000 0 0

This fails on an Ubuntu 20.04 guest with the following error:

/sbin/mount.vboxsf: mounting failed with the error: No such device or address

Some combinations I tried:

mount -t vboxsf /media/sf_Projects -o uid=1000,gid=1000 /home/fboender/Projects/
mount -t vboxsf Projects -o uid=1000,gid=1000 /home/fboender/Projects/
mount -t vboxsf sf_Projects -o uid=1000,gid=1000 /home/fboender/Projects/

None of it worked. It turns out that somehow, things got case-(in?)sensitive, and you need to specify the lower-case version of the Shared Folder name:

mount -t vboxsf projects -o uid=1000,gid=1000 /home/fboender/Projects/

Hope this saves someone somewhere some headaches, cause I couldn’t find anything about it on the Googles.

Sla (Simple Little Automator 🥗) v1.1 now supports long rule descriptions

Saturday, September 26th, 2020

Version 1.1 of the Simple Little Automator adds the ability to have long descriptions for build rules. For example:

install () {
    # Install sla
    # Install sla to $PREFIX (/usr/local by default).
    #
    # You can specify the prefix with an environment variable:
    # 
    # $ PREFIX=/usr sla install
    
    # Set the prefix
    PREFIX=${PREFIX:-/usr/local}
    DEST="$PREFIX/bin/sla"
    env install -m 755 ./sla "$DEST"
    echo "sla installed in $DEST"
}

This documentation can then be access using sla <rule> --help. E.g.:

$ sla install --help
install: Install sla

    Install sla to $PREFIX (/usr/local by default).
    
    You can specify the prefix with an environment variable:

        $ PREFIX=/usr sla install

Get the release from the Github releases page.

Sec-tools v0.3: HTTP Security Headers

Wednesday, July 24th, 2019

The latest version of my sec-tools project includes a new tool “sec-gather-http-headers“. It scans one of more URLs for security HTTP headers. As usual, you can use sec-diff to generate alerts about changes in the output and sec-report to generate a matrix overview of the headers for each URL.

The JSON output looks like this:

$ sec-gather-http-headers https://github.com/ https://gitlab.com/
{
    "http_headers": {
        "https://github.com/": {
            "Expect-CT": "max-age=2592000, report-uri=\"https://api.github.com/_private/browser/errors\"",
            "Feature-Policy": null,
            "Access-Control-Allow-Origin": null,
            "X-Frame-Options": "deny",
            "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
            "Access-Control-Allow-Headers": null,
            "X-XSS-Protection": "1; mode=block",
            "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
            "Public-key-pins": null,
            "Content-Security-Policy": "default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com; img-src 'self' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com customer-stories-feed.github.com; manifest-src 'self'; media-src 'none'; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com",
            "X-Content-Type-Options": "nosniff",
            "Access-Control-Allow-Methods": null
        },
        "https://gitlab.com/": {
            "Expect-CT": null,
            "Feature-Policy": null,
            "Access-Control-Allow-Origin": null,
            "X-Frame-Options": null,
            "Referrer-Policy": null,
            "Access-Control-Allow-Headers": null,
            "X-XSS-Protection": "1; mode=block",
            "Strict-Transport-Security": "max-age=31536000; includeSubdomains",
            "Public-key-pins": null,
            "Content-Security-Policy": "frame-ancestors 'self' https://gitlab.lookbookhq.com https://learn.gitlab.com;",
            "X-Content-Type-Options": "nosniff",
            "Access-Control-Allow-Methods": null
        }
    }
}

An example PDF output with a matrix overview:

http_headers

WordPress update hangs after “Unpacking the update”

Monday, March 11th, 2019

If your WordPress installation updates just stops after showing the message “Unpacking the update”, try increasing the memory limit of PHP. Unzipping the update takes quite a bit of memory. Newer versions of WordPress keep getting larger and larger, requiring more memory to unpack. So it can suddenly break, as it did for me.

You may want to check the actual limit PHP is using by creating a small “php info” PHP page in your webroot and opening that in your browser. For example:

<?php
phpinfo();
?>

Name it something like “phpinfo_52349602384.php”. The random name is so that if you forget to remove the file, automated vulnerability scanners won’t find it. Open that file in the browser and the memory limit should be mentioned somewhere under “memory_limit”.

sla: The Simple Little Automator

Monday, November 19th, 2018

I’m tired of using Make and its arcane syntax. 90% of the projects I write or deal with don’t require any kind of incremental compilation, but that’s all any build system talks about. That, and how insanely fast it is. The drawback is usually that you need to install several terabytes of dependencies, and then you need a 6-day course to learn how to actually write targets in it. I just want to convert some file formats, run a linter or execute some tests.

So I took an hour or two and wrote sla: the Simple Little Automator. (the name was chosen because ‘sla’ is easy to type; sorry).

sla is simple. It’s just shell functions in a file called build.sla. The sla script searches your project for this file, and runs the requested function. Simple, elegant, powerful, extensible and portable. Here’s an example build.sla:

#
# This is a script containing functions that are used as build rules. You can
# use the Simple Little Automator (https://github.com/fboender/sla) to run
# these rules, or you can run them directly in your shell:
#
#   $ bash -c ". build.sla && test"
#

clean () {
    # Clean artifacts and trash from repo
    find ./ -name "*.pyc" -delete
    find ./ -name "*.tmp" -delete
}

test () {
    # Run some code tests
    clean  # Depend on 'clean' rule
    flake8 --exclude src/llt --ignore=E501 src/*.py
}

You can run rules with:

$ sla test
./src/tools.py:25:80: E501 line too long (111 > 79 characters)
Exection of rule 'test' failed with exitcode 2

The best thing is, since it’s simple shell functions, you don’t even need sla installed in order to run them! Sourcing the rules.sla file in your shell is all you need:

$ bash -c ". build.sla && test"
./src/tools.py:25:80: E501 line too long (111 > 79 characters)
Exection of rule 'test' failed with exitcode 2

More info and installation instructions can be found on the Github project page.

multi-git-status can now do a “git fetch” for each repo.

Saturday, October 27th, 2018

Just a quick note:

My multi-git-status project can now do a “git fetch” for each repo, before showing the status. This fetches the latest changes in the remote repository (without changing anything in your local checked out branch), so that mgitstatus will also show any “git pull”s you’d have to do. 

direnv: Directory-specific environments

Sunday, June 3rd, 2018

Over the course of a single day I might work on a dozen different admin or development projects. In the morning I could be hacking on some Zabbix monitoring scripts, in the afternoon on auto-generated documentation and in the evening on a Python or C project.

I try to keep my system clean and my projects as compartmentalized as possible, to avoid library version conflicts and such. When jumping from one project to another, the requirements of my shell environment can change significantly. One project may require /opt/nim/bin to be in my PATH. Another project might require a Python VirtualEnv to be active, or to have GOPATH set to the correct value. All in all, switching from one project to another incurs some overhead, especially if I haven’t worked on it for a while.

Wouldn’t it be nice if we could have our environment automatically set up simply by changing to the project’s directory? With direnv we can.

direnv is an environment switcher for the shell. It knows how to hook into bash, zsh, tcsh, fish shell and elvish to load or unload environment variables depending on the current directory. This allows project-specific environment variables without cluttering the ~/.profile file.

Before each prompt, direnv checks for the existence of a “.envrc” file in the current and parent directories. If the file exists (and is authorized), it is loaded into a bash sub-shell and all exported variables are then captured by direnv and then made available to the current shell.

It’s easy to use. Here’s a quick guide:

Install direnv (I’m using Ubuntu, but direnv is available for many Unix-like systems):

fboender @ jib ~ $ sudo apt install direnv

You’ll have to add direnv to your .bashrc in order for it to work:

fboender @ jib ~ $ tail -n1 ~/.bashrc
eval "$(direnv hook bash)"

In the base directory of your project, create a .envrc file. For example:

fboender @ jib ~ $ cat ~/Projects/fboender/foobar/.envrc 
#!/bin/bash

# Settings
PROJ_DIR="$PWD"
PROJ_NAME="foobar"
VENV_DIR="/home/fboender/.pyenvs"
PROJ_VENV="$VENV_DIR/$PROJ_NAME"

# Create Python virtualenv if it doesn't exist yet
if [ \! -d "$PROJ_VENV" ]; then
    echo "Creating new environment"
    virtualenv -p python3 $PROJ_VENV
    echo "Installing requirements"
    $PROJ_VENV/bin/pip3 install -r ./requirements.txt
fi

# Emulate the virtualenv's activate, because we can't source things in direnv
export VIRTUAL_ENV="$PROJ_VENV"
export PATH="$PROJ_VENV/bin:$PATH:$PWD"
export PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"
export PYTHONPATH="$PWD/src"

This example automatically creates a Python3 virtualenv for the project if it doesn’t exist yet, and installs the dependencies. Since we can only export environment variables directly, I’m emulating the virtualenv’s bin/activate script by setting some Python-specific variables and exporting a new prompt.

Now when we change to the project’s directory, or any underlying directory, direnv tries to activate the environment:

fboender @ jib ~ $ cd ~/Projects/fboender/foobar/
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.

This warning is to be expected. Running random code when you switch to a directory can be dangerous, so direnv wants you to explicitly confirm that it’s okay. When you see this message, you should always verify the contents of the .envrc file!

We allow the .envrc, and direnv starts executing the contents. Since the python virtualenv is missing, it automatically creates it and installs the required dependencies. It then sets some paths in the environment and changes the prompt:

fboender @ jib ~ $ direnv allow
direnv: loading .envrc
Creating new environment
Already using interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /home/fboender/.pyenvs/foobar/bin/python3
Also creating executable in /home/fboender/.pyenvs/foobar/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
Installing requirements
Collecting jsonxs (from -r ./requirements.txt (line 1))
Collecting requests (from -r ./requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/49/df/50aa1999ab9bde74656c2919d9c0c085fd2b3775fd3eca826012bef76d8c/requests-2.18.4-py2.py3-none-any.whl
Collecting tempita (from -r ./requirements.txt (line 3))
Collecting urllib3<1.23,>=1.21.1 (from requests->-r ./requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/63/cb/6965947c13a94236f6d4b8223e21beb4d576dc72e8130bd7880f600839b8/urllib3-1.22-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests->-r ./requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests->-r ./requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/7c/e6/92ad559b7192d846975fc916b65f667c7b8c3a32bea7372340bfe9a15fa5/certifi-2018.4.16-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests->-r ./requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/27/cc/6dd9a3869f15c2edfab863b992838277279ce92663d334df9ecf5106f5c6/idna-2.6-py2.py3-none-any.whl
Installing collected packages: jsonxs, urllib3, chardet, certifi, idna, requests, tempita
Successfully installed certifi-2018.4.16 chardet-3.0.4 idna-2.6 jsonxs-0.6 requests-2.18.4 tempita-0.5.2 urllib3-1.22
direnv: export +PYTHONPATH +VIRTUAL_ENV ~PATH
(foobar) fboender @ jib ~/Projects/fboender/foobar (master) $

I can now work on the project without having to manually switch anything. When I’m done with the project and change to a different dir, it automatically unloads:

(foobar) fboender @ jib ~/Projects/fboender/foobar (master) $ cd ~
direnv: unloading
fboender @ jib ~ $

And that’s about it! You can read more about direnv on its homepage.

The text of all posts on this blog, unless specificly mentioned otherwise, are licensed under this license.