Creating a personal apt repository using `dpkg-scanpackages`

From time to time, I build and backport deb packages. Most of them are for my personal use, but sharing them would be nice. Another advantage of setting up a personal repository over directly installing deb files is that you can install dependencies from that repository automatically. This is especially useful if one source package builds multiple binary packages that depend on one another.

There is a list of ways to set up such a personal repository in the Debian wiki. However, I found most of them to be too cumbersome for my limited requirements. The way I’m describing below is probably the simplest and easiest way to get up and running.

The first thing to do is install dpkg-dev, which provides dpkg-scanpackages.

sudo apt install dpkg-dev

Next, put the deb files you created in some local repository, such as /usr/local/debian, and cd into it.

# dpkg-scanpackages -m . | gzip -c > Packages.gz

This will scan all the *.deb files in the directory and create an appropriate Packages.gz file. You need to repeat this step whenever you add new packages to /usr/local/debian.

Finally, to enable the new local repository, add the following line to /etc/apt/sources.list:

deb [trusted=yes] file:///usr/local/debian ./

The [trusted=yes] option instructs apt to treat the packages as authenticated. Alternatively, if you want to share it with others, make sure that your web server serves the directory and point to it:

deb https://www.guyrutenberg.com/debian/jessie ./

(You will need apt-transport-https in order to use HTTPS repositories.)

Don’t forget to apt update before trying to install packages from the new repository.

Playing Opus Files on Android Marshmallow (6.0)

The Opus codec provides superior audio quality over codecs such as AAC, MP3, and Vorbis. Android has supported Opus since Android 5.0 (Lollipop). However, when I tried playing Opus files on my LG G4, it wouldn’t recognize the file as a media file at all. It turns out that the default .opus extension is not recognized by Android. The workaround is to change the extension to .ogg. Generally speaking, this is technically correct, as most Opus streams are encapsulated in an Ogg container; however, .opus is the recommended extension (but apparently not for Android).

Fixing HTML Rendering in Wine on Debian Jessie

Some applications rely on Internet Explorer to provide HTML rendering capabilities. Wine implements the same functionality based on a custom version of Mozilla’s Gecko rendering engine (the same engine used in Firefox). In Debian Jessie, you have a package called libwine-gecko-2.24 (the version is part of the name), which provides this rendering engine for Wine. However, different versions of Wine require different versions of wine-gecko. The package provided in Debian Jessie matches the Wine version provided by wine-development from the main Jessie repository (1.7.29). Unfortunately, wine-development from jessie-backports is version 1.9.8 and requires wine-gecko version 2.44, which is not provided by any Debian repository. This will lead to errors like

Could not load wine-gecko. HTML rendering will be disabled.

and blank spaces where HTML content would be rendered in many applications.

The solution is to manually install the required version of wine-gecko. We start by downloading the MSI binaries provided by Wine:

$ wget https://dl.winehq.org/wine/wine-gecko/2.44/wine_gecko-2.44-x86.msi
$ wget https://dl.winehq.org/wine/wine-gecko/2.44/wine_gecko-2.44-x86_64.msi

Now install the required one, based on whether you are using a 32-bit or 64-bit Wine environment:

wine-development msiexec /i wine_gecko-2.44-x86.msi

(Be sure to set the correct $WINEPREFIX if needed.)

Greasemonkey: Fix links to PDFs in Bank Hapoalim

This fixes both the links to the PDFs and the embedding in the mailbox. Click on “View Raw” to install.

// ==UserScript==
// @name Bank Hapoalim
// @description Workaround bugs in Bank Hapoalim website to display pdf messages.
// @author Guy Rutenberg
// @namespace http://www.guyrutenberg.com
// @include https://login.bankhapoalim.co.il/portalserver/mailInbox#/folders/0
// @include https://login.bankhapoalim.co.il/ng1-portals/rb/he/mails#/folders/0
// @run-at document-idle
// @version 1.1
// @grant none
// ==/UserScript==
//
// @include url should be the url of the inner iframe containing the list of mails.
var MutationObserver = window.MutationObserver;
var myObserver = new MutationObserver (mutationHandler);
var obsConfig = {
childList: true, attributes: false,
subtree: true,
};
var target = document.getElementsByTagName('mail-manager')[0];
myObserver.observe (target, obsConfig);
function mutationHandler (mutationRecords) {
console.log('here');
mutationRecords.forEach ( function (mutation) {
for (var item of mutation.addedNodes) {
if (item.tagName == 'PDF-VIEWER') {
var url = 'https://login.bankhapoalim.co.il' + item.getAttribute('pdf-show');
iframe = item.querySelector('iframe');
iframe.src = url;
}
}
});
}

Lossless JPEG rotation

JPEG is a lossy format, and naive rotation results in a loss of quality. JPEG does allow some lossless operations, such as rotation by 90 degrees and flipping, on the basic blocks (MCUs) that compose the image. It also allows re-arranging those blocks. Using this lossless operation, it is possible to perform a lossless JPEG rotation. To do so, the rotated image must meet some basic criteria, such as having its size be a multiple of the MCU size (usually 16×16).

Not all programs perform a lossless JPEG rotation, so it is useful to be aware of which ones do. I checked a couple of commonly used programs to see if they indeed perform lossless rotation. The testing procedure was:

  1. Start with the original JPEG photo.
  2. Rotate it once to the right using each program.
  3. Rotate a copy of the rotated photo back to the right using the same program.
  4. Compare the results using ImageMagick (compare -metric ae).

Results

Gnome’s Image Viewer 3.14.1 is lossless.
digiKam (4.4.0) is lossless; however, rotating with digiKam’s Image Editor is lossy.
Shotwell (0.20.1) does lossy rotation.

en_IL: English locale for Israel

Update: The new locale was committed to glibc and should be part of glibc-2.24.

Most Israelis are literate in English, and for a large percentage of them, English is also the preferred language when it comes to computers. They prefer English because it solves right-to-left issues and general inconsistencies (it might be annoying when some programs are translated and some are not). The downside is that, currently, the existing English locales are not suitable for Israel, as there are cultural differences:

  • American English spelling is more common in Israel.
  • The metric system is used, along with the relevant paper sizes (“A4” instead of Letter).
  • Dates are written in dd/mm/YYYY format, unlike in the USA.
  • The first day of the week, and also the first workday, is Sunday.
  • The currency used is ILS (₪).

So, up until now, users had to choose locales such as en_US or en_GB and compromise on some stuff. To solve this issue and create a truly suitable English locale for Israel, I wrote a localedef file for the en_IL locale.

To install the new locale, copy the en_IL file from the gist below and place it under /usr/local/share/i18n/locales/en_IL (no extension). Next:

# echo "en_IL.UTF-8 UTF-8" >> /usr/local/share/i18n/SUPPORTED

Now complete the installation by running dpkg-reconfigure locales, then enable en_IL.UTF-8 from the list and set it as the default locale.

comment_char %
escape_char /
% This file is part of the GNU C Library and contains locale data.
% The Free Software Foundation does not claim any copyright interest
% in the locale data contained in this file. The foregoing does not
% affect the license of the GNU C Library as a whole. It does not
% exempt you from the conditions of the license if your use would
% otherwise be governed by that license.
% Locale for English locale in Israel
% Contributed by Guy Rutenberg <guyrutenberg@gmail.com>, 2016
LC_IDENTIFICATION
title "English locale for Israel"
source "Free Software Foundation, Inc."
address "http:////www.gnu.org//software//libc//"
contact ""
email "bug-glibc-locales@gnu.org"
tel ""
fax ""
language "English"
territory "Israel"
revision "1.1"
date "2016-04-19"
%
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_COLLATE
category "i18n:2012";LC_TIME
category "i18n:2012";LC_NUMERIC
category "i18n:2012";LC_MONETARY
category "i18n:2012";LC_MESSAGES
category "i18n:2012";LC_PAPER
category "i18n:2012";LC_NAME
category "i18n:2012";LC_ADDRESS
category "i18n:2012";LC_TELEPHONE
category "i18n:2012";LC_MEASUREMENT
END LC_IDENTIFICATION
LC_CTYPE
copy "en_GB"
END LC_CTYPE
LC_COLLATE
copy "en_GB"
END LC_COLLATE
LC_MONETARY
copy "he_IL"
END LC_MONETARY
LC_NUMERIC
copy "he_IL"
END LC_NUMERIC
LC_TIME
abday "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/
"<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/
"<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/
"<U0053><U0061><U0074>"
day "<U0053><U0075><U006E><U0064><U0061><U0079>";/
"<U004D><U006F><U006E><U0064><U0061><U0079>";/
"<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/
"<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
"<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
"<U0046><U0072><U0069><U0064><U0061><U0079>";/
"<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>"
abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/
"<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
"<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/
"<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/
"<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/
"<U004E><U006F><U0076>";"<U0044><U0065><U0063>"
mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/
"<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
"<U004D><U0061><U0072><U0063><U0068>";/
"<U0041><U0070><U0072><U0069><U006C>";/
"<U004D><U0061><U0079>";/
"<U004A><U0075><U006E><U0065>";/
"<U004A><U0075><U006C><U0079>";/
"<U0041><U0075><U0067><U0075><U0073><U0074>";/
"<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
"<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
"<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
"<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
d_fmt "<U0025><U0064><U002F><U0025><U006D><U002F><U0025><U0079>"
t_fmt "<U0025><U0054>"
am_pm "";"" % 24-hour clock is used
t_fmt_ampm ""
date_fmt "<U0025><U0061><U0020><U0025><U0065><U0020><U0025><U0062>/
<U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U005A><U0020><U0025><U0059>"
week 7;19971130;1
% In Israel Sunday is a workday.
first_workday 1
END LC_TIME
LC_MESSAGES
copy "en_US"
END LC_MESSAGES
LC_PAPER
copy "he_IL"
END LC_PAPER
LC_NAME
copy "en_US"
END LC_NAME
LC_ADDRESS
postal_fmt "<U0025><U0066><U0025><U004E><U0025><U0061><U0025><U004E>/
<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
<U004E><U0025><U007A><U0020><U0025><U0054><U0025>/
<U004E><U0025><U0063><U0025><U004E>"
country_name "<U0049><U0073><U0072><U0061><U0065><U006C>"
country_post "<U0049><U0053><U0052>"
country_ab2 "<U0049><U004C>"
country_ab3 "<U0049><U0053><U0052>"
country_num 376
country_car "<U0049><U004C>"
lang_name "<U0045><U006E><U0067><U006C><U0069><U0073><U0068>"
lang_ab "<U0065><U006E>"
lang_term "<U0065><U006E><U0067>"
lang_lib "<U0065><U006E><U0067>"
END LC_ADDRESS
LC_TELEPHONE
copy "he_IL"
END LC_TELEPHONE
LC_MEASUREMENT
copy "he_IL"
END LC_MEASUREMENT
view raw en_IL hosted with ❤ by GitHub

nginx and SNI

Server name indication (SNI) allows you to serve multiple sites with different TLS/SSL certificates using a single IP address. Nginx has supported SNI for quite some time, and actually setting it up is easy: simply add server entries for the corresponding sites. There is one caveat: the server_name entry must come before the server_certificate for SNI to be activated:

server {
    listen          443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
    ...
}

server {
    listen          443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
    ...
}

is good, but

server {
    listen          443 ssl;
    ssl_certificate www.example.com.crt;
    server_name     www.example.com;
    ...
}

server {
    listen          443 ssl;
    ssl_certificate www.example.org.crt;
    server_name     www.example.org;
    ...
}

will serve the wrong certificate for www.example.org.

WordPress.com Login Loop

Sometimes, when I try to use certain functions on wordpress.com, I get redirected to a login page. After I sign in, I get redirected again to the same login page. This repeats in an endless loop. It usually doesn’t bother me, as I self-host my blog, but for some things, like the yearly annual report that came in about two weeks ago, it does bother me. I looked into the matter, and the issue turned out to be due to blocking third-party cookies. To resolve the endless login loop, you need to add https://wordpress.com (note the https) to the exception list of accepted third-party cookies (in Firefox, it’s under Preferences -> Privacy -> Exceptions).

Skip Updates When Using the Let’s Encrypt `letsencrypt-auto` Client

To use Let’s Encrypt CA to issue free certificates, you need to use their client. The recommended method to install it is to use letsencrypt-auto, a script that automatically fetches and installs all the required dependencies. There is no doubt that letsencrypt-auto is the fastest and simplest way to get a Let’s Encrypt client up and running. I’ve used it myself when I wrote a guide to get Let’s Encrypt up and running easily.

Automatically updating required dependencies has its downside. As letsencrypt-auto does it every time you run it, it quickly gets annoying. Running a simple ./letsencrypt-auto --help takes a whopping 15 seconds just figuring out that there are no updates available. Supposing that you know that no updates are available, and you wish to save some time, you can run the letsencrypt executable directly, skipping the update process of letsencrypt-auto:

~/.local/share/letsencrypt/bin/letsencrypt

Most actions require you to be root, so you might need to run it with sudo.

You can expect this issue to be resolved in the future. There is already an open issue for it and active work that will resolve it.

Installing Debian Unstable’s Source Packages in Debian Jessie

Sometimes a package that you need is not available for Debian Jessie, but you can find it in Sid (unstable). You may be tempted to try to install it manually by downloading the binary deb package, but it will most likely fail due to binary incompatibilities with the different library versions you have. The better method is to get the source package used to build the binary package and build it yourself. Most of the time, the process is not as hard as it sounds.

First, a short preliminary setup is needed. Add the following lines to /etc/apt/sources.list:

deb http://http.debian.net/debian jessie-backports main
deb-src http://httpredir.debian.org/debian unstable main contrib

You can replace unstable with testing if you prefer to use packages from testing. Update the package lists:

sudo apt-get update

Next, you need to get the build dependencies for your package. The example below uses the package lyx:

sudo apt-get build-dep lyx/unstable

Now you are ready to fetch and build the source package:

sudo apt-get source -b lyx/unstable

Finally, you will see the resulting DEBs in the current directory. Simply install them:

sudo gdebi lyx-common_2.1.4-2_all.deb
sudo gdebi lyx_2.1.4-2_amd64.deb

You can later mark the dependencies that you manually installed as automatic:

sudo apt-mark auto lyx-common