Ansible Home Server Pt. 1 – Installation, Environment, Inventory, Tasks & Variables

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Alright, let’s see how my  last home server video did... Woah. Okay. I guess you guys really liked it then! No but seriously, the response  to that video has been amazing, And I cannot thank you all  enough for all of your support. And if I got one thing clear from your reactions, It’s that a lot of you guys wanted to see a  deep dive into my infrastructure as code set up. Because of that, I decided to make a series  of videos with a working title IaC Deep Dive, In which we are going to create  an Infrastracture as Code project To set up a home server from scratch. In this video, which is a part one, We’re going to go through basics of  Ansible and write our first little playbook To automate the initial  configuration for a Linux machine. This video is geared towards complete beginners, people who don’t know anything about Ansible, but have some knowledge of Linux,  command line and shell scripting. If you’re already familiar with Ansible, Feel free to skip this part And make sure to subscribe, so  that you don’t miss part two. So, without further ado, let’s get started! *1. What is Ansible?* Ansible is an orchestration and  automation tool for Linux, Windows And BSD-based operating systems. It is primarily used to automate deploying,  provisioning and setting up multiple machines, But we can also use it to  automate one home server, Since it makes your configuration easily  reproducible, idempotent and resilient. If you want to know more about why Ansible  and Infrastructure as Code are so cool, Check out my previous video here,  especially the part about IaC. *2. Requirements* You will pretty much only need  one thing for this project, And that is a server that  we’re gonna be configuring. I’ll use a virtual machine for that And you can do the same if you  don’t have a spare computer. I’m using Fedora Linux as my  target OS today instead of Ubuntu, Just to show you that Ansible  works for pretty much any distro. You should also have access to your server via SSH And have a non-root user set up during  the installation with sudo privileges. Ubuntu server enables sudo  access for your user by default, And on Fedora Server this can be  configured during the installation. And that’s pretty much it. First things first, we need to install  Ansible, and that is pretty simple. I’m on Mac, so I’ll use the Homebrew package  manager and type `brew install ansible`. If you’re on Linux, you can use  your distro’s package manager, so for example, on Debian-based distros  it’s `sudo apt install ansible`. Once that’s done, let’s create  a folder called "homeserver". That’s gonna be our project folder. *3. Project structure and inventory* Now let’s move on to the structure of our project. Ansible has a pretty rigid structure when  it comes to projects (or “playbooks”), and some terms like “role”, “inventory”  and “playbook” can definitely be confusing. So let’s see what they’re all about. First thing we need to do in an Ansible project Is tell Ansible what machines  we’re gonna be working on. For that, we need to create  a so called “inventory”. Let’s create a file called “hosts” and edit it. Here, we need to create a  group, I’m gonna call it “home”, And in the group, we’re gonna create our host. The way a host is declared is  basically the name of the host, In my case i’ll call it “homeserver”, Then its IP address or  hostname, I’m gonna put mine... Then the username that Ansible  will use to connect to our server, In my case it's "notthebee"... Then `ansible_connection=ssh`... And finally, the private key file. This is going to let us save the effort  of manually typing out the SSH password Every time we do something with our server If you don’t have an SSH key set up  yet, let me show you how to do it. Let’s open a terminal tab and type  `ssh-keygen -o -a 100 -t ed25519` (this is the hip new SSH cypher, by the way) then “-f”, the path to the key,  `-C`, and your email address. Then let’s press Enter, make the  password empty by pressing Enter again. Now you can type `ssh-copy-id -i path-to-the-key`, then your username, at, the address of the server. And that’s it! Now let’s test the key to make  sure everything works... good! One more thing we need to do  is create an `ansible.cfg` file And point it towards our inventory file. Let’s create a file, create  a group called “[defaults]” and write INVENTORY = hosts. I’m also gonna create a group  called “[ssh_connections]” And write “pipelining = true”. This is going to speed up the  Ansible commands considerably. Now that we’ve put our host into the inventory, We need to test the connection,  so that we know that Ansible is able to communicate with our host. For that, let’s go into the  directory with our inventory And type this command: `ansible  all -m ping`, and press “Enter”. We want to see “SUCCESS” here,  and that’s exactly what we see. *4. Tasks* Tasks are the bread and butter of Ansible. This is what your playbook is actually  going to do on your target hosts. So now we’re going to create our first task. Let’s create a folder called `tasks` and  create a file in there called `essential.yml`. Ansible uses a markup language called YAML, which relies heavily on  indentation, kind of like Python. If you’ve ever written a docker-compoe  file, you’ll feel right at home here. Our essential task should basically  be able to do the following things: Update the packages on our target system Install some required software,  like vim, tmux, htop and so on Give our login user paswordless sudo privileges And finally, harden the SSH configuration  and enable public-key only authentication Those are the basics of setting up a fresh server. You’ll probably have to do it regardless  of what you want to use the machine for, So I think it’s a good first  example. Let’s get started So the individual tasks in  Ansible have the following format `name: `, then what the task does.  Let’s call this one “Update packages” Then the name of the module.  Ansible has a module called `dnf` that we can use for managing and  installing packages on Fedora Then we indent the next line and  type `name: "*", as in "all packages" Next, we specify a parameter caled `state`. This is a pretty common one in  Ansible, and we want it to be `latest`. As in, “update all packages to the latest state”. For apt, the syntax would be a bit different. You’ll have to use `upgrade: yes`  and `update_cache: yes instead`. And that’s pretty much it! We just wrote  our first task. Let’s write another one. We’re gonna call this one  “Install essential packages”, and this task we’re gonna use  a module called `package`. It’s distro-agnostic and works for  pretty much all package managers. We’re gonna call this one  “Install essential packages”, then write `name:`, and here you can put all of  the packages that you want to have on your system. For example vim, htop, neofetch,  tmux and let’s say, speedtest-cli. Finally, let’s also type `state: latest`. *5. Variables* Now you might have noticed that we have  quite a lot of hardcoded values in our code. Username, list of packages to be installed All of those values are things that we might  need in many other places of our Ansible project, So hardcoding them everywhere  is probably a bad idea. Instead, we’ll use variables. There are two places you can put  your variables in an Ansible project. `group_vars` and `host_vars`. In `group_vars` you can store variables  that are limited to groups of hosts, which are these things in square  brackets that can group multiple hosts. And in `host_vars` you can store  variables for individual hosts. For example, if you use different  SSH keys for your hosts, You can put each of your keys  in the host variable file. For now though, we’re going to  create a folder called "group_vars", and here we’re going to  create a folder called "all". In this folder, we’re gonna  create a file called "vars.yml" The variables that we’re  going to store in that file Will apply to all hosts and all groups, But we can also override them for individual hosts By putting some different values  in the host variable file. Here, we’re going to specify our  username – mine is notthebee. And the list of packages that I want to  install, I’m gonna put that here as well. In the future, you might need to declare variables That shouldn’t be stored in plain text, Like passwords, API keys or access tokens. So we’re going to create another variable  file that will store encrypted variables. Let’s navigate to the `all`  folder that we just created, and type `ansible-vault create secret.yml`. It’s gonna ask you for a password twice, And then open a file where you  can put your secret variables. I’m gonna put my super secret password  here, and then hit `:x` to save the file. Now if we cat that file, you can see  that it’s just a bunch of gibberish. If you want to actually edit the file later, You’ll have to use the  command `ansible-vaule edit` And Enter the password that you  specified earlier. And that’s it Now that we have our variables, we need to actually use them in our task file. Let’s go back to it and replace all of  our hardcoded values with variables. In Ansible, variables have to be surrounded  by double curly braces and quotes. *6. More tasks* Now as you might remember, We have two more things to do on our target system Harden the SSH configuration  and enable passwordless sudo. In order to change values in  the sshd configuration file, We’ll use a module called `lineinfile`. This module replaces lines in  files according to the parameters. Let’s type `name: Disable SSH  password auth`, lineinfile: dest /etc/ssh/sshd_config Then we’re specify our regular expression, `^#PasswordAuthentication yes, and line (that’s what we want to replace  it with): `PasswordAuthentication no`. Last thing we need to do  is restart the SSH daemon. But we only want to restart  it if there were actually   changes made in the SSH configuration file. So let’s write `register:  sshd_config` here at the end, That’s gonna create a variable called sshd_config. Next, we type `name: Restart  SSHD on config change`, `service`, `name` is `sshd`, `state: restarted`. And then we also write `when: sshd_config.changed` So that is only going to  execute this particular task If Ansible made changes to the config file. But before we restart SSHD, we also need  to enable passwordless sudo for our user. For that, we’re going to use `lineinfile` again, But this time, the destination  file is `/etc/sudoers`. Next, we also specify `state: present`, and the regular expression  is going to be `^%wheel`. And we need to replace it with this long line. Finally, we also need to validate the sudoers  file to make sure we didn’t mess it up. The reason why you’re supposed to use `visudo`  on Linux instead of editing the file directly, Is because an error in it can  prevent you from using sudo at all. And that is not good. So let’s write `validate: /usr/sbin/visudo -cf %s` This will validate our sudoers  file after the edit has been done, And revert the file in case  it doesn’t pass the check. *7. Playbook* So now that we’ve created our task  file, we also need to create a playbook. A playbook is basically a list of all the  tasks and roles that Ansible has to execute. For now we only have one task, But we will be writing more stuff  in the next parts of this series, So we need a playbook file. Let’s create a file called "run.yml"  in the root of the project. Here, we’re gonna put three dashes to  signify the beginning of a YML file. then another dash, `hosts: all`, `become: yes`. “Become” is basically “sudo”, this means that  Ansible will run the tasks as a sudo user. Now we write `tasks:`, indentation,  `- import_tasks: tasks/essential.yml`. And that’s pretty much it! Now  we’re ready to execute our playbook. Let’s exit the editor and type  `ansible-playbook run.yml -K —ask-vault-pass`. `-K` will ask us for the sudo password, and `--ask-vault-pass` will  ask us for the vault password. Thankfully, you can avoid  entering all of those passwords By enabling passwordless sudo, which we just did, And storing the vault  password in your OS keychain, But that’s a topic for another video. Let’s launch our playbook and see what happens! As you can see, all tasks  have been executed succesfully And the tasks that actually enacted  changes in the system were marked yellow. Let’s see what happens if we  execute the playbook again! This time around we can omit `-K`,  since we just enabled passwordless sudo, And as you can see, there were no changes made  to the system, since there’s nothing to change. So there you go, guys! In this video we wrote our first  Ansible playbook to automate the   initial configuration for  your typical Linux machine! In the next part, we’re gonna go more in depth,   and I’ll show you how to do  more complex things with roles, Use Ansible-Galaxy for  importing other users’ roles, How to store your Vault password in your  system keychain and other cool stuff! I hope you liked this video,  and if you want to see part two,   make sure to subscribe so you don’t miss it. As usual at the end of this video  I’d like to thank my Patrons.
Info
Channel: Wolfgang's Channel
Views: 62,358
Rating: undefined out of 5
Keywords:
Id: Z7p9-m4cimg
Channel Id: undefined
Length: 13min 1sec (781 seconds)
Published: Thu Jan 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.