Dropbox on ZFS in NixOS

May 1, 2019

Tags: nix, nixos

Warning: Use any information on this website at your own risk! Fooling Dropbox may lead to data loss. But you were making backups anyway. Right?

Introduction

Last year, Dropbox has stopped supporting all Linux filesystems except ext4. Since I am on ZFS, ext4 feels like too many steps back. Luckily, the Dropbox client uses fairly superficial filesystem checks, such as using statfs64(2) or reading /proc/filesystems to query the filesystem that the Dropbox folder is on (depending on the client version). Various people have made libraries that can be preloaded to override statfs64 or open64 to circumvent the checks of the Dropbox client. Of course, Dropbox could just warn the user that they are running their client on an unsupported filesystem, but that’s no fun!

Luckily, it is easy to bring Dropbox back to life on non-ext4 filesystems on NixOS with home-manager. It works as follows:

  1. Write a derivation for a library that misleads the Dropbox client, such as libdropbox_fs_fix.
  2. Write a derivation that creates a wrapper for the dropbox script. This wrapper set the LD_PRELOAD variable to preload libdropbox_fs_fix.
  3. Create a XDG entry that autostarts Dropbox using the wrapper.

The derivations in (1) and (2) can be defined in an overlay in e.g. .config/nixpkgs/overlays. The XDG entry (3) can be created through home-manager. Of course, you could also generate the entry in the system-wide NixOS configuration.

The Dropbox overlay

libdropbox_fs_fix is a small library that comes with a simple makefile. We let stdenv.mkDerivation compile the library and provide our own installPhase to copy the library to the output path:

dropbox-filesystem-fix = with super; stdenv.mkDerivation rec {
  name = "dropbox-filesystem-fix-${version}";
  version = "20190417";

  src = fetchFromGitHub {
      owner = "dark";
      repo = "dropbox-filesystem-fix";
      rev = "72f4d04852d5002d9ba29b3f77fbacb2c12d1432";
      sha256 = "03h95lncbw8mss1f67697jl3diiw7iyq6cxqlzgl3xwgxwbhqd0j";
  };

  installPhase = ''
      mkdir -p $out/lib
      cp libdropbox_fs_fix.so $out/lib
  '';

  meta = with stdenv.lib; {
      description = "Fix filesystem detection in Dropbox";
      license = licenses.gpl30;
      platforms = platforms.linux;
  };
};

Next, we use makeWrapper to create a filesystem-agnostic version of Dropbox by wrapping the dropbox script that is provided by the dropbox derivation. However, we prefix the library preload list with libdropbox_fs_fix.so.

dropbox-filesystem-agnostic = with super; stdenv.mkDerivation rec {
  name = "dropbox-fixed";

  buildInputs = [ makeWrapper ];

  unpackPhase = "true";
  installPhase = ''
    mkdir -p $out/bin
    makeWrapper ${pkgs.dropbox}/bin/dropbox $out/bin/dropbox \
      --prefix LD_PRELOAD : ${self.dropbox-filesystem-fix}/lib/libdropbox_fs_fix.so
  '';
};

The full overlay can be found in my home configuration. With the overlay put in place, you could just start Dropbox manually:

$ nix-shell -p dropbox-filesystem-agnostic
$ dropbox

Starting Dropbox automatically

The proper way to start Dropbox automatically differs per desktop environment or window manager. On GNOME, you could create an XDG entry that start GNOME using home-manager:

{
  xdg.configFile."autostart/dropbox.desktop".text = ''
    [Desktop Entry]
    Type=Application
    Exec=${pkgs.dropbox-filesystem-agnostic}/bin/dropbox
    Terminal=false
    Name=Dropbox
    Categories=Network;FileTransfer;
    Comment=Sync your files across computers and to the web
    GenericName=File Synchronizer
    StartupNotify=false
  '';
}