Secure Shell (SSH) access is fundamental to remote server administration, making its security and performance settings critical for IT professionals and managed service providers (MSPs). One frequently overlooked configuration is learning how to set Linux SSH login timeout with Shell scripting, controlled by the LoginGraceTime directive. This setting determines how long a server will wait for a user to successfully authenticate before terminating the session. Automating the configuration of this parameter using a shell script ensures consistency, saves time, and helps enforce security best practices across infrastructure.
Background
The LoginGraceTime directive in the sshd_config file controls the window of time SSH servers allow unauthenticated connections to remain open. The default is usually 120 seconds—ample time for a user to log in, but unnecessarily long in environments where tight security policies are enforced.
For IT administrators managing fleets of Linux machines, especially via RMM platforms like NinjaOne, manually updating sshd_config on each system is not scalable. Automating this with a shell script offers not just convenience but also version control, consistency, and error reduction. This is where the featured script comes in.
The Script
#!/usr/bin/env bash # Description: Sets the SSH login timeout via LoginGraceTime. # By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. # Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. # Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. # Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. # Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. # Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. # Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. # EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). # # Preset Parameter: --setTimeoutInSeconds "ReplaceMeWithANumber" # The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds. # # Links: https://man.openbsd.org/sshd_config#LoginGraceTime # Logs an error message and exits with the specified exit code die() { local _ret="${2:-1}" echo "$1" >&2 exit "${_ret}" } _sshd_config="/etc/ssh/sshd_config" backup_file() { file_source=$1 file_backup="${file_source}_$(date +%Y-%m-%d_%H-%M-%S).backup" if [[ -f "${file_source}" ]]; then echo "[Info] Backing up $file_source to $file_backup" cp "${file_source}" "${file_backup}" fi # Remove the oldest backup file if there are more than 3 backups # Get the list of backup files echo "[Info] Finding backup files..." _sshd_config_dir=$(dirname "${_sshd_config}") _sshd_config_file=$(basename "${_sshd_config}") backup_files=$(find "$_sshd_config_dir" -name "${_sshd_config_file}_*.backup" -printf '%T+ %p\n' 2>/dev/null | sort -r | tail -n +4 | cut -d' ' -f2-) # Loop through each backup file and remove it for backup_file in $backup_files; do echo "[Info] Removing $backup_file" rm -f "$backup_file" done } # Check that we are running as root if [[ $EUID -ne 0 ]]; then die "[Error] This script must be run as root." 1 fi if [[ -z "${setTimeoutInSeconds}" ]]; then die "[Error] Timeout was not specified." 1 fi # Remove any leading zeros setTimeoutInSeconds=$((setTimeoutInSeconds)) if ((setTimeoutInSeconds > 86400)); then die "[Error] Timeout can not be greater than 86400." 1 fi if ((setTimeoutInSeconds < 0)); then die "[Error] Timeout can not be less than 0." 1 fi _should_reload="false" # Default is 0; which is disabled _loginGraceTime="LoginGraceTime ${setTimeoutInSeconds}" # Check if the sshd_config file exists if [[ -f "${_sshd_config}" ]]; then # Check if the LoginGraceTime option is already set to _loginGraceTime if grep -q "^${_loginGraceTime}" "${_sshd_config}"; then echo "[Info] Timeout is already set to ${setTimeoutInSeconds}." _should_reload="false" elif grep -q "^LoginGraceTime .*" "${_sshd_config}"; then backup_file "${_sshd_config}" # First check if the option is not commented out and set to yes # Then set the LoginGraceTime option to ${setTimeoutInSeconds} sed -i "s/^LoginGraceTime.*/${_loginGraceTime}/" "${_sshd_config}" echo "[Info] LoginGraceTime set to ${setTimeoutInSeconds}." _should_reload="true" elif grep -q "^#LoginGraceTime" "${_sshd_config}"; then backup_file "${_sshd_config}" # First check if the option is commented out # Then set the LoginGraceTime option to ${setTimeoutInSeconds} sed -i "s/^#LoginGraceTime.*/${_loginGraceTime}/" "${_sshd_config}" echo "[Info] LoginGraceTime set to ${setTimeoutInSeconds}, as it was commented out." _should_reload="true" else backup_file "${_sshd_config}" # Append the LoginGraceTime option to the end of the sshd_config file # If the past checks have not found the option, appending it will ensure that it is set to no echo "${_loginGraceTime}" >>"${_sshd_config}" echo "[Info] LoginGraceTime set to ${setTimeoutInSeconds} at the end of the sshd_config file." _should_reload="true" fi # Check that this system is running systemd-based _type=$( # Get the type of init system file /sbin/init 2>/dev/null | awk -F/ '{print $NF}' 2>/dev/null ) if [[ "${_type}" == "systemd" ]] && [ "$(command -v systemctl)" ]; then echo "[Info] Reloading ${sshd_service} service..." # Find the sshd service sshd_service=$( # Get the ssh service, if two are found use the first one. Likely the first one is a symlink to the actual service file. systemctl list-unit-files | grep -E "^(sshd|ssh|openssh-server)\.service" | awk -F' ' '{print $1}' | head -n 1 ) if [[ -z "${sshd_service}" ]]; then die "[Error] sshd service is not available. Please install it and try again." 1 fi # Check that ssh service is enabled if systemctl is-enabled "${sshd_service}" >/dev/null; then echo "[Info] ${sshd_service} is enabled." else die "[Info] ${sshd_service} is not enabled. When enabled and started, PermitEmptyPasswords will be set to no." 0 fi # Check that ssh service is running if systemctl is-active "${sshd_service}" >/dev/null; then echo "[Info] ${sshd_service} is running." if [[ "${_should_reload}" == "true" ]]; then # Reload sshd.service if systemctl reload "${sshd_service}"; then echo "[Info] sshd service configuration reloaded." else die "[Error] Failed to reload ${sshd_service}. Please try again." 1 fi else echo "[Info] sshd service configuration will not be reloaded as there is no need to do so." fi else echo "[Info] ${sshd_service} is not running." fi else echo "[Info] Restarting sshd service..." # Check that the service command is available if ! [ "$(command -v service)" ]; then die "[Error] The service command is not available. Is this an initd type system (e.g. SysV)? Please try again." 1 fi # Find the sshd service sshd_service=$( # Get the list of services service --status-all | awk -F' ' '{print $NF}' | grep sshd ) if [[ -z "${sshd_service}" ]]; then die "[Error] sshd service is not available. Please install it and try again." 1 fi if [[ "${_should_reload}" == "true" ]]; then # Restart sshd service if service "${sshd_service}" restart; then echo "[Info] sshd service restarted." else die "[Error] Failed to restart sshd service. Please try again." 1 fi else echo "[Info] sshd service configuration will not be restarted as there is no need to do so." fi fi else die "[Error] The sshd_config file does not exist." 1 fi
Detailed Breakdown
The provided shell script automates the process of setting the SSH login timeout on a Linux system by modifying the LoginGraceTime directive in /etc/ssh/sshd_config. Here’s a step-by-step breakdown of its operation:
- Input Validation
The script expects a preset parameter –setTimeoutInSeconds. It ensures:- The user running the script is root.
- The timeout value is within a valid range (0 to 86400 seconds).
- Backup Handling
Before any modification:- The script backs up the current sshd_config file with a timestamped suffix.
- It retains the three most recent backups, deleting older ones to avoid clutter.
- Configuration Logic
The script intelligently updates the LoginGraceTime directive:- If already set correctly, it exits early.
- If present but incorrect, or commented out, it updates the line.
- If missing, it appends the new setting to the end of the file.
- Service Reload/Restart
Based on the init system:- On systemd-based systems: uses systemctl reload for efficiency.
- On SysV/init.d systems: falls back to service sshd restart.
- Error Handling
The script includes robust checks and user-friendly messages to alert administrators of issues, such as missing sshd_config or SSH services not running.
Potential Use Cases
Case Study
An MSP manages 500 Linux servers for a client with strict compliance requirements. The client mandates that SSH sessions terminate if authentication isn’t completed within 30 seconds. Using NinjaOne’s custom scripting capabilities, the MSP deploys this script with the parameter –setTimeoutInSeconds 30 across the entire infrastructure. The script runs silently, backs up configurations, enforces the policy, and restarts services as needed—saving hours of manual work and ensuring compliance.
Comparisons
There are alternative ways to set LoginGraceTime, such as:
- Manual Editing
Logging into each machine and editing /etc/ssh/sshd_config using vim or nano. This is time-consuming and error-prone. - Ansible or Puppet Modules
While powerful, these tools require significant setup and are overkill for simple changes on small to mid-sized networks. - Shell Script Automation (this script)
Lightweight, portable, and easy to integrate into RMM platforms. It balances simplicity with robustness.
FAQs
Q: What happens if sshd_config doesn’t exist?
The script will exit with an error message, ensuring no operations continue.
Q: Can I set the timeout to 0 for no limit?
Yes. Setting –setTimeoutInSeconds 0 removes the timeout, though it’s not recommended for security reasons.
Q: What if the SSH service isn’t enabled or running?
The script will alert you and halt if necessary services aren’t in place.
Q: How do I run this with NinjaOne?
Set the parameter via NinjaOne’s custom script interface, passing –setTimeoutInSeconds 60 as an example.
Implications
Automating SSH login timeout configuration reduces the window for brute-force or unauthorized access attempts. By ensuring consistent timeout policies, organizations minimize idle open sessions—an often exploited vector in attacks. This also ensures compliance with industry standards like CIS Benchmarks and internal security policies.
Moreover, regular backups maintained by the script make it safer to deploy changes without fear of irreversible errors.
Recommendations
- Always test on a non-production machine before widespread deployment.
- Use conservative timeout values (e.g., 30–60 seconds) that balance usability with security.
- Document the deployment process and maintain logs of changes for auditing.
- Leverage RMM tools like NinjaOne to deploy the script at scale and monitor outcomes.
- Avoid setting timeout to 0 unless there is a specific, justified need.
Final Thoughts
As IT environments scale, so does the need for secure, consistent, and automated configurations. This script exemplifies how even simple shell scripting can enforce best practices without complex infrastructure. For MSPs and IT admins using NinjaOne, integrating such scripts into automated policies enhances operational efficiency and security posture.
NinjaOne’s automation capabilities—like scheduled scripts, policy-based deployment, and centralized monitoring—make it the ideal platform to deploy and manage configurations like LoginGraceTime. When paired with well-crafted scripts like this one, NinjaOne empowers teams to deliver secure, scalable, and responsive IT management.