nbdkit is a pluggable NBD server with lots of plugins and filters. Two of the plugins handle compressed files (for gzip and xz respectively). We can uncompress and serve a file on the fly. For gzip it’s kind of inefficient. For xz it’s very efficient provided you prepared your xz files ahead of time with a smaller than default block size.
Let’s use nbdkit to loopback mount an xz file:
$ nbdkit -fv xz file=/var/tmp/fedora-28.img.xz
# nbd-client -b 512 localhost /dev/nbd0 Warning: the oldstyle protocol is no longer supported. This method now uses the newstyle protocol with a default export Negotiation: ..size = 6144MB Connected /dev/nbd0 # ls /dev/nbd0p* /dev/nbd0p1 /dev/nbd0p2 /dev/nbd0p3 /dev/nbd0p4 # fdisk -l /dev/nbd0 Device Start End Sectors Size Type /dev/nbd0p1 2048 4095 2048 1M BIOS boot /dev/nbd0p2 4096 2101247 2097152 1G Linux filesystem /dev/nbd0p3 2101248 3360767 1259520 615M Linux swap /dev/nbd0p4 3360768 12580863 9220096 4.4G Linux filesystem # mount -o ro /dev/nbd0p4 /mnt
Of course it’s read-only. To write to a compressed file would involve changing the size of inner parts of the file. Use qcow2 compression if you want a writable compressed file (although writes to that format are not compressed).
Also loopback mounting in general is unsafe. Use libguestfs to safely mount untrusted disk images.
 These should really be filters, not plugins, so that you can chain an uncompression filter into an existing plugin, and one day I’ll get around to writing that.