I see. This is really astonishing.
I always preferred using plain SSH and Shell for automatically configuring servers.
That's why I had a look at Ansible, but despite this simple concept, it seemed too bloated to me: too many layers around this simple idea. But I had never thought to be proven right, let alone that this complexity actually translates into 6 scary security holes in a row.
To propose an alternative, this is how I'm currently doing it. I'd love to hear what others think about it, or whether others have tried similar things:
Note: This works best of a relatively small and/or heterogenous set of servers/VMs. So it's not really the full-blown Ansible use case. But then, how many people really do have billions of users and a large set of homogenous servers at their hands? I bet the "long tail" of web applications doesn't need more than a few servers. Or, if your hardware is strong enough, just two servers, where the first one takes all the load, and the second one is a failover system on stand-by.
Use a plain shell and plain shell commands, which has the advantage that you can quickly try these interactively in any VM. Use "set -eu" so it halts on error, instead of blindly executing all following commands. Use appropriate commands, e.g. "install" instead of "cat+chmod+chown". Use "--backup=numbered" to keep backups of previous versions of files, if you want. Use only idempotent commands, i.e. commands that you can run multiple times without changing anything of significance. Prefer portable commands, but use distro-specific code as needed. The time you switch to another distro you'll have a new script, anyway, because you'll have a different system with different requirements. Write everything down in the style of a "copy&paste" documentation (Does this count as "literate programming"?), but put all your remarks in shell commands. Then automate the "paste" part by making it executable.
Example file (executable file "myserver_config"):
#!/bin/sh
tail -n +3 "$0" | ssh -p 1234 root@myserver_ip ; exit
set -eu
# Install packages
...
# Configure Foo
...
# Configure Bar
...
# Configure Nginx
#
# Configure Nginx so that the foo fits into the bar
# and boggles the foobar.
install --backup=numbered -o root -g root -m 600 /dev/stdin /etc/nginx/nginx.conf <<'EOF'
error_log /var/log/nginx/error.log;
events {
...
}
http {
access_log /var/log/nginx/access.log;
...
}
EOF
# Do more stuff
...
Edit this file and redeploy by simply executing it:
./myserver_config
The script may seem hard to read, but with syntax highlighting it is a breeze. And you can easily convert this to HTML, AsciiDoc or Markdown if you need a "real" documentation for your customer or other project members. It's just a few lines of code in Python, or whatever language you prefer.