For some systems that I have user accounts on but do not administer, I use Salt SSH (agent-less salt minion) to manage the common user-local files that are managed on the systems I do administer on these systems. I have previously made notes about it.

In the past I ran a virtual machine in VirtualBox just for this, however I have been moved onto a Windows laptop at work and VirtualBox will not co-exist nicely with Docker which I also use. As I do not use VirtualBox for much else any more, I have migrated doing this to Docker.

The plan

(Because having a plan is good.)

The Docker build file will set-up a master-less minion, run that to set-up the salt-ssh configuration which will then be the docker image.

Why do this and not just configure it in the Docker file? The salt-ssh configuration is also used on other salt master systems that manage clients, so to keep them consistent using the same mechanism to configure them all provides instant gratification.

The master-less minion

See my previous post on this, but this will be state 1 of the multi-stage build:

FROM debian:latest AS builder
RUN apt-get update
RUN apt-get install -qq salt-minion git
# Kill the service, we do not need it.
RUN systemctl is-active salt-minion && systemctl stop salt-minion
COPY files.conf /etc/salt/minion.d/files.conf
WORKDIR /srv
RUN git clone "https://deploy_user:deply_pass@git_server/path/to/salt-repo.git" salt
COPY minion_id /etc/salt/minion_id
RUN salt-call --local state.highstate

files.conf contains:

file_client: local
file_roots:
  base:
    - /srv/salt/states
pillar_roots:
  base:
    - /srv/salt/pillar

and minion_id contains:

salt-ssh.docker

At this stage of the docker build I have a Debian image that has my salt-ssh configuration.

The salt-ssh build

Now that we have gotten salt-minion to bootstrap the configuration, I can build a salt-ssh image:

FROM debian:latest
RUN apt-get update
# Why doesn't salt-ssh depend on an ssh client?
RUN apt-get -qq install salt-ssh openssh-client
COPY --from=builder /srv/salt /srv/salt
COPY --from=builder /etc/salt /etc/salt
COPY --from=builder /var/lib/salt /var/lib/salt
# salt-ssh falls over if the salt user doesn't exist
RUN useradd -d /var/lib/salt -s /bin/sh salt
ENTRYPOINT ["salt-ssh"]

And the image can be built from a directory containing the two docker snippets above as Dockerfile, plus the files.conf and minion_id file:

docker build --rm -t salt-ssh salt-ssh/

and run like this:

docker run salt-ssh --help

Future improvements

It might be more space-efficient to base this on Alpine rather than Debian, however all of my salt states are only tested on the platforms I have which are Debian, Windows and some macOS & CentOS.