One place for hosting & domains

      Commands

      How To Manage Multiple Servers with Ansible Ad Hoc Commands


      Introduction

      Ansible is a modern configuration management tool that facilitates the task of setting up and maintaining remote servers. With a minimalist design intended to get users up and running quickly, it allows you to control one to hundreds of systems from a central location with either playbooks or ad hoc commands.

      Unlike playbooks — which consist of collections of tasks that can be reused — ad hoc commands are tasks that you don’t perform frequently, such as restarting a service or retrieving information about the remote systems that Ansible manages.

      In this cheat sheet guide, you’ll learn how to use Ansible ad hoc commands to perform common tasks such as installing packages, copying files, and restarting services on one or more remote servers, from an Ansible control node.

      Prerequisites

      In order to follow this guide, you’ll need:

      • One Ansible control node. This guide assumes your control node is an Ubuntu 20.04 machine with Ansible installed and configured to connect to your Ansible hosts using SSH keys. Make sure the control node has a regular user with sudo permissions and a firewall enabled, as explained in our Initial Server Setup guide. To set up Ansible, please follow our guide on How to Install and Configure Ansible on Ubuntu 20.04.
      • Two or more Ansible hosts. An Ansible host is any machine that your Ansible control node is configured to automate. This guide assumes your Ansible hosts are remote Ubuntu 20.04 servers. Make sure each Ansible host has:
        • The Ansible control node’s SSH public key added to the authorized_keys of a system user. This user can be either root or a regular user with sudo privileges. To set this up, you can follow Step 2 of How to Set Up SSH Keys on Ubuntu 20.04.
      • An inventory file set up on the Ansible control node. Make sure you have a working inventory file containing all your Ansible hosts. To set this up, please refer to the guide on How To Set Up Ansible Inventories. Then, make sure you’re able to connect to your nodes by running the connection test outlined in the section Testing Connection to Ansible Hosts.

      Testing Connection to Ansible Hosts

      The following command will test connectivity between your Ansible control node and all your Ansible hosts. This command uses the current system user and its corresponding SSH key as the remote login, and includes the -m option, which tells Ansible to run the ping module. It also features the -i flag, which tells Ansible to ping the hosts listed in the specified inventory file

      • ansible all -i inventory -m ping

      If this is the first time you’re connecting to these servers via SSH, you’ll be asked to confirm the authenticity of the hosts you’re connecting to via Ansible. When prompted, type yes and then hit ENTER to confirm.

      You should get output similar to this:

      Output

      server1 | SUCCESS => { "changed": false, "ping": "pong" } server2 | SUCCESS => { "changed": false, "ping": "pong" }

      Once you get a "pong" reply back from a host, it means the connection is live and you’re ready to run Ansible commands on that server.

      Adjusting Connection Options

      By default, Ansible tries to connect to the nodes as a remote user with the same name as your current system user, using its corresponding SSH keypair.

      To connect as a different remote user, append the command with the -u flag and the name of the intended user:

      • ansible all -i inventory -m ping -u sammy

      If you’re using a custom SSH key to connect to the remote servers, you can provide it at execution time with the --private-key option:

      • ansible all -i inventory -m ping --private-key=~/.ssh/custom_id

      Note: For more information on how to connect to nodes, please refer to our How to Use Ansible guide, which demonstrates more connection options.

      Once you’re able to connect using the appropriate options, you can adjust your inventory file to automatically set your remote user and private key, in case they are different from the default values assigned by Ansible. Then, you won’t need to provide those parameters in the command line.

      The following example inventory file sets up the ansible_user variable only for the server1 server:

      ~/ansible/inventory

      server1 ansible_host=203.0.113.111 ansible_user=sammy
      server2 ansible_host=203.0.113.112
      

      Ansible will now use sammy as the default remote user when connecting to the server1 server.

      To set up a custom SSH key, include the ansible_ssh_private_key_file variable as follows:

      ~/ansible/inventory

      server1 ansible_host=203.0.113.111 ansible_ssh_private_key_file=/home/sammy/.ssh/custom_id
      server2 ansible_host=203.0.113.112
      

      In both cases, we have set up custom values only for server1. If you want to use the same settings for multiple servers, you can use a child group for that:

      ~/ansible/inventory

      [group_a]
      203.0.113.111
      203.0.113.112
      
      [group_b]
      203.0.113.113
      
      
      [group_a:vars]
      ansible_user=sammy
      ansible_ssh_private_key_file=/home/sammy/.ssh/custom_id
      

      This example configuration will assign a custom user and SSH key only for connecting to the servers listed in group_a.

      Defining Targets for Command Execution

      When running ad hoc commands with Ansible, you can target individual hosts, as well as any combination of groups, hosts and subgroups. For instance, this is how you would check connectivity for every host in a group named servers:

      • ansible servers -i inventory -m ping

      You can also specify multiple hosts and groups by separating them with colons:

      • ansible server1:server2:dbservers -i inventory -m ping

      To include an exception in a pattern, use an exclamation mark, prefixed by the escape character , as follows. This command will run on all servers from group1, except server2:

      • ansible group1:!server2 -i inventory -m ping

      In case you’d like to run a command only on servers that are part of both group1 and group2, for instance, you should use & instead. Don’t forget to prefix it with a escape character:

      • ansible group1:&group2 -i inventory -m ping

      For more information on how to use patterns when defining targets for command execution, please refer to Step 5 of our guide on How to Set Up Ansible Inventories.

      Running Ansible Modules

      Ansible modules are pieces of code that can be invoked from playbooks and also from the command-line to facilitate executing procedures on remote nodes. Examples include the apt module, used to manage system packages on Ubuntu, and the user module, used to manage system users. The ping command used throughout this guide is also a module, typically used to test connection from the control node to the hosts.

      Ansible ships with an extensive collection of built-in modules, some of which require the installation of additional software in order to provide full functionality. You can also create your own custom modules using your language of choice.

      To execute a module with arguments, include the -a flag followed by the appropriate options in double quotes, like this:

      ansible target -i inventory -m module -a "module options"
      

      As an example, this will use the apt module to install the package tree on server1:

      • ansible server1 -i inventory -m apt -a "name=tree"

      Running Bash Commands

      When a module is not provided via the -m option, the command module is used by default to execute the specified command on the remote server(s).

      This allows you to execute virtually any command that you could normally execute via an SSH terminal, as long as the connecting user has sufficient permissions and there aren’t any interactive prompts.

      This example executes the uptime command on all servers from the specified inventory:

      • ansible all -i inventory -a "uptime"

      Output

      server1 | CHANGED | rc=0 >> 14:12:18 up 55 days, 2:15, 1 user, load average: 0.03, 0.01, 0.00 server2 | CHANGED | rc=0 >> 14:12:19 up 10 days, 6:38, 1 user, load average: 0.01, 0.02, 0.00

      Using Privilege Escalation to Run Commands with sudo

      If the command or module you want to execute on remote hosts requires extended system privileges or a different system user, you’ll need to use Ansible’s privilege escalation module, become. This module is an abstraction for sudo as well as other privilege escalation software supported by Ansible on different operating systems.

      For instance, if you wanted to run a tail command to output the latest log messages from Nginx’s error log on a server named server1 from inventory, you would need to include the --become option as follows:

      • ansible server1 -i inventory -a "tail /var/log/nginx/error.log" --become

      This would be the equivalent of running a sudo tail /var/log/nginx/error.log command on the remote host, using the current local system user or the remote user set up within your inventory file.

      Privilege escalation systems such as sudo often require that you confirm your credentials by prompting you to provide your user’s password. That would cause Ansible to fail a command or playbook execution. You can then use the --ask-become-pass or -K option to make Ansible prompt you for that sudo password:

      • ansible server1 -i inventory -a "tail /var/log/nginx/error.log" --become -K

      Installing and Removing Packages

      The following example uses the apt module to install the nginx package on all nodes from the provided inventory file:

      • ansible all -i inventory -m apt -a "name=nginx" --become -K

      To remove a package, include the state argument and set it to absent:.

      • ansible all -i inventory -m apt -a "name=nginx state=absent" --become -K

      Copying Files

      With the file module, you can copy files between the control node and the managed nodes, in either direction. The following command copies a local text file to all remote hosts in the specified inventory file:

      • ansible all -i inventory -m copy -a "src=./file.txt dest=~/myfile.txt"

      To copy a file from the remote server to your control node, include the remote_src option:

      • ansible all -i inventory -m copy -a "src=~/myfile.txt remote_src=yes dest=./file.txt"

      Changing File Permissions

      To modify permissions on files and directories on your remote nodes, you can use the file module.

      The following command will adjust permissions on a file named file.txt located at /var/www on the remote host. It will set the file’s umask to 600, which will enable read and write permissions only for the current file owner. Additionally, it will set the ownership of that file to a user and a group called sammy:

      • ansible all -i inventory -m file -a "dest=/var/www/file.txt mode=600 owner=sammy group=sammy" --become -K

      Because the file is located in a directory typically owned by root, we might need sudo permissions to modify its properties. That’s why we include the --become and -K options. These will use Ansible’s privilege escalation system to run the command with extended privileges, and it will prompt you to provide the sudo password for the remote user.

      Restarting Services

      You can use the service module to manage services running on the remote nodes managed by Ansible. This will require extended system privileges, so make sure your remote user has sudo permissions and you include the --become option to use Ansible’s privilege escalation system. Using -K will prompt you to provide the sudo password for the connecting user.

      To restart the nginx service on all hosts in group called webservers, for instance, you would run:

      • ansible webservers -i inventory -m service -a "name=nginx state=restarted" --become -K

      Restarting Servers

      Although Ansible doesn’t have a dedicated module to restart servers, you can issue a bash command that calls the /sbin/reboot command on the remote host.

      Restarting the server will require extended system privileges, so make sure your remote user has sudo permissions and you include the --become option to use Ansible’s privilege escalation system. Using -K will prompt you to provide the sudo password for the connecting user.

      Warning: The following command will fully restart the server(s) targeted by Ansible. That might cause temporary disruption to any applications that rely on those servers.

      To restart all servers in a webservers group, for instance, you would run:

      • ansible webservers -i inventory -a "/sbin/reboot" --become -K

      Gathering Information About Remote Nodes

      The setup module returns detailed information about the remote systems managed by Ansible, also known as system facts.

      To obtain the system facts for server1, run:

      • ansible server1 -i inventory -m setup

      This will print a large amount of JSON data containing details about the remote server environment. To print only the most relevant information, include the "gather_subset=min" argument as follows:

      • ansible server1 -i inventory -m setup -a "gather_subset=min"

      To print only specific items of the JSON, you can use the filter argument. This will accept a wildcard pattern used to match strings, similar to fnmatch. For example, to obtain information about both the ipv4 and ipv6 network interfaces, you can use *ipv* as filter:

      • ansible server1 -i inventory -m setup -a "filter=*ipv*"

      Output

      server1 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "203.0.113.111", "10.0.0.1" ], "ansible_all_ipv6_addresses": [ "fe80::a4f5:16ff:fe75:e758" ], "ansible_default_ipv4": { "address": "203.0.113.111", "alias": "eth0", "broadcast": "203.0.113.111", "gateway": "203.0.113.1", "interface": "eth0", "macaddress": "a6:f5:16:75:e7:58", "mtu": 1500, "netmask": "255.255.240.0", "network": "203.0.113.0", "type": "ether" }, "ansible_default_ipv6": {} }, "changed": false }

      If you’d like to check disk usage, you can run a Bash command calling the df utility, as follows:

      • ansible all -i inventory -a "df -h"

      Output

      server1 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on udev 3.9G 0 3.9G 0% /dev tmpfs 798M 624K 798M 1% /run /dev/vda1 155G 2.3G 153G 2% / tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/vda15 105M 3.6M 101M 4% /boot/efi tmpfs 798M 0 798M 0% /run/user/0 server2 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on udev 2.0G 0 2.0G 0% /dev tmpfs 395M 608K 394M 1% /run /dev/vda1 78G 2.2G 76G 3% / tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/vda15 105M 3.6M 101M 4% /boot/efi tmpfs 395M 0 395M 0% /run/user/0

      Conclusion

      In this guide, we demonstrated how to use Ansible ad hoc commands to manage remote servers, including how to execute common tasks such as restarting a service or copying a file from the control node to the remote servers managed by Ansible. We’ve also seen how to gather information from the remote nodes using limiting and filtering parameters.

      As an additional resource, you can check Ansible’s official documentation on ad hoc commands.



      Source link

      Ansible Adhoc Commands – A Tutorial


      Updated by Linode Contributed by Avi

      Marquee image for Ansible Adhoc Commands - A Tutorial

      In this tutorial, you’ll learn about several Ansible adhoc commands which are used by system and devops engineers.

      Adhoc commands are commands which you run from the command line, outside of a playbook. These commands run on one or more managed nodes and perform a simple/quick task–most often, these will be tasks that you don’t need to repeat. For example, if you want to reload Apache across a cluster of web servers, you can run a single adhoc command to achieve that task.

      Note

      In Ansible, all modules can be executed in either a playbook or through an adhoc command.

      The basic syntax for invoking an adhoc command is:

      ansible host_pattern -m module_name -a "module_options"
      

      Before You Begin

      To run the commands in this tutorial, you’ll need:

      • A workstation or server with the Ansible command line tool installed on it that will act as the control node. The Set Up the Control Node section of the Getting Started With Ansible guide has instructions for setting up a Linode as a control node. Installation instructions for non-Linux distributions can be found on the Ansible documentation site.

      • At least one other server that will be managed by Ansible. Some commands in this guide will target a non-root user on this server. This user should have sudo privileges. There are a couple options for setting up this user:

      Note

      The commands in this guide will be run from the control node and will target a host named Client. Your control node’s Ansible inventory should be configured so that at least one of your managed nodes has this name. The Create an Ansible Inventory section of the Getting Started With Ansible guide outlines how to set up an inventory file.

      Note

      Alternatively, you can modify the commands in this guide to use a different host name.

      Basic Commands

      Ping

      To check that you can reach your managed node, use the ping module:

      ansible -m ping Client
      
        
      node1 | SUCCESS => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": false,
          "ping": "pong"
      }
      
      

      Run with Privilege Escalation

      This adhoc command demonstrates how a non-root user on the managed node can gain the privileges of a root user when executing a module. Specifically, this example shows how to use privilege escalation to run the fdisk command through the shell module:

      ansible Client -m shell -a 'fdisk -l' -u non_root_user --become -K
      
        
      BECOME password:
      node1 | CHANGED | rc=0 >>
      Disk /dev/sda: 79.51 GiB, 85362475008 bytes, 166723584 sectors
      Disk model: QEMU HARDDISK
      Units: sectors of 1 * 512 = 512 bytes
      Sector size (logical/physical): 512 bytes / 512 bytes
      I/O size (minimum/optimal): 512 bytes / 512 bytes
      Disk /dev/sdb: 512 MiB, 536870912 bytes, 1048576 sectors
      Disk model: QEMU HARDDISK
      Units: sectors of 1 * 512 = 512 bytes
      Sector size (logical/physical): 512 bytes / 512 bytes
      I/O size (minimum/optimal): 512 bytes / 512 bytes
      
      
      • The -u option is used to specify the user on the managed node.

        Note

        By default, Ansible will try to establish a connection to the managed node under the same user that you execute the Ansible CLI with on the control node.

      • The --become option is used to execute the command with the privileges of the root user.

      • The -K option is used to prompt for the privilege escalation password of the user.

      Reboot a Managed Node

      Below is a command that reboots the managed node:

      ansible Client -a "/sbin/reboot" -f 1
      

      This command omits the -m option that specifies the module. When the module is not specified, the command module is the default that’s used.

      The command module is similar to the shell module in that both will execute a command that you pass to it. The shell module will run the command through a shell on the managed node, while the command module will not run it through a shell.

      Note

      The -f option is used to define number of forks that Ansible will use on the control node when running your command.

      Note

      If your managed node is a Linode, then Linode’s shutdown watchdog Lassie needs to be enabled for the reboot to succeed. This is because a Linode is not able to turn itself on–instead, Linode’s host environment must boot the Linode.

      Collecting System Diagnostics

      Check Free Disk Space

      This command is used to check the free disk space on all of a managed node’s mounted disks. It lists all the filesystems present on the managed node along with the filesystem size, space used, and space available in a human-readable format:

      ansible Client -a "df -h"
      
        
      node1 | CHANGED | rc=0 >>
      Filesystem      Size  Used Avail Use% Mounted on
      udev            1.9G     0  1.9G   0% /dev
      tmpfs           394M  596K  394M   1% /run
      /dev/sda         79G  2.6G   72G   4% /
      tmpfs           2.0G  124K  2.0G   1% /dev/shm
      tmpfs           5.0M     0  5.0M   0% /run/lock
      tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
      tmpfs           394M     0  394M   0% /run/user/0
      
      

      This command checks the available and used space on a specific filesystem:

      ansible Client -m shell -a 'df -h /dev/sda'
      
        
      node1 | CHANGED | rc=0 >>
      Filesystem      Size  Used Avail Use% Mounted on
      /dev/sda         79G  2.6G   72G   4% /
      
      

      Check Memory and CPU Usage

      Use the free command with the shell module to see the free and used memory of your managed node in megabytes:

      ansible Client -m shell -a 'free -m'
      
        
      node1 | CHANGED | rc=0 >>
                    total        used        free      shared  buff/cache   available
      Mem:           3936         190        3553           0         192        3523
      Swap:           511           0         511
      
      

      Use the mpstat command with the shell module to check CPU usage:

      ansible Client -m shell -a 'mpstat -P ALL'
      
        
      node1 | CHANGED | rc=0 >>
      Linux 5.3.0-40-generic (localhost)      03/21/2020      _x86_64_        (2 CPU)
      
      07:41:27 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
      07:41:27 PM  all    0.96    0.00    0.72    0.08    0.00    0.02    0.01    0.00    0.00   98.21
      07:41:27 PM    0    0.93    0.00    0.73    0.06    0.00    0.03    0.01    0.00    0.00   98.24
      07:41:27 PM    1    1.00    0.00    0.71    0.09    0.00    0.01    0.01    0.00    0.00   98.17
      
      

      Check System Uptime

      This Ansible command will show how long your managed nodes have been up and running:

      ansible Client -a "uptime"
      
        
      node1 | CHANGED | rc=0 >>
       19:40:11 up 8 min,  2 users,  load average: 0.00, 0.02, 0.00
      
      

      File Transfer

      Copy Files

      The copy module is used to transfer a file or directory from the control node to your managed nodes by defining the source and destination paths. You can define the file owner and file permissions in the command:

      cd ~
      echo "Hello World" > test.txt
      ansible Client -m copy -a 'src=test.txt dest=/etc/ owner=root mode=0644' -u non_root_user --become -K
      
        
      BECOME password:
      node1 | CHANGED => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": true,
          "checksum": "13577023221e91069c21d8f10a4b90f8192d6a26",
          "dest": "/etc/test",
          "gid": 0,
          "group": "root",
          "md5sum": "eb662c21e683b643f0fcb5997d7bbccf",
          "mode": "0644",
          "owner": "root",
          "size": 18,
          "src": "/root/.ansible/tmp/ansible-tmp-1584820375.14-54524496813834/source",
          "state": "file",
          "uid": 0
      }
      
      

      You can also use Ansible to check whether your file got copied to your destination location:

      sudo ansible Client -m shell -a 'ls -l /etc/test*'
      
        
      node1 | CHANGED | rc=0 >>
      -rw-r--r-- 1 root root 12 Jun  1 22:35 /etc/test.txt
      
      

      Fetch Files

      The fetch module is used to transfer a file from a managed node to the control node. After the command runs successfully, the changed variable in Ansible’s output will be set to true.

      ansible Client -m fetch -a 'src=/etc/test.txt dest=/etc/'
      
        
      node1 | CHANGED => {
          "changed": true,
          "checksum": "648a6a6ffffdaa0badb23b8baf90b6168dd16b3a",
          "dest": "/etc/192.0.2.4/etc/test.txt",
          "md5sum": "e59ff97941044f85df5297e1c302d260",
          "remote_checksum": "648a6a6ffffdaa0badb23b8baf90b6168dd16b3a",
          "remote_md5sum": null
      }
      
      

      Note that the fetched file was placed into /etc/192.0.2.4/etc/test.txt. By default, the fetch module will put fetched files into separate directories for each hostname that you’re fetching from. This prevents a file from one managed node from overwriting the file from another managed node.

      To avoid creating these directories, include the flat=yes option:

      ansible Client -m fetch -a 'src=/etc/test.txt dest=/etc/ flat=yes'
      
        
      node1 | SUCCESS => {
          "changed": false,
          "checksum": "648a6a6ffffdaa0badb23b8baf90b6168dd16b3a",
          "dest": "/etc/test.txt",
          "file": "/etc/test.txt",
          "md5sum": "e59ff97941044f85df5297e1c302d260"
      }
      
      

      Create Directories

      The file module is used to create, remove, and set permissions on files and directories, and create symlinks. This command will create a directory at /root/linode/new/ on the the managed node with the owner and permissions defined in the options:

      ansible Client -m file -a "dest=/root/linode/new/ mode=755 owner=root group=root state=directory" -u non_root_user --become -K
      
        
      node1 | CHANGED => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": true,
          "gid": 0,
          "group": "root",
          "mode": "0755",
          "owner": "root",
          "path": "/root/linode/new",
          "size": 4096,
          "state": "directory",
          "uid": 0
      }
      
      

      Note that all intermediate directories that did not exist will also be created. In this example, if the linode/ subdirectory did not already exist, then it was created.

      Managing Packages

      Install a Package

      The package module can be used to install a new package on the managed node. This command installs the latest version of NGINX:

      ansible Client -m package -a 'name=nginx state=present' -u non_root_user --become -K
      
        
      node1 | CHANGED => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "cache_update_time": 1584821061,
          "cache_updated": false,
          "changed": true,
          "stderr": "",
          "stderr_lines": [],
          "stdout": "Reading package lists...nBuilding dependency tree...
              "Unpacking nginx (1.16.1-0ubuntu2.1) ...",
              "Setting up libxpm4:amd64 (1:3.5.12-1) ...",
              "Setting up nginx-common (1.16.1-0ubuntu2.1) ...",
              "Setting up nginx-core (1.16.1-0ubuntu2.1) ...",
              "Setting up nginx (1.16.1-0ubuntu2.1) ...",
          ]
      }
      
      

      Note

      The package module works across distributions. There are also modules for specific package managers (e.g. the apt module and the yum module). These modules offer more options that are specific to those package managers.

      Uninstall a Package

      To uninstall a package, set state=absent in the command’s options:

      ansible Client -m package -a 'name=nginx state=absent' -u non_root_user --become -K
      
        
      node1 | CHANGED => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": true,
          "stderr": "",
          "stderr_lines": [],
          "stdout": "Reading package lists...nBuilding dependency tree …
              "  nginx-core",
              "Use 'sudo apt autoremove' to remove them.",
              "The following packages will be REMOVED:",
              "  nginx*",
              "Removing nginx (1.16.1-0ubuntu2.1) ..."
          ]
      }
      
      

      Managing Services

      Start a Service

      Use the service module to start a service on the managed node. This command will start and enable the NGINX service:

      ansible Client -m service -a 'name=nginx state=started enabled=yes' -u non_root_user --become -K
      
        
      node1 | SUCCESS => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": false,
          "enabled": true,
          "name": "nginx",
          "state": "started",
          "status": {
              "ActiveEnterTimestamp": "Sat 2020-03-21 20:04:35 UTC",
              "ActiveEnterTimestampMonotonic": "1999615481",
              "ActiveExitTimestampMonotonic": "0",
              "ActiveState": "active",
              "After": "system.slice systemd-journald.socket network.target sysinit.target basic.target",
              "AllowIsolate": "no",
              "AmbientCapabilities": "",
              "AssertResult": "yes",
              "AssertTimestamp": "Sat 2020-03-21 20:04:35 UTC",
              "AssertTimestampMonotonic": "1999560256",
              "Before": "multi-user.target shutdown.target",
          }
      }
      
      

      Stop a Service

      When you change the state to stopped, the service will stop running.

      ansible Client -m service -a 'name=nginx state=stopped' -u non_root_user --become -K
      
        
      node1 | CHANGED => {
          "ansible_facts": {
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": true,
          "name": "nginx",
          "state": "stopped",
          "status": {
              "ActiveEnterTimestamp": "Sat 2020-03-21 20:04:35 UTC",
              "ActiveEnterTimestampMonotonic": "1999615481",
              "ActiveExitTimestampMonotonic": "0",
              "ActiveState": "active",
              "After": "system.slice systemd-journald.socket network.target sysinit.target basic.target",
              "AllowIsolate": "no",
              "AmbientCapabilities": "",
              "AssertResult": "yes",
              "AssertTimestamp": "Sat 2020-03-21 20:04:35 UTC",
      }
      }
      
      

      Gathering Facts

      The setup module can be used to gather information about your managed nodes:

      ansible Client -m setup
      
        
      node1 | SUCCESS => {
          "ansible_facts": {
              "ansible_all_ipv4_addresses": [
                  "192.0.2.4"
              ],
              "ansible_all_ipv6_addresses": [
                  "2400:8904::f03c:92ff:fee9:dcb3",
                  "fe80::f03c:92ff:fee9:dcb3"
              ],
              "ansible_apparmor": {
                  "status": "enabled"
              },
              "ansible_architecture": "x86_64",
              "ansible_bios_date": "04/01/2014",
              "ansible_bios_version": "rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org",
              "ansible_cmdline": {
                  "BOOT_IMAGE": "/boot/vmlinuz-5.3.0-40-generic",
                  "console": "ttyS0,19200n8",
                  "net.ifnames": "0",
                  "ro": true,
                  "root": "/dev/sda"
              },
              "ansible_date_time": {
                  "date": "2020-03-21",
                  "day": "21",
                  "epoch": "1584821656",
                  "hour": "20",
                  "iso8601": "2020-03-21T20:14:16Z",
                  "iso8601_basic": "20200321T201416267047",
                  "iso8601_basic_short": "20200321T201416",
                  "iso8601_micro": "2020-03-21T20:14:16.267127Z",
                  "minute": "14",
                  "month": "03",
                  "second": "16",
                  "time": "20:14:16",
                  "tz": "UTC",
                  "tz_offset": "+0000",
                  "weekday": "Saturday",
                  "weekday_number": "6",
                  "weeknumber": "11",
                  "year": "2020"
              },
              "ansible_default_ipv4": {
                  "address": "192.0.2.4",
                  "alias": "eth0",
                  "broadcast": "192.0.2.255",
                  "gateway": "192.0.2.1",
                  "interface": "eth0",
                  "macaddress": "f2:3c:92:e9:dc:b3",
                  "mtu": 1500,
                  "netmask": "255.255.255.0",
                  "network": "192.0.2.0",
                  "type": "ether"
              },
              "gather_subset": [
                  "all"
              ],
              "module_setup": true
          },
          "changed": false
      }
      
      

      Filtering Facts

      Using the filter option with the setup module will limit what is returned by the module. This command lists the details of your managed nodes’ installed distributions:

      ansible Client -m setup -a "filter=ansible_distribution*"
      
        
      node1 | SUCCESS => {
          "ansible_facts": {
              "ansible_distribution": "Ubuntu",
              "ansible_distribution_file_parsed": true,
              "ansible_distribution_file_path": "/etc/os-release",
              "ansible_distribution_file_variety": "Debian",
              "ansible_distribution_major_version": "19",
              "ansible_distribution_release": "eoan",
              "ansible_distribution_version": "19.10",
              "discovered_interpreter_python": "/usr/bin/python"
          },
          "changed": false
      }
      
      

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      How To Use nsh to Run Secure Remote Commands On Ubuntu 18.04


      Introduction

      It can often be difficult to manage multiple machines on a daily basis. While Secure Shell (SSH) is a good choice for remote access, the protocol itself has some drawbacks in both convenience and security.

      For instance, remote machines need to have a public IP address and a forwarded port in order to access them, which exposes them to the internet, or at least a larger network. This is especially concerning if you use a password for authentication instead of a public and private key pair. Furthermore, if you don’t know the remote machine’s public key in advance, you might be vulnerable to a “man-in-the-middle” attack. And many remote machines you want to access either don’t have public IP address, or they have a dynamic IP address you might not know.

      In addition, SSH requires one connection per remote session. If a user needs to run a single command across hundreds or even thousands of machines, they must first establish a connection to each machine with a TCP handshake, which is less efficient.

      NKN Shell, or nsh, is an alternative to SSH that provides a convenient and secure way to run remote commands. nsh takes advantage of NKN’s global public network which provides secure and decentralized data transmission. The architecture uses unique addresses that contain a public key used for both routing and end-to-end encryption without any public key infrastructure (PKI). The network also does not require the remote server to have a public IP address. The remote server only needs to have Internet access and be able to establish outbound HTTP and websocket connections. As a result, your remote machines are not exposed to the open Internet.

      In this tutorial you will use the NKN shell daemon and the NKN Shell Client Xterm applications to execute commands on a remote machine. To do so, you will install and configure the NKN Shell daemon on a remote machine with internet access, generate a key pair, and make your connection from a client.

      Prerequisites

      To follow this tutorial you will need the following:

      Step 1 — Installing NKN Shell Daemon on a Remote Server

      First, install the NKN shell daemon (nsd) on your server. This application will invoke nkn-multiclient, which will connect to NKN’s public network and obtain an address for routing. The daemon will then listen for incoming shell commands from authenticated and whitelisted clients, execute those commands, and then send back results.

      Start by downloading the latest pre-built nshd binary from GitHub:

      • wget https://github.com/nknorg/nkn-shell-daemon/releases/latest/download/linux-amd64.tar.gz

      Decompress the file:

      • tar -zxvf linux-amd64.tar.gz

      Then move the files into the /usr/local/bin directory so they are available system wide:

      • sudo mv ./linux-amd64/* /usr/local/bin/

      Next, you’ll configure this to run as a daemon process using Systemd so that it will restart if the server is reset.

      Create a file called nshd.service in /etc/systemd/system:

      • sudo nano /etc/systemd/system/nshd.service

      Add the following service definition to the file to configure the service:

      /etc/systemd/system/nshd.service

      [Unit]
      Description=NKN Shell Daemon
      After=network.target
      
      [Service]
      Type=simple
      User=root
      Group=root
      Restart=always
      ExecStart=/usr/local/bin/nshd
      
      [Install]
      WantedBy=multi-user.target
      

      Learn more about Systemd unit files in Understanding Systemd Units and Unit Files.

      Save the file and exit the editor. Then enable and start the nshd service with the following commands:

      • sudo systemctl enable nshd.service
      • sudo systemctl start nshd.service

      Run the following command to ensure the service is active and started:

      • sudo systemctl status nshd.service

      You’ll see that the status is active:

      Output

      ● nshd.service - NKN Shell Daemon Loaded: loaded (/etc/systemd/system/nshd.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-02-19 19:16:02 UTC; 7s ago Main PID: 3457 (nshd) Tasks: 10 (limit: 1152) CGroup: /system.slice/nshd.service └─3457 /usr/local/bin/nshd Feb 19 19:16:02 your_hostname systemd[1]: Started NKN Shell Daemon. Feb 19 19:16:03 your_hostname nshd[3457]: Create directory /etc/nshd/ Feb 19 19:16:03 your_hostname nshd[3457]: Create password and save to file /etc/nshd/wallet.pswd Feb 19 19:16:03 your_hostname nshd[3457]: Create wallet and save to file /etc/nshd/wallet.json Feb 19 19:16:03 your_hostname nshd[3457]: Create authorized pubkeys file /etc/nshd/authorized_pubkeys Feb 19 19:16:03 your_hostname nshd[3457]: Listening at d46567b883a3070ee3fe879d9fa2d5dc55a95f79ff2797c42df36c6979e5c4Aba

      In order to connect to your server, you’ll need to get its NKN address, which you can find in the output of the previous command. You can also run the following command to obtain the address:

      You’ll see your address appear:

      Output

      e70ca28ede84fc0659f2869255e8a393aef35b4fa5a7e036f29127c7dba75383

      Take note of this address as you will need it to connect to your server.

      Now that the daemon is running and listening, you can configure the web-based client to talk to the server.

      Step 2 — Configuring Permissions for NKN Shell Client

      You’ll need a compatible client that can connect to the remote machine. In this tutorial you’ll use NKN Shell Client Xterm, a web-based NKN shell client. There are a few different ways to run it:

      In this tutorial you’ll use the hosted version. On your local machine, open your web browser and navigate to https://nsh.nkn.org. You’ll see a welcome screen:

      The Shell Client

      Click Generate New Key Pair. Your keys will be generated and displayed as shown in the following image:

      The generated key pair

      Note: When you generate a new key pair, you will see a Secret Seed. Keep this secret seed secure and safe, just like you would with your SSH private key. Anyone who has this secret seed can use it to regenerate your public key and then run commands on your remote machines. Your browser will remember this seed, but you should copy it somewhere safe so you can use it again on a new machine.

      Save the Secret Seed somewhere safe. You can use it later to regenerate your public key so you can connect from a different client machine.

      Since this is a new key pair, you must add the Public Key to the file /etc/nshd/authorized_pubkeys on your server.

      /etc/nshd/authorized_pubkeys has a similar role as the ~/authorized_keys file which controls which SSH public keys can log in. The authorized_pubkeys file can specify which user is associated with a key. For security purposes, you’ll want to log in using a non-root user in this tutorial, so you’ll associate the generated public key with your sammy user you created in the Initial Server Setup guide in this article’s prerequisite.

      To associate a user with the public key, you’ll need to get the user id (UID) and group id (GID) of this user. Execute the following command on your server while logged in as the sammy user:

      You’ll see the UID and GID of the user:

      Output

      uid=1000(sammy) gid=1000(sammy) groups=1000(sammy),27(sudo)

      Now open the authorized_pubkeys file in your editor:

      • sudo nano /etc/nshd/authorized_pubkeys

      Add a single line containing the public key, uid, and gid, separated by spaces:

      authorized_pubkeys

      5d5367a5730427c205904a4457392051d2045dbce0186518fb6eb24dd9e41ba6 1000 1000
      

      Save the file.

      Verify that the file contains the correct content:

      • cat /etc/nshd/authorized_pubkeys

      You’ll see your key printed on the screen:

      Output

      5d5367a5730427c205904a4457392051d2045dbce0186518fb6eb24dd9e41ba6 1000 1000

      Then restart the nshd daemon to apply the changes:

      • sudo systemctl restart nshd.service

      Now let’s test it out by connecting to the server and running a command.

      Step 3 — Sending a Command to the remote machine and receive a response

      In NKN Shell Client, enter your remote nshd address from Step 1, as well as an optional client identifier:

      The nsh website with remote address filled in

      Click Connect to initiate the connection.

      You’ll be connected to your remote machine and shown a terminal prompt within the browser. From here you can use it just like SSH. For example, execute the following command to switch to the /etc/nshd directory:

      Then list its contents:

      You’ll see the contents of the directory:

      Output

      authorized_pubkeys wallet.json wallet.pswd

      You can disconnect by typing exit. When you need to reconnect, revisit the web interface and enter your connection details. If you generate a new key pair, you’ll need to add the new public key to your server.

      Conclusion

      In this tutorial, you installed and configured nsh to securely and conveniently send commands to a remote machine. nsh is a great way to access your remote machines when you need to quickly run a command to get the latest status of a service or peek at some configuration settings. The application is based on NKN’s global public network, and it’s free to use so you can incorporate it into your own application or workflow today.

      You can also explore nkn-tunnel which supports SSH or any other TCP based applications.



      Source link