Using PAM for SSH Login Telephony

post-thumb

Real-Time SSH Login Alerts Using PAM and Gotify

Pluggable Authentication Modules ( PAM) provide a flexible mechanism for authenticating users on Linux systems. By integrating PAM with Gotify, you can receive real-time notifications for SSH login attempts, enhancing your system’s security and awareness.

I’ve been using this approach for over 5 years across many systems — it’s lightweight, reliable, and highly effective. Let’s walk through how to set it up.


Prerequisites

Before you begin, make sure you have the following:

  1. A Linux server with SSH access.
  2. Root or sudo privileges.
  3. curl installed.

Step 1: Install and Configure Gotify

Gotify is a simple self-hosted server for sending notifications. You can also use a hosted instance if desired.

  1. Install Gotify or use an existing instance.

  2. Create an application in Gotify and note down the application token.

  3. Test that your setup works by sending a test message:

    curl -X POST "http://<gotify-server>/message" \
      -H "X-Gotify-Key: <application-token>" \
      -F "title=Test Notification" \
      -F "message=This is a test message"
    

Step 2: Create the PAM Notification Script

We’ll configure PAM to trigger this script every time someone logs in via SSH.

  1. Create the script:

    sudo vim /usr/local/bin/pam-ssh-notify.sh
    

    Paste the following:

    #!/usr/bin/env bash
    
    GOTIFY_URL="http://<gotify-server>/message"
    GOTIFY_TOKEN="<gotify-token>"
    
    /usr/bin/curl -s -X POST "$GOTIFY_URL" \
      -H "X-Gotify-Key: $GOTIFY_TOKEN" \
      -F "title=SSH Login Alert" \
      -F "message=User \"$PAM_USER\" logged in from \"$PAM_RHOST\""
    
  2. Make it executable:

    sudo chmod +x /usr/local/bin/pam-ssh-notify.sh
    

Step 3: Update PAM Configuration

  1. Edit the PAM configuration for SSH:

    sudo vim /etc/pam.d/sshd
    
  2. Add this line at the end of the file:

    session optional pam_exec.so /usr/local/bin/pam-ssh-notify.sh
    

Why optional? If Gotify is unreachable and this script fails, PAM will ignore the failure. If you use required, login failures could result from simple network errors — not ideal for a monitoring hook.


Step 4: Enable and Test It

  1. Ensure the UsePAM setting is set to ‘yes’ inside of /etc/ssh/sshd_config (or wherever your configuration is).

  2. Restart SSH:

    sudo systemctl restart sshd
    
  3. Log in from another machine and confirm that your Gotify app receives a notification.


Appendix: PAM Environment Variables

When PAM executes your custom script, it passes in useful environment variables that can be used to enhance logic, filtering, and alerting.

VariableDescriptionExample Use Case
PAM_USERUser being authenticatedNotify only on root logins
PAM_RHOSTRemote IP or hostnameGeoIP filter or blacklist
PAM_SERVICEService name (e.g. sshd, sudo)Alert only on sshd logins
PAM_TTYTerminal device (e.g. pts/0)Log which TTY was used
PAM_TYPEEvent type (auth, session, etc.)Differentiate login vs session start
PAM_RUSEROriginating user (e.g. for sudo)Log who used sudo

Considerations

While this PAM-to-Gotify setup is simple and effective, it’s best suited for single-node systems like personal VPS setups or small self-hosted boxes, systems you’re willing to give your full attention to. It is not scalable for large fleets or production environments with dozens or hundreds of machines. For those cases, you’d want something more robust and asynchronous — like a logging agent with webhook triggers or a centralized security event bus. For a midrange use case with an audit trail, I’ve also swapped out Gotify for a custom Slack App, using the channel webhooks in the past.

Also, a critical caution: setting your PAM module to required instead of optional can be dangerous. If Gotify (or DNS) is down, a required script failure will prevent user logins entirely. This is not hypothetical — in 2021 Facebook famously locked themselves out of their own data center because DNS broke, and they couldn’t log in to fix the DNS server. By marking this hook as optional, you avoid cascading failures. Learn from their mistakes.

PAM is capable of much more–adding 2-factor authentication, YubiKey support, LDAP auth, encrypted filesystem mounting, etc. If you want to learn more, the ArchLinux Wiki is a great source, even if you’re not running Arch yourself.

Conclusion

With just a few lines of shell and PAM configuration, you can build powerful real-time login alerts and security automation using Gotify. The $PAM_* variables give you rich context for decision-making and logging, and the system is lightweight and reliable.

Feel free to extend this setup to logins via sudo, su, or even failed login attempts — and adapt it to your environment as needed.

Stay secure!

You May Also Like