Managing Systems and Applications with pyinfra
Using Host Data
You can also assign data to individual hosts. For example, you might assign a list of packages to install on each host. This is done by using a tuple with the hostname and a dictionary of data in the group list in the inventory file (inventory.py), as illustrated in Listing 1.
Listing 1
inventory.py with Host Data
01 servers = [
02 ("podpile.home", {"packages": ["tmux", "vim"]}),
03 ("code.example.com", {"packages": ["tmux"]})
04 ]
05 workstations = [
06 ("nov.home", {"packages": ["git", "tmux", "vim", "taskwarrior"]}),
07 ("tux.home", {"packages": ["git"]})
08 ]
With this host data in the inventory, the deploy file (deploy.py) can be made more generic, referring to the packages variable as host.data.packages, as in Listing 2. When you run this deploy, pyinfra installs a specific list of packages on each host.
Listing 2
deploy.py to Install Packages
01 from pyinfra import host 02 from pyinfra.operations import server 03 04 server.packages( 05 name="Install packages", packages=host.data.packages, _sudo=True 06 )
Using Group Data
Of course, you create groups of your hosts because they share common features. Therefore, pyinfra allows you to assign data to a group. For instance, if you want to install tmux and Vim on all your servers, you can define these in group_data/servers.py with
packages = ["tmux", "vim"]
And then, to install Git, tmux, Vim, and Taskwarrior on all your workstations, you would define them in group/data/workstations.py like this:
packages = ["git", "tmux", "vim", "taskwarrior"]
Within your inventory file, you can remove the host data, though you can still override the data for particular hosts. If you specify a key with host data in the inventory file, pyinfra uses this value. If not, it searches for the variable in the group data file from the host's group. If it isn't found there, it searches for the variable in a file group_data/all.py.
Installing Caddy in a Task
When your pyinfra deploy becomes more complex, it's best to break it into tasks. You can create a tasks directory and then put each task in its own Python file. I'll create a task to install the Caddy [6] web server, which will install the caddy package, upload a configuration file, and then restart and enable Caddy's systemd service. The task to accomplish this is shown in Listing 3.
Listing 3
Task to Install Caddy
01 from pyinfra import host 02 from pyinfra.operations import server, files, systemd 03 04 server.packages(name="Install Caddy", packages=["caddy"], _sudo=True) 05 06 caddyfile_installed = files.template( 07 name="Upload templated Caddyfile", 08 src="templates/Caddyfile.j2", 09 dest="/etc/caddy/Caddyfile", 10 message=host.data.welcome_message, 11 _sudo=True, 12 ) 13 14 systemd.service( 15 name="Restart Caddy", 16 service="caddy", 17 restarted=True, 18 enabled=True, 19 _sudo=True, 20 _if=caddyfile_installed.did_change, 21 )
After installing Caddy, this task uses the files.template operation to generate a Jinja2 [7] template and copy the result to the Caddyfile. Then the systemd.service operation restarts Caddy's systemd service, but only if the Caddyfile was changed.
The template, in templates/Caddyfile.j2, looks like
:80 {
respond "{{ message }}"
}The message placeholder is replaced by the message argument in the files.template operation, which points to host.data.welcome_message. So you need to set this host data in the inventory file:
webservers = [
("playground.home", {"packages": ["tmux"], "welcome_message": "Hello world!"})
]If your intent is to execute the Caddy task only on web servers, change your deploy.py according to Listing 4.
Listing 4
Import Specific Group Tasks in deploy.py
01 from pyinfra import host, local
02 from pyinfra.operations import server
03
04 server.packages(
05 name="Install packages", packages=host.data.packages, _sudo=True
06 )
07
08 if "webservers" in host.groups:
09 local.include("tasks/caddy.py")
Running tasks for specific hosts is also possible:
if host.name == "playground.home":
local.include("tasks/caddy.py")Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Digital Autonomy
• How the Fediverse Found Parts for Its Platforms
• The Answer Was Already on the Shelf
• Changing the Chip Industry: How Public Investment Has Grown Open Silicon
• United Nations Open Source Portal Goes Live
• EU Open Source Strategy Plays Key Role in Tech Sovereignty Package
• France Says “Au Revoir” to Microsoft
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Epic Games Targets Linux for New Launcher
The Epic Games new launcher is still in preview, but it looks to land on several Linux distributions.
-
Fedora 45 Now Available
The latest iteration of Fedora has arrived with Gnome 51 and KDE Plasma 6.8.
-
Linux 7.4 is "Much Healthier" Thanks to AI
At nearly 42 million lines, Linux 7.4 is the largest merge in the kernel’s history.
-
Working Exploit for a Linux Kernel Flaw Made Public
Even before a bug received its CVE identifier or an upstream fix, the local privilege escalation vulnerability exploit found its way into the wild.
-
r/opensource Bans AI-Assisted and AI-Related Projects
The de facto subreddit for all things open source has not only banned AI-related projects but also users who "don't speak English."
-
Bottlenecks Discovered by Meta Engineers Lead to Scalability Improvements
Thanks to a small group of engineers at Meta, the Linux kernel module kernfs has been improved, which has led to some serious gains.
-
PwnEscape Poses VM Vulnerability
A guest-to-host escape flaw in Linux KVM, named PwnEscape, might be yet another means of attacking Linux.
-
Linux Mint 27 Set for a Christmas Release
The developers behind Linux Mint have announced a Christmas release, and it looks like Santa's sack will be brimming with features.
-
Is Linus Torvalds Vibe Coding?
The creator of Linux has added AI into his process for Linux kernel development, and it's more than just for debugging.
-
openKylin 3.0 Released with Expanded AI Integration
The latest release features a pre-installed AI agent to help perform tasks.
