hmm there several ways:
For example: stateful (puppet (provisioning client) + puppeteer (provisioning - server)) are things like puppet -> you save your puppet configuration and you system will be restored to this template. (ruby)
so you update your puppet configuration and your system will update as well as you got a meta representation of you configuration.
stateless ansible / fabric again same thing you can version it in git and trigger your setup via ansible script. They basically do the thing that Emil Moe mentioned but you can have it concurrent with results (python)
Those are just the top of my head things. And ofc I tend to put everything biznez related into a LXC container aka docker. But even here as moe mentioned it depends on your usecase as well as time and interest in this topic.
j
stuff ;)