Ansible: ad-hoc commands

Ansible is not usefull only to run large complicated playbooks, its also usefull when you want to run simple commands on group of servers.

In this scenario we have a group of two servers named web1 and web2, and they are grouped into the [webservers] section of our inventory.

[webservers]
web1
web2

The goal is to create on each server a user named webops, create a directory that will hold the ssh key for this user and finally copy the key to web1 and web2, Finnaly we will verify that nginx is set to start on boot.

Create users

Create user webops on web1 and web2

Enter the following commands from the ansible host

$ ansible webservers -b -m user -a "name=webops"

This command does the following

  • ssh to each hosts in the webservers group
  • -b: becomes root user to execute the commands
  • -m user: uses the user module
  • -a pass parameters to the user module
  • -”name=webops” instructs the module to create a user called webops

If the command executes successfully will generate something like the following, note the SUCCESS message and the changed:true that indicates that the user created.

web1 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 1005,
"home": "/home/webops",
"name": "webops",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1005
}
web2 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 1005,
"home": "/home/webops",
"name": "webops",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1005
}

Create directories

Lets create the directory .ssh on the home directory of the webops user

$ ansible webservers -b -m file -a "path=/home/webops/.ssh state=directory owner=webops group=consultant mode=0755"

The command does the following

  • ssh to each hosts in the webservers group
  • -b: becomes root user to execute the commands
  • -m file: uses the file module
  • -a pass parameters to the file module
  • -”path=/home/webops/.ssh state=directory owner=webops group=consultant mode=0755”: The parameters instructs the file module to create the directory with specific owner,group,rights.

If the command executed successfully will an ouput with SUCCESS and changed:true

web1 | SUCCESS => {
"changed": true,
"gid": 1004,
"group": "webops",
"mode": "0755",
"owner": "webops",
"path": "/home/webops/.ssh",
"secontext": "unconfined_u:object_r:ssh_home_t:s0",
"size": 6,
"state": "directory",
"uid": 1004
}
web2 | SUCCESS => {
"changed": true,
"gid": 1004,
"group": "webops",
"mode": "0755",
"owner": "webops",
"path": "/home/webops/.ssh",
"secontext": "unconfined_u:object_r:ssh_home_t:s0",
"size": 6,
"state": "directory",
"uid": 1004
}

Copy authorized_keys file

On this step of the scenario we will copy the authorized_keys file to the directory we just created, in my case i have placed the file to the /home/ansible/keys/webops/authorized_keys

$ ansible webservers -b -m copy -a "src=/home/ansible/keys/webops/authorized_keys dest=/home/webops/.ssh/authorized_keys mode=0600 owner=webops group=webops"

The command does the following

  • ssh to each hosts in the webservers group
  • -b: becomes root user to execute the commands
  • -m copy: uses the copy module
  • -a pass parameters to the file module
  • -”src=/home/ansible/keys/webops/authorized_keys dest=/home/webops/.ssh/authorized_keys mode=0600 owner=webops group=webops”: The parameters define the source path of the file to be copied, the dest defines the path on the remote host, mode,owner,group parameters are also passed.

If the command executed successfully the output will contain SUCCESS for each host and changed will be equal to true

web1 | SUCCESS => {
"changed": true,
"checksum": "dd256d19a26c2048e1598cdf40aa4fcc06e543f5",
"dest": "/home/webops/.ssh/authorized_keys",
"gid": 1005,
"group": "webops",
"md5sum": "4c0cffffc8f0f00e28fb98aa59fd0717",
"mode": "0600",
"owner": "webops",
"secontext": "unconfined_u:object_r:ssh_home_t:s0",
"size": 395,
"src": "/home/ansible/.ansible/tmp/ansible-tmp-1612718304.88-254067009390961/source",
"state": "file",
"uid": 1005
}
web2 | SUCCESS => {
"changed": true,
"checksum": "dd256d19a26c2048e1598cdf40aa4fcc06e543f5",
"dest": "/home/webops/.ssh/authorized_keys",
"gid": 1005,
"group": "webops",
"md5sum": "4c0cffffc8f0f00e28fb98aa59fd0717",
"mode": "0600",
"owner": "webops",
"secontext": "unconfined_u:object_r:ssh_home_t:s0",
"size": 395,
"src": "/home/ansible/.ansible/tmp/ansible-tmp-1612718304.89-64960865606057/source",
"state": "file",
"uid": 1005
}

Start the nginx service and set to start on boot

The final step of the scenario is start and set nginx to start on boot

$ ansible webservers -b -m service -a "name=nginx state=started enabled=yes"

The command does the following

  • ssh to each hosts in the webservers group
  • -b: becomes root user to execute the commands
  • -m service: uses the service module
  • -a pass parameters to the file module
  • -”name=nginx state=started enabled=yes”: Those parameters define the name of the service, nginx in this case, the desired state which in this case is to start if not started, and enabled=yes which means to start nginx on boot.

If the command is successfull will print something like this for each host

web1 | SUCCESS => {
"changed": true,
"enabled": true,
"name": "nginx",
"state": "started",
"status": {
.
.
.