Skip to content

Quick Start

This guide walks you through writing your first fscm configuration.

Your First Script

Create a file called setup.py:

#!/usr/bin/env python3
"""Configure a basic web server."""

import fscm
from fscm import s, file, run, mkdir

def main():
    # Install nginx
    s.pkgs_install("nginx")

    # Create a simple static site
    mkdir("/var/www/mysite", mode="0755")

    file(
        "/var/www/mysite/index.html",
        "<html><body><h1>Hello from fscm!</h1></body></html>\n",
        mode="0644"
    )

    # Create nginx config
    nginx_config = """
server {
    listen 80;
    server_name _;
    root /var/www/mysite;
    index index.html;
}
"""
    file("/etc/nginx/sites-available/mysite", nginx_config, mode="0644")

    # Enable the site
    run("ln -sf /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/")
    run("rm -f /etc/nginx/sites-enabled/default")

    # Reload nginx
    run("systemctl reload nginx", sudo=True)

    # Print what we did
    print("\n=== Changes made ===")
    for change in fscm.CHANGELIST:
        print(f"  {change}")

if __name__ == "__main__":
    main()

Running Your Script

Dry Run (Preview Changes)

Always preview changes first:

python setup.py --dry-run

Dry Run Mode

In dry-run mode, fscm shows what would happen without making any changes. Always use this first to verify your configuration.

Apply Changes

When you're ready, run without --dry-run:

sudo python setup.py

Sudo

Most system configuration requires root privileges. Run with sudo or use fscm's built-in sudo support.

Using Dry Run Programmatically

You can also enable dry-run mode in your code:

import fscm

# Enable dry-run mode
fscm.settings.dry_run = True

# Now all operations will only be simulated
s.pkgs_install("nginx")  # Won't actually install
file("/etc/config", "content")  # Won't actually write

Adding Command-Line Arguments

For more control, use the built-in clii module:

#!/usr/bin/env python3
import fscm
from fscm.thirdparty.clii import App

cli = App(description="Configure server")

@cli.main
def main(dry_run: bool = False):
    """dry_run: Preview changes without applying"""
    fscm.settings.dry_run = dry_run

    # Your configuration here...
    fscm.s.pkgs_install("nginx")

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

Arguments are derived from function parameters. Boolean defaults create --flag options.

Using Templates

For complex configurations, use Jinja2 templates:

import fscm

# Create templates/nginx.conf.j2:
# server {
#     listen {{ port }};
#     server_name {{ domain }};
#     root {{ root_dir }};
# }

config = fscm.template(
    "templates/nginx.conf.j2",
    port=80,
    domain="example.com",
    root_dir="/var/www/html"
)

fscm.file("/etc/nginx/sites-available/mysite", config)

Remote Execution

To run on a remote host:

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

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

# Execute remotely
with executor(host) as exe:
    exe.fscm.s.pkgs_install("nginx")
    exe.fscm.file("/var/www/index.html", "<h1>Hello!</h1>")

See Remote Execution Guide for details.

Next Steps