Skip to content

Instantly share code, notes, and snippets.

@vlandham
Forked from deathbearbrown/deployment-notes.md
Created December 18, 2015 18:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlandham/e54ef60de80b1302ae75 to your computer and use it in GitHub Desktop.
Save vlandham/e54ef60de80b1302ae75 to your computer and use it in GitHub Desktop.

Command Line Basics

Rando Stuff

Find the full path of the folder you're in

pwd

Find your username on your machine

whoami

Create a new empty file

touch filename.txt

Open finder folder to where you are (only works on Mac).

open .

Open a file in a specific application (on Mac)

open -a "applicationname" filename

eg - open -a "sublime text" playbook.yml

File Permissions

View what's inside a folder:

ls /path

View the permissions of what's inside a folder:

ls -la /path

Change the permissions of a file:

chmod 400 filename

The 400 is the type of permissions you want to give it.

Change the permissions of a folder:

chmod -R 400 folder

The R is for recursive, so it's changing everything in there :)

Here is an example:

 chmod 400 ~/.ssh/id_rsa

This would change the permissions for the id_rsa file in the folder .ssh.

Unix file permissions are a non-trivial topic! Here, we are glossing over the specifics of what particular permissions this file has.

SSH

SSH allows you to connect to a remote server via the command line and work and do things on that remote computer.

To log into a remote box using ssh, you would do something like

ssh name.of.remote.host.com

Here is an example where we log into the remote machine known as workshop.learndeployment.com

ssh workshop.learndeployment.com

Now - this is trying to connect to the remote machine as you. If your username is 'happy' on your machine, this command would try to log onto the remote machine as the user 'happy'.

Sometimes, you want to log in as a different user. To do this, you would prepend the username and then the @ to the path of the server you are trying to connect to.

Let's try to log into the remote server as the user 'sad':

 ssh sad@workshop.learndeployment.com

if you want your computer to sing to you when you can loging

watch -t 'ssh -i ssh-basics/privatekey.pem workshop@workshop.learndeployment.com echo I have logged in |say -v Cellos'

Known Hosts

When you log into a machine for the first time, an new line will be added to your ~/.ssh/known_hosts file

You could look at your current known_hosts using the cat command:

cat ~/.ssh/known_hosts

But sometimes, the actual machine behind a server gets changed. This changes the unique 'signature' or 'fingerprint' for the server you are trying to connect to - which is a red flag to ssh. If the fingerprint of your server has changed, the fingerprint listed in your known_hosts file won't match the new fingerprint of your server - and ssh won't allow you to connect.

You can remove the entry in your known_hosts using the

ssh-keygen -R domain.com (or IP address)

Lets try removing workshop.learndeployment.com

ssh-keygen -R workshop.learndeployment.com

You could also just edit the known_hosts file directly - but that can be tedious and fragile.

SUDO

Each user on a unix machine has a certain set of permissions. A bit different from "file permissions", "user permissions" indicate what actions the user can do on a server.

Your default user will typically not have the capability to do much - and so "elevating" to a user that does have permissions becomes something you want to do often.

The su command allows you to "switch users". You can use this to switch users to the 'root' user. The root user is the canonical name for the user with all permissions on the server.

Here is how to switch to the root user:

sudo su -

You should be asked for a password. At Bocoup, this password has been set to your 'shadow password'. This is a special password setup for you by the coop. If you don't remember your shadow password, you can contact Tyler to get it reset.

But if you are successful in logging in, your terminal prompt should change to look something more like:

root@ip-172-31-35-223:~#

The 'root' at the front indicates you are logged in as root. The stuff that follows is the ip address or name of the server. The # is another indicator that you are now logged in as root.

BE CAREFUL!

As root, you can wreck everything. :O Like literally delete all the things.

Why do you need sudo and su ?

su is just for switching user. Only root can do this. But we can't log in as root just willy nilly.

So we have to elevate "as" root first and then switch to the root user. The sudo command runs the current command using "root privelages"

ANSIBLE

What is Ansible?

Ok. What is Ansible anyways? Ansible is an open source tool that can be used to automatically setup and configure new servers. This is really powerful for a group like Bocoup as every time we want to spin up a new server (for a client, or for a new wordpress site, or for fun), we don't have to remember all the commands to get it going. You also don't have to sit and type all the commands manually. Instead, we can write some Ansible configuration just once, and have Ansible run using this configuration to setup the server just like we want it. Ansible is also easier to use than say, Chef (a competing provisioning tool), which was made by the Devil.

What does it mean to 'setup' a server? Well, each server we use needs some basic tools installed to make it ready to work with. A webserver. A compiler. Perhaps even a database needs to be installed. All this can be configured automatically. Additionally, other configurations like "who has access to this server" can be automated using something like Ansible.

A good way to demystify setting up a server, is to think of it like setting up your local machine for a project. If you're working on a wordpress site, you'd need MYSQL & PHP, and nginx or apache to serve it. Same with a server. (Just don't install MAMP on a server, that's nuts.) You might be used to using Homebrew on a mac to install things. These are linux servers, and they use apt-get. Ansible set ups run those commands for you as well as bash, pip, modifying files and anything else you gotta do.

Also, don't be scared of setting up servers. You can always destroy and recreate them. Breaking servers is really fun. Better than bricking your local machine ;D

Ansible playbooks

The overall configuration structure in Ansible lingo is known as a 'playbook'. These playbooks are 'declarative' - which should make it easier to understand then complex bash scripts. Storing configurations in a playbook means we can keep our servers consistent and easily spin up new servers.

Ansible configuration is written in 'YAML' - a human friendly markup language - which is equavalent to JSON. The playbook commands can be written in JavaScript.

Playbooks are just written in YAML files. YAML files are just text files. Typically, YAML files end with a .yml suffix.

Yaml is picky about spacing and indentation. Use this linter: http://www.yamllint.com/

Lets create one now!

touch playbook.yml

Will create a new blank yml file

We can edit this file to include a yaml configuation. Add this to the playbook.yml file:

- hosts: all

What does this mean? It means - for all the hosts you indicate (as part of running the playbook) run this playbook on all of them. This particular playbook has no other stuff - so it will do nothing more to run it - and then exit.

Now we want to run this playbook on the servers we want. As a shortcut, we can pass in the name of the host we want to run this on from the command line:

ansible-playbook -i vlandham.learndeployment.com, playbook.yml

With this command, we are running our playbook.yml on the server name you passed in. in this case vlandham.learndeployment.com. Note the COMMA "," in there.

If this is successful, you should see something like:

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [vlandham.learndeployment.com]

PLAY RECAP ********************************************************************
vlandham.learndeployment.com : ok=1    changed=0    unreachable=0    failed=0

So this is cool! We've run some commands on a remote machine (your server) without having to explicitly log in and run the commands manually.

Inventory Files

Inventory files are used to list servers that you are interested in working with. Instead of passing in the server name when you run the command (which would be hard to remember and hard to do for lots of servers), you can create a Inventory file to specify the servers you want to run the playbook on.

Inventory files are written in INI format. Each server name goes on a new line.

touch inventory

Creates a new file called inventory. Lets add our server name to this inventory file. edit the file to include:

vlandham.learndeployment.com

or whatever the name of your server is. We can run the playbook with our new inventory file:

ansible-playbook -i inventory playbook.yml

Ansible Tasks

Ok. Right now our playbook can connect - but doesn't do anything yet. Tasks are how we get ansible to execute commands for us.

We add tasks to our playbook.yml by providing a tasks: section.

Let's add a tasks section to our playbook. This task will install the latest git version on our server. This will task use the 'apt' module - which controls the apt command on the server. To see all its configuration options, check out the ansible docs: http://docs.ansible.com/ansible/apt_module.html

We need to modify our playbook.yml to include this task in a new tasks. This is where knowing YAML becomes important. Here is what the final solution will look like:

    -
hosts: all
sudo: true

  tasks:
    - name: install git
      apt: name=git state=latest update_cache=yes

The tasks section is an array of commands. Our only task here is named 'install git'. Then we configure the apt module with some parameters. These parameters are key=value format - with spaces in between them.

We have indicated that sudo is required for this set of tasks, as only root has the ability to install new tools.

Now lets run our updated playbook to execute this task on the server. There is one more thing we need to do. As this task requires sudo, we need to pass in our sudo password when we run the command. The flag to do this is --ask-sudo-pass:

ansible-playbook --ask-sudo-pass -i inventory playbook.yml 

NOTE: playbook.yml always comes last in the command

We can add more tasks to execute on our server. Lets add node and nginx to our tasks. Now our playbook looks like:

-
  hosts: all
  sudo: true

  tasks:
    - name: install git
      apt: name=git state=latest update_cache=yes

    - name: install nodejs
      apt: name=nodejs state=latest update_cache=yes

    - name: install nginx
      apt: name=nginx state=latest update_cache=yes

We can see that the format for installing these new tools is all very similar. We are using apt to install all these!

Lets run the playbook again

ansible-playbook --ask-sudo-pass -i inventory playbook.yml 

You should see something like:

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [vlandham.learndeployment.com]

TASK: [install git] ***********************************************************
ok: [vlandham.learndeployment.com]

TASK: [install nodejs] ********************************************************
changed: [vlandham.learndeployment.com]

TASK: [install nginx] *********************************************************
changed: [vlandham.learndeployment.com]

PLAY RECAP ********************************************************************
vlandham.learndeployment.com : ok=4    changed=2    unreachable=0    failed=0

We could ssh into our server and verify that this stuff is installed. But that would be an exercise for you!

Removing files & stuff from the server with ansible

You cannot just remote the command from a file and hope it checks the server and magically knows to delete/uninstall it. Set it's state to absent. eg- - name: install nginx apt: name=nginx state=absent

Loops in Ansible Playbooks

Loops are a way to DRY (don't repeat yourself) your ansible playbooks. Using variables you can create a list of packages you want to install and loop through them like so:

-
  hosts: all
  sudo: true
  vars:
    apt_packages:
      - git
      - nodejs
      - nginx
  tasks:
    - name: install apt packages
      apt: name={{item}} state=latest update_cache=yes
      with_items: apt_packages

Note that the vars section is outside of your tasks section. You can add as many vars as you want. Here we have a var known as apt_packages - which itself is an array. {{item}} refers to the item in the array as it loops through. with_items is the name of your array. This (magic) will loop your task for each item - and the items configuration indicates the contents of each item - which points back to apt_packages.

Conditionals

Sometimes you only want to run particular tasks

....

Deploying a service

...

Tools / formats you need to understand to understand Ansible

  • SSH
  • Python
  • YAML
  • INI Format
  • Jinja2 templating languange
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment