How do I setup Phoenix Qubes with Salt?

Hi @restive,

I am not overly familiar with @unman’s formulas, but I hope I can help clarifying some aspects of using Salt in Qubes OS:

  • You can read about top files in the official Salt documentation (they are not specific to Qubes OS). They are the mechanism that allows to coordinate multiple state files (.sls) together. (Remember: Salt state files should ideally be kept as simple and reusable as possible --do little and do it clearly-- so you’ll often need a few of them to achieve anything meaningful.)
  • Salt minions are indeed assumed to be separate machines that operate independently. That being said, isn’t that also the underlying assumption in Qubes OS? (And the base of compartimentalization?)

I agree that the official Salt docs don’t always seem to match closely some scenarios that are common in Qubes OS, yet I don’t think it has to do with minions being separate independent machines or not.

What I think makes using Salt with Qubes OS somewhat different to what the official docs describe is that:

  • Usually, in non-Qubes OS scenarios, minions exist already before we even consider applying Salt formulas to them.
  • In Qubes OS, ensuring the presence of the qubes (and creating them if necessary) is often part of a Salt formula’s reponsibilities. (Whether you make that the responsibility of a dedicated formula or make it part of bigger formulas is up to you. I include the qubes presence as part of the formulas I write, but there are pros and cons to each approach.)
  • In Qubes OS, some jobs also require interacting with multiple qubes (for example, installing packages is usually done in a qube’s template).

In that context, I find that top files come handy to create logical units. For example, in this tutorial about creating a Salt state for split-SSH, ensuring that a qube is configured to behave like a “SSH client” involves some configuration in dom0, some in the qube template and some in the qube itself, but all that can be enabled at once by enabling a single top file, and the entire state across those three qubes can be applied with a single command.

Example top file:

# /srv/user_salt/split-ssh/client.top

user:
  dom0:
    - split-ssh.client.vm # sls file that ensures the ssh-client qube exists

  fedora-32:
    - split-ssh.client.packages # sls file that ensures required packages are available in ssh-client

  ssh-client:
    - split-ssh.client.sock # sls file that ensures ssh-client is configured (ensures the presence of a Unix socket in this case, hence the name)

Example usage:

# dom0

sudo qubesctl top.enable split-ssh.client # only once, to enable the top file

sudo qubesctl --target=fedora-32,ssh-client state.apply # as often as you want. This applies all the enabled top files and ensures that ssh-client exists and is properly configured. (Note that dom0 is an implicit target.)

Disclaimer: the tutorial collects my own notes as I make sense of using Salt in Qubes OS, so you’ll find that it closely matches the way I think about top files. That doesn’t mean it’s the only way to think about them, or that it’s the way that will work best for you. That way of thinking allows me to reliably create states for specific Qubes OS features (like split-SSH) where all pieces seem to fit nicely together, so I believe you may find it useful to complement other docs you are reading about Salt and Qubes OS, but you tell me!

Anyhow, I hope these thoughts on top files help! :slightly_smiling_face:

Also: the tutorial linked above describes how to create a Salt state. Bringing Salt pillar into the mix to create a Salt formula is possible and makes the state configurable, but I found useful to wrap my head around how states work in Qubes OS before adding that extra layer. In the same page as the tutorial there is a follow up example of how that split-SSH state looks like once turned into a configurable formula if you don’t mind reading some code.