#!/bin/sh
# logpulse-agent installer
#
# Usage:
#   curl -fsSL https://get.logpulse.io | sudo sh
#   curl -fsSL https://get.logpulse.io | LOGPULSE_VERSION=v0.1.0 sudo sh
#
# What this does:
#   1. Detects OS/arch
#   2. Downloads the version-specific tarball + SHA-256 checksum
#   3. Verifies the checksum
#   4. (Optional) Verifies the cosign signature if cosign is installed
#   5. Creates the `logpulse` system user + state/log/config dirs
#   6. Installs the binary to /usr/local/bin and the systemd unit
#
# Audit before running:
#   curl -fsSL https://get.logpulse.io | less
#
# Source: https://github.com/Layer-Group/LogPulse/tree/main/apps/agent/installer
set -eu

DOWNLOADS_BASE="${LOGPULSE_DOWNLOADS_BASE:-https://dl.logpulse.io}"
INSTALL_DIR="/opt/logpulse-agent"
STATE_DIR="/var/lib/logpulse-agent"
LOG_DIR="/var/log/logpulse-agent"
CONFIG_DIR="/etc/logpulse-agent"
SERVICE_USER="logpulse"
# /usr/bin (not /usr/local/bin) so that sudo's secure_path picks it up on
# RHEL/Rocky/Alma — those distros omit /usr/local/bin from the default
# sudoers secure_path. Same convention as Datadog and Tailscale.
BIN_LINK="/usr/bin/logpulse-agent"

err() { printf 'error: %s\n' "$1" >&2; exit 1; }
info() { printf '==> %s\n' "$1"; }

# --- Pre-flight checks ----------------------------------------------------

[ "$(id -u)" -eq 0 ] || err "must run as root (try: curl … | sudo sh)"

OS_NAME="$(uname -s | tr '[:upper:]' '[:lower:]')"
[ "$OS_NAME" = "linux" ] || err "only Linux is supported in v1 (got: $OS_NAME)"

case "$(uname -m)" in
  x86_64|amd64)  ARCH=amd64 ;;
  aarch64|arm64) ARCH=arm64 ;;
  *) err "unsupported architecture: $(uname -m)" ;;
esac

command -v curl >/dev/null 2>&1 || err "curl is required"
command -v tar  >/dev/null 2>&1 || err "tar is required"
command -v sha256sum >/dev/null 2>&1 || err "sha256sum is required"
command -v systemctl >/dev/null 2>&1 || err "systemd is required"

# --- Resolve version ------------------------------------------------------

if [ -n "${LOGPULSE_VERSION:-}" ]; then
  VERSION="$LOGPULSE_VERSION"
else
  info "fetching latest version"
  VERSION="$(curl -fsSL "$DOWNLOADS_BASE/latest.txt" | tr -d '[:space:]')"
fi
[ -n "$VERSION" ] || err "could not determine version to install"
info "installing logpulse-agent $VERSION ($OS_NAME/$ARCH)"

# --- Download + verify tarball -------------------------------------------

TARBALL="logpulse-agent_${VERSION}_${OS_NAME}_${ARCH}.tar.gz"
URL="$DOWNLOADS_BASE/$VERSION/$TARBALL"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

info "downloading $TARBALL"
curl -fsSL -o "$TMP/$TARBALL"        "$URL"
curl -fsSL -o "$TMP/$TARBALL.sha256" "$URL.sha256"

info "verifying SHA-256 checksum"
( cd "$TMP" && sha256sum -c "$TARBALL.sha256" >/dev/null ) \
  || err "checksum mismatch — refusing to install"

if command -v cosign >/dev/null 2>&1; then
  info "verifying cosign signature"
  curl -fsSL -o "$TMP/$TARBALL.sig" "$URL.sig" 2>/dev/null || {
    printf 'warn: cosign signature not found at %s.sig — continuing\n' "$URL"
  }
  if [ -f "$TMP/$TARBALL.sig" ]; then
    cosign verify-blob \
      --certificate-identity-regexp "https://github\.com/Layer-Group/LogPulse/.github/workflows/release-agent\.yml@refs/tags/.*" \
      --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
      --signature "$TMP/$TARBALL.sig" \
      "$TMP/$TARBALL" \
      || err "cosign verification failed — refusing to install"
  fi
else
  printf 'note: cosign not installed; skipping signature verification (sha256 still verified)\n'
fi

# --- Create user + dirs ---------------------------------------------------

if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then
  info "creating system user '$SERVICE_USER'"
  useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER"
fi

# Group memberships needed by common input types — best-effort, silently
# skipped when a group doesn't exist on this distribution.
#   systemd-journal → read /var/log/journal/ for the journald source
#   adm             → read /var/log/* on Debian/Ubuntu for file source
for grp in systemd-journal adm; do
  if getent group "$grp" >/dev/null 2>&1; then
    usermod -a -G "$grp" "$SERVICE_USER" 2>/dev/null || true
  fi
done

# /etc/logpulse-agent must be writable by the agent user — Vector config is
# rewritten there on every successful config poll. `install -d` is idempotent
# and also fixes ownership on existing installs (was root:root 0755 in v0.1.4
# and earlier; the agent failed to write vector.yaml.tmp).
install -d -o "$SERVICE_USER" -g "$SERVICE_USER" -m 0750 "$STATE_DIR" "$LOG_DIR" "$CONFIG_DIR"
# Vector's data_dir lives under our state dir so it falls inside the
# systemd unit's ReadWritePaths and we don't need a separate writable
# path. Vector writes checkpoints, validate scratch, etc. here.
install -d -o "$SERVICE_USER" -g "$SERVICE_USER" -m 0750 "$STATE_DIR/vector"

# --- Extract --------------------------------------------------------------

info "extracting to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
tar -xzf "$TMP/$TARBALL" -C "$INSTALL_DIR"

# Normalise permissions. Tarballs produced by `mktemp -d` carried a 0700
# root mode through to the install dir, blocking the unprivileged
# `logpulse` service user from traversing /opt/logpulse-agent. Force
# 0755 on dirs and preserve 0755 on the binary; non-exec files keep their
# stored mode. This is idempotent — safe to re-run.
chmod -R u+rwX,go+rX "$INSTALL_DIR"

# --- Wire up binary + systemd --------------------------------------------

ln -sf "$INSTALL_DIR/bin/logpulse-agent" "$BIN_LINK"

# Best-effort cleanup of the v0.1.0 layout where the symlink lived in
# /usr/local/bin. Harmless if it never existed.
rm -f /usr/local/bin/logpulse-agent

if [ -f "$INSTALL_DIR/systemd/logpulse-agent.service" ]; then
  install -m 0644 "$INSTALL_DIR/systemd/logpulse-agent.service" /etc/systemd/system/logpulse-agent.service
  systemctl daemon-reload
fi

# Vector is bundled in the tarball at /opt/logpulse-agent/bin/vector and
# referenced by the systemd unit's ExecStart. No external repository
# (timber.io, github.com/vectordotdev) is touched at install time, so
# customers only need to allow *.logpulse.io through their proxy/firewall.
if [ ! -x "$INSTALL_DIR/bin/vector" ]; then
  printf 'warn: bundled vector binary missing from tarball (this is a release bug).\n' >&2
  printf 'warn: agent will not collect logs until /opt/logpulse-agent/bin/vector is present.\n' >&2
fi

# Restart only if the service is currently running. Never start a service that
# was deliberately stopped — the operator may have stopped it intentionally.
if systemctl is-active --quiet logpulse-agent 2>/dev/null; then
  info "restarting logpulse-agent to load the new binary"
  systemctl restart logpulse-agent
fi

# --- Done -----------------------------------------------------------------

cat <<EOF

LogPulse Agent $VERSION installed.

Next steps:
  sudo logpulse-agent enroll --token=<ENROLLMENT_TOKEN> [--group=<slug>]
  sudo systemctl enable --now logpulse-agent

Logs:    journalctl -u logpulse-agent -f
Status:  logpulse-agent status
Docs:    https://logpulse.io/docs/agents
EOF
