Command Line Basics
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
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 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 [email protected]
if you want your computer to sing to you when you can loging
watch -t 'ssh -i ssh-basics/privatekey.pem [email protected] echo I have logged in |say -v Cellos'
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.
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"
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
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 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
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!
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 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
.
Sometimes you only want to run particular tasks
....
...
- SSH
- Python
- YAML
- INI Format
- Jinja2 templating languange