fs-sshfs: PyFilesystem2 over SSH
fs-sshfs is a PyFilesystem2 extension that allows you to treat a remote SSH server's filesystem as a local `fs.FS` object, leveraging Paramiko for SSH connectivity. The current version is 1.0.2, and it receives updates as needed, particularly for compatibility with its core `paramiko` dependency, ensuring robust and secure remote file access.
Common errors
-
paramiko.ssh_exception.NoValidConnectionsError: Unable to connect to ...
cause The SSH server is unreachable, the host or port is incorrect, or a firewall is blocking the connection.fixVerify the SSH host and port are correct and the server is running and accessible from your client machine. Check network connectivity and local/remote firewall rules. Confirm the target host's SSH service is operational. -
paramiko.ssh_exception.AuthenticationException: Authentication failed.
cause The provided username, password, or SSH key is incorrect or not authorized on the remote server.fixDouble-check the `user`, `passwd`, or `pkey` arguments passed to `SSHFS`. Ensure the SSH key has the correct permissions (e.g., `chmod 400 keyfile.pem`) and is correctly loaded if using key-based authentication. -
paramiko.ssh_exception.SSHException: Server '...' not found in known_hosts and not a host certificate.
cause The remote host's SSH key is unknown or has changed, and `paramiko`'s policy is set to reject unknown hosts.fixSet an appropriate `missing_host_key_policy` in the `SSHFS` constructor. For convenience during development, use `paramiko.AutoAddPolicy()`. For production, manually add the host's public key to your `~/.ssh/known_hosts` file, or implement a stricter policy like `paramiko.WarningPolicy()` or `paramiko.RejectPolicy()` after verifying the key.
Warnings
- breaking Explicit support for Paramiko 3 was added in `fs-sshfs` v1.0.2. If you are using an older version of `fs-sshfs` (prior to 1.0.2) with `paramiko` v3.x, you may encounter compatibility issues or unexpected behavior due to API changes in Paramiko.
- gotcha SSH host key verification can prevent connections if the remote host's key is not present in the local `known_hosts` file or if a strict policy is configured, leading to `SSHException` errors.
- gotcha `fs-sshfs` instances establish and hold SSH connections. It is crucial to properly close these connections to release system resources, especially in long-running applications or when opening multiple connections.
Install
-
pip install fs-sshfs
Imports
- SSHFS
from fs.sshfs import SSHFS
from fs_sshfs import SSHFS
Quickstart
import os
from fs_sshfs import SSHFS
from paramiko import AutoAddPolicy
# Set these environment variables or replace with actual values
# For password authentication: export SSH_HOST='your_host' SSH_USER='your_user' SSH_PASSWORD='your_password'
# For key-based authentication: export SSH_HOST='your_host' SSH_USER='your_user' SSH_PKEY_PATH='/path/to/your/key'
host = os.environ.get('SSH_HOST', '')
user = os.environ.get('SSH_USER', '')
password = os.environ.get('SSH_PASSWORD')
pkey_path = os.environ.get('SSH_PKEY_PATH')
port = int(os.environ.get('SSH_PORT', 22))
if not host or not user:
print("Please set SSH_HOST and SSH_USER environment variables.")
exit(1)
# Configure SSH key if path is provided
pkey = None
if pkey_path:
try:
from paramiko import RSAKey, Ed25519Key, ECDSAKey, DSSKey
# Attempt to load common key types; more robust error handling might be needed
try: pkey = RSAKey.from_private_key_file(pkey_path)
except Exception: pass
try: pkey = Ed25519Key.from_private_key_file(pkey_path)
except Exception: pass
try: pkey = ECDSAKey.from_private_key_file(pkey_path)
except Exception: pass
try: pkey = DSSKey.from_private_key_file(pkey_path)
except Exception: pass
if not pkey: raise ValueError("Could not load PKEY from path")
print(f"Using SSH key from: {pkey_path}")
except Exception as e:
print(f"Warning: Could not load SSH key from {pkey_path}: {e}")
print("Falling back to password or no authentication if key fails.")
pkey = None
try:
with SSHFS(
host=host,
user=user,
passwd=password,
port=port,
pkey=pkey,
# AutoAddPolicy is convenient for development but insecure for production
missing_host_key_policy=AutoAddPolicy(),
) as remote_fs:
print(f"Successfully connected to {host} as {user}")
print("Listing root directory of the remote filesystem:")
# Check if root is accessible and list contents
if remote_fs.exists('/'):
for info in remote_fs.scandir('/'):
print(f" {info.name} ({'directory' if info.is_dir else 'file'})")
else:
print(" Root directory '/' does not exist or is inaccessible.")
except Exception as e:
print(f"Error connecting or listing remote files: {e}")
print("Please ensure SSH_HOST, SSH_USER, and either SSH_PASSWORD or SSH_PKEY_PATH are set correctly.")
print("Also, verify the SSH server is running and accessible.")