Category Archives: unix

Proxying Camlistore through nginx

I’ve went through this in order to secure access to Camlistore and delegate authorization to nginx. This doesn’t help, as I don’t yet have a securely stored password set up to protect it, but the first steps are there. Moving to something like LDAP-backed authorization for authentication on my machine and authentication of Camlistore is probably the way to go.

Without further ado, here is my partial nginx configuration, which should be useful if you already have a domain set up and you’d just like to direct toward Camlistore. I didn’t want to set up a subdomain, as I would have to get a new SSL certificate.

I’m bound to have made a mistake in configuration, so comments are welcome.

server {
        access_log /var/log/nginx/ivan.vucica.net_access.log;
        error_log /var/log/nginx/ivan.vucica.net_error.log;
        root /somewhere/on/my/disk;
        listen 80;
        # skipped...

        location /camli {
                return 302$request_uri;
server {
        access_log /var/log/nginx/ivan.vucica.net_access.log;
        error_log /var/log/nginx/ivan.vucica.net_error.log;
        root /somewhere/on/my/disk;
        listen 443 ssl;
        # skipped...

        location /camli {
                return 302 $scheme://$request_uri;

        ssl_certificate /ssl/directory/on/my/disk/;
        ssl_certificate_key /ssl/directory/on/my/disk/;
        # ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        # ssl_ciphers         HIGH:!aNULL:!MD5;

        # from:
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        # for ssl cache - see 
        keepalive_timeout   70;
server {
        access_log /var/log/nginx/ivan.vucica.net_camli_access.log;
        error_log /var/log/nginx/ivan.vucica.net_camli_error.log;
        root /somewhere/on/my/disk;
        listen 3180 ssl;

        location /camli {
                rewrite ^/camli/(.*) /$1 redirect;
                rewrite ^/camli$ / redirect;
        location / {
                proxy_connect_timeout 5;

                # not using after all, as it would need access to /etc/shadow.
                # see
                # auth_pam "Secured Camli";
                # auth_pam_service_name "nginx";

                auth_basic "Secured Camli";
                auth_basic_user_file /path/to/ivucica-camli-user_file;

        ssl_certificate /ssl/directory/on/my/disk/;
        ssl_certificate_key /ssl/directory/on/my/disk/;
        # ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        # ssl_ciphers         HIGH:!aNULL:!MD5;

        # from:
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        # for ssl cache - see 
        keepalive_timeout   70;

Camlistore itself is configured to listen only on It doesn’t handle authentication, as using localhost authentication would require running nginx and camlistored under the same user. Adding a username+password authentication and using internal SSL would limit my long-term options for configuring authentication.

    "auth": "none",
    "listen": "localhost:3179",
    "identity": "AC5742DD",
    "identitySecretRing": "/path/to/camlistore/identity-secring.gpg",
    "blobPath": "/path/to/camlistore/blobs",
    "sqlite": "/path/to/camlistore/camli-index.db",
    "baseURL": "",

    "shareHandler": true


To generate the .htpasswd file, refer to nginx documentation. Here follows an example; consider hard whether this is secure enough and appropriate for you.

printf "John:$(openssl passwd -crypt V3Ry)\n" >> .htpasswd # this example uses crypt encryption

Don’t forget that this will store the line in your .bash_history. (One way to avoid this specific issue is to prefix the command line with a space. Think hard whether this is enough for you.)

Mails appearing from d1stkfactory

If you have a Debian machine and emails appear to be coming from hostname @d1stkfactory, edit /etc/mailname and set this to your actual FQDN. Another instance where I found it locally is in /etc/exim4/update-exim4.conf.conf, which is almost certainly not read by my installation of Postfix (which does explicitly refer to /etc/mailname in one place).

This appeared on a machine running on DigitalOcean, so I presume “d” refers to DigitalOcean, and “factory” refers to their internal disk image building service. That’s just speculation though.

Ubuntu, touchscreen and dualscreen: HD Touchscreen on the left, laptop on the right

If you read about calibrating touchscreen with X11 and are capable of simple addition and division, you won’t have a problem building the transformation matrix and applying it. I won’t cover the same details on how to set the matrix using xinput set-prop since I just want to write down the resulting matrix and, perhaps, save people some time if they have a setup similar to mine.

To get the name of the device, open Terminal and punch in:


In the output I found that my “Acer T232HL”‘s input component is actually called “Advanced Silicon S.A CoolTouch(TM) System”. I can see all of its properties with:

xinput list-props Advanced Silicon S.A CoolTouch(TM) System

Since I’ve set up the screen to be on the left site, that means top-left corner of my touch area is simply offset by 0,0, and bottom-right is 1920,1080. Considering that the total width of the usable X area is 1920+1280, I get 1920/3600=0.6 as the c0 constant on the above link.

My usable area’s height is max(1080, 800) (the respective y component of the resolutions of the two displays). Considering that touch area’s height is also 1080, then the c2 component does not need to be scaled and should be exactly 1.

I also have absolutely no offsets, so c1 and c3 stay 0.


xinput set-prop "Advanced Silicon S.A CoolTouch(TM) System" --type=float "Coordinate Transformation Matrix" 0.6 0 0 0 1 0 0 0 1
# And if needed, to make the display configured as described above:
xrandr --output DP-0 --auto --left-of LVDS-0

From the times when I was trying to get Linux to run on iPaq H3800 devices using the kernel and distributions published at the now-defunct, I remember the “tslib” which included a touchscreen calibration tool. I wonder if that can and should be used to calibrate the modern multitouch displays.

Update (April 5th 2014): I just dug out package ‘xinput_calibrator’ by random googling, but have not tried it out yet.

A few notes on Camlistore

(Useful as of April 7 2014, git commit 6842063f7c1ff6ae47e302b50b6a5030867cc2cd)

I was playing a bit with Camlistore and I like what I see. The presentation of Camlistore on FOSDEM 2014 done by Brad Fitzpatrick is quite insightful.

Here’s just a few notes so I don’t forget the caveats etc. I didn’t use a completely clean machine, so these are not instructions completely vetted up for public consumption. I presume a Debian Wheezy machine. Leave comments below, or mail me at blogの

Installing Go

Camlistore depends on Go language, at least Go 1.1. To install on Debian, as of early 2014 you need to use testing or unstable distributions. Here’s my /etc/apt/sources.list:

deb wheezy main
deb wheezy/updates main

deb testing main
deb unstable main

Here’s my /etc/apt/preferences.d/prioritize-stable (I prefer to use stable):

Package: *
Pin: release a=stable
Pin-Priority: 950

Package: *
Pin: release a=testing
Pin-Priority: 900

Package: *
Pin: release a=unstable
Pin-Priority: 800

Then use aptitude to choose golang version from testing. Hit e to use automated conflict resolver. With r, mark unsatisfactory solutions, then use , and . to browse different resolutions. At some point you’ll be offered correct installation of dependencies for golang. Hit ! to apply, then hit g twice to install.

Installing Camlistore

Nearly straight from the website:

git clone
cd camlistore/
go run make.go

If instructed to install any packages, do so. I know I was requested to install sqlite3 libraries.

Start camlistored:


You’ll automatically get default config placed at ${HOME}/.config/camlistore/server-config.json and secret keyring at ${HOME}/.config/camlistore/identity-secring.gpg.

Interesting locations

  • ${HOME}/camlistore – you installed Camlistore here
  • ${HOME}/.config/camlistore – configuration files
  • ${HOME}/var/camlistore – blobstore

Preparing clients

Again taken from GettingStarted document and modified.

Upon startup, camlistored should have output the GPG key to use in the command below. For me, it was third line:

2014/03/04 23:26:24 Generated new identity with keyId "F300546B" in file /home/ivucica/.config/camlistore/identity-secring.gpg

Use this here:

./bin/camput init --gpgkey ${REPLACE_WITH_GPG_KEY}

Your new client configuration file should be at ${HOME}/.config/camlistore/client-config.json.

You’ll get output like this:

2014/03/04 23:29:29 Your Camlistore identity (your GPG public key's blobref) is: sha1-0b40618f0b2f6ff90ede6dc4ca7c5231eedf508b
2014/03/04 23:29:29 Wrote "/home/ivucica/.config/camlistore/client-config.json"; modify as necessary.

Web UI

Web UI will be available at http://${hostname}:3179. If accessing from local machine, use http://localhost:3179.

If you are visiting from a remote server, edit ${HOME}/.config/camlistore/server-config.json and under auth set this: userpass:alice:secret:+localhost (replace ‘alice’ and ‘secret’). This uses the completely insecure PLAIN authentication; use this only as a last resort. If you absolutely need this, you should consider turning on HTTPS, too, or reverse-proxying using nginx with HTTPS, so that you’re at least not leaking the password over the wire. Your password is also, obviously, stored locally in plaintext. This is all a BAD idea, but okay for testing.

Uploading blobs, files and directories

./bin/camput blob bin/README  # uploads a raw blob with no metadata; no filename, no nothing

./bin/camput blob bin/README  # note -- same output

BLOBHASH=$(./bin/camput blob bin/README)  # store hash in a variable...
./bin/camget ${BLOBHASH}  # ... then get this blob and print it out:
This is where Camlistore binaries go after running "go run make.go" in
the Camlistore root directory.

./bin/camtool list  # observe: just one blob, size 102
sha1-4a8b6d44e3030bf36f39f0e0415209f8319ce019 102

./bin/camput file bin/README  # uploads file data + creates metadata blob

./bin/camtool list  # Note, no new content blob (content is the same) -- but there is the metadata blob
sha1-129583b2870e357b17468508c4b8345faf228695 356
sha1-4a8b6d44e3030bf36f39f0e0415209f8319ce019 102

./bin/camget sha1-129583b2870e357b17468508c4b8345faf228695
{"camliVersion": 1,
  "camliType": "file",
  "fileName": "README",
  "parts": [
      "blobRef": "sha1-4a8b6d44e3030bf36f39f0e0415209f8319ce019",
      "size": 102
  "unixGroup": "ivucica",
  "unixGroupId": 1000,
  "unixMtime": "2014-03-04T23:21:29.152341812Z",
  "unixOwner": "ivucica",
  "unixOwnerId": 1000,
  "unixPermission": "0644"

This file is not a permanode so it didn’t appear in the web UI.

./bin/camput file --permanode bin/README

Now if you visit the WebUI, you’ll see the file appeared there. (You may also see it appear live if you had the web UI open.)

First hash is the file metadata, second is a claim, and the third one is the permanode itself, which you can use in the web UI to reach the content.

What is a claim? Quoting:

If you sign a schema blob, it’s now a “signed schema blob” or “claim”. The terms are used pretty interchangeably but generally it’s called a claim when the target of the schema blob is an object’s permanode (see below).

Signing involves claiming interest by a user over a blob. Signing is done with the previously created GPG key. It is my probably incorrect understanding that blobs without owners could be garbage collected. I can’t find the documentation to verify this; please leave a comment or email me whether this is correct or incorrect.

To upload a directory and simultaneously provide a title and some tags, as well as create a permanode:

./bin/camput file --permanode --title="Camlistore Documentation" --tag=documentation,camlistore ./doc/

Search system’s camtool describe

Ask the search system about an object:

  "meta": {
    "sha1-75d3db43c8b07bf82d601d65375ec64f7769a4bf": {
      "blobRef": "sha1-75d3db43c8b07bf82d601d65375ec64f7769a4bf",
      "camliType": "permanode",
      "size": 562,
      "permanode": {
        "attr": {
          "camliContent": [
          "tag": [
          "title": [
            "Camlistore Documentation"
        "modtime": "2014-03-04T23:55:05.941276174Z"

Mounting Camlistore filesystem

You won’t be mounting the Camlistore filesystem; you’ll be mounting a Camlistore filesystem. But first, we need to prepare you a bit.

cammount uses FUSE. Mounting (and FUSE) needs appropriate root-level permissions to, well, mount a filesystem. So, let’s use sudo -E (-E to maintain ${HOME} et al so Camlistore can find configuration)?

Not so fast. The localhost auth that is still used here is doing checks on several levels. First, you need to be on the local host (check!). Second, the socket connecting to camlistored needs to come from the same UID as the one that is running camlistored. Your sudo‘ed cammount would be running with UID=0; your camlistored runs under 1000 or more. (Presuming Debian Wheezy here.) So, camlistored rejects the auth. Don’t bother sudo‘ing camlistored; it doesn’t want to be run as root.


sudo -E adduser ${USER} fuse

Yes, you just add the user to the fuse group. You now need to create a new login session (e.g. log out and log in is fine) so the appropriate subsystems notice you are a member of a new group. (“Hey, you never need to reboot Linux.”)

Alright, now we’re good to go. Find the hash of a permanode you want to mount. You can use web UI to do so. It’ll even have a handy instruction on what to do! Quoting from web ui:

./bin/cammount /some/mountpoint sha1-ff227e6af6647d2c3958824a036d7a362a89d675

Or more sanely:

mkdir -p mountpoint/
./bin/cammount mountpoint/ sha1-ff227e6af6647d2c3958824a036d7a362a89d675

Open a new session, and observe how there is actual content in the mountpoint/ directory!

After shutting down cammount with ctrl+c, you might need to unmount using:

fusermount -u mountpoint/

Use mount to see if you need to do that.

If you skip the permanode, you’ll get a special filesystem with virtual directories such as at, date, recent, roots, tag… and even though you can’t see that directory, you can cd sha1-ff227e6af6647d2c3958824a036d7a362a89d675 and see the same directory as before.

Closing notes

  • I haven’t looked at alternative indexing engines or alternative blobstores. For example, Amazon S3, Google Drive, Google Cloud Storage, …
  • I haven’t looked at blobstore sync.
  • I haven’t managed to correctly use ‘publishing’, especially for /pics/ (which is an example given in the documentation).
  • I haven’t shown you camput attr which sets custom attributes on permanodes.
  • I find the idea of importers, especially IMAP importers, very appealing. The Flickr one is already there. An IMAP importer (at 51:40) and an IMAP server (at 51:57) was mentioned in the FOSDEM 2014 talk.
  • I also find the idea of a built-in SMTP server quite appealing (mentioned at 32:12).

Given that the Camlistore filesystem is mountable and splits files into chunks a-la GFS (although in chunks that are far smaller in size than 64MB quoted in the GFS whitepaper), and given that the talk was given as recently as February 2014, and given that there is enthusiasm on author’s side, I’m really looking forward to something that could truly grow into a personalized distributed filesystem.

OS X’s Terminal: Getting Home, End, PgUp, PgDn to work

Apple’s Terminal on a Macbook requires a weird combination of fn+shift+left/right, fn+shift+up/down to get Home, End, PgUp and PgDn to work. And that still causes issues in a couple of places.

Despite maintaining my philosophy of “use defaults wherever possible”, I’ve decided to ditch iTerm and iTerm2 for a simple reason: after quitting from Apple’s Terminal, upon restart in Lion I get a screenful of information from my previous session. Quite handy if I had to restart a machine for some reason, but I don’t want to lose the context!

Here are two fixes found Francois Planque’s post.

First part involves fixing the escape sequences sent by the Terminal. Open Preferences (for example, by hitting Cmd+,), and navigate to Settings tab, then for the profile you want to adjust, navigate to Keyboard tab.

Over there, define the following escape sequences upon pressing home, end, page up and page down:

home: \033[1~
end: \033[4~
page up: \033[5~
page down: \033[6~

If you mess up something during input, use your mouse to hit the button “Delete one character”. To get \033 in the dialog box, just press the Escape key instead of typing backslash, zero, three, three.

After applying this, voila! vim and mc now type these keys correctly.

But, you’ve just messed up bash.

Second fix involves editing ~/.inputrc (or /etc/inputrc). Neither of these rc files existed on my machine. From Garret LeSage‘s blog post (and as suggested in a comment on Francois’s blog), I simply copy pasted the following:

"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word
set completion-ignore-case On

It’s nice to see an OS X-related tech post that’s still as useful in 2012 as it was in 2005. And it’s even nicer to see that it was originally intended for other UNIX and UNIX-style systems.

By the way: this post’s ID is 2 * 333. Make of it whatever you want. :-)

Why GNU/Linux is not successful on desktops

I used Debian for a long time. I used it as a desktop OS. I did a lot of development and tinkering. I don’t have time for tinkering anymore, and I was lucky enough to get a Mac.

I was inspired to write this short outline of my views why GNU/Linux is, sadly, not right for an average user on the desktop, by a tweet from @ivan_gustin (retweeted by @ambivalentcase) that mentioned Linus Torvalds’ thoughts on the same subject from LinuxCon Europe 2011.

Let me point out: I WANT STRONG LINUX. I want freedom, I want power. What I don’t want is ground slipping below my feet.

Technical issues

Torvalds is spot on here. You can’t give the end-user a machine that might or might not work. Things are extremely improved here, and were already good back in 2006.

Greatest issue, however, are regressions and constant feeling of land moving under user’s feet. I can’t in good faith press that “update” button and be nearly certain that the machine will work after the update is performed. Ubuntu is doing very well here if you update within the same release. Next release may or may not work. However, I have had almost no upgrade of a graphics card driver that didn’t require some sort of tinkering in console afterwards and messing with Xorg.conf.

Linux is awesome because it recognizes almost every piece of software that you throw at it.

User interface keeps changing

Look at OS X Tiger. Then look at OS X Leopard. Then look at OS X Snow Leopard. Then look at OS X Lion.

If you go from one version to the next one, you get the user experience that is different, but not very different. Apart from performance issues, what was a major adoption blocker for Windows Vista? A radical reworking of the UI.

People don’t like changes to UI that are forced on them. If I just want, for example, a better mail client that let’s-say comes with Ubuntu 11.04, why am I expected to get used to Ubuntu Unity? If I just want the terminal to keep working and be improved, why do the GNOME team force me to upgrade not just the terminal, but the entire desktop, if I want a complete and integrated user experience? Oh, and that new desktop environment in GNOME 3 is, of course, completely different from GNOME 2.

And GNOME 3 and Ubuntu Unity are just reruns of the KDE 4 saga.

KDE 4 decided to make everything modular. GNOME 3 and Ubuntu Unity decided to develop a UI that is usable on both tablets and desktops. What happens next? Someone bright decides that desktop users must use a media center-like interface?

Features that disappear

I really don’t like it when a package suddenly gets removed from Debian. Remember XMMS? A beautiful clone of Winamp whose only flaw was that it was written with GTK1. Someone thought it was a good idea to rewrite it as a server that plays the music, and a client that controls the playing and called this XMMS2. End-user’s client was, of course, seriously flawed and buggy, and its only boon was that it was written with GTK2. (That didn’t help it, because it was unskinnable and it was ugly.) Debian removed original XMMS because it was “unmaintained”. Great move!

Same thing happened to BitchX. Users who realized this were directed to use other command line IRC clients, such as irssi, which is far less usable and far uglier. At least to me.

Things changing, changing, changing, moving around, breaking down

I’m not exactly a kid anymore. I don’t have time or will to continuously tinker with stuff I already tinkered with. I just want things to work.

I don’t want to worry about packages conflicting.
I don’t want to worry that after an upgrade, a package will be removed due to a conflict.
I don’t want to worry that after an upgrade, my graphics card and my wireless card suddenly stop working because, hey, the kernel was upgraded and previously installed modules no longer work with the new kernel.
I don’t want to worry that after an upgrade, I will have to relearn basically everything because some dimwit decided to “fix” what was not broken: the previously extremely usable UI.
I don’t want to worry that after an upgrade, no icons appear on my desktop.

Applications and features

Hello. Meet my friend, Anna. She’s a graphics artist. She heavily uses Photoshop on a Mac. She needs, at the very least, effects applied on layers. She also needs to work with other designers’ PSD files.

What option does she have on Linux? GIMP? Seriously?

I can use GIMP. I like GIMP. Unfortunately, Anna cannot.

Hello. Meet aunt Silvia. She’s a 60 year old woman taught to work with Microsoft’s Word 2007 for Windows.

Can she use either Word for Mac, or OpenOffice? Let me tell you, she cannot.

You cannot force her to use it. She does not want to learn, even if she will pirate the software. (She does not understand that your refusal to install pirated Windows and Office is a moral choice. She will think you are a jerk.)

Hello. Meet Tom. Tom writes a lot of documentation. Tom got used to one thing that Macs do really well: drag and drop. He grabs almost anything, drags it, presses F3 to show Exposé, points to a window, presses space so he doesn’t have to wait for the window to be zoomed into, and drops it.

It works great with, for example, word processing.

Screenshotting is also nice. Keyboard shortcut is extremely nasty and unergonomic, but being able to get any portion of a screen, or a nice image of a window (complete with a shadow) is just a few keytaps away, and it’s integrated into what would be a “window manager” under GNU/Linux or other X11 environments. You can easily get the screenshot in a file on the desktop, or you can get it into the clipboard for quick pasting into the mail client.

And under GNU/Linux, you have to worry if dragging-and-dropping, copying-and-pasting will even work between programs under same desktop environment — situation is way worse when you have to do content exchange between different environments. Can I be sure that an image put into clipboard under Konqueror will be pasteable into GIMP or Thunderbird?

Exposé doesn’t seem useful until you realize how useful it is with drag-drop, especially when you press space. I can’t remember any use for desktop cube effect except that it made me feel warm deep inside. (Yep, I still love desktop cube. Sometimes I perform ‘switch user’ on OS X just to watch the default desktop cube animation.)

Hello. Meet me. I’m a developer, and what I’m about to say is unfair. I love Objective-C. I love the concept of building the UI in an Interface Builder. I don’t need Objective-C per se, as long as I can use similar software building practices.

Java seems awfully close.

Except it isn’t. It’s static and restrictive where it shouldn’t be.

GNUstep folks are great, and they’re doing great job. But they don’t really have the resources to build a good IDE, nor prepare good introduction for new Objective-C developers. C++ developers have the very nice Code::Blocks/, which is wonderful, until you need to develop a GUI app.

I also want to sell my software. I love doing free software/open source work, but sometimes a person has to live off something. My end users expect good quality packaging, an easy to install app, and support that will last even if I don’t update the app manually. Developer portal for Ubuntu is an excellent step forward for distribution, but building a quality .deb package is still difficult. Intel’s AppUp is confusing and little-known. I’m also from Croatia — can you folks send me cash to my country? (AppUp had issues with that — or so I’m told.)

Hello. Meet Harry. He’s a 14-year old gamer who wants to play StarCraft II, Call of Duty: Modern Warfare 2 and Portal 2.

I’ve had mostly bad experiences with Wine. Sure, you can play singleplayer original StarCraft. You can even play it in multiplayer! However, what if something goes wrong? Also, have you tried playing using

Have you tried playing Rise of Nations? Have you tried any other old title that uses DirectPlay? Did you see how many titles work, but their installers don’t work?

What happens when Harry’s graphics card drivers don’t start? Does he want to worry whether or not he may update nVidia’s drivers? Does he want to worry where the installer will put the launch icons? What happens when the .desktop file (the shortcut for launching apps) doesn’t work? I can probably get the title to work with Wine, but will Harry be able to?

And let me tell you, Harry won’t be happy when the 60 EUR game he just bought doesn’t work and he has to tinker with the computer to get it to run.


Who is GNU/Linux for?

Enthusiasts and people who use computers only for Skype, surfing, mail.

That’s not the massive user base that pushes the desktops and desktop usage forward. User base that pushes desktops and desktop usage forward are home power users, gamers, business users, artists, developers. Even a person who can do word processing with one package cannot use it with another these days.

And you know what “people who use computers only for Skype, surfing, mail” can use?

A tablet or (shudder) a netbook.

Either an Android tablet, an iPad or a Chromebook will do for them.


* Stabilize the UI. (Apple faced backlash for its reworking of scrollbars.)
* Be careful before making drastic incompatibility moves. (Apple faced backlash for removing Rosetta, breaking TurboTax 2007.)
* Stabilize the ABI. (Apple often ships very old versions of libraries. Removing Rosetta allowed removal of old PowerPC-only code.)
* Help the developers. (You are a free software enthusiast and that’s fine. But don’t think everyone is. If I want to ship paid software, and I have a market, don’t lock me out.)

Don’t break stuff, don’t change stuff. Help the dev.

I admire Linux Game Publishing‘s struggle in face of licensing issues (for example, SDL’s LGPL), in face of incompatibility, in face of historic disregard for ABI. It’s difficult to package executables that are easily relocatable to different places in the filesystem – because, since the software is open source, you can simply recompile the program for the new location. (Dependency on dynamic libraries put in fixed locations is the biggest issue.)