Server Operations

The server module takes care of os-level state. Targets POSIX compatibility, tested on Linux/BSD.

server.crontab

Add/remove/update crontab entries.

server.crontab(
    command, present=True, user=None, cron_name=None, minute='*', hour='*', month='*',
    day_of_week='*', day_of_month='*', special_time=None, interpolate_variables=False,
)
  • command: the command for the cron
  • present: whether this cron command should exist
  • user: the user whose crontab to manage
  • cron_name: name the cronjob so future changes to the command will overwrite
  • minute: which minutes to execute the cron
  • hour: which hours to execute the cron
  • month: which months to execute the cron
  • day_of_week: which day of the week to execute the cron
  • day_of_month: which day of the month to execute the cron
  • special_time: cron “nickname” time (@reboot, @daily, etc), overrides others
  • interpolate_variables: whether to interpolate variables in command
Cron commands:
Unless name is specified the command is used to identify crontab entries. This means commands must be unique within a given users crontab. If you require multiple identical commands, provide a different name argument for each.
Special times:
When provided, special_time will be used instead of any values passed in for minute/hour/month/day_of_week/day_of_month.

Example:

# simple example for a crontab
server.crontab(
    name='Backup /etc weekly',
    command='/bin/tar cf /tmp/etc_bup.tar /etc',
    name='backup_etc',
    day_of_week=0,
    hour=1,
    minute=0,
)

server.group

Add/remove system groups.

server.group(group, present=True, system=False, gid=None)
  • group: name of the group to ensure
  • present: whether the group should be present or not
  • system: whether to create a system group
System users:
System users don’t exist on BSD, so the argument is ignored for BSD targets.

Examples:

server.group(
    name='Create docker group',
    group='docker',
)

# multiple groups
for group in ['wheel', 'lusers']:
    server.group(
        name=f'Create the group {group}',
        group=group,
    )

server.hostname

Set the system hostname.

server.hostname(hostname, hostname_file=None)
  • hostname: the hostname that should be set
  • hostname_file: the file that permanently sets the hostname
Hostname file:

By default pyinfra will auto detect this by targetting /etc/hostname on Linux and /etc/myname on OpenBSD.

To completely disable writing the hostname file, set hostname_file=False.

Example:

server.hostname(
    name='Set the hostname',
    hostname='server1.example.com',
)

server.modprobe

Load/unload kernel modules.

server.modprobe(module, present=True, force=False)
  • module: name of the module to manage
  • present: whether the module should be loaded or not
  • force: whether to force any add/remove modules

Example:

server.modprobe(
    name='Silly example for modprobe',
    module='floppy',
)

server.mount

Manage mounted filesystems.

server.mount(path, mounted=True, options=None)
  • path: the path of the mounted filesystem
  • mounted: whether the filesystem should be mounted
  • options: the mount options
Options:
If the currently mounted filesystem does not have all of the provided options it will be remounted with the options provided.
/etc/fstab:
This operation does not attempt to modify the on disk fstab file - for that you should use the files.line operation.

server.reboot

Reboot the server and wait for reconnection.

server.reboot(delay=10, interval=1, reboot_timeout=300)
  • delay: number of seconds to wait before attempting reconnect
  • interval: interval (s) between reconnect attempts
  • reboot_timeout: total time before giving up reconnecting

Example:

server.reboot(
    name='Reboot the server and wait to reconnect',
    delay=60,
    reboot_timeout=600,
)

server.script

Upload and execute a local script on the remote host.

server.script(src)
  • src: local script filename to upload & execute

Example:

# Note: This assumes there is a file in files/hello.bash locally.
server.script(
    name='Hello',
    src='files/hello.bash',
)

server.script_template

Generate, upload and execute a local script template on the remote host.

server.script_template(src)
  • src: local script template filename

Example:

# Example showing how to pass python variable to a script template file.
# The .j2 file can use `{{ some_var }}` to be interpolated.
# To see output need to run pyinfra with '-v'
# Note: This assumes there is a file in templates/hello2.bash.j2 locally.
some_var = 'blah blah blah '
server.script_template(
    name='Hello from script',
    src='templates/hello2.bash.j2',
    some_var=some_var,
)

server.service

Manage the state of services. This command checks for the presence of all the Linux init systems pyinfra can handle and executes the relevant operation.

server.service(service, running=True, restarted=False, reloaded=False, command=None, enabled=None)
  • service: name of the service to manage
  • running: whether the service should be running
  • restarted: whether the service should be restarted
  • reloaded: whether the service should be reloaded
  • command: custom command execute
  • enabled: whether this service should be enabled/disabled on boot

Example:

server.service(
    name='Enable open-vm-tools service',
    service='open-vm-tools',
    enabled=True,
)

server.shell

Run raw shell code on server during a deploy. If the command would modify data that would be in a fact, the fact would not be updated since facts are only run at the start of a deploy.

server.shell(commands)
  • commands: command or list of commands to execute on the remote server

Example:

server.shell(
    name='Run lxd auto init',
    commands=['lxd init --auto'],
)

server.sysctl

Edit sysctl configuration.

server.sysctl(key, value, persist=False, persist_file='/etc/sysctl.conf')
  • key: name of the sysctl setting to ensure
  • value: the value or list of values the sysctl should be
  • persist: whether to write this sysctl to the config
  • persist_file: file to write the sysctl to persist on reboot

Example:

server.sysctl(
    name='Change the fs.file-max value',
    key='fs.file-max',
    value=100000,
    persist=True,
)

server.user

Add/remove/update system users & their ssh authorized_keys.

server.user(
    user, present=True, home=None, shell=None, group=None, groups=None, public_keys=None,
    delete_keys=False, ensure_home=True, system=False, uid=None, add_deploy_dir=True,
)
  • user: name of the user to ensure
  • present: whether this user should exist
  • home: the users home directory
  • shell: the users shell
  • group: the users primary group
  • groups: the users secondary groups
  • public_keys: list of public keys to attach to this user, home must be specified
  • delete_keys: whether to remove any keys not specified in public_keys
  • ensure_home: whether to ensure the home directory exists
  • system: whether to create a system account
  • add_deploy_dir: any public_key filenames are relative to the deploy directory
Home directory:
When ensure_home or public_keys are provided, home defaults to /home/{name}.
Public keys:
These can be provided as strings containing the public key or as a path to a public key file which pyinfra will read.

Examples:

server.user(
    name='Ensure user is removed',
    user='kevin',
    present=False,
)

server.user(
    name='Ensure myweb user exists',
    user='myweb',
    shell='/bin/bash',
)

# multiple users
for user in ['kevin', 'bob']:
    server.user(
        name=f'Ensure user {user} is removed',
        user=user,
        present=False,
    )

server.wait

Waits for a port to come active on the target machine. Requires netstat, checks every second.

server.wait(port=None)
  • port: port number to wait for

Example:

server.wait(
    name='Wait for webserver to start',
    port=80,
)