When managing remote servers with Time-Based One-Time Password (TOTP) authentication, relying on smartphone apps like Google Authenticator can be limiting. System administrators often need command-line alternatives for:
- Headless server environments
- Automation scripts
- Backup authentication methods
- Linux-based workflows
The most robust solution is oathtool
from the OATH-Toolkit package, available in most Linux distributions:
# Installation on Debian/Ubuntu
sudo apt-get install oathtool
# Installation on RHEL/CentOS
sudo yum install oathtool
To generate verification codes from your secret key:
# Basic usage (replace SECRET with your base32 key)
oathtool --totp -b SECRET
# Example with real key (truncated for security)
oathtool --totp -b "JBSWY3DPEHPK3PXP"
The tool supports several useful parameters:
# Generate code for specific time window (useful for testing)
oathtool --totp --now "2023-01-01 00:00:00" -b SECRET
# Generate multiple consecutive codes (helpful for time sync issues)
oathtool --totp -w 3 -b SECRET
# Using hex-encoded secrets instead of base32
oathtool --totp --hex SECRET_HEX
For automated SSH logins, you can combine oathtool with expect:
#!/bin/bash
TOTP=$(oathtool --totp -b SECRET)
expect -c "
spawn ssh user@server
expect \"Verification code:\"
send \"$TOTP\r\"
expect \"Password:\"
send \"YOUR_PASSWORD\r\"
interact
"
Never store secrets in plaintext. Consider these alternatives:
# Option 1: Encrypted file with GPG
oathtool --totp -b $(gpg -d secret.gpg)
# Option 2: Password manager integration (pass)
oathtool --totp -b $(pass show server/totp-secret)
# Option 3: Environment variables (slightly better than plaintext)
export TOTP_SECRET="JBSWY3DPEHPK3PXP"
oathtool --totp -b "$TOTP_SECRET"
If OATH-Toolkit isn't available:
- Python solution with PyOTP:
pip install pyotp
- Go implementation: github.com/gokyle/totp
- Node.js package: npm install notp
- Regularly rotate your TOTP secrets
- Use hardware security modules for production environments
- Never commit secrets to version control
- Consider rate limiting for brute force protection
When managing servers with two-factor authentication (2FA) via TOTP (Time-based One-Time Password), relying on mobile apps like Google Authenticator can be limiting for sysadmins. The standard 30-second rotating codes can be generated directly from the command line, offering better integration with server management workflows.
Here are three robust CLI solutions for generating TOTP codes:
# 1. oathtool (part of OATH Toolkit)
# Installation on Debian/Ubuntu:
sudo apt-get install oathtool
# Usage with secret key:
oathtool --totp -b "YOUR_BASE32_SECRET"
# 2. google-authenticator-cli
# Installation via pip:
pip install google-authenticator-cli
# Generate new secret:
google-authenticator -t -d -f -r 3 -R 30 -w 3
# Verify code:
google-authenticator --code "YOUR_SECRET"
# 3. Python script alternative
import hmac, base64, struct, hashlib, time
def get_totp_token(secret):
key = base64.b32decode(secret)
msg = struct.pack(">Q", int(time.time())//30)
h = hmac.new(key, msg, hashlib.sha1).digest()
o = h[19] & 15
h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
return "{0:06d}".format(h)
print(get_totp_token("YOUR_BASE32_SECRET"))
For PAM-enabled SSH 2FA like in your setup, ensure your /etc/pam.d/sshd
contains:
auth required pam_google_authenticator.so
And sshd_config
has:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive:pam
- Store secrets in encrypted files (e.g., GPG-encrypted or vault)
- Set proper file permissions (600 for config files)
- Consider using
pass
orgopass
to manage secrets - Rotate secrets periodically
For automated processes, combine with expect
scripts:
#!/usr/bin/expect -f
set secret "YOUR_SECRET"
spawn ssh user@host
expect "Verification code:"
send "[exec oathtool --totp -b $secret]\r"
expect "$ "
interact