{"id":28794347,"url":"https://github.com/nohajc/anylinuxfs","last_synced_at":"2026-02-08T00:09:17.360Z","repository":{"id":288936272,"uuid":"948758833","full_name":"nohajc/anylinuxfs","owner":"nohajc","description":"macOS: mount any linux-supported filesystem read/write using NFS and a microVM","archived":false,"fork":false,"pushed_at":"2025-06-11T23:42:14.000Z","size":707,"stargazers_count":215,"open_issues_count":3,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-06-12T00:34:35.175Z","etag":null,"topics":["btrfs","container","disk","disk-management","docker","encrypted-data","ext4","filesystem","libkrun","linux","luks","lvm","macos","mount","virtualization","xfs"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nohajc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"ko_fi":"nohajc"}},"created_at":"2025-03-14T22:56:35.000Z","updated_at":"2025-06-10T11:40:10.000Z","dependencies_parsed_at":"2025-05-24T21:25:14.807Z","dependency_job_id":"06357e08-664d-4928-95fe-d9b13255ee8c","html_url":"https://github.com/nohajc/anylinuxfs","commit_stats":null,"previous_names":["nohajc/anylinuxfs"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/nohajc/anylinuxfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nohajc%2Fanylinuxfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nohajc%2Fanylinuxfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nohajc%2Fanylinuxfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nohajc%2Fanylinuxfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nohajc","download_url":"https://codeload.github.com/nohajc/anylinuxfs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nohajc%2Fanylinuxfs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260471671,"owners_count":23014256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btrfs","container","disk","disk-management","docker","encrypted-data","ext4","filesystem","libkrun","linux","luks","lvm","macos","mount","virtualization","xfs"],"created_at":"2025-06-18T02:07:22.045Z","updated_at":"2026-02-08T00:09:17.354Z","avatar_url":"https://github.com/nohajc.png","language":"Rust","readme":"# anylinuxfs\nAn easy way to mount ext4, btrfs or in fact any linux-supported filesystem on a Mac.\nWith full write support, based on the libkrun microVM hypervisor and NFS. Doesn't require installing any kernel extensions or lowering system security.\n\n\u003ca href='https://ko-fi.com/Q5Q41EHAGK' target='_blank'\u003e\u003cimg height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi1.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n\n\u003e [!IMPORTANT]\n\u003e **The VM freezing issue with low RAM has now been fixed!** Make sure you're running libkrun 1.17 or newer (`brew update \u0026\u0026 brew upgrade libkrun`).\n\u003e Then you should have no problem running VMs with less than 1 GB RAM again (see `anylinuxfs config -r`).\n\n## Features\n- mounts any filesystem supported by Linux (**ext4**, **btrfs**, **xfs**, ... but also **NTFS** and **exFAT**)\n- supports **LUKS**-encrypted drives\n- supports **BitLocker**-encrypted drives – **NTFS** or **FAT32** (using your recovery key as passphrase)\n- supports **LVM** (even volume groups spanning multiple drives)\n- supports **LVM on LUKS** (i.e. encrypted LVM)\n- supports **Linux RAID** (mdadm) and **multi-disk btrfs**\n- supports **ZFS** (including native ZFS encryption)\n- works with both external and internal drives\n- works with disk images\n- supports disks with **GPT**, **MBR** or no partition table (single filesystem or LVM/LUKS container)\n- NFS share by default only reachable from localhost but can be shared across network too\n- define your own [custom actions](#custom-actions) (e.g. mount **borg backup** located on a Linux drive)\n\n## Limitations\n- Only one drive can be mounted at a time (this might be improved in the future)\n- Only Apple Silicon Macs are supported (libkrun limitation)\n- Some disks with non-ASCII labels might fail to mount unless a custom mount point with \"safe\" characters is used (this is a macOS bug) \n\n\u003e [!CAUTION]\n\u003e Before using anylinuxfs with **NTFS**, please read [the notes](#ntfs)\n\n## Installation\n```\nbrew tap nohajc/anylinuxfs\nbrew install anylinuxfs\n```\n\n\u003e [!TIP]\n\u003e This is a CLI utility. If you prefer GUI, [there is one](https://github.com/fenio/anylinuxfs-gui) under development.\n\n## Demo\nhttps://github.com/user-attachments/assets/6ec6ce46-ce08-45b9-9fa4-e3d6d078d811\n\n## Introduction\n\nMounting 3rd-party filesystems on macOS has always been tricky. There's official support for reading NTFS but otherwise we've mainly used solutions based on macFUSE.\nWe've got NTFS-3g which is a pretty mature driver but for Linux filesystems there's only a couple of experimental solutions like [fuse-ext2](https://github.com/alperakcan/fuse-ext2) or [ext4fuse](https://github.com/gerard/ext4fuse).\n\nIf you want a reliable solution with write access, you need to run a Linux virtual machine with physical disk access and take care of exposing the mounted filesystem to the host.\nThis is exactly what `anylinuxfs` does and it streamlines it so that it's as easy as running one command in terminal.\n\nYou pick a drive, mount it with `anylinuxfs` and it appears as a NFS share on localhost. This spins up a microVM in the background which uses the real linux drivers, so you can access anything from `ext*` to `btrfs`. Any mount options on the command-line will be forwarded to the linux mount command, so you can mount read-only, read-write, pick btrfs subvolumes, etc. Then you simply eject the drive in Finder or use `anylinuxfs unmount` in terminal and the virtual machine will be turned off.\n\nThis all sounds like a lot of work but it's actually very fast. Not like a traditional virtual machine which takes a while to boot.\nThis one is just a stripped down version of Linux, there's not even a UEFI firmware. Practically, it takes only a couple of seconds before the drive is mounted and ready to use.\n\n## Basic usage\n\nMost often, you will probably use the following commands:\n* `anylinuxfs mount` - mount a filesystem; this is the default command, so the `mount` keyword can be omitted\n* `anylinuxfs unmount` - safe unmount, useful in case of multiple mounts (typically ZFS datasets) which need to be ejected in a particular order\n* `anylinuxfs list` - show available filesystems (`-m`/`-l` shows Microsoft/Linux partitions only)\n* `anylinuxfs status` - show what is currently mounted\n* `anylinuxfs log` - show details about the current (or last) run, useful for troubleshooting\n\n### Mounting filesystems\n\nFrom `anylinuxfs mount --help`:\n```\nUsage: anylinuxfs [mount] [OPTIONS] \u003cDISK_IDENT\u003e [MOUNT_POINT]\n\nArguments:\n  \u003cDISK_IDENT\u003e   File path(s), LVM identifier or RAID identifier, e.g.:\n                 /dev/diskXsY[:/dev/diskYsZ:...]\n                 lvm:\u003cvg-name\u003e:diskXsY[:diskYsZ:...]:\u003clv-name\u003e\n                 raid:diskXsY[:diskYsZ:...]\n                 (see `list` command output for available volumes)\n  [MOUNT_POINT]  Custom mount path to override the default under /Volumes\n```\n\n* The only required parameter is the disk identifier.\n* It must always refer to one or more partitions or logical volumes (not whole disks).\n* Basic syntax of an identifier is `/dev/diskXsY` - based on how `anylinuxfs list` or `diskutil list` identifies your drives.\n* If your filesystem is on a logical volume, you will usually need a special prefixed identifier starting with `lvm` or `raid` (for mdadm Linux RAID).\n  These can be deduced from `anylinuxfs list` output where any logical volumes will be shown as synthesized disks (similar to how `diskutil` does it for APFS containers)\n* In case of btrfs filesystems spanning multiple disks (like RAID1 or JBOD), these will not be grouped in the `anylinuxfs list` output.\n* In order to mount a filesystem like this, you use the `/dev/diskXsY:/dev/diskYsZ` syntax. Basically, you must specify all partitions that need to be attached to our microVM so that they can be scanned for any multi-disk btrfs filesystems.\n\n## Examples\n\n**List available drives with compatible filesystems**\n```\nsudo anylinuxfs list\n```\n\n```\n/dev/disk0 (internal, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:      GUID_partition_scheme                        *500.3 GB   disk0\n   5:                       ext4 BOOT                    1.0 GB     disk0s5\n   6:                      btrfs fedora                  144.2 GB   disk0s6\n\n/dev/disk7 (external, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:     FDisk_partition_scheme                        *30.8 GB    disk7\n   1:                LVM2_member                         30.8 GB    disk7s1\n\n/dev/disk8 (external, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:      GUID_partition_scheme                        *4.2 GB     disk8\n   1:                LVM2_member                         4.2 GB     disk8s1\n\n/dev/disk9 (external, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:                crypto_LUKS                        *8.1 GB     disk9\n\n/dev/disk10 (disk image):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:     FDisk_partition_scheme                        +268.4 MB   disk10\n   1:          linux_raid_member debian:0                267.4 MB   disk10s1\n\n/dev/disk11 (disk image):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:      GUID_partition_scheme                        +268.4 MB   disk11\n   1:          linux_raid_member debian:0                266.3 MB   disk11s1\n\nraid:disk10s1:disk11s1 (volume):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:                       ext4 raid-test               265.3 MB   disk10s1:disk11s1\n\nlvm:vg1 (volume group):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:                LVM2_scheme                        +35.0 GB    vg1\n                                 Physical Store disk7s1\n                                                disk8s1\n   1:                       ext4 lvol0                   15.4 GB    vg1:disk7s1:lvol0\n   2:                        xfs lvol1                   7.7 GB     vg1:disk7s1:lvol1\n   3:                      btrfs lvol2                   11.9 GB    vg1:disk7s1:disk8s1:lvol2\n```\n\n**Mount partition read/write**\n```\nsudo anylinuxfs /dev/disk0s6\n```\n\n**Mount partition read-only**\n```\nsudo anylinuxfs /dev/disk0s6 -o ro\n```\n\n**Mount logical volume from group vg1 backed by disk7s1**\n```\nsudo anylinuxfs lvm:vg1:disk7s1:lvol0\n```\n\n**Mount logical volume from group vg1 backed by disk7s1 and disk8s1**\n```\nsudo anylinuxfs lvm:vg1:disk7s1:disk8s1:lvol2\n```\n\n**Mount RAID volume backed by disk10s1 and disk11s1**\n```\nsudo anylinuxfs raid:disk10s1:disk11s1\n```\n\n**List available drives and decrypt LUKS or BitLocker metadata of disk9**\n```\nsudo anylinuxfs list -d /dev/disk9\n```\n\nOutput will show the encrypted partition filesystem and label\n```\n...\n/dev/disk9 (external, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:          crypto_LUKS: ext4 enc-ext4               *8.1 GB     disk9\n...\n```\n\n**List available drives and decrypt all LUKS or BitLocker metadata**\n\nMay reveal encrypted LVM volume groups or additional filesystem information\n```\nsudo anylinuxfs list -d all\n```\n[See here for more info](docs/luks-lvm.md)\n\n**Mount LUKS-encrypted or BitLocker-encrypted partition**\n```\n# anylinuxfs will show an interactive passphrase prompt\nsudo anylinuxfs /dev/disk9\n\n# or it can take the passphrase from environment\nexport ALFS_PASSPHRASE=\"my_strong_password\"\nsudo -E anylinuxfs /dev/disk9\n```\n\n\u003e [!NOTE]\n\u003e If you have more disks with different passphrases you can define variables named `ALFS_PASSPHRASE1`, `ALFS_PASSPHRASE2`, `ALFS_PASSPHRASE3`, etc.\n\n**Mount partition and share it via NFS to other devices in any subnet**\n```\nsudo anylinuxfs /dev/disk0s6 -b 0.0.0.0\n```\n\n**Mount partition and share it via NFS to devices within your subnet (more secure)**\n```\n# by server, we mean the device which is sharing the mounted filesystem\nsudo anylinuxfs /dev/disk0s6 -b \u003cYOUR_SERVER_IP\u003e\n```\n\n**Show current mount status**\n```\nanylinuxfs status\n```\n\n**Try to stop anylinuxfs in case umount or eject didn't completely terminate the VM**\n```\nanylinuxfs stop\n```\n\n## Custom actions\n\nWith custom actions, you're able to define sets of scripts which will run inside the virtual machine at specific points.\nCurrently supported actions: `before_mount`, `after_mount`, `before_unmount` (typically to do cleanup).\nYou can also override the path inside the virtual machine which gets shared with macOS via NFS. This is useful for mounting nested filesystems (from disk images, etc.).\n\nYour custom actions can also depend on additional packages not included in the base Linux installation by default. `anylinuxfs` exposes the Alpine package manager for that purpose. That means it can maintain a list of extra packages installed by the user and reinstall them again when you reinit your Linux image (or when reinit is forced by `anylinuxfs` upgrade).\n\n### Pre-defined actions\n\nThere are custom actions that come pre-installed with `anylinuxfs`. You can check the `/opt/homebrew/etc/anylinuxfs.toml` config file. For any other actions that you define, use `~/.anylinuxfs/config.toml` instead.\n\n### List available actions\n\nTo quickly check which actions are available, run `anylinuxfs actions` which will give you their names and descriptions. Any modifications are done in config files directly.\n\n### Examples\n\n#### Mount borg backup located on a Linux drive\n\nFor this, we will first need to install additional alpine packages:\n```\nanylinuxfs apk add borgbackup fuse py3-llfuse\n```\n\nThen we define a custom action by editing (or creating) `~/.anylinuxfs/config.toml`:\n```\n[custom_actions.borg]\nafter_mount = \"mkdir -p /mnt/borg \u0026\u0026 borg mount $ALFS_VM_MOUNT_POINT/$BORG_REPO /mnt/borg\"\nbefore_unmount = \"borg umount /mnt/borg \u0026\u0026 rmdir /mnt/borg\"\noverride_nfs_export = \"/mnt/borg\"\n```\n\nYou can refer to environment variables from custom actions. Those starting with `$ALFS_` are set by anylinuxfs. Any other variables must be set by the user.\nIf you want your custom action to use any other environment variable which is not explicitly used in the script (e.g. borg might use `$BORG_PASSPHRASE`), you can list them like this:\n```\n[custom_actions.borg]\nafter_mount = \"...\"\nbefore_unmount = \"...\"\ncapture_environment = [\"BORG_PASSPHRASE\"]\noverride_nfs_export = \"/mnt/borg\"\n```\n\nTo invoke your action when mounting a drive, use the `-a` flag (and make sure sudo preserves your environment):\n```\nexport BORG_REPO=\u003cpath to borg repo relative to mount point\u003e\nsudo -E anylinuxfs mount /dev/disk4s2 -a borg\n```\n\nYou will be asked for your passphrase (if you haven't set `capture_environment` and exported `BORG_PASSPHRASE`) and your borg backup will be mounted instead of the whole Linux drive.\n\n## Notes\n\n### VM initialization\n- When you first run `anylinuxfs` to mount a drive, it will download the alpine Linux image from Docker hub and unpack it to your user profile (`~/.anylinuxfs/alpine`).\nThen it will spin up a VM so it can install dependencies and do the initial environment setup. After that, the Linux root filesystem will be reused for every mount operation.\nYou can also run `anylinuxfs init` to download a fresh copy of `alpine:latest` and reinitialize the environment at any time.\n\n### Custom CA certificates\n- If you need to add custom CA certificates for the alpine VM to download packages, you can do so by adding them to a file in your user profile (`~/.anylinuxfs/ca-certificates.crt`). The CA certificates must be in newline-separated PEM blocks. These will be appended to the alpine image defaults during the first run of `anylinuxfs`, or when calling `anylinuxfs init`.\n\n### Permissions\n- It is needed to run mount commands with `sudo` otherwise we're not allowed direct access to `/dev/disk*` files. However, the virtual machine itself will in fact run under the regular user who invoked `sudo` in the first place (i.e. all unnecessary permissions are dropped after the disk is opened)\n\n### Memory requirements for LUKS\n- When you mount a LUKS-encrypted drive, the microVM requires at least 2.5 GiB RAM for cryptsetup to work properly. If your VM is configured with a lower amount of memory, you'll get a warning about it and the RAM configuration will be adjusted automatically. If you don't want to see the warning, set your default RAM to match this requirement (`anylinuxfs config -r \u003csize-in-MiB\u003e`)\n- Configured amount of RAM is the maximum that can be allocated. The actual amount of memory consumed by the VM can be lower.\n\n### NTFS\n* anylinuxfs provides two different NTFS drivers\n  - the user-space FUSE-based **ntfs-3g** (better compatibility)\n  - the more recent kernel-space **ntfs3** (significantly better performance)\n* **ntfs-3g** is used by default\n* **ntfs3** can be used by specifying `-t ntfs3` option when mounting\n* Important things to keep in mind\n  - **ntfs3** cannot mount NTFS drives from Windows systems which were hibernated or which have Fast Startup enabled\n  - **ntfs-3g** will fall back to read-only mount and issue a warning in this case\n  - **ntfs3** will generally refuse to mount a drive if it has any filesystem errors\n  - using any unofficial tools like `ntfsfix` to clear dirty flag will not really fix those errors and can lead to further data corruption!\n  - `chkdsk` on Windows is the recommended way to fix NTFS errors\n  - some users also have good experience with [`chkntfs`](https://gist.github.com/nohajc/51fdecb2dda75dd8c600173ea42b3700) by Paragon (proprietary)\n  - there are permission issues reported when using **ntfs3** with Windows system drives\n  - specifically, `/Program Files` some folders within `/Users` are read-only (see this [reddit](https://www.reddit.com/r/archlinux/comments/r325t3/permissions_problems_with_the_new_ntfs3_driver/) post for details)\n\n**To summarize**\n* There are stories online about data corruption (or system freezes) caused by the **ntfs3** driver.\n* They might or might not be caused by improper use of `ntfsfix`.\n* **ntfs3** is included in the mainline Linux kernel so it is considered stable. It was contributed by Paragon Software in [2021](https://www.paragon-software.com/paragon-software-announces-the-inclusion-of-its-ntfs3-driver-into-linux-kernel-5-15/).\n* If you trust it, want the best performance and you're OK with inconsistent permissions on Windows system drives, use **ntfs3**\n* Otherwise you're probably better of with the default and more established **ntfs-3g**\n\n## Troubleshooting\n- Make sure nothing is running on ports 2049, 32765 and 32767. If there's another NFS server already running, `anylinuxfs` will not work.\n- Check your mount flags (e.g. the `subvol` flag from demo is specific to btrfs, make sure you don't use it with other filesystems)\n- Check file owner and permissions with `ls -l` and adjust accordingly. Typically, your macOS user won't have write access to your drive out of the box so you need to write files as root or first prepare a target directory writable by everyone (`chmod 777`).\n- If you get `fcopyfile failed: Operation not permitted`, it can actually mean the file you're trying to copy has the quarantine attribute set (can be removed with `xattr -d com.apple.quarantine \u003cfilename\u003e`)\n- Accessing disks might require Full Disk Access permission (although you should get pop-ups that let you allow access case-by-case)\n\n## Build from source\n\n```\n# build dependencies\nbrew install go rustup   # Skip if not relevant. You need Go and Rust toolchains but not necessarily installed via homebrew\nbrew install lld pkgconf # These are for cross-compiling the Linux helper running in the VM\n\n# if you just installed rustup from homebrew\nrustup default stable\nexport PATH=\"$PATH:/opt/homebrew/opt/rustup/bin\"\n\n# runtime dependencies\nbrew install util-linux slp/krun/libkrun # Libblkid library and the hypervisor - you should already have these if you installed anylinuxfs from homebrew\n\n# building anylinuxfs\ngit clone https://github.com/nohajc/anylinuxfs.git\ncd anylinuxfs\nrustup target add aarch64-unknown-linux-musl\nrustup +nightly-2026-01-25 component add rust-src\n./download-dependencies.sh\n./build-app.sh             # debug build\n./build-app.sh --release   # release build\n\n# compiled executable will be available under ./bin\nbin/anylinuxfs list\n```\n\n## Acknowledgements\nThis project was made possible by\n- [libkrun](https://github.com/containers/libkrun) the microVM hypervisor for Linux and Mac\n- [libkrunfw](https://github.com/containers/libkrunfw) - Linux kernel bundled for libkrun as a dynamic library\n- [gvproxy](https://github.com/containers/gvisor-tap-vsock) - user space networking for virtual machines (also used by podman)\n- [docker-nfs-server](https://github.com/ehough/docker-nfs-server) - launcher for NFS server in a container\n\nThank you all for your great work!\n","funding_links":["https://ko-fi.com/nohajc","https://ko-fi.com/Q5Q41EHAGK'"],"categories":["File Management Tools","Applications","Rust"],"sub_categories":["Utils","System tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnohajc%2Fanylinuxfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnohajc%2Fanylinuxfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnohajc%2Fanylinuxfs/lists"}