Skip to content

Remote Execution

Classes and functions for remote execution via SSH.

Installation

pip install "fscm[remote]"

Quick Example

from fscm.remote import Host, SSH, Sudo, executor

host = Host(
    name="webserver",
    connection=SSH(hostname="10.0.0.5", username="ubuntu"),
    become=Sudo()
)

with executor(host) as exe:
    exe.fscm.s.pkgs_install("nginx")

Classes

Host

Represents a remote host.

from fscm.remote import Host, SSH, Sudo

host = Host(
    name="webserver",
    connection=SSH(hostname="10.0.0.5", username="ubuntu"),
    become=Sudo(),
    secrets={"db_pass": "secret"},
    tags=["web", "production"]
)

Parameters:

Name Type Description
name str Friendly identifier
connection SSH/Local Connection specification
become Sudo/Su Privilege escalation
secrets dict Host-specific secrets
tags list Categorization tags

SSH

SSH connection specification.

from fscm.remote import SSH

conn = SSH(
    hostname="10.0.0.5",
    username="ubuntu",
    port=22,
    identity_file="/path/to/key.pem",
    ssh_args=["-o", "StrictHostKeyChecking=no"]
)

Parameters:

Name Type Default Description
hostname str required Host to connect to
username str required SSH username
port int 22 SSH port
identity_file str None Path to SSH key
ssh_args list None Additional SSH arguments

Local

Local execution (no SSH).

from fscm.remote import Local

conn = Local()

Useful for testing or running locally with the same API.


Sudo

Sudo privilege escalation.

from fscm.remote import Sudo

become = Sudo(
    password="secret",
    username="root"
)

Parameters:

Name Type Default Description
password str None Sudo password
username str "root" User to become

Su

Su privilege escalation.

from fscm.remote import Su

become = Su(
    password="root_password",
    username="root"
)

Parameters:

Name Type Default Description
password str required Su password
username str "root" User to become

Functions

executor

Context manager for remote execution.

from fscm.remote import executor

with executor(host, dry_run=False, sudo_password=None) as exe:
    exe.fscm.run("ls")

Parameters:

Name Type Default Description
host Host required Target host
dry_run bool False Simulate operations
sudo_password str None Override sudo password

Returns: Executor context with exe.fscm access.


RemoteCliApp

CLI framework for deployment scripts.

from fscm.remote_cli import RemoteCliApp

app = RemoteCliApp(
    description="My deployment script",
    hosts_path="hosts.yaml",
    secrets_path="secrets/"
)

@app.cmd
def deploy(ctx):
    ctx.fscm.s.pkgs_install("nginx")

if __name__ == "__main__":
    app.run()

Command Line Arguments

Argument Description
--host NAME Target specific host
--dry-run Preview changes
--sudo-password Prompt for sudo password

hosts.yaml Format

hosts:
  - name: webserver
    connection:
      type: ssh
      hostname: 10.0.0.5
      username: ubuntu
    become:
      type: sudo
    tags:
      - web

  - name: database
    connection:
      type: ssh
      hostname: 10.0.0.6
      username: ubuntu
    become:
      type: sudo
    tags:
      - database

Example: Multiple Hosts

from fscm.remote import Host, SSH, Sudo, executor

hosts = [
    Host(name="web1", connection=SSH(hostname="10.0.0.1", username="ubuntu"), become=Sudo()),
    Host(name="web2", connection=SSH(hostname="10.0.0.2", username="ubuntu"), become=Sudo()),
]

def configure(exe):
    exe.fscm.s.pkgs_install("nginx")
    exe.fscm.file("/var/www/index.html", "<h1>Hello</h1>")

for host in hosts:
    print(f"Configuring {host.name}...")
    with executor(host) as exe:
        configure(exe)

Example: With Secrets

from fscm.remote import Host, SSH, Sudo, executor
import fscm

# Load secrets from pass
secrets = fscm.get_secrets("myapp/production")

host = Host(
    name="webserver",
    connection=SSH(hostname="10.0.0.5", username="ubuntu"),
    become=Sudo(),
    secrets=secrets
)

with executor(host) as exe:
    db_pass = host.secrets["db_password"]
    config = f"DATABASE_PASSWORD={db_pass}\n"
    exe.fscm.file("/etc/myapp/env", config, mode="0600")