Introduction

It's not uncommon to need to re-install a computer, in the days when I used Windows more it seemed a good way to re-gain performance, as well as eradicate any viruses or other malware. These days its often because I've upgraded Ubuntu and it hasn't really been seamless. Admittedly this was an issue for Windows too. Generally speaking, upgrades never really feel that clean. Nevertheless I always try it first, just in case it works flawlessly...

The other day I upgraded my desktop to Ubuntu 18.10 and there were a number of quirks, including the periodic loss of all USB devices, visual freezing and inputs not being delivered to applications despite being represented on-screen.

I don't mind a re-install, it is at least cathartic in a way, but I also appreciate the challenges of building a seamless update process for a non-concrete system so I can easily forgive any OS developer for not having a perfect process.

My main gripe is the time required to re-install or restore all the regularly used software that was previously installed!

In addition I have more than one computer at home that I use (usually at least one laptop and desktop) and for a while I have been keen on keeping them in sync so that moving between devices is low friction.

Salt

Over the last few years I have used a number of configuration management tools including Puppet, Chef and SaltStack. Personally I found SaltStack most user friendly and after a few quick searches found that it supports a concept called a Standalone Minion (also known as Masterless). In principal this was exactly what I was looking for.

I had considered having a master/slave setup but unlike production servers its more common for personal devices to be offline, tethered to limited or costly connectivity, or behind devices performing services like NAT,  a firewall, etc, so the topology along with the behaviour and performance when 'offline' becomes a key consideration.

The nice thing about the Masterless setup is that it can all run out a a version controlled repository and each device can be as independent or consistent as desired. If you remove the version control element it is essentially entirely standalone.

It is very straightforward to set up, so this post will not be amazingly extensive but should be enough to get up and running.

Getting Started

The Masterless guide is an excellent starting point: https://docs.saltstack.com/en/latest/topics/tutorials/quickstart.html

To start, Bootstrap Salt, update the minion configuration to use a local file_client.

Then, following the guide, create /srv/salt. As I am the only (or at least primary) user of my devices I opted to own that folder.

Next I made it a git repository with git init . and connected it to GitHub.

top.sls is the starting point for all hosts, declaring on a host-level (minion_id) basis the configurations that should be applied.

Formulas

Salt provides a number of ways to control the configuration of a device, from system packages to custom scripts.

Naturally countless others have already created formulas to solve common requirements: https://github.com/saltstack-formulas.

My repository has a focus on less server-oriented formulas: https://github.com/paul-ridgway/home-salt-configuration and because I currently only use Ubuntu there are a number that are only likely to work on Ubuntu (18.*) and maybe Debian.

My focus has been on the installation and configuration of tools and other elements I use commonly, including elements like configuring shortcuts, gnome extensions and more custom installation scripts.

Application

To apply changes on any machine that has the repository cloned to /srv/salt simply run:

-> % sudo salt-call --local state.apply

Many operations (for example installing packages) require sudo, however when running scripts you can specify which user to runas.