Server Operations¶
The server module takes care of os-level state. Targets POSIX compatibility, tested on Linux/BSD.
Facts used in these operations: server.Crontab, files.Directory, files.FindInFile, server.Groups, server.Home, server.Hostname, server.KernelModules, files.Link, server.Locales, server.Mounts, server.Os, server.Sysctl, server.Users, server.Which.
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 forminute
/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
- gid: use a specific groupid number
- 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 using hostnamectl
or hostname
on older systems.
server.hostname(hostname, hostname_file=None)
- hostname: the hostname that should be set
- hostname_file: the file that permanently sets the hostname
- Hostname file:
The hostname file only matters no systems that do not have
hostnamectl
, which is part ofsystemd
.By default pyinfra will auto detect this by targeting
/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.locale
¶
Enable/Disable locale.
server.locale(locale, present=True)
- locale: name of the locale to enable/disable
- present: whether this locale should be present or not
Examples:
server.locale(
name="Ensure en_GB.UTF-8 locale is not present",
locale="en_GB.UTF-8",
present=False,
)
server.locale(
name="Ensure en_GB.UTF-8 locale is present",
locale="en_GB.UTF-8",
)
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, device=None, fs_type=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.packages
¶
Add or remove system packages. This command checks for the presence of all the system package managers pyinfra can handle and executes the relevant operation.
server.packages(packages, present=True)
- packages: list of packages to ensure
- present: whether the packages should be installed
Example:
server.packages(
name="Install Vim and vimpager",
packages=["vimpager", "vim"],
)
server.reboot
¶
Stateless operation
This operation will always execute commands and is not idempotent.
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
¶
Stateless operation
This operation will always execute commands and is not idempotent.
Upload and execute a local script on the remote host.
server.script(src, args=())
- src: local script filename to upload & execute
- args: iterable to pass as arguments to the script
Example:
# Note: This assumes there is a file in files/hello.bash locally.
server.script(
name="Hello",
src="files/hello.bash",
)
# Example passing arguments to the script
server.script(
name="Hello",
src="files/hello.bash",
args=("do-something", "with-this"),
)
server.script_template
¶
Stateless operation
This operation will always execute commands and is not idempotent.
Generate, upload and execute a local script template on the remote host.
server.script_template(src, args=())
- 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.security_limit
¶
Edit /etc/security/limits.conf configuration.
server.security_limit(domain, limit_type, item, value)
- domain: the domain (user, group, or wildcard) for the limit
- limit_type: the type of limit (hard or soft)
- item: the item to limit (e.g., nofile, nproc)
- value: the value for the limit
Example:
security_limit(
name="Set nofile limit for all users",
domain='*',
limit_type='soft',
item='nofile',
value=1024,
)
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
¶
Stateless operation
This operation will always execute commands and is not idempotent.
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, create_home=False, system=False, uid=None,
comment=None, add_deploy_dir=True, unique=True, password=None,
)
- 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 - create_home: whether to new user create home directories from the system skeleton
- system: whether to create a system account
- uid: use a specific userid number
- comment: the user GECOS comment
- add_deploy_dir: any public_key filenames are relative to the deploy directory
- unique: prevent creating users with duplicate UID
- password: set the encrypted password for the user
- Home directory:
- When
ensure_home
orpublic_keys
are provided,home
defaults to/home/{name}
. Whencreate_home
isTrue
any newly created users will be created with the-m
flag to build a new home directory from the systems skeleton directory. - 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.user_authorized_keys
¶
Manage authorized_keys of system users.
server.user_authorized_keys(
user, public_keys, group=None, delete_keys=False, authorized_key_directory=None,
authorized_key_filename=None,
)
- user: name of the user to ensure
- public_keys: list of public keys to attach to this user,
home
must be specified - group: the users primary group
- delete_keys: whether to remove any keys not specified in
public_keys
- 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_authorized_keys(
name="Ensure user has a public key",
user="kevin",
public_keys=["ed25519..."],
)
server.wait
¶
Stateless operation
This operation will always execute commands and is not idempotent.
Waits for a port to come active on the target machine. Requires netstat, checks every second.
server.wait(port)
- port: port number to wait for
Example:
server.wait(
name="Wait for webserver to start",
port=80,
)