# mounter
Mount remote SSH directories in your file manager. No FUSE, no Docker, no kernel extensions.
Works on macOS and Linux.
## Quick start
```bash
cd smb-sshfs
cargo build --release
# One command: mount, serve, Ctrl-C to stop
./target/release/smb-sshfs mount user@server:/path
```
Or start the server and mount separately:
```bash
./target/release/smb-sshfs user@server:/path # prints mount command
mount_smbfs //guest@localhost:<port>/server ~/mnt/server # macOS
```
## Commands
```
smb-sshfs mount [user@]host:[path] [opts] Mount and serve (Ctrl-C to stop)
smb-sshfs [user@]host:[path] [opts] Start SMB server only
```
Options:
```
-p PORT SSH port (default: 22)
-i IDENTITY SSH identity file
-n NAME Share name (default: host)
--smb-port PORT Local SMB port (default: auto)
```
## How it works
```
File manager <--SMB2--> smb-sshfs (localhost) <--SFTP/SSH--> remote server
```
`smb-sshfs` is a single Rust binary that speaks SMB2 to your OS and SFTP v3 to
the remote. It spawns `ssh -s sftp` as a subprocess — existing SSH keys,
config, and agent just work. No kernel extensions, no privileged containers.
## Platform support
| macOS | `mount_smbfs` (built-in) | Full support |
| Linux | `smbclient` / userspace tools | Works |
| Linux | `mount -t cifs` (kernel) | Needs NTLMSSP improvements |
On Linux, the SMB2 server works — `smbclient` can list and read files. The
kernel `mount.cifs` driver requires stricter NTLMSSP authentication than
macOS's client; this is being worked on.
## Performance
Benchmarked against raw `ssh cat` on the same connection:
| `ls -la` (45 files, cold) | 103 ms |
| `ls -la` (45 files, warm) | 5 ms |
| `stat` single file | 5 ms |
| 108 MB sequential read | 91% of SSH throughput |
Key optimizations:
- **Session-level directory cache** — macOS sends hundreds of per-file
QUERY_DIRECTORY lookups for `ls -la`; all served from a 15s TTL cache
after one SFTP readdir.
- **Pipelined SFTP reads** — large reads send multiple 256KB requests
in parallel to saturate the SSH pipe.
- **Read caching** — each SFTP response is cached so small
resource-fork probes don't trigger extra round-trips.
- **Negative caching** — Apple metadata files (.DS_Store, ._*, etc.)
that never exist on Linux are cached as absent for 60s.
## Requirements
- macOS or Linux
- SSH key auth to your remote server
- Rust toolchain (to build)
## Tests and benchmarks
```bash
cargo test # 54 unit tests
cargo bench # criterion benchmarks for hot paths
```
## License
Apache 2.0