This is the eighth part of the series Save yourself from a disaster: Redundancy on a budget.
Snowflakes servers are our enemies, we should avoid them like the plague. Our best allied are fail-proof reproducible steps, even better if coded in an actionable code, like Infrastructure as Code.
We went through many steps, are you sure you remember all the steps? Yes, I know there this guide, but what if you want to add another server? What if you leave the company? What if you change provider? Too many “what if”.
This guide won’t cover everything, it won’t be a comprehensive guide, and the steps that are shown need to be carefully reviewed and tested in your development/pre-production environment. I don’t take any responsibility for any damage, interruption of service nor leak/loss of data for the use of the instructions in the ebook (nor from any external website I’ve mentioned).
Tools
In our toolbox are necessary Ansible and Terraform, these two will be your best friends in documenting the infrastructure and make everything replicable to scale up/out easily.
Those 2 tools are vendor-agnostic, so they can work with any provider and avoid you to lock-in with a configuration management tool, like AWS CloudFormation / CDK.
Other tools for provisioning are Puppet, Chef and SaltStack.
Remember to keep the Infrastructure as Code always up-to-date, avoid any configuration drifting whatsoever.
Creating VMs
For creating the infrastructure we’ll use Terraform.
This is an example of how to create a new VM (or like they call it a Droplet to be precise):
# Create a web server resource "digitalocean_droplet" "web" { image = "ubuntu-20-04-x64" name = "web-1" region = "fra1" size = "s-1vcpu-1gb" monitoring = "true" ssh_keys = [digitalocean_ssh_key.default.fingerprint] depends_on = [ digitalocean_ssh_key.default, ] }
Just like that we could simply do copy & paste and create many others (even though it is best practice to use the count argument).
Provisioning
--- - name: "Initial Provisioning" hosts: all become: true vars_files: - ../vars/init.yml roles: - oefenweb.swapfile - oefenweb.apt - ahuffman.resolv - ajsalminen.hosts - geerlingguy.ntp - geerlingguy.firewall - dev-sec.os-hardening - dev-sec.ssh-hardening - uzer.crontab tasks: - name: Add user manager ansible.builtin.user: name: "manager" shell: /bin/bash generate_ssh_key: yes ssh_key_type: rsa ssh_key_bits: 4096 - name: Allow manager to have passwordless sudo lineinfile: dest: /etc/sudoers state: present insertafter: '^root' line: 'manager ALL=(ALL) NOPASSWD: ALL' validate: 'visudo -cf %s' - name: "Logrotate Configs" copy: src: "{{ item.src }}" dest: "{{ item.dst }}" with_items: "{{ app_logrotate_config_items }}" - name: Set the policy for the INPUT chain to DROP ansible.builtin.iptables: chain: INPUT policy: DROP
The next post will be about Disaster Recovery Plan, Stay Tuned.
Check out the whole version of this post in the ebook.