--- title: SSH icon: terminal description: Mount a remote filesystem over SSH/SFTP. --- The SSH resource mounts a remote server's filesystem over SFTP. It supports full read and write operations. ## Config ```python from mirage import MountMode, Workspace from mirage.resource.ssh import SSHConfig, SSHResource config = SSHConfig( host="myserver", username="deploy", identity_file="~/.ssh/id_ed25519", root="/var/data", ) resource = SSHResource(config=config) ws = Workspace({"/remote": resource}, mode=MountMode.WRITE) ``` | Field | Required | Default | Description | | --------------- | -------- | ------- | ------------------------------------ | | `host` | yes | | SSH host (name or IP) | | `hostname` | no | | Override resolved hostname | | `port` | no | `22` | SSH port | | `username` | no | | SSH username | | `identity_file` | no | | Path to private key | | `root` | no | `/` | Remote directory to mount | | `timeout` | no | `30` | Connection timeout in seconds | | `known_hosts` | no | | Path to known_hosts file | The `host` field matches entries in `~/.ssh/config`, so existing SSH configurations are automatically picked up. ## Filesystem Layout ```text /remote/ ``` The mounted tree mirrors the remote filesystem starting at `root`. Example with `root="/var/data"`: ```text /remote/ logs/ app.log nginx/ access.log error.log config/ app.yaml uploads/ image.png ``` ## Cache Uses `IndexCacheStore` for directory listings. Freshness is checked via `{mtime}:{size}` fingerprints - files are re-fetched only when the remote has changed. ## Example ```python import asyncio from mirage import MountMode, Workspace from mirage.resource.ssh import SSHConfig, SSHResource config = SSHConfig( host="myserver", username="deploy", identity_file="~/.ssh/id_ed25519", root="/var/log", ) resource = SSHResource(config=config) async def main(): ws = Workspace({"/logs": resource}, mode=MountMode.READ) # List remote directory r = await ws.execute("ls /logs/") print(await r.stdout_str()) # Read last 20 lines of a log r = await ws.execute("tail -n 20 /logs/nginx/access.log") print(await r.stdout_str()) # Search across log files r = await ws.execute('grep "ERROR" /logs/app.log') print(await r.stdout_str()) # Find large files r = await ws.execute("find /logs/ -name '*.log'") print(await r.stdout_str()) # File metadata r = await ws.execute("stat /logs/app.log") print(await r.stdout_str()) if __name__ == "__main__": asyncio.run(main()) ``` ## Shell Commands | Command | Notes | | ---------------------- | ------------------------------------------ | | `ls` | List remote files and directories | | `cat` | Read remote file content | | `head` / `tail` | First/last N lines | | `grep` / `rg` | Pattern search (use targeted paths) | | `wc` | Line/word/byte counts | | `stat` | File metadata (size, mtime) | | `find` | Recursive search with `-name`, `-maxdepth` | | `tree` | Directory tree view | | `mkdir` | Create remote directories | | `touch` | Create empty remote files | | `cp` / `mv` / `rm` | Copy, move, delete on remote | | `tee` | Write stdin to remote file | | `diff` / `cmp` | Compare remote files | | `sort` / `cut` / `tr` | Text processing | | `tar` / `zip` / `gzip` | Compression |