[Salt][] is a remote execution and automated deployment system. It's great for running your own clusters once your website outgrows a single box. If you get bored of running your own boxes, you can use [salt-cloud][] to provision minions on someone else's cloud (Amazon EC2, Linode, …). You can install Salt on [[Gentoo]] with: # USE=git emerge -av app-admin/salt [Usually][syndic] you'll have one master, and a host of minions running salt daemons that locally execute commands sent from the master. After setting up [[BIND]] so `salt` (the [default master name][master-name]) resolves to your development box, you should be able to run: # rc-service salt-master start # rc-service salt-minion restart # salt-key -L Accepted Keys: Unaccepted Keys: devbox.example.net Rejected Keys: # salt-key -A The following keys are going to be accepted: Unaccepted Keys: devbox.example.net Proceed? [n/Y] y Key for minion devbox.example.net accepted. If you were not confined to the local box, it would be wise to compare the proposed key: # salt-key -p devbox.example.net with that on the minon itself: # cat /etc/salt/pki/minion/minion.pub before accepting the key. Once you have accepted the minon, ping it: # salt '*' test.ping devbox.example.net: True Then you can browse through all of the [available goodies][api]: # salt '*' sys.doc Once you've had some fun reading about those, it's time to [configure your state tree][state]. For a quick intro, we can just borrow the [salt-state example repository][salt-states]. The salt state data is conventionally kept in `/srv/salt`, which seemed odd to me, but does indeed follow the [FHS][FHS-srv]. # mkdir /srv/ $ git clone git://github.com/saltstack/salt-states.git # mv salt-states /srv/salt This leaves `/srv/salt` owned by my personal user (instead of root), because as much as I love [[Git]], I'm not going to run it as root. Once you've got a state tree in `/srv/salt`, you can mock-install the configured state for each node. It's always a good idea to [test your commands][testing] before you run them, to make sure they won't do something wonky. # salt '*' state.highstate test=True devbox.example.net: ---------- State: - file Name: /etc/hosts Function: comment Result: None Comment: File /etc/hosts is set to be updated Changes: ---------- State: - file Name: /etc/hosts Function: uncomment Result: True Comment: Pattern already uncommented Changes: ---------- State: - cmd Name: date > /tmp/date Function: run Result: None Comment: Command "date > /tmp/date" would have been executed Changes: ---------- … You can also install a particular sub-state on a particular minon (again, I'm showing the testing version): # salt 'devbox.example.net' state.sls python,ssh.server test=True devbox.example.net: ---------- State: - pkg Name: openssh Function: installed Result: False Comment: Package category missing for "openssh" (possible matches: net-misc/openssh). Changes: ---------- State: - pkg Name: python-mako Function: installed Result: False Comment: Package category missing for "python-mako" and no match found in portage tree. Changes: ---------- … The comments (Package category missing for…) mean that the [salt-states][] repository hasn't been updated to [recent][3008] [versions][3009] [of][3019] Salt (0.12+), which [require fully qualified package names][ebuild-cat]. You can also install a particular [ID declaration][id] on a particular minon (again, I'm showing the testing version): # salt 'devbox.example.net' state.sls python,ssh.server test=True For single-box testing, you can also skip the master node, running commands on a [masterless minion][masterless] by using `salt-call --local` instead of `salt ''` in your Salt invocations: # salt-call --local state.highstate test=True local: ---------- State: - file Name: /etc/hosts Function: comment Result: None Comment: File /etc/hosts is set to be updated Changes: ---------- … Because you don't have a master passing you state, `--local` calls require you to have the state stored on your local box (in `/srv/salt` by default). It's hard to imagine using Salt without storing state anywhere ;). It's also possible to [run Salt as a non-root user][nonroot], but I haven't looked into that yet. [Salt]: http://saltstack.com/community.html [salt-cloud]: https://github.com/saltstack/salt-cloud [syndic]: http://docs.saltstack.com/ref/syndic.html [master-name]: http://docs.saltstack.com/ref/configuration/minion.html#master [api]: http://docs.saltstack.com/ref/modules/all/ [state]: http://docs.saltstack.com/topics/tutorials/starting_states.html [salt-states]: https://github.com/saltstack/salt-states [FHS-srv]: http://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#SRVDATAFORSERVICESPROVIDEDBYSYSTEM [testing]: http://docs.saltstack.com/ref/states/testing.html [3008]: https://github.com/saltstack/salt/pull/3008 [3009]: https://github.com/saltstack/salt/pull/3009 [3019]: https://github.com/saltstack/salt/pull/3019 [ebuild-cat]: http://docs.saltstack.com/ref/modules/all/salt.modules.ebuild.html [id]: http://docs.saltstack.com/ref/states/highstate.html#id-declaration [masterless]: http://docs.saltstack.com/topics/tutorials/quickstart.html [nonroot]: https://salt.readthedocs.org/en/v0.17.0/topics/nonroot.html [[!tag tags/linux]] [[!tag tags/tools]]