Skip to content

feat(facts, operations): add support for s6-rc service management - #1854

Draft
epicrazzmatazz wants to merge 25 commits into
pyinfra-dev:3.xfrom
epicrazzmatazz:s6
Draft

feat(facts, operations): add support for s6-rc service management#1854
epicrazzmatazz wants to merge 25 commits into
pyinfra-dev:3.xfrom
epicrazzmatazz:s6

Conversation

@epicrazzmatazz

@epicrazzmatazz epicrazzmatazz commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

s6 is a set of utilities for process supervision, service management, linux PID 1, and more. It is in active development; a new frontend was released in January, tying all the components together in an easier to use CLI. A few linux distributions use s6: antiX, Artix linux, Bedrock linux, Obarun, and glaucus, as well as docker containers using the s6-overlay project.

Why

Because I use it on my machine, and I think it will be more popular in the future. Alpine linux devs plan to switch to s6 as the init system and service manager once it is ready.

Implementation

"Big" operations implement logic for idempotence while calling smaller stateless operations. The smaller operations often correspond directly to an s6 program, just being a light wrapper around them.

Unlike other service management operations, s6.service can manage multiple services in one operation call, leveraging s6 live's option to specify multiple services at once.

At this time, most of the code relies on the s6 program from s6-frontend. The facts sometimes fall back to the lower-level programs such as s6-rc-repo-list as needed when the s6 program is insufficient. Because of the reliance on s6, the operations inherit the management policy from s6-frontend (below).

^ No longer true, I have since migrated most operations to use the lower-level programs.

Currently, the "big" operations don't support managing repositories outside of the one configured in /etc/s6.conf or the compiled-in defaults, which are the implicit repositories for the s6 commands. As such, user services are not yet supported.

Checklist

Will check these off as I complete them, as this is a draft PR

  • Pull request is based on the default branch (3.x at this time)
  • Pull request includes tests for any new/updated operations/facts
  • Pull request includes documentation for any new/updated operations/facts
  • Tests pass (see scripts/dev-test.sh)
  • Type checking & code style passes (see scripts/dev-lint.sh)
  • Pull request title follows the
    conventional commits format

@wowi42 wowi42 added new feature facts Issues with facts. operations Issues with operations. CLI CLI mode specific issues. labels Jun 29, 2026
@epicrazzmatazz

Copy link
Copy Markdown
Contributor Author

tests/operations/s6.set_save/save_force_backup.yaml test failed on the Windows runner, but not the Ubuntu runner. I set the required platforms to "Linux" and "Darwin" for that test to continue with the GitHub checks. Seems to be something with the way fake files.Directory facts from fixtures are handled on Windows?

FAILED tests/test_operations.py::s6.set_save::test_s6_set_save_save_force_backup - KeyError: 'Missing test fact key: files.Directory -> path=/etc/s6/repo\\myset'

logs

@wowi42 wowi42 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issues

1. Shell injection in command parameter (inline)

2. raise RuntimeWarning instead of warnings.warn (inline)

Notes

  • The idempotent_notice on service() says "only when at least one of commit_set or install_set are True" but restarted, reloaded, and command also break idempotency. The notice should list all non-idempotent triggers or the operation should be split.
  • S6SetStatus.check_preconditions always checks /etc/s6/frontend.conf even when the fact will use s6-rc-set-status (non-default repository/set). This causes false negatives when using a non-default repository. check_preconditions doesn't receive the fact's parameters, so this is a design limitation worth documenting in the fact's docstring.
  • S6SetStatus docstring warns about _success_exit_codes=[3] being needed, but the command uses echo EXIT CODE: $? to capture the exit code as text output, so the overall exit code is always 0. The note is misleading and should be removed.
  • The set function name shadows the built-in set, requiring import builtins + builtins.set(...). Consider renaming the operation or the parameter.
  • dont_restart_if_stopped.yaml fixture is missing noop_description (test warns about it).

Comment thread src/pyinfra/operations/s6.py Outdated
yield from live_install._inner()

if command:
yield make_formatted_string_command("s6 {0}", command)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

command is user-controlled and passed unquoted to make_formatted_string_command. When command = "system reboot; rm -rf /", the rendered command is s6 system reboot; rm -rf / — the semicolon is interpreted by the shell. Since command is meant to be a multi-word s6 subcommand, use shlex.split and quote each token:

if command:
    yield StringCommand("s6", *map(QuoteString, shlex.split(command)))

Comment thread src/pyinfra/operations/s6.py Outdated
)
if len(lines) != 1:
# no OperationWarning
raise RuntimeWarning(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RuntimeWarning is a Warning subclass, not an exception meant for raising. Use warnings.warn(...) or log via logger.warning(...). Raising it will crash the deploy with a traceback, which is not the intent of a warning.

@epicrazzmatazz

Copy link
Copy Markdown
Contributor Author

Thanks for the early review. I'm still working on this feature, albeit slowly due to other priorities, so I may not address the concerns for some time. I will remove the draft status and squash the commits when I am satisfied with the API and implementation that I still may change a little and when I have tested a local deploy on my machine with s6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLI CLI mode specific issues. facts Issues with facts. new feature operations Issues with operations.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants