mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/selfhosting-blogposts.git
synced 2025-05-16 12:16:59 +00:00
1152 lines
40 KiB
Markdown
1152 lines
40 KiB
Markdown
---
|
||
search:
|
||
exclude: true
|
||
---
|
||
# Ansible
|
||
|
||

|
||
|
||
In this tutorial we're going to take a look at how Ansible can be used.
|
||
|
||
## **Initial SSH Setup**
|
||
|
||
One fundamental requirement for ansible to work is to have a working SSH connection. we can setup key-based ssh authentication connections or we can just setup a regular ssh connection using passwords. let's first take a look at how you can setup a regular ssh connection:
|
||
|
||

|
||
|
||
We're going to show an example using a debian LXC container (CT) from a proxmox server. Once the CT is launched get into it's console:
|
||
|
||

|
||
|
||
We're going to edit the ssh config as follows:
|
||
|
||
|
||
PermitRootLogin yes
|
||
|
||
|
||
|
||
inside vim, press **i** to enter the insert mode, then make your text changes, then press **ESC** to exit out of insert mode, and type **:wq** to save and quit vim. After that, restart the sshd service:
|
||
|
||

|
||
|
||
Once you have a working SSH connection, that's the bare minimum requirement you need to be able to use ansible. If you want to skip the password prompt you can use key-based authentication SSH connection as follows:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/10 ] [~]
|
||
→ ssh root@10.0.0.102
|
||
root@10.0.0.102's password:
|
||
Linux test 5.4.106-1-pve #1 SMP PVE 5.4.106-1 (Fri, 19 Mar 2021 11:08:47 +0100) x86_64
|
||
|
||
The programs included with the Debian GNU/Linux system are free software;
|
||
the exact distribution terms for each program are described in the
|
||
individual files in /usr/share/doc/*/copyright.
|
||
|
||
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
||
permitted by applicable law.
|
||
Last login: Tue Apr 6 15:55:31 2021
|
||
root@test:~# id
|
||
uid=0(root) gid=0(root) groups=0(root)
|
||
root@test:~# mkdir ~/.ssh
|
||
root@test:~# cd ~/.ssh
|
||
root@test:~/.ssh# ssh-keygen -t ed25519
|
||
Generating public/private ed25519 key pair.
|
||
Enter file in which to save the key (/root/.ssh/id_ed25519):
|
||
Enter passphrase (empty for no passphrase):
|
||
Enter same passphrase again:
|
||
Your identification has been saved in /root/.ssh/id_ed25519.
|
||
Your public key has been saved in /root/.ssh/id_ed25519.pub.
|
||
The key fingerprint is:
|
||
SHA256:9SovHVeK8XlycaJDGzHsukb0CvIv9qaNspSZRCV3kn8 root@test
|
||
The key's randomart image is:
|
||
+--[ED25519 256]--+
|
||
| . +... |
|
||
| +.o + |
|
||
| . ... o |
|
||
| . .+.E + .|
|
||
| . S. O.B + |
|
||
| ..+. =.@ o |
|
||
| =o.+.= = |
|
||
| .. ==* |
|
||
| .+oO= |
|
||
+----[SHA256]-----+
|
||
root@test:~/.ssh# cat id_ed25519.pub >> authorized_keys
|
||
root@test:~/.ssh# python3 -m http.server 8080
|
||
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
|
||
|
||
|
||
|
||
With the **ssh-keygen** command we generated the private key **id_ed25519** and the public key **id_ed25519.pub**. the private key is a file we need to give to the client that is going to connect to the SSH server, and we permit it's use by making sure the public key that is associated with it is referenced in the authorized_keys file on the server. Now how do we transfer the private key to the client ? I think the easiest method is to temporarily use python3's http module to transfer the ssh key somewhere else on the network. Our last command opened a http server in the server's /root/.ssh directory, as you can see here:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ curl 10.0.0.102:8080
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# Directory listing for /
|
||
|
||
|
||
|
||
|
||
* * *
|
||
|
||
|
||
|
||
|
||
|
||
|
||
* [authorized_keys](authorized_keys)
|
||
|
||
|
||
* [id_ed25519](id_ed25519)
|
||
|
||
|
||
* [id_ed25519.pub](id_ed25519.pub)
|
||
|
||
|
||
|
||
|
||
|
||
* * *
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
And especially here:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ curl 10.0.0.102:8080/id_ed25519
|
||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||
QyNTUxOQAAACDY0+xVKpBv9IhRkRH4C55/SaF+FJsd7vTJq7IvX6/RlgAAAJCwK2ycsCts
|
||
nAAAAAtzc2gtZWQyNTUxOQAAACDY0+xVKpBv9IhRkRH4C55/SaF+FJsd7vTJq7IvX6/Rlg
|
||
AAAEDELHAkjN/D62SUBd7QYQ6tKQ3RZV192RKP5xLz9BZ1itjT7FUqkG/0iFGREfgLnn9J
|
||
oX4Umx3u9Mmrsi9fr9GWAAAACXJvb3RAdGVzdAECAwQ=
|
||
-----END OPENSSH PRIVATE KEY-----
|
||
|
||
|
||
|
||
This is how you can transfer a file from a host to another on the same network. Now that we know we can access it, let's retrieve the ssh key:
|
||
|
||
![]()
|
||
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ curl http://10.0.0.102:8080/id_ed25519
|
||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||
QyNTUxOQAAACDY0+xVKpBv9IhRkRH4C55/SaF+FJsd7vTJq7IvX6/RlgAAAJCwK2ycsCts
|
||
nAAAAAtzc2gtZWQyNTUxOQAAACDY0+xVKpBv9IhRkRH4C55/SaF+FJsd7vTJq7IvX6/Rlg
|
||
AAAEDELHAkjN/D62SUBd7QYQ6tKQ3RZV192RKP5xLz9BZ1itjT7FUqkG/0iFGREfgLnn9J
|
||
oX4Umx3u9Mmrsi9fr9GWAAAACXJvb3RAdGVzdAECAwQ=
|
||
-----END OPENSSH PRIVATE KEY-----
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ curl http://10.0.0.102:8080/id_ed25519 > ~/.ssh/test.pkey
|
||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||
Dload Upload Total Spent Left Speed
|
||
100 399 100 399 0 0 129k 0 --:--:-- --:--:-- --:--:-- 129k
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ ssh root@10.0.0.102 -i ~/.ssh/test.pkey
|
||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
|
||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
Permissions 0644 for '/home/nothing/.ssh/test.pkey' are too open.
|
||
It is required that your private key files are NOT accessible by others.
|
||
This private key will be ignored.
|
||
Load key "/home/nothing/.ssh/test.pkey": bad permissions
|
||
root@10.0.0.102's password:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ chmod 600 ~/.ssh/test.pkey
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/14 ] [blog/servers/ansible]
|
||
→ ssh root@10.0.0.102 -i ~/.ssh/test.pkey
|
||
Linux test 5.4.106-1-pve #1 SMP PVE 5.4.106-1 (Fri, 19 Mar 2021 11:08:47 +0100) x86_64
|
||
|
||
The programs included with the Debian GNU/Linux system are free software;
|
||
the exact distribution terms for each program are described in the
|
||
individual files in /usr/share/doc/*/copyright.
|
||
|
||
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
||
permitted by applicable law.
|
||
Last login: Tue Apr 6 16:01:04 2021 from 10.0.0.10
|
||
root@test:~#
|
||
|
||
|
||
|
||
|
||
We saved the private key in our client's ~/.ssh folder, we gave it the 600 permissions with chmod, and in the end we have been able to ssh into the server as the root user using that private key, and we didn't get prompted for a password, this is ideal for ansible to work best, but you can settle for the basic password-based authentication and ansible should work fine that way aswell.
|
||
|
||
## **Setting up Ansible**
|
||
|
||
We're going to follow this network graph:
|
||
|
||

|
||
|
||
Now we have our main node at 10.0.0.101, and we want each of our other nodes to be ran a specific command. normally what you would do is to login via ssh into each node one by one to run your set of specific commands one after the other. This is fine if you have 5 or less nodes, but when you end up with 20 or 50 linux nodes it starts to get tedious running these commands one after the other. This is why ansible. All you need is ssh access to your linux cluster to be able to run those commands via ssh for each of them in one go thanks to ansible. Let's setup ansible on our main node:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/10 ] [~]
|
||
→ ssh root@10.0.0.101
|
||
root@10.0.0.101's password:
|
||
Linux home 4.19.0-13-amd64 #1 SMP Debian 4.19.160-2 (2020-11-28) x86_64
|
||
|
||
The programs included with the Debian GNU/Linux system are free software;
|
||
the exact distribution terms for each program are described in the
|
||
individual files in /usr/share/doc/*/copyright.
|
||
|
||
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
||
permitted by applicable law.
|
||
Last login: Tue Apr 6 18:31:43 2021 from 10.0.0.10
|
||
root@home:~# apt install ansible -y
|
||
|
||
|
||
|
||
ansible is there by default in debian10's repositories, next we're going to need to set it up. The first config file we need to edit is **/etc/ansible/hosts** :
|
||
|
||
|
||
root@home:~# vim /etc/ansible/hosts
|
||
|
||
|
||
|
||
In here we're going to list the ips or hostnames of our other nodes, for this tutorial i'm going to include every LXC container in my proxmox server:
|
||
|
||

|
||
|
||
|
||
# Ex 3: A collection of database servers in the 'dbservers' group
|
||
|
||
#[dbservers]
|
||
#
|
||
#db01.intranet.mydomain.net
|
||
#db02.intranet.mydomain.net
|
||
#10.25.1.56
|
||
#10.25.1.57
|
||
|
||
# Here's another example of host ranges, this time there are no
|
||
# leading 0s:
|
||
|
||
#db-[99:101]-node.example.com
|
||
10.0.0.102
|
||
10.0.0.103
|
||
10.0.0.104
|
||
10.0.0.105
|
||
10.0.0.108
|
||
10.0.0.109
|
||
10.0.0.110
|
||
10.0.0.111
|
||
10.0.0.112
|
||
10.0.0.113
|
||
10.0.0.114
|
||
10.0.0.159
|
||
10.0.0.160
|
||
10.0.0.161
|
||
10.0.0.162
|
||
10.0.0.164
|
||
10.0.0.165
|
||
10.0.0.198
|
||
10.0.0.199
|
||
|
||
|
||
|
||
In here i listed the ip addresses of my other nodes i know i can access via SSH, hit :wq to save and quit out of vim. Next step is to test if each of these ips are reachable.
|
||
|
||
|
||
root@home:~# ansible all -a "/bin/echo hello" -K --ask-pass
|
||
SSH password:
|
||
SUDO password[defaults to SSH password]:
|
||
10.0.0.103 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.102 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.104 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.105 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.108 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.109 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.110 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.111 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.112 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.113 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.114 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.160 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.159 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.161 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.162 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.164 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.165 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.198 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
10.0.0.199 | FAILED | rc=-1 >>
|
||
to use the 'ssh' connection type with passwords, you must install the sshpass program
|
||
|
||
|
||
|
||
We forgot to install sshpass, so let's do it again:
|
||
|
||
|
||
root@home:~# apt install sshpass -y
|
||
|
||
root@home:~# ansible all -a "/bin/echo hello" -K --ask-pass
|
||
SSH password:
|
||
SUDO password[defaults to SSH password]:
|
||
10.0.0.102 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.103 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.105 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.104 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.108 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.109 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.110 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.111 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.112 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.113 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.114 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.161 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.162 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.164 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.165 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
10.0.0.159 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.160 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Invalid/incorrect password: Permission denied, please try again.",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.198 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.0.198 port 22: No route to host",
|
||
"unreachable": true
|
||
}
|
||
10.0.0.199 | UNREACHABLE! => {
|
||
"changed": false,
|
||
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.0.199 port 22: No route to host",
|
||
"unreachable": true
|
||
}
|
||
|
||
|
||
|
||
|
||
And here we see that there are some nodes i forgot to setup to have root access. But we managed to make ansible run a simple hello command on the ones that had ssh activated on them! Before hitting the next part of this tutorial, i'm going to setup key-based authentication on all of my nodes and then configure ssh to use them automatically. The idea here is that my main node 10.0.0.101 is in fact the client, and all of the other nodes will be accessed by the main node with their respective private ssh key which will be stored on the main node, therefore the main node has to collect them all.
|
||
|
||
|
||
root@home:~# cd ~/.ssh
|
||
root@home:~/.ssh# ls -lash
|
||
total 16K
|
||
4.0K drwx------ 2 root root 4.0K Oct 29 21:40 .
|
||
4.0K drwx------ 7 root root 4.0K Apr 6 18:52 ..
|
||
8.0K -rw-r--r-- 1 root root 4.2K Apr 6 18:40 known_hosts
|
||
|
||
|
||
|
||
As i've already explained how to setup SSH with key based authentication, we can now use a script to automate that:
|
||
|
||
|
||
[ 10.0.0.10/16 ] [ /dev/pts/12 ] [blog/servers/ansible]
|
||
→ curl https://raw.githubusercontent.com/ech1/serverside/master/ssh/ssh.sh
|
||
#!/bin/bash
|
||
if [ "$EUID" -ne 0 ]
|
||
then
|
||
echo 'MUST RUN AS ROOT!'
|
||
exit
|
||
fi
|
||
|
||
apt update -y
|
||
apt install openssh-server rsync -y
|
||
systemctl status ssh
|
||
cd /etc/ssh
|
||
rm sshd_config
|
||
wget https://raw.githubusercontent.com/ech1/serverside/master/ssh/sshd_config
|
||
systemctl restart ssh
|
||
|
||
#WE ARE ON THE SERVER !!!
|
||
#So we generate the public ssh key
|
||
mkdir ~/.ssh/
|
||
cd ~/.ssh/
|
||
ssh-keygen -t ed25519
|
||
cat id_ed25519.pub >> authorized_keys
|
||
|
||
#ssh server has the public key
|
||
#we give the private key to the user somehow
|
||
#the user puts id_ed25519 into his own ~/.ssh/
|
||
#and he does "chmod 600 ~/.ssh/id_ed25519"
|
||
#and only after he can login
|
||
|
||
systemctl status ssh
|
||
|
||
|
||
|
||
|
||
Let's use that script on each node one by one starting with my test node (10.0.0.102):
|
||
|
||
|
||
root@test:~# wget https://raw.githubusercontent.com/ech1/serverside/master/ssh/ssh.sh
|
||
--2021-04-06 17:05:16-- https://raw.githubusercontent.com/ech1/serverside/master/ssh/ssh.sh
|
||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.109.133, ...
|
||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 652 [text/plain]
|
||
Saving to: 'ssh.sh'
|
||
|
||
ssh.sh 100%[==================================================================================================>] 652 --.-KB/s in 0s
|
||
|
||
2021-04-06 17:05:16 (12.0 MB/s) - 'ssh.sh' saved [652/652]
|
||
|
||
root@test:~# chmod +X ssh.sh
|
||
root@test:~# chmod +x ssh.sh
|
||
root@test:~# ./ssh.sh
|
||
Hit:1 http://security.debian.org buster/updates InRelease
|
||
Hit:2 http://ftp.debian.org/debian buster InRelease
|
||
Hit:3 http://ftp.debian.org/debian buster-updates InRelease
|
||
Reading package lists... Done
|
||
Building dependency tree
|
||
Reading state information... Done
|
||
All packages are up to date.
|
||
Reading package lists... Done
|
||
Building dependency tree
|
||
Reading state information... Done
|
||
openssh-server is already the newest version (1:7.9p1-10+deb10u2).
|
||
rsync is already the newest version (3.1.3-6).
|
||
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
|
||
* ssh.service - OpenBSD Secure Shell server
|
||
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
|
||
Active: active (running) since Tue 2021-04-06 17:04:07 UTC; 1min 26s ago
|
||
Docs: man:sshd(8)
|
||
man:sshd_config(5)
|
||
Process: 9646 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
|
||
Main PID: 9647 (sshd)
|
||
Tasks: 1 (limit: 7372)
|
||
Memory: 1.2M
|
||
CGroup: /system.slice/ssh.service
|
||
`-9647 /usr/sbin/sshd -D
|
||
|
||
Apr 06 17:04:07 test systemd[1]: Starting OpenBSD Secure Shell server...
|
||
Apr 06 17:04:07 test sshd[9647]: Server listening on 0.0.0.0 port 22.
|
||
Apr 06 17:04:07 test sshd[9647]: Server listening on :: port 22.
|
||
Apr 06 17:04:07 test systemd[1]: Started OpenBSD Secure Shell server.
|
||
--2021-04-06 17:05:34-- https://raw.githubusercontent.com/ech1/serverside/master/ssh/sshd_config
|
||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133, 185.199.110.133, 185.199.111.133, ...
|
||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 3307 (3.2K) [text/plain]
|
||
Saving to: 'sshd_config'
|
||
|
||
sshd_config 100%[==================================================================================================>] 3.23K --.-KB/s in 0s
|
||
|
||
2021-04-06 17:05:34 (13.2 MB/s) - 'sshd_config' saved [3307/3307]
|
||
|
||
Generating public/private ed25519 key pair.
|
||
Enter file in which to save the key (/root/.ssh/id_ed25519):
|
||
Enter passphrase (empty for no passphrase):
|
||
Enter same passphrase again:
|
||
Your identification has been saved in /root/.ssh/id_ed25519.
|
||
Your public key has been saved in /root/.ssh/id_ed25519.pub.
|
||
The key fingerprint is:
|
||
SHA256:qZBD/lo/RULWgbmOS+gajCCtcmnACP24FHKd3RL4C3w root@test
|
||
The key's randomart image is:
|
||
+--[ED25519 256]--+
|
||
| .. +.. |
|
||
| . ..o o= . |
|
||
|o +.+.oo.. |
|
||
|++ *o.E.o.. |
|
||
|=.+ *+ +So |
|
||
|o* o.++.. . |
|
||
|+ B. .+. . |
|
||
|.o ..o... |
|
||
| ... .. |
|
||
+----[SHA256]-----+
|
||
* ssh.service - OpenBSD Secure Shell server
|
||
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
|
||
Active: active (running) since Tue 2021-04-06 17:05:34 UTC; 2s ago
|
||
Docs: man:sshd(8)
|
||
man:sshd_config(5)
|
||
Process: 9912 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
|
||
Main PID: 9913 (sshd)
|
||
Tasks: 1 (limit: 7372)
|
||
Memory: 1.2M
|
||
CGroup: /system.slice/ssh.service
|
||
`-9913 /usr/sbin/sshd -D
|
||
|
||
Apr 06 17:05:34 test systemd[1]: Starting OpenBSD Secure Shell server...
|
||
Apr 06 17:05:34 test sshd[9913]: Server listening on 0.0.0.0 port 22.
|
||
Apr 06 17:05:34 test sshd[9913]: Server listening on :: port 22.
|
||
Apr 06 17:05:34 test systemd[1]: Started OpenBSD Secure Shell server.
|
||
|
||
|
||
|
||
|
||
once it finished running, check the ~/.ssh directory:
|
||
|
||
|
||
root@test:~# ls -lash ~/.ssh/
|
||
total 20K
|
||
4.0K drwxr-xr-x 2 root root 4.0K Apr 6 17:05 .
|
||
4.0K drwx------ 4 root root 4.0K Apr 6 17:05 ..
|
||
4.0K -rw-r--r-- 1 root root 91 Apr 6 17:05 authorized_keys
|
||
4.0K -rw------- 1 root root 399 Apr 6 17:05 id_ed25519
|
||
4.0K -rw-r--r-- 1 root root 91 Apr 6 17:05 id_ed25519.pub
|
||
|
||
|
||
|
||
And what we want from here is the id_ed25519 file which is our test node's private key.
|
||
|
||
|
||
root@test:~# ip a | grep inet
|
||
inet 127.0.0.1/8 scope host lo
|
||
inet6 ::1/128 scope host
|
||
inet 10.0.0.102/16 brd 10.0.255.255 scope global eth0
|
||
inet6 fe80::b847:2bff:fe85:4dd3/64 scope link
|
||
root@test:~# python3 -m http.server 8080
|
||
|
||
|
||
|
||
and retrieve the ssh key on the main node:
|
||
|
||
|
||
root@home:~# wget 10.0.0.102:8080/.ssh/id_ed25519 -O ~/.ssh/test.pkey
|
||
--2021-04-06 19:08:33-- http://10.0.0.102:8080/.ssh/id_ed25519
|
||
Connecting to 10.0.0.102:8080... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 399 [application/octet-stream]
|
||
Saving to: ‘/root/.ssh/test.pkey’
|
||
|
||
/root/.ssh/test.pkey 100%[===============================>] 399 --.-KB/s in 0s
|
||
|
||
2021-04-06 19:08:33 (22.0 MB/s) - ‘/root/.ssh/test.pkey’ saved [399/399]
|
||
|
||
|
||
|
||
Easy! Now after doing the same on the other nodes we end up with the following:
|
||
|
||
|
||
root@home:~/.ssh# ls -l
|
||
total 84
|
||
-rw------- 1 root root 411 Apr 6 20:07 cyber-160.pkey
|
||
-rw------- 1 root root 399 Apr 6 20:16 dns198.pkey
|
||
-rw------- 1 root root 399 Apr 6 20:16 dns199.pkey
|
||
-rw------- 1 root root 399 Apr 6 19:58 etherpad-111.pkey
|
||
-rw------- 1 root root 399 Apr 6 19:56 gitea-110.pkey
|
||
-rw------- 1 root root 399 Apr 6 19:54 hastebin-109.pkey
|
||
-rw------- 1 root root 399 Apr 6 19:52 kanboard-105.pkey
|
||
-rw-r--r-- 1 root root 4662 Apr 6 20:17 known_hosts
|
||
-rw------- 1 root root 411 Oct 11 12:29 nextcloud-103.pkey
|
||
-rw------- 1 root root 411 Apr 6 19:59 pgadmin-112.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:02 pgadmin4-114.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:13 pgbouncer-165.pkey
|
||
-rw------- 1 root root 419 Apr 6 20:01 phpmyadmin-113.pkey
|
||
-rw------- 1 root root 411 Apr 6 19:50 privatebin-104.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:10 psql1-161.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:10 psql1-162.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:10 psql1-163.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:10 psql1-164.pkey
|
||
-rw------- 1 root root 411 Apr 6 20:05 rev-159.pkey
|
||
-rw------- 1 root root 399 Apr 6 19:18 test-102.pkey
|
||
|
||
|
||
|
||
Basically i have a bunch of private ssh keys and i want my ssh client to automatically associate them with their corresponding IPs to make sure that this is an automatic connection
|
||
|
||
|
||
root@home:~/.ssh# vim ~/.ssh/config
|
||
|
||
|
||
|
||
|
||
Host nextcloud
|
||
Hostname 10.0.0.103
|
||
IdentityFile ~/.ssh/nextcloud-103.pkey
|
||
User root
|
||
|
||
Host privatebin
|
||
Hostname 10.0.0.104
|
||
IdentityFile ~/.ssh/privatebin-104.pkey
|
||
User root
|
||
|
||
Host kanboard
|
||
Hostname 10.0.0.105
|
||
IdentityFile ~/.ssh/kanboard-105.pkey
|
||
User root
|
||
|
||
Host hastebin
|
||
Hostname 10.0.0.109
|
||
IdentityFile ~/.ssh/hastebin-109.pkey
|
||
User root
|
||
|
||
Host gitea
|
||
Hostname 10.0.0.110
|
||
IdentityFile ~/.ssh/gitea-110.pkey
|
||
User root
|
||
|
||
Host etherpad
|
||
Hostname 10.0.0.111
|
||
IdentityFile ~/.ssh/etherpad-111.pkey
|
||
User root
|
||
|
||
Host pgadmin
|
||
Hostname 10.0.0.112
|
||
IdentityFile ~/.ssh/pgadmin-112.pkey
|
||
User root
|
||
|
||
Host phpmyadmin
|
||
Hostname 10.0.0.113
|
||
IdentityFile ~/.ssh/phpmyadmin-113.pkey
|
||
User root
|
||
|
||
Host pgadmin4
|
||
Hostname 10.0.0.114
|
||
IdentityFile ~/.ssh/pgadmin4-114.pkey
|
||
User root
|
||
Host revshells
|
||
Hostname 10.0.0.159
|
||
IdentityFile ~/.ssh/rev-159.pkey
|
||
User root
|
||
Host cyberchef
|
||
Hostname 10.0.0.160
|
||
IdentityFile ~/.ssh/cyber-160.pkey
|
||
User root
|
||
|
||
|
||
|
||
Each of the hosts defined in here can be re-used in ansible's config file:
|
||
|
||
|
||
root@home:~# cat ~/.ssh/config | grep 'Host\ '
|
||
Host nextcloud
|
||
Host privatebin
|
||
Host kanboard
|
||
Host hastebin
|
||
Host gitea
|
||
Host etherpad
|
||
Host pgadmin
|
||
Host phpmyadmin
|
||
Host pgadmin4
|
||
Host revshells
|
||
Host cyberchef
|
||
Host psql1
|
||
Host psql2
|
||
Host psql3
|
||
Host psql4
|
||
Host pgbouncer
|
||
Host pihole1
|
||
Host pihole2
|
||
|
||
root@home:~/.ssh# vim /etc/ansible/hosts
|
||
|
||
root@home:~/.ssh# cat /etc/ansible/hosts | tail -n20
|
||
|
||
nextcloud
|
||
privatebin
|
||
kanboard
|
||
hastebin
|
||
gitea
|
||
etherpad
|
||
pgadmin
|
||
phpmyadmin
|
||
pgadmin4
|
||
revshells
|
||
cyberchef
|
||
psql1
|
||
psql2
|
||
psql3
|
||
psql4
|
||
pgbouncer
|
||
pihole1
|
||
pihole2
|
||
|
||
|
||
|
||
Once added run ansible to test the changes:
|
||
|
||
|
||
root@home:~/.ssh# ansible all -a "/bin/echo hello"
|
||
gitea | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
hastebin | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
nextcloud | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
privatebin | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
kanboard | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
pgadmin | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
phpmyadmin | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
etherpad | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
pgadmin4 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
revshells | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
cyberchef | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
psql2 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
psql4 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
psql1 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
psql3 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
pgbouncer | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
pihole1 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
pihole2 | CHANGED | rc=0 >>
|
||
hello
|
||
|
||
|
||
|
||
Another way of testing it is by using the ping module:
|
||
|
||
|
||
root@home:~/.ssh# ansible all -m ping
|
||
kanboard | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
nextcloud | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
gitea | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
hastebin | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
privatebin | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
pgadmin | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
phpmyadmin | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
pgadmin4 | SUCCESS => {
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
|
||
[...]
|
||
|
||
|
||
|
||
That's the correct way of using ansible.To summarize, you first setup key-based authentication ssh connections on all hosts (you can run a script to do that), then you retrieve the private ssh keys to the master node, and create the **~/.ssh/config** file to associate the private keys with their corresponding ips which gives you **SSH Host aliases (private key + ip pairs)** to give to ansible via **/etc/ansible/hosts** and from there, ansible is going to run what you want on the hosts without requiring a password.
|
||
|
||
## **Ansible Playbooks**
|
||
|
||
|
||
root@home:~# mkdir playbooks
|
||
root@home:~# cd playbooks/
|
||
root@home:~/playbooks# vim update.yml
|
||
|
||
|
||
|
||
Be careful when you do .yml files, you need to watch out for indentations, just like for python programs.
|
||
|
||
|
||
root@home:~/playbooks# vim update.yml
|
||
---
|
||
- name: Playbook
|
||
hosts: all
|
||
become: yes
|
||
tasks:
|
||
- name: Update and upgrade apt packages
|
||
become: true
|
||
apt:
|
||
upgrade: yes
|
||
update_cache: yes
|
||
cache_valid_time: 86400 #One day
|
||
|
||
|
||
|
||
|
||
ansible has an apt module to run apt updates, the 'become' line means that we want to run our commands as the root user (become root = yes)
|
||
|
||
:wq to save and quit out of vim, and then run the playbook like so:
|
||
|
||
|
||
|
||
root@home:~/playbooks# ansible-playbook update.yml
|
||
|
||
PLAY [Playbook] ***********************************************************************************************************************************************
|
||
|
||
TASK [Gathering Facts] ****************************************************************************************************************************************
|
||
ok: [hastebin]
|
||
ok: [kanboard]
|
||
ok: [privatebin]
|
||
ok: [gitea]
|
||
ok: [nextcloud]
|
||
ok: [etherpad]
|
||
ok: [phpmyadmin]
|
||
ok: [revshells]
|
||
ok: [pgadmin]
|
||
ok: [pgadmin4]
|
||
ok: [cyberchef]
|
||
ok: [psql2]
|
||
ok: [psql3]
|
||
ok: [psql4]
|
||
ok: [psql1]
|
||
ok: [pgbouncer]
|
||
ok: [pihole1]
|
||
ok: [pihole2]
|
||
|
||
TASK [Update and upgrade apt packages] ************************************************************************************************************************
|
||
|
||
|
||
|
||
At this point it's going to take a bit of time to effectively run on all hosts, but when it finishes it looks like that:
|
||
|
||
|
||
|
||
TASK [Update and upgrade apt packages] ************************************************************************************************************************
|
||
[WARNING]: Could not find aptitude. Using apt-get instead.
|
||
|
||
changed: [hastebin]
|
||
changed: [gitea]
|
||
ok: [pgadmin]
|
||
changed: [etherpad]
|
||
ok: [pgadmin4]
|
||
changed: [phpmyadmin]
|
||
changed: [kanboard]
|
||
changed: [nextcloud]
|
||
changed: [privatebin]
|
||
ok: [psql2]
|
||
ok: [psql1]
|
||
ok: [psql3]
|
||
ok: [psql4]
|
||
ok: [pgbouncer]
|
||
changed: [revshells]
|
||
changed: [cyberchef]
|
||
changed: [pihole1]
|
||
changed: [pihole2]
|
||
|
||
PLAY RECAP ****************************************************************************************************************************************************
|
||
cyberchef : ok=2 changed=1 unreachable=0 failed=0
|
||
etherpad : ok=2 changed=1 unreachable=0 failed=0
|
||
gitea : ok=2 changed=1 unreachable=0 failed=0
|
||
hastebin : ok=2 changed=1 unreachable=0 failed=0
|
||
kanboard : ok=2 changed=1 unreachable=0 failed=0
|
||
nextcloud : ok=2 changed=1 unreachable=0 failed=0
|
||
pgadmin : ok=2 changed=0 unreachable=0 failed=0
|
||
pgadmin4 : ok=2 changed=0 unreachable=0 failed=0
|
||
pgbouncer : ok=2 changed=0 unreachable=0 failed=0
|
||
phpmyadmin : ok=2 changed=1 unreachable=0 failed=0
|
||
pihole1 : ok=2 changed=1 unreachable=0 failed=0
|
||
pihole2 : ok=2 changed=1 unreachable=0 failed=0
|
||
privatebin : ok=2 changed=1 unreachable=0 failed=0
|
||
psql1 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql2 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql3 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql4 : ok=2 changed=0 unreachable=0 failed=0
|
||
revshells : ok=2 changed=1 unreachable=0 failed=0
|
||
|
||
root@home:~/playbooks#
|
||
|
||
|
||
|
||
So from that we see that i had to run apt update and apt upgrade on 11 of my LXC containers. If we run the same playbook again we see that it shouldn't need to change anything:
|
||
|
||
|
||
root@home:~/playbooks# ansible-playbook update.yml
|
||
|
||
PLAY [Playbook] ***********************************************************************************************************************************************
|
||
|
||
TASK [Gathering Facts] ****************************************************************************************************************************************
|
||
ok: [hastebin]
|
||
ok: [gitea]
|
||
ok: [privatebin]
|
||
ok: [nextcloud]
|
||
ok: [kanboard]
|
||
ok: [phpmyadmin]
|
||
ok: [pgadmin]
|
||
ok: [revshells]
|
||
ok: [pgadmin4]
|
||
ok: [etherpad]
|
||
ok: [cyberchef]
|
||
ok: [psql2]
|
||
ok: [psql4]
|
||
ok: [psql1]
|
||
ok: [psql3]
|
||
ok: [pgbouncer]
|
||
ok: [pihole1]
|
||
ok: [pihole2]
|
||
|
||
TASK [Update and upgrade apt packages] ************************************************************************************************************************
|
||
[WARNING]: Could not find aptitude. Using apt-get instead.
|
||
|
||
ok: [gitea]
|
||
ok: [nextcloud]
|
||
ok: [privatebin]
|
||
ok: [kanboard]
|
||
ok: [hastebin]
|
||
ok: [phpmyadmin]
|
||
ok: [pgadmin]
|
||
ok: [pgadmin4]
|
||
ok: [revshells]
|
||
ok: [cyberchef]
|
||
ok: [etherpad]
|
||
ok: [psql2]
|
||
ok: [pihole1]
|
||
ok: [pgbouncer]
|
||
ok: [psql1]
|
||
ok: [psql4]
|
||
ok: [psql3]
|
||
ok: [pihole2]
|
||
|
||
PLAY RECAP ****************************************************************************************************************************************************
|
||
cyberchef : ok=2 changed=0 unreachable=0 failed=0
|
||
etherpad : ok=2 changed=0 unreachable=0 failed=0
|
||
gitea : ok=2 changed=0 unreachable=0 failed=0
|
||
hastebin : ok=2 changed=0 unreachable=0 failed=0
|
||
kanboard : ok=2 changed=0 unreachable=0 failed=0
|
||
nextcloud : ok=2 changed=0 unreachable=0 failed=0
|
||
pgadmin : ok=2 changed=0 unreachable=0 failed=0
|
||
pgadmin4 : ok=2 changed=0 unreachable=0 failed=0
|
||
pgbouncer : ok=2 changed=0 unreachable=0 failed=0
|
||
phpmyadmin : ok=2 changed=0 unreachable=0 failed=0
|
||
pihole1 : ok=2 changed=0 unreachable=0 failed=0
|
||
pihole2 : ok=2 changed=0 unreachable=0 failed=0
|
||
privatebin : ok=2 changed=0 unreachable=0 failed=0
|
||
psql1 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql2 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql3 : ok=2 changed=0 unreachable=0 failed=0
|
||
psql4 : ok=2 changed=0 unreachable=0 failed=0
|
||
revshells : ok=2 changed=0 unreachable=0 failed=0
|
||
|
||
root@home:~/playbooks#
|
||
|
||
|
||
|
||
As expected, our playbook didn't need to change anything this time.For our next part, although not recommended, we can also bypass the need for playbooks:
|
||
|
||
|
||
root@home:~/playbooks# ansible all -m apt -a "upgrade=yes update_cache=yes cache_valid_time=86400" --become
|
||
[WARNING]: Could not find aptitude. Using apt-get instead.
|
||
|
||
privatebin | SUCCESS => {
|
||
"changed": false,
|
||
"msg": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
|
||
"stderr": "",
|
||
"stderr_lines": [],
|
||
"stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
|
||
"stdout_lines": [
|
||
"Reading package lists...",
|
||
"Building dependency tree...",
|
||
"Reading state information...",
|
||
"Calculating upgrade...",
|
||
"0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."
|
||
]
|
||
}
|
||
gitea | SUCCESS => {
|
||
"changed": false,
|
||
"msg": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
|
||
"stderr": "",
|
||
"stderr_lines": [],
|
||
"stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n",
|
||
"stdout_lines": [
|
||
"Reading package lists...",
|
||
"Building dependency tree...",
|
||
"Reading state information...",
|
||
"Calculating upgrade...",
|
||
"0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."
|
||
]
|
||
}
|
||
|
||
[...]
|
||
|
||
root@home:~/playbooks# ansible all -m shell -a "ping -c1 1.1.1.1"
|
||
privatebin | CHANGED | rc=0 >>
|
||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=21.9 ms
|
||
|
||
--- 1.1.1.1 ping statistics ---
|
||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||
rtt min/avg/max/mdev = 21.889/21.889/21.889/0.000 ms
|
||
|
||
hastebin | CHANGED | rc=0 >>
|
||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=27.9 ms
|
||
|
||
--- 1.1.1.1 ping statistics ---
|
||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||
rtt min/avg/max/mdev = 27.925/27.925/27.925/0.000 ms
|
||
|
||
nextcloud | CHANGED | rc=0 >>
|
||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=26.6 ms
|
||
|
||
--- 1.1.1.1 ping statistics ---
|
||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||
rtt min/avg/max/mdev = 26.642/26.642/26.642/0.000 ms
|
||
|
||
gitea | CHANGED | rc=0 >>
|
||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=25.7 ms
|
||
|
||
--- 1.1.1.1 ping statistics ---
|
||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||
rtt min/avg/max/mdev = 25.708/25.708/25.708/0.000 ms
|
||
|
||
kanboard | CHANGED | rc=0 >>
|
||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=22.0 ms
|
||
|
||
[...]
|
||
|
||
|
||
Like this you can run any commands you want. But ideally we want to use playbooks. Now let's make sure this ansible playbook runs daily, we're going to use crontab to do that:
|
||
|
||
|
||
root@home:~/playbooks# which ansible-playbook
|
||
/usr/bin/ansible-playbook
|
||
root@home:~/playbooks# /usr/bin/ansible-playbook /root/playbooks/update.yml
|
||
|
||
PLAY [Playbook] ***********************************************************************************************************************************************
|
||
|
||
TASK [Gathering Facts] ****************************************************************************************************************************************
|
||
ok: [hastebin]
|
||
ok: [privatebin]
|
||
ok: [gitea]
|
||
ok: [kanboard]
|
||
ok: [nextcloud]
|
||
ok: [pgadmin]
|
||
ok: [pgadmin4]
|
||
ok: [phpmyadmin]
|
||
ok: [revshells]
|
||
ok: [etherpad]
|
||
ok: [cyberchef]
|
||
ok: [psql2]
|
||
ok: [psql4]
|
||
ok: [psql1]
|
||
ok: [psql3]
|
||
ok: [pgbouncer]
|
||
ok: [pihole2]
|
||
|
||
|
||
|
||
Cron needs the absolute paths so now we know we can do it:
|
||
|
||
|
||
root@home:~/playbooks# crontab -e
|
||
|
||
0 3 * * * "/usr/bin/ansible-playbook /root/playbooks/update.yml"
|
||
|
||
:wq
|
||
|
||
|
||
Now with this, cron is going to run our playbook every night at 3 am.
|
||
|