#!/bin/bash

#############################################################
#### ntfy Push Notification Server Setup                 ####
#### Install and configure ntfy as a systemd service     ####
####                                                     ####
#### Author: Phil Connor                                 ####
#### Contact: contact@mylinux.work                       ####
#### License: MIT                                        ####
#### Version: 1.1                                        ####
####                                                     ####
#### Usage: sudo ./install-ntfy-server.sh                ####
#############################################################

set -euo pipefail

# --- Configuration (edit these before running) ---
NTFY_VERSION="2.8.0"
DOMAIN="ntfy.example.com"

NTFY_USER="ntfy"
NTFY_DIR="/var/lib/ntfy"
CONFIG_DIR="/etc/ntfy"

# Ensure script is run as root
if [[ $EUID -ne 0 ]]; then
    echo "ERROR: This script must be run as root (use sudo)."
    exit 1
fi

# Detect noexec /tmp — fall back to /usr/local/src
STAGE_DIR="/tmp"
_exec_test=$(mktemp /tmp/.exec_test.XXXXXX 2>/dev/null)
if [[ -n "$_exec_test" ]]; then
    printf '#!/bin/sh\nexit 0\n' > "$_exec_test"
    chmod +x "$_exec_test"
    "$_exec_test" 2>/dev/null || STAGE_DIR="/usr/local/src"
    rm -f "$_exec_test"
else
    STAGE_DIR="/usr/local/src"
fi

echo "=== Installing ntfy v${NTFY_VERSION} ==="

# Create ntfy user
if ! id "$NTFY_USER" &>/dev/null; then
    echo "Creating ntfy user..."
    useradd --system --no-create-home --shell /usr/sbin/nologin "$NTFY_USER"
fi

# Create directories
echo "Creating directories..."
mkdir -p "$NTFY_DIR" "$CONFIG_DIR"
chown "$NTFY_USER:$NTFY_USER" "$NTFY_DIR"

# Download and install ntfy
echo "Downloading ntfy..."
rm -rf ${STAGE_DIR}/ntfy_extract
mkdir -p ${STAGE_DIR}/ntfy_extract
wget -q -O ${STAGE_DIR}/ntfy.tar.gz "https://github.com/binwiederhier/ntfy/releases/download/v${NTFY_VERSION}/ntfy_${NTFY_VERSION}_linux_amd64.tar.gz"
tar -xzf ${STAGE_DIR}/ntfy.tar.gz -C ${STAGE_DIR}/ntfy_extract
find ${STAGE_DIR}/ntfy_extract -name "ntfy" -type f -exec mv {} /usr/local/bin/ntfy \;
chmod +x /usr/local/bin/ntfy
rm -rf ${STAGE_DIR}/ntfy.tar.gz ${STAGE_DIR}/ntfy_extract

# Verify installation
echo "Verifying installation..."
if [ -x /usr/local/bin/ntfy ]; then
    echo "✓ ntfy binary installed at /usr/local/bin/ntfy"
else
    echo "✗ ntfy binary not found"
    exit 1
fi

# Create configuration
echo "Installing configuration..."

cat > "$CONFIG_DIR/server.yml" << EOF
# ntfy server configuration
# Location: /etc/ntfy/server.yml

# Base URL for the server (used in notification links)
base-url: "http://${DOMAIN}"

# Listen address - use internal port, proxy externally
listen-http: "127.0.0.1:8090"

# Authentication - deny by default, require tokens
auth-default-access: "deny-all"
auth-file: "/var/lib/ntfy/user.db"

# Cache for offline message delivery
cache-file: "/var/lib/ntfy/cache.db"
cache-duration: "24h"

# Behind nginx/caddy reverse proxy
behind-proxy: true

# Attachment settings
attachment-cache-dir: "/var/lib/ntfy/attachments"
attachment-total-size-limit: "1G"
attachment-file-size-limit: "10M"
attachment-expiry-duration: "24h"

# Logging
log-level: "info"
log-format: "json"

# Rate limiting per visitor
visitor-subscription-limit: 30
visitor-request-limit-burst: 60
visitor-request-limit-replenish: "5s"
EOF

cat > /etc/systemd/system/ntfy.service << 'EOF'
# ntfy systemd service
# Location: /etc/systemd/system/ntfy.service

[Unit]
Description=ntfy push notification server
Documentation=https://ntfy.sh/docs/
After=network.target

[Service]
Type=simple
User=ntfy
Group=ntfy

ExecStart=/usr/local/bin/ntfy serve --config /etc/ntfy/server.yml
Restart=always
RestartSec=5

# Security hardening
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/ntfy

# Resource limits
LimitNOFILE=65535
MemoryMax=512M

[Install]
WantedBy=multi-user.target
EOF

# Enable and start service
echo "Enabling ntfy service..."
systemctl daemon-reload
systemctl enable ntfy
systemctl start ntfy

# Wait for service to start
sleep 2

# Check status
if systemctl is-active --quiet ntfy; then
    echo "✓ ntfy service is running"
else
    echo "✗ ntfy service failed to start"
    systemctl status ntfy
    exit 1
fi

echo ""
echo "=== Setting up authentication ==="
echo ""

# Create admin user (skip if exists)
echo "Creating admin user..."
if ntfy user list 2>/dev/null | grep -q "^admin "; then
    echo "✓ admin user already exists"
else
    ntfy user add --role=admin admin
fi
echo ""

# Set access permissions for alert topics
echo "Setting access permissions for alert topics..."
ntfy access admin 'alerts-*' rw
echo "✓ admin has rw access to alerts-*"

echo ""
echo "=== Next Steps ==="
echo ""
echo "1. Create user accounts for desktop clients:"
echo "   ntfy user add --role=user <username>"
echo "   ntfy token add <username>"
echo ""
echo "2. Grant topic access:"
echo "   ntfy access <username> alerts-myapp ro     # Read-only to app alerts"
echo "   ntfy access <username> alerts-critical ro  # Read-only to critical alerts"
echo ""
echo "3. Set up a reverse proxy (nginx/caddy) for ${DOMAIN}"
echo "   pointing to 127.0.0.1:8090"
echo ""
echo "4. Test with:"
echo "   curl -u admin:<password> -d 'Test notification' http://127.0.0.1:8090/alerts-test"
echo ""
echo "=== Installation complete ==="
