ssh-notify-tool
Version:
Universal notification system for CLI tools with support for local and remote execution via SSH
698 lines (525 loc) • 15 kB
Markdown
# SSH Remote Setup Guide
Complete guide for setting up SSH tunnels to send notifications from remote servers.
## Table of Contents
- [Overview](#overview)
- [Architecture](#architecture)
- [Prerequisites](#prerequisites)
- [Server Setup](#server-setup)
- [Client Setup](#client-setup)
- [SSH Configuration](#ssh-configuration)
- [Security Considerations](#security-considerations)
- [Troubleshooting](#troubleshooting)
- [Advanced Scenarios](#advanced-scenarios)
## Overview
The SSH Notify Tool supports remote notifications through SSH tunnels, allowing you to:
- Send notifications from remote servers to your local desktop
- Centralize notifications from multiple servers
- Maintain security through encrypted SSH connections
- Work behind firewalls and NAT networks
## Architecture
```
[Remote Server] --SSH Tunnel--> [Local Machine] ---> [Desktop Notification]
│ │ │
┌──▼──┐ ┌───▼───┐ ┌────▼────┐
│ CLI │ │Server │ │Desktop │
│Tool │ │:3000 │ │Slack │
└─────┘ └───────┘ │Email...│
└─────────┘
```
**Flow**:
1. CLI tool on remote server establishes SSH tunnel to local machine
2. Notification sent through tunnel to local notification server
3. Local server processes notification and sends to configured channels
## Prerequisites
### Local Machine Requirements
- **Node.js 16+**: For running the notification server
- **SSH Server**: OpenSSH server or similar (for receiving connections)
- **SSH Notify Tool**: Installed globally via npm
### Remote Server Requirements
- **Node.js 16+**: For running the CLI client
- **SSH Client**: OpenSSH client or similar
- **Network Access**: Ability to connect to local machine via SSH
### Network Requirements
- **SSH Port**: Port 22 (or custom) accessible on local machine
- **Notification Port**: Internal port for tunnel (e.g., 3000)
## Server Setup
### 1. Local Machine (Notification Server)
#### Install SSH Notify Tool
```bash
npm install -g ssh-notify-tool
```
#### Create Configuration File
```bash
mkdir -p ~/.notifytool
cat > ~/.notifytool/config.json << 'EOF'
{
"server": {
"port": 3000,
"host": "127.0.0.1",
"auth": {
"enabled": true,
"token": "your-secure-token-replace-this"
}
},
"plugins": {
"desktop": {
"enabled": true,
"sound": true,
"timeout": 5000
},
"email": {
"enabled": true,
"provider": "gmail",
"auth": {
"user": "your-email@gmail.com",
"pass": "your-app-password"
},
"from": "your-email@gmail.com",
"to": ["your-email@gmail.com"]
},
"slack": {
"enabled": false,
"webhookUrl": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
}
},
"channels": ["desktop", "email"]
}
EOF
```
#### Generate Secure Token
```bash
# Generate a secure random token
node -e "console.log('Token:', require('crypto').randomBytes(32).toString('hex'))"
# Update config with generated token
sed -i 's/your-secure-token-replace-this/YOUR_GENERATED_TOKEN/' ~/.notifytool/config.json
```
#### Start Notification Server
```bash
# Start server with config
notify-server --config ~/.notifytool/config.json
# Or as a service (see Advanced Scenarios)
npm install -g pm2
pm2 start notify-server --name notifications -- --config ~/.notifytool/config.json
pm2 save
pm2 startup
```
#### Enable SSH Server
**Linux (Ubuntu/Debian)**:
```bash
sudo apt update
sudo apt install openssh-server
sudo systemctl start ssh
sudo systemctl enable ssh
```
**Linux (CentOS/RHEL)**:
```bash
sudo yum install openssh-server
sudo systemctl start sshd
sudo systemctl enable sshd
```
**macOS**:
```bash
# Enable Remote Login in System Preferences > Sharing
# Or via command line:
sudo systemsetup -setremotelogin on
```
### 2. Remote Server Setup
#### Install SSH Notify Tool
```bash
npm install -g ssh-notify-tool
```
#### Test SSH Connection
```bash
# Test basic SSH connection to your local machine
ssh username@your-local-machine-ip
# Test with specific port
ssh -p 2222 username@your-local-machine-ip
# Exit after successful connection test
exit
```
## Client Setup
### 1. SSH Key Authentication (Recommended)
#### Generate SSH Key on Remote Server
```bash
# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -f ~/.ssh/notify_key
# Enter passphrase or leave empty for automated scripts
# Display public key (copy this)
cat ~/.ssh/notify_key.pub
```
#### Add Public Key to Local Machine
```bash
# On your local machine, add the public key
mkdir -p ~/.ssh
echo "ssh-rsa AAAAB3... remote-user@remote-server" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
```
#### Test Key-based Authentication
```bash
# From remote server, test key authentication
ssh -i ~/.ssh/notify_key username@your-local-machine-ip
```
### 2. Basic Notification Test
#### Simple Test from Remote Server
```bash
# Test notification with SSH tunnel
notify-cli "Test from Remote" \
--message "Testing SSH tunnel notification" \
--remote username@your-local-machine-ip \
--ssh-key ~/.ssh/notify_key \
--token YOUR_GENERATED_TOKEN
```
#### Verify on Local Machine
You should see:
- Desktop notification (if enabled)
- Email notification (if configured)
- Server logs showing received notification
## SSH Configuration
### 1. SSH Config File (Recommended)
Create SSH config for easier management:
```bash
# On remote server: ~/.ssh/config
cat > ~/.ssh/config << 'EOF'
Host notify-local
HostName your-local-machine-ip
User your-username
Port 22
IdentityFile ~/.ssh/notify_key
ServerAliveInterval 30
ServerAliveCountMax 3
LocalForward 13000 127.0.0.1:3000
ExitOnForwardFailure yes
Host notify-local-alt
HostName your-local-machine-domain.com
User your-username
Port 2222
IdentityFile ~/.ssh/notify_key
EOF
# Set correct permissions
chmod 600 ~/.ssh/config
```
#### Using SSH Config
```bash
# Test connection using config
ssh notify-local
# Send notification using config
notify-cli "Config Test" --remote notify-local --ssh-config --token YOUR_TOKEN
```
### 2. Advanced SSH Options
#### Custom Port Forwarding
```bash
# Forward remote port 13000 to local port 3000
notify-cli "Test" \
--remote user@server.com \
--ssh-port 2222 \
--local-port 13000 \
--remote-port 3000 \
--token YOUR_TOKEN
```
#### Multiple Tunnel Support
```bash
# ~/.ssh/config for multiple servers
Host notify-prod
HostName prod-server.com
User deploy
IdentityFile ~/.ssh/prod_key
LocalForward 13001 127.0.0.1:3000
Host notify-staging
HostName staging-server.com
User deploy
IdentityFile ~/.ssh/staging_key
LocalForward 13002 127.0.0.1:3000
```
### 3. Automation Scripts
#### Notification Wrapper Script
```bash
#!/bin/bash
# notify-remote.sh - Wrapper script for remote notifications
REMOTE_HOST="notify-local"
AUTH_TOKEN="YOUR_TOKEN_HERE"
send_notification() {
local title="$1"
local message="$2"
local level="${3:-info}"
notify-cli "$title" \
--message "$message" \
--level "$level" \
--remote "$REMOTE_HOST" \
--ssh-config \
--token "$AUTH_TOKEN" \
--quiet
}
# Usage examples
send_notification "Script Started" "Backup script initiated" "info"
send_notification "Script Complete" "Backup completed successfully" "success"
send_notification "Script Failed" "Backup failed with errors" "error"
```
#### Integration with Cron Jobs
```bash
# Add to crontab: crontab -e
0 2 * * * /home/user/backup.sh && /home/user/notify-remote.sh "Backup Complete" "Daily backup finished successfully" "success" || /home/user/notify-remote.sh "Backup Failed" "Daily backup encountered errors" "error"
```
## Security Considerations
### 1. Authentication Security
#### Strong Token Generation
```bash
# Generate cryptographically secure token
openssl rand -hex 32
# Or using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
#### Token Storage
```bash
# Store token securely in environment
export NOTIFY_TOKEN="your-secure-token"
# Add to shell profile
echo 'export NOTIFY_TOKEN="your-secure-token"' >> ~/.bashrc
# Use in notifications
notify-cli "Test" --remote host --token "$NOTIFY_TOKEN"
```
### 2. SSH Security
#### SSH Key Security
```bash
# Secure key file permissions
chmod 600 ~/.ssh/notify_key
chmod 600 ~/.ssh/config
# Use SSH agent for automated scripts
ssh-agent bash
ssh-add ~/.ssh/notify_key
```
#### SSH Server Configuration
```bash
# /etc/ssh/sshd_config (on local machine)
Port 22
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
AllowUsers your-username
ClientAliveInterval 300
ClientAliveCountMax 2
# Restart SSH service
sudo systemctl restart ssh
```
#### Firewall Configuration
```bash
# UFW (Ubuntu)
sudo ufw allow from REMOTE_SERVER_IP to any port 22
# iptables
sudo iptables -A INPUT -p tcp -s REMOTE_SERVER_IP --dport 22 -j ACCEPT
```
### 3. Network Security
#### Port Forwarding Best Practices
```bash
# Bind tunnel to localhost only (secure)
ssh -L 127.0.0.1:13000:127.0.0.1:3000 user@local-machine
# Avoid binding to all interfaces (insecure)
# ssh -L 0.0.0.0:13000:127.0.0.1:3000 user@local-machine
```
#### Connection Monitoring
```bash
# Monitor SSH connections
sudo tail -f /var/log/auth.log | grep ssh
# Monitor notification server
notify-server --config ~/.notifytool/config.json --verbose
```
## Troubleshooting
### Common Issues
#### 1. SSH Connection Refused
**Error**: `Connection refused` or `No route to host`
**Solutions**:
```bash
# Test basic connectivity
ping your-local-machine-ip
telnet your-local-machine-ip 22
# Check SSH service
sudo systemctl status ssh
# Check firewall
sudo ufw status
sudo iptables -L
# Test with verbose SSH
ssh -v user@your-local-machine-ip
```
#### 2. Authentication Failures
**Error**: `Permission denied (publickey)`
**Solutions**:
```bash
# Verify key permissions
ls -la ~/.ssh/notify_key*
chmod 600 ~/.ssh/notify_key
# Test key
ssh -i ~/.ssh/notify_key -v user@local-machine
# Check authorized_keys on local machine
ls -la ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```
#### 3. Tunnel Connection Issues
**Error**: `channel 2: open failed: connect failed: Connection refused`
**Solutions**:
```bash
# Verify server is running
ssh user@local-machine "ps aux | grep notify-server"
# Check port binding
ssh user@local-machine "netstat -tlnp | grep 3000"
# Test local connection
ssh user@local-machine "curl -s http://localhost:3000/api/health"
```
#### 4. Notification Server Not Accessible
**Error**: `ECONNREFUSED` or timeout errors
**Solutions**:
```bash
# Check server status
notify-server --config ~/.notifytool/config.json --dry-run
# Verify configuration
cat ~/.notifytool/config.json | jq .server
# Check logs
tail -f ~/.notifytool/logs/server.log
# Test direct connection
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/api/health
```
### Debug Mode
#### Enable Verbose Logging
```bash
# Debug SSH connection
ssh -vvv user@local-machine
# Debug notification client
DEBUG=notify:* notify-cli "Test" --remote user@local-machine
# Debug server
DEBUG=notify:* notify-server --config ~/.notifytool/config.json
```
#### Network Diagnostics
```bash
# Check tunnel status
ss -tlnp | grep 3000
# Monitor network traffic
sudo tcpdump -i lo port 3000
# Check process connections
lsof -i :3000
```
### Log Analysis
#### SSH Logs
```bash
# View SSH authentication logs
sudo tail -f /var/log/auth.log
# Filter for specific user
sudo grep "your-username" /var/log/auth.log | tail -20
```
#### Application Logs
```bash
# Server logs
tail -f ~/.notifytool/logs/server.log
# Client logs (if configured)
tail -f ~/.notifytool/logs/client.log
# System logs
journalctl -u ssh --no-pager -l
```
## Advanced Scenarios
### 1. Multiple Remote Servers
#### Hub Configuration
```bash
# Local machine config for multiple servers
cat > ~/.notifytool/config.json << 'EOF'
{
"server": {
"port": 3000,
"host": "0.0.0.0"
},
"plugins": {
"desktop": {"enabled": true},
"slack": {
"enabled": true,
"webhookUrl": "YOUR_SLACK_WEBHOOK",
"channel": "#alerts"
}
}
}
EOF
```
#### Remote Server Scripts
```bash
# Production server notification script
#!/bin/bash
# /usr/local/bin/notify-prod
notify-cli "$1" \
--message "$2" \
--level "${3:-info}" \
--remote notify-local \
--ssh-config \
--token "$NOTIFY_TOKEN" \
--tags "production,$(hostname)" \
--metadata '{"server":"production","environment":"prod"}'
```
### 2. Load Balancer Setup
#### Multiple Notification Servers
```bash
# ~/.ssh/config for failover
Host notify-primary
HostName primary.local
User notify
IdentityFile ~/.ssh/notify_key
ConnectTimeout 5
Host notify-backup
HostName backup.local
User notify
IdentityFile ~/.ssh/notify_key
ConnectTimeout 5
```
#### Failover Script
```bash
#!/bin/bash
# notify-failover.sh
send_with_failover() {
local title="$1"
local message="$2"
# Try primary server
if notify-cli "$title" --message "$message" --remote notify-primary --ssh-config; then
echo "Notification sent via primary server"
# Fallback to backup
elif notify-cli "$title" --message "$message" --remote notify-backup --ssh-config; then
echo "Notification sent via backup server"
else
echo "All notification servers failed" >&2
return 1
fi
}
```
### 3. Service Management
#### Systemd Service (Local Machine)
```bash
# /etc/systemd/system/notify-server.service
cat > /etc/systemd/system/notify-server.service << 'EOF'
[Unit]
Description=SSH Notify Server
After=network.target
[Service]
Type=simple
User=notify
Group=notify
WorkingDirectory=/home/notify
ExecStart=/usr/local/bin/notify-server --config /home/notify/.notifytool/config.json
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Enable and start service
sudo systemctl enable notify-server
sudo systemctl start notify-server
```
#### Docker Deployment
```dockerfile
# Dockerfile
FROM node:18-alpine
RUN npm install -g ssh-notify-tool
COPY config.json /app/config.json
WORKDIR /app
EXPOSE 3000
CMD ["notify-server", "--config", "/app/config.json"]
```
```bash
# Build and run
docker build -t notify-server .
docker run -d -p 3000:3000 -v ~/.notifytool/config.json:/app/config.json notify-server
```
This comprehensive SSH setup guide should help users configure secure, reliable remote notifications through SSH tunnels.