Cloud Systems

Using cloud config with CoreOS

CoreOS has depreciated cloud-config… see https://coreos.com/ignition/docs/latest/what-is-ignition.html

This is how I got a CoreOS box up on Digital Ocean using a cloud configfile.  You can find the cloud-config documentation with examples on the CoreOS site.  When I first did this many months ago, the documentation didn’t have much in the way of real examples.  Thankfully its been updated.

What is a cloud config file and its purpose?  Well it is to give brand new servers a starting point that makes sense, and can help with automation.  Cloud config is written with YAML, which is a simple text file with basic formatting.  The “old way” of ordering a cloud server would give some email or popup box with the root password to let you login. A cloud config lets you define users, ssh-keys, firewalls and do basic file creation. No more dealing with clunky password exchanges from your cloud provider, or hoping the SSH key you have is current in the “defaults” server creations. or do many manual steps before you can have the new server able have automation services build out the system.  I recommend doing just enough so you can fire up a system automation tool without first needing to login and setup enough access right manually for automation to work.

This screenshot is from Digital Ocean when creating a new server (droplet).  Once I select the ‘User Data’ checkbox, I can paste in my cloud-config yml.  Part of the confusion is that all the different cloud providers that support CoreOS don’t always make it clear where one should be putting the cloud-init.yml contents when creating new servers.

cloud-init.yml
digital ocean droplet for CoreOS with cloud-init.yml

In my case, I’m doing a few basic things:

  • Starting iptables (firewall) on boot
  • Adding my user account and my ssh pub key so I can login
  • Adding my user to various system groups so I can run docker commands and sudo
  • Setting the contents of the iptables file.  In this instance, I’m using Cloudflare as my CDN/WAF, thus port 80 is only listening for Cloudflare IPs.  Because my home IP is dynamic, I cannot limit down port 22 (ssh).
  • Disabling root login for ssh

Taking the cloud-init a step further, you might install service discovery (I like consul for this)  and define the role of the new server.

Also take note that you cannot later change the cloud config file.  This is for the first boot up of the new server.  It is never used again.  Thus order and destroy a small server while working on a cloud config script.

#cloud-config

---
coreos:
 units:
 - name: iptables-restore.service
 enable: true
 command: start
 - name: "docker.service"
 enable: true
 command: "start"
users:
- name: joecool
 ssh-authorized-keys:
 - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINe6e1zxtHDUK6mhYY0YQeoMQukIdDchyL8+o9xgUle7 joecool@local
 shell: "/bin/bash"
 groups:
 - docker
 - rkt
 - fleet
 - docker
 - systemd-journal
 - portage
 - sudo
write_files:
- path: "/var/lib/iptables/rules-save"
 permissions: 420
 owner: root:root
 content: |
 *filter
 :INPUT DROP [0:0]
 :FORWARD DROP [0:0]
 :OUTPUT ACCEPT [0:0]
 -A INPUT -i lo -j ACCEPT
 -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 103.21.244.0/22 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 103.22.200.0/22 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 103.31.4.0/22 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 104.16.0.0/12 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 108.162.192.0/18 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 131.0.72.0/22 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 141.101.64.0/18 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 162.158.0.0/15 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 172.64.0.0/13 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 173.245.48.0/20 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 188.114.96.0/20 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 190.93.240.0/20 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 197.234.240.0/22 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 198.41.128.0/17 --dport 80 -j ACCEPT
 -A INPUT -p tcp -m tcp -s 199.27.128.0/21 --dport 80 -j ACCEPT
 -A INPUT -p tcp --dport 80 -j REJECT
 COMMIT
runcmd:
- sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
- restart ssh