Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ef25f0f
Add mount/umount commands to SSH driver for sshfs-based filesystem mo…
Apr 8, 2026
e27c07c
refactor: extract sshfs mount/umount into separate jumpstarter-driver…
Apr 8, 2026
7254e19
fix: add ssh-mount to docs toctree and use SSH driver in example config
Apr 8, 2026
0e53d5d
refactor: make SSHMount consume SSH driver for credentials and TCP ac…
Apr 8, 2026
ba58dae
Rename driver to 'mount', use --umount flag for cleaner CLI UX
Apr 8, 2026
ba868e7
fix: address PR review feedback for ssh-mount driver
Apr 9, 2026
036a5ad
Fix lint C901 complexity in umount, add CLI dispatch tests
Apr 9, 2026
bc71488
Fix macOS test failures: use os.path.realpath for mount path assertions
Apr 9, 2026
6385e9c
Refactor mount to run sshfs in foreground with subshell
Apr 10, 2026
ab2ef17
Fix lint errors and test failures in ssh-mount driver
Apr 10, 2026
2a8a1c2
Fix CI failures: unused variable lint error and test mock side_effects
Apr 10, 2026
a53fc54
Add jumpstarter-driver-ssh-mount to UV workspace sources
Apr 10, 2026
d62c230
Address second review round: fix sshfs cleanup, deadlock, and macOS u…
Apr 14, 2026
32aab8c
Fix CI: remove unused sys import and fix generic failure test assertion
Apr 14, 2026
0ada859
Fix extra_args -o prefix, remove dead port_forward param, add subshel…
Apr 15, 2026
155cc91
Fix SIGPIPE risk and ruff B904 lint error
Apr 15, 2026
644350e
Fix ruff B904: add 'from None' to raise in except clause
Apr 15, 2026
4817f42
Address review feedback: fix fragile mountpoint extraction and misc i…
Apr 15, 2026
2dd3d89
ssh-mount: follow-up improvements from PR #434 review
Apr 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion python/docs/source/reference/package-apis/drivers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ General-purpose utility drivers:
* **[Shell](shell.md)** (`jumpstarter-driver-shell`) - Shell command execution
* **[TMT](tmt.md)** (`jumpstarter-driver-tmt`) - TMT (Test Management Tool) wrapper driver
* **[SSH](ssh.md)** (`jumpstarter-driver-ssh`) - SSH wrapper driver
* **[SSH Mount](ssh-mount.md)** (`jumpstarter-driver-ssh-mount`) - SSHFS remote filesystem mounting

```{toctree}
:hidden:
Expand Down Expand Up @@ -140,8 +141,9 @@ gpiod.md
ridesx.md
sdwire.md
shell.md
ssh.md
snmp.md
ssh.md
ssh-mount.md
someip.md
tasmota.md
tmt.md
Expand Down
3 changes: 3 additions & 0 deletions python/packages/jumpstarter-driver-ssh-mount/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__pycache__/
.coverage
coverage.xml
119 changes: 119 additions & 0 deletions python/packages/jumpstarter-driver-ssh-mount/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# SSHMount Driver

`jumpstarter-driver-ssh-mount` provides remote filesystem mounting via sshfs. It allows you to mount remote directories from a target device to your local machine using SSHFS (SSH Filesystem).

## Installation

```shell
pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple/ jumpstarter-driver-ssh-mount
```

You also need `sshfs` installed on the client machine:

- **Fedora/RHEL**: `sudo dnf install fuse-sshfs`
- **Debian/Ubuntu**: `sudo apt-get install sshfs`
- **macOS**: Install macFUSE from https://macfuse.github.io/ and then install
sshfs from source, as Homebrew has removed sshfs support.

## Configuration

The SSHMount driver references an existing SSH driver to inherit credentials
(username, identity key) and TCP connectivity. No duplicate configuration is needed.

Example exporter configuration:

```yaml
export:
ssh:
type: jumpstarter_driver_ssh.driver.SSHWrapper
config:
default_username: "root"
# ssh_identity_file: "/path/to/ssh/key"
children:
tcp:
type: jumpstarter_driver_network.driver.TcpNetwork
config:
host: "192.168.1.100"
port: 22
mount:
type: jumpstarter_driver_ssh_mount.driver.SSHMount
children:
ssh:
ref: "ssh"
```

## CLI Usage

Inside a `jmp shell` session:

```shell
# Mount remote filesystem (spawns a subshell; type 'exit' to unmount)
j mount /local/mountpoint
j mount /local/mountpoint -r /remote/path
j mount /local/mountpoint --direct

# Mount in foreground mode (blocks until Ctrl+C)
j mount /local/mountpoint --foreground

# Pass extra sshfs options
j mount /local/mountpoint -o reconnect -o cache=yes

# Unmount an orphaned mount
j mount --umount /local/mountpoint
j mount --umount /local/mountpoint --lazy
```

By default, `j mount` runs sshfs in foreground mode and spawns a subshell
with a modified prompt. The mount stays active while the subshell is running.
When you type `exit` (or press Ctrl+D), sshfs is terminated and all resources
(port forwards, temporary identity files) are cleaned up automatically.

Use `--foreground` to skip the subshell and block directly on sshfs. Press
Ctrl+C to unmount.

The `--umount` flag is available as a fallback for mounts that were orphaned
(e.g., if the process was killed without cleanup).

## Security: `allow_other` mount option

By default, sshfs is invoked with `-o allow_other`, which permits all local
users to access the mounted filesystem — not just the user who ran `j mount`.
This is convenient for build workflows where tools run under different UIDs,
but it has security implications on multi-user systems:

- Any local user can read (and potentially write) files on the remote device
through the mountpoint.
- The option requires that `/etc/fuse.conf` contains `user_allow_other`;
otherwise the mount will fail.

**Automatic fallback:** if `allow_other` is rejected by FUSE (e.g.,
`user_allow_other` is not set), the driver automatically retries the mount
without it. In that case only the mounting user can access the filesystem.

To explicitly disable `allow_other` without relying on the fallback, you can
override the option via `--extra-args`:

```shell
j mount /mnt/device -o allow_other=0
```

## API Reference

### SSHMountClient

- `mount(mountpoint, *, remote_path="/", direct=False, foreground=False, extra_args=None)` - Mount remote filesystem locally via sshfs
- `umount(mountpoint, *, lazy=False)` - Unmount an sshfs filesystem (fallback for orphaned mounts)

### Required Children

| Child name | Type | Description |
|-----------|------|-------------|
| `ssh` | `jumpstarter_driver_ssh.driver.SSHWrapper` | SSH driver providing credentials (username, identity key) and TCP connectivity. Must itself have a `tcp` child of type `TcpNetwork`. |

### CLI

The driver registers as `mount` in the exporter config. When used in a `jmp shell` session, the CLI is a single command with a `--umount` flag for unmounting.

Note: `extra_args` values (passed via `-o`) are forwarded directly to sshfs. This
can be used to override defaults such as `StrictHostKeyChecking=no` -- for example,
`-o StrictHostKeyChecking=yes`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: jumpstarter.dev/v1alpha1
kind: ExporterConfig
metadata:
namespace: default
name: demo
endpoint: grpc.jumpstarter.192.168.0.203.nip.io:8082
token: "<token>"
export:
ssh:
type: jumpstarter_driver_ssh.driver.SSHWrapper
config:
default_username: "root"
# ssh_identity_file: "/path/to/key"
children:
tcp:
type: jumpstarter_driver_network.driver.TcpNetwork
config:
host: "192.168.1.100"
port: 22
mount:
type: jumpstarter_driver_ssh_mount.driver.SSHMount
children:
ssh:
ref: "ssh"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading
Loading