| 1 | # FUSE |
| 2 | |
| 3 | **EXPERIMENTAL:** FUSE support is functional but still evolving. Please report issues at [kubo/issues](https://github.com/ipfs/kubo/issues). |
| 4 | |
| 5 | Kubo can mount `/ipfs`, `/ipns`, and `/mfs` namespaces in your OS, |
| 6 | letting arbitrary apps access IPFS through standard filesystem operations. |
| 7 | |
| 8 | The underlying FUSE implementation uses [`hanwen/go-fuse`](https://github.com/hanwen/go-fuse). |
| 9 | |
| 10 | - [Install FUSE](#install-fuse) |
| 11 | - [Linux](#linux) |
| 12 | - [macOS](#macos) |
| 13 | - [FreeBSD](#freebsd) |
| 14 | - [Prepare mountpoints](#prepare-mountpoints) |
| 15 | - [Mounting IPFS](#mounting-ipfs) |
| 16 | - [MFS mountpoint](#mfs-mountpoint) |
| 17 | - [Mode and mtime](#mode-and-mtime) |
| 18 | - [Troubleshooting](#troubleshooting) |
| 19 | |
| 20 | ## Install FUSE |
| 21 | |
| 22 | You will need to install and configure FUSE before you can mount IPFS. |
| 23 | |
| 24 | #### Linux |
| 25 | |
| 26 | Install `fuse3` with your package manager: |
| 27 | |
| 28 | ```sh |
| 29 | # Debian / Ubuntu |
| 30 | sudo apt-get install fuse3 |
| 31 | |
| 32 | # Fedora |
| 33 | sudo dnf install fuse3 |
| 34 | |
| 35 | # Arch |
| 36 | sudo pacman -S fuse3 |
| 37 | ``` |
| 38 | |
| 39 | On some older Linux distributions, you may need to add yourself to the `fuse` group |
| 40 | for `allow_other` support (if no `fuse` group exists, you can skip this step): |
| 41 | |
| 42 | ```sh |
| 43 | sudo usermod -a -G fuse <username> |
| 44 | ``` |
| 45 | |
| 46 | Restart your session for the change to apply. |
| 47 | |
| 48 | #### macOS |
| 49 | |
| 50 | Install [macFUSE](https://macfuse.github.io/): |
| 51 | |
| 52 | ```sh |
| 53 | brew install --cask macfuse |
| 54 | ``` |
| 55 | |
| 56 | After installation, open **System Settings > Privacy & Security** and allow the macFUSE kernel extension to load. A reboot may be required. |
| 57 | |
| 58 | Kubo automatically sets `volname`, `noapplexattr`, and `noappledouble` mount options on macOS: |
| 59 | |
| 60 | - `volname` shows the filesystem name (ipfs, ipns, mfs) in Finder instead of the generic "macfuse Volume 0" |
| 61 | - `noapplexattr` stops Finder from probing Apple-private extended attributes on every file access, cutting FUSE traffic on network-backed mounts |
| 62 | - `noappledouble` prevents macOS from creating `._` resource fork sidecar files, which would pollute the DAG with macOS-only metadata |
| 63 | |
| 64 | > [!NOTE] |
| 65 | > macOS has known FUSE limitations (frequent STATFS calls, limited notification support) that may affect performance. See the [`hanwen/go-fuse` macOS notes](https://github.com/hanwen/go-fuse#macos-support) for details. |
| 66 | |
| 67 | #### FreeBSD |
| 68 | |
| 69 | Load the FUSE kernel module: |
| 70 | |
| 71 | ```sh |
| 72 | sudo kldload fusefs |
| 73 | ``` |
| 74 | |
| 75 | To load automatically on boot: |
| 76 | |
| 77 | ```sh |
| 78 | echo 'fusefs_load="YES"' | sudo tee -a /boot/loader.conf |
| 79 | ``` |
| 80 | |
| 81 | ## Prepare mountpoints |
| 82 | |
| 83 | By default ipfs uses `/ipfs`, `/ipns` and `/mfs` directories for mounting. These can be |
| 84 | changed in config (see [`Mounts`](https://github.com/ipfs/kubo/blob/master/docs/config.md#mounts)). You will have to create the directories |
| 85 | explicitly. Note that modifying root requires sudo permissions. |
| 86 | |
| 87 | ```sh |
| 88 | # make the directories |
| 89 | sudo mkdir /ipfs /ipns /mfs |
| 90 | |
| 91 | # chown them so ipfs can use them without root permissions |
| 92 | sudo chown <username> /ipfs /ipns /mfs |
| 93 | ``` |
| 94 | |
| 95 | ## Mounting IPFS |
| 96 | |
| 97 | Make sure no other IPFS daemon is already running, then start the daemon with FUSE mounts enabled: |
| 98 | |
| 99 | ```sh |
| 100 | ipfs daemon --mount |
| 101 | ``` |
| 102 | |
| 103 | Or, if the daemon is already running: |
| 104 | |
| 105 | ```sh |
| 106 | ipfs mount |
| 107 | ``` |
| 108 | |
| 109 | If you wish to allow other users to use the mount points, edit `/etc/fuse.conf` |
| 110 | to enable non-root users: |
| 111 | |
| 112 | ```sh |
| 113 | # /etc/fuse.conf - Configuration file for Filesystem in Userspace (FUSE) |
| 114 | |
| 115 | # Set the maximum number of FUSE mounts allowed to non-root users. |
| 116 | # The default is 1000. |
| 117 | #mount_max = 1000 |
| 118 | |
| 119 | # Allow non-root users to specify the allow_other or allow_root mount options. |
| 120 | user_allow_other |
| 121 | ``` |
| 122 | |
| 123 | Next set `Mounts.FuseAllowOther` config option to `true`: |
| 124 | |
| 125 | ```sh |
| 126 | ipfs config --json Mounts.FuseAllowOther true |
| 127 | ipfs daemon --mount |
| 128 | ``` |
| 129 | |
| 130 | ## MFS mountpoint |
| 131 | |
| 132 | The `/mfs` mount exposes the MFS (Mutable File System) root as a FUSE filesystem. |
| 133 | This is the same virtual mutable filesystem as the one behind `ipfs files` commands |
| 134 | (see `ipfs files --help`), enabling manipulation of content-addressed data like regular files. |
| 135 | |
| 136 | Standard tools like `vim`, `rsync`, and `tar` work on writable mounts (`/mfs` and `/ipns`). |
| 137 | Operations like `fsync`, `ftruncate`, `chmod`, `touch`, and rename-over-existing are all supported. |
| 138 | |
| 139 | The CID for any file or directory is retrievable via the `ipfs.cid` |
| 140 | extended attribute: |
| 141 | |
| 142 | ```sh |
| 143 | $ getfattr -n ipfs.cid /mfs/hello.txt |
| 144 | # file: mfs/hello.txt |
| 145 | ipfs.cid="bafkreifjjcie6lypi6ny7amxnfftagclbuxndqonfipmb64f2km2devei4" |
| 146 | ``` |
| 147 | |
| 148 | > [!TIP] |
| 149 | > New IPFS nodes should run `ipfs config profile apply unixfs-v1-2025` to use CIDv1 with modern defaults. Without this, files default to CIDv0 (base58 `Qm...` hashes). |
| 150 | |
| 151 | ## Mode and mtime |
| 152 | |
| 153 | By default, IPFS does not persist POSIX mode or mtime, and most content on IPFS omits this metadata. |
| 154 | |
| 155 | When mode or mtime is absent, FUSE mounts use sensible defaults: |
| 156 | |
| 157 | - Read-only mounts (`/ipfs`): files `0444`, directories `0555` |
| 158 | - Writable mounts (`/ipns`, `/mfs`): files `0644`, directories `0755` |
| 159 | |
| 160 | When UnixFS metadata is present in the DAG (e.g. content added with mode/mtime preservation), |
| 161 | all three mounts show the stored values in `stat` responses regardless of config flags. |
| 162 | |
| 163 | To persist mode and mtime when writing through FUSE, enable the opt-in config flags: |
| 164 | |
| 165 | ```sh |
| 166 | ipfs config --json Mounts.StoreMtime true |
| 167 | ipfs config --json Mounts.StoreMode true |
| 168 | ``` |
| 169 | |
| 170 | These flags change the resulting CID even when file content is identical, because mode and mtime |
| 171 | are stored in the UnixFS DAG node metadata. |
| 172 | |
| 173 | See [`Mounts.StoreMtime`](https://github.com/ipfs/kubo/blob/master/docs/config.md#mountsstoremtime) and [`Mounts.StoreMode`](https://github.com/ipfs/kubo/blob/master/docs/config.md#mountsstoremode). |
| 174 | |
| 175 | ## Troubleshooting |
| 176 | |
| 177 | #### `Permission denied` or `fusermount: user has no write access to mountpoint` error in Linux |
| 178 | |
| 179 | Verify that the config file can be read by your user: |
| 180 | |
| 181 | ```sh |
| 182 | sudo ls -l /etc/fuse.conf |
| 183 | -rw-r----- 1 root fuse 216 Jan 2 2013 /etc/fuse.conf |
| 184 | ``` |
| 185 | |
| 186 | In most distributions, the group named `fuse` will be created during fuse |
| 187 | installation. You can check this with: |
| 188 | |
| 189 | ```sh |
| 190 | sudo grep -q fuse /etc/group && echo fuse_group_present || echo fuse_group_missing |
| 191 | ``` |
| 192 | |
| 193 | If the group is present, just add your regular user to the `fuse` group: |
| 194 | |
| 195 | ```sh |
| 196 | sudo usermod -G fuse -a <username> |
| 197 | ``` |
| 198 | |
| 199 | If the group didn't exist, create `fuse` group (add your regular user to it) and |
| 200 | set necessary permissions, for example: |
| 201 | |
| 202 | ```sh |
| 203 | sudo chgrp fuse /etc/fuse.conf |
| 204 | sudo chmod g+r /etc/fuse.conf |
| 205 | ``` |
| 206 | |
| 207 | Note that the use of `fuse` group is optional and may depend on your operating |
| 208 | system. It is okay to use a different group as long as proper permissions are |
| 209 | set for user running `ipfs mount` command. |
| 210 | |
| 211 | #### Mount command crashes and mountpoint gets stuck |
| 212 | |
| 213 | ```sh |
| 214 | sudo umount /ipfs |
| 215 | sudo umount /ipns |
| 216 | sudo umount /mfs |
| 217 | ``` |
| 218 | |
| 219 | #### Mounting fails with "error mounting: could not resolve name" |
| 220 | |
| 221 | Make sure your node's IPNS address has a directory published: |
| 222 | |
| 223 | ```sh |
| 224 | $ mkdir hello/; echo 'hello world' > hello/hello.txt |
| 225 | $ ipfs add -rQ ./hello/ |
| 226 | bafybeidhkumeonuwkebh2i4fc7o7lguehauradvlk57gzake6ggjsy372a |
| 227 | |
| 228 | $ ipfs name publish bafybeidhkumeonuwkebh2i4fc7o7lguehauradvlk57gzake6ggjsy372a |
| 229 | ``` |
| 230 | |
| 231 | #### Enabling debug logging |
| 232 | |
| 233 | Set the `IPFS_FUSE_DEBUG` environment variable before starting the daemon to log all FUSE operations to stderr: |
| 234 | |
| 235 | ```sh |
| 236 | IPFS_FUSE_DEBUG=1 ipfs daemon --mount |
| 237 | ``` |