Automating Tasks With Automation

SSH Series: Part 7
Posted by Munish Mehta on Monday, January 27, 2025
Tired of repetitive server chores? Let SSH automation handle the heavy lifting, so you can focus on real innovation

This article is part of a series.

ssh

Throughout this SSH series, I’ve explored everything from basic setups and key-based authentication to best practices and troubleshooting. Now, I’m going to show you how to automate tasks using SSH—an essential skill in modern DevOps and system administration. Whether you’re executing simple commands on multiple servers or orchestrating complex deployments, SSH can simplify and secure your workflow.

Basics of SSH Usage in Bash Scripting

Bash Scripting with SSH Commands

One of the most straightforward ways to automate tasks with SSH is by writing bash scripts. For instance, suppose I want to run a disk usage check on a remote server every day. Instead of logging in manually, I can script it:

#!/bin/bash

REMOTE_USER="myuser"
REMOTE_HOST="example.com"
REMOTE_CMD="df -h"

echo "Checking disk usage on $REMOTE_HOST..."
ssh "${REMOTE_USER}@${REMOTE_HOST}" "$REMOTE_CMD"
  • ssh user@host "<command>"
    • Runs a single command on the remote host without opening an interactive shell.
  • Advantages
    • You can store these commands in scripts, schedule them with cron, or trigger them on demand.

Error Handling

If you want to detect errors (like permission issues or missing commands), you can check $? (the exit code)

ssh "${REMOTE_USER}@${REMOTE_HOST}" "$REMOTE_CMD"
if [ $? -ne 0 ]; then
  echo "Error: Could not run command on $REMOTE_HOST"
fi

Handling Non-Interactive Authentication

For automation, non-interactive logins are key. I recommend key-based authentication (as covered in Part 3 of this series). Here’s a quick recap:

  1. Generate SSH Keys (on your local machine)

    ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_automation
    
  2. Copy the Public Key to the Server

    ssh-copy-id -i ~/.ssh/id_ed25519_automation.pub user@host
    
  3. Use the Private Key in Your Script

    ssh -i ~/.ssh/id_ed25519_automation user@host "<command>"
    

You can store the key in a secure location and reference it from your script. This way, the script never needs to prompt for a password, which is crucial for scheduled tasks or large-scale automation.

[!Tip] To add a passphrase to your key for extra security, consider using an SSH agent or keychain to cache passphrases if the script environment allows it.

Handling Multiple Servers

Using for Loops

If you have a small set of servers, a simple bash for loop can do the trick

#!/bin/bash

SERVERS=("server1.example.com" "server2.example.com" "server3.example.com")
CMD="uptime"

for HOST in "${SERVERS[@]}"; do
  echo "----- $HOST -----"
  ssh "myuser@$HOST" "$CMD"
done

This will SSH into each server and run uptime. Of course, you can expand this with different commands, error handling, or output parsing.

Parallel SSH (pssh)

If you have dozens or hundreds of servers, waiting on them one by one can be slow. Tools like pssh (parallel SSH) let you run commands in parallel:

  1. Install pssh

    • Ubuntu/Debian
        sudo apt-get install pssh
      
  2. Create a Host File (hosts.txt)

        server1.example.com
        server2.example.com
        server3.example.com 
    
  3. Run a Command

        pssh -h hosts.txt -l myuser -A -i "uptime"
    

    Where

    • -h hosts.txt: Reads the list of hosts.
    • -A: Prompts you for a password (if not using key-based auth).
    • -i: Prints output inline.

This way, each SSH session is executed in parallel, saving you time.

Ansible as an Alternative

For more sophisticated automation, Ansible is a popular choice. It uses SSH under the hood by default, so you don’t need extra daemons.

  1. Install Ansible

        sudo apt-get install ansible
    
  2. Inventory File (inventory.ini)

    [webservers]
    server1.example.com
    server2.example.com
    
    [dbservers]
    server3.example.com
    
  3. Run a Command

    ansible webservers -m shell -a "uptime" -u myuser
    

Ansible handles parallel execution, conditional tasks, modules for different actions, and more.

Best Practices for SSH Automation

Key Management

  • Separate Keys
    • Use different SSH keys for automated tasks than for interactive logins. This way, if one key is compromised, you don’t lose all access.
  • Rotate Keys
    • Regularly: Update keys periodically to reduce the risk of old keys being abused.
  • Least Privilege
    • Limit each key to exactly what it needs (e.g., command="uptime" in authorized_keys if you only want that command to run).

Secrets Handling

  • Never Store Passwords in Plain Text
    • If you must use passwords, consider environment variables or secure vaults (e.g., Ansible Vault, HashiCorp Vault).
  • Encrypted Filesystems
    • If your automation server stores multiple private keys, keep them on an encrypted filesystem or use strong passphrases.

3.3 Minimizing Exposure

  • Restrict IP Addresses
    • Use firewalls to limit SSH access to known management stations.
  • Logging and Monitoring
    • Keep an eye on /var/log/auth.log or equivalent. Automated tasks can run frequently, so watch for anomalies.
  • Periodic Review
    • Regularly audit which scripts and cron jobs use SSH. Remove anything unnecessary or outdated.

Example Workflow: Automated Software Update

Let me show you a quick scenario:

  1. Script (update_servers.sh):

    #!/bin/bash
    
    SERVERS=("web1" "web2" "db1")
    CMD="sudo apt-get update && sudo apt-get upgrade -y"
    
    for HOST in "${SERVERS[@]}"; do
      echo "Updating $HOST..."
      ssh -i ~/.ssh/id_automation "myuser@$HOST" "$CMD"
    done
    
  2. Set a Cron Job:

    crontab -e
    
    # Run at 2 AM every Sunday
    0 2 * * 0 /home/myuser/update_servers.sh >> /var/log/update_servers.log 2>&1
    
  3. Check Logs

    • Each Sunday, the script auto-updates all listed servers. The logs can be reviewed for any errors.

[!Warning] Automatic upgrades can sometimes break services if dependencies change. Always test updates on a staging environment before rolling them out.

Conclusion

By leveraging SSH in scripts, using tools like pssh or Ansible, and adhering to best practices for key management and secrets handling, you can streamline admin tasks and reduce manual overhead. This approach is especially invaluable when managing large server fleets or complex deployments.

Key Takeaways

  • Scripting SSH calls can handle repetitive tasks like collecting logs, running health checks, or deploying updates.
  • Parallel tools (pssh, Ansible) greatly speed up tasks that would be tedious to run server-by-server.
  • Security is paramount: treat your automation keys like the keys to your kingdom—because they are.

In our next and final posts, I’ll dive deeper into more SSH tools and alternatives. Feel free to leave a comment if you have questions or want to share your own automation tips!

Further Reading

Happy automating, and I’ll see you in the next part of this SSH series!

This article is part of a series.


comments powered by Disqus