First, we should be sure that ansible is configured correctly, to run commands on a server or a group of servers within the
/etc/ansible/hosts file, run any of the below commands
ansible -m ping hostname ansible -m ping 22.214.171.124 ansible -a "sudo ls /" hostname ansible -a "sudo ls /" 126.96.36.199 ansible -a "free -h" hostname ansible -a "free -h" 188.8.131.52
While the above is an example of running bash commands on remote hosts ad-hoc via the commandline, you can also run ansible modules from the commandline in a similar way -
ansible remotehostname -m fetch -a "src=/home/remoteuser/path/file.txt dest=/home/localuser/ flat=yes"
Here, we grab
file.txt from a remote host and copy it to our local home directory. Where
-m is selecting which module to use and
-a is providing the options that you would specify within a normal playbook via a command. Be sure to enclose any module options after
-a with double quotes or the command will fail. We use
flat=yes to tell Ansible that we just want the file, and not to rebuild the directory from the remote host.
flat defaults to
no, which would result in this command building out the full directory
/home/localuser/www.remotedomain.com/home/remoteuser/path/file.txt on our local host. See the Ansible documentation for each module for more information on their arguments. Here's a link to the documentation for the fetch module
For the above command, we used the
fetch module, which may not work for directories and may consume a lot of memory if you are transferring a large file. For example, I experienced issues with this when transferring large database backup files between hosts. If this is your use case, I would recommend checking out the synchronize module documentation.
As an example of an ad-hoc
synchronize command, I have used this in the past to retrieve fail2ban configurations on a remote host. Note the
mode=pull parameter that tells ansible that we want to get the files from the remote host and place them at the local destination. By default,
mode is set to
push, which would attempt to copy files from our local host and send them to a directory on the remote host.
ansible -m synchronize remotehostname -b -a "src=/etc/fail2ban/filter.d/ dest=/some/local/directory/fail2ban/ mode=pull"
Ansible can be configured to carry out tedious or otherwise common tasks on any number of hosts, as we see below in the example playbook where Ansible is being used to backup an instance of Bookstack.
--- - hosts: bookstack become: yes tasks: - name: Backup Bookstack container files command: tar -cvzf bookstack-backup.tar.gz /home/admin/bookstack - name: Fetch backup files from remote host command: scp -P 2222 -i /home/username/.ssh/id_rsa /home/admin/bookstack-backup.tar.gz email@example.com:/home/admin/backups/bookstack/
Here, we use
scp instead of Ansible's Fetch module to save memory on the small host that runs the BookStack you are viewing. When fetching large files, memory errors can be encountered so here we have worked around the module using an alternative method for transferring our files.
Here is another example, using ansible to synchronize the fail2ban configurations used between multiple hosts. This allows us to configure one host, which is the local host that runs the playbook, and once we have configured this host correctly we can just run the play and push our changes to a group of hosts. Note that
hostgroup should be specified in the local
/etc/ansible/hosts file, or ansible will not be able to run the play. Also notice that the
src directories in this playbook are relative to the path of the playbook itself. This allows me to store custom fail2ban configurations for different groups of host alongside this playbook to avoid configuring fail2ban to monitor services that don't exist on the system. If you try to monitor a service that does not exist, fail2ban will fail to reload.
--- - hosts: hostgroup become: yes tasks: - name: Copy custom fail2ban filters synchronize: mode: push src: fail2ban/filter.d/ dest: /etc/fail2ban/filter.d/ - name: Copy custom fail2ban jail.local synchronize: mode: push src: fail2ban/jail.local dest: /etc/fail2ban/ - name: Reload fail2ban service ansible.builtin.service: name: fail2ban state: reloaded - name: Checking status of fail2ban service after restart command: systemctl status fail2ban register: result - name: Showing fail2ban status report debug: var: result
Be careful when synchronizing configurations in this way, hosts can be configured with different services which could result in the fail2ban service failing to reload when it is unable to find the related log files. For this reason, I use a seperate directory to configure fail2ban for hosts with similar filters. In my case, my host that runs the ansible playbooks does not have nginx installed, so copying over configurations for nginx jails will result in fail2ban failing to reload.