#!/usr/bin/env bash
#
#  Mattermost Team Edition — one-shot installer for Ubuntu 24.04 LTS
#  From the NUILab docs: https://help.nuilab.org/systems/mattermost/self-hosting/
#
#  ⚠️  USE AT YOUR OWN RISK.  Provided as-is, with NO warranty of any kind.
#      NUILab does not guarantee this script works or is current. Read it before
#      you run it, and run it only on a server YOU own and can afford to wipe.
#
#  What it does: installs Docker, opens the firewall (80/443), writes the stack
#  files into /opt/mattermost, and starts Postgres + Mattermost + Caddy (TLS).
#
#  Usage:   sudo bash mattermost-install-ubuntu2404.sh chat.example.edu
#  (You must already have a DNS A record for that domain pointing at this server,
#   and ports 80 + 443 reachable from the internet — including any cloud firewall.)
#
set -euo pipefail

# ---- preconditions ---------------------------------------------------------
if [ "$(id -u)" -ne 0 ]; then
  echo "Please run with sudo:  sudo bash $0 <your-domain>" >&2
  exit 1
fi
if ! grep -qi 'ubuntu' /etc/os-release; then
  echo "This script targets Ubuntu 24.04. Your /etc/os-release is not Ubuntu." >&2
  echo "Use the Fedora or AlmaLinux script instead, or run the manual steps." >&2
  exit 1
fi

DOMAIN="${1:-}"
if [ -z "$DOMAIN" ]; then
  read -rp "Domain for this server (e.g. chat.example.edu): " DOMAIN
fi
if [ -z "$DOMAIN" ]; then echo "No domain given. Aborting." >&2; exit 1; fi

INSTALL_DIR=/opt/mattermost
MM_VERSION=11.7   # pin a version; check Docker Hub for the current Team Edition tag

echo "==> Installing Mattermost for https://${DOMAIN} into ${INSTALL_DIR}"

# ---- 1. Docker Engine + Compose plugin (Docker's official apt repo) --------
echo "==> [1/4] Installing Docker"
apt-get update -y
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${VERSION_CODENAME} stable" \
  > /etc/apt/sources.list.d/docker.list
apt-get update -y
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
systemctl enable --now docker
# let the human who invoked sudo use docker without sudo (takes effect next login)
if [ -n "${SUDO_USER:-}" ] && [ "${SUDO_USER}" != "root" ]; then
  usermod -aG docker "${SUDO_USER}" || true
fi

# ---- 2. Firewall: allow SSH (so we don't lock out), then 80/443 ------------
echo "==> [2/4] Configuring ufw firewall"
if command -v ufw >/dev/null 2>&1; then
  ufw allow OpenSSH || true
  ufw allow 80/tcp
  ufw allow 443/tcp
  ufw --force enable
else
  echo "    ufw not present; skipping (open 80/443 yourself if you have another firewall)."
fi

# ---- 3. Stack files --------------------------------------------------------
echo "==> [3/4] Writing stack files to ${INSTALL_DIR}"
mkdir -p "${INSTALL_DIR}"
cd "${INSTALL_DIR}"

# .env — secrets only; generate a strong random DB password if first run
if [ ! -f .env ]; then
  PWGEN="$(openssl rand -hex 24)"
  cat > .env <<EOF
POSTGRES_PASSWORD=${PWGEN}
DOMAIN=${DOMAIN}
EOF
  chmod 600 .env
  echo "    wrote .env (DB password generated; keep this file private)"
else
  echo "    .env already exists — leaving it untouched"
fi

# docker-compose.yml — ${...} stays literal so Compose reads it from .env
cat > docker-compose.yml <<'YAML'
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: mmuser
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: mattermost
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mmuser -d mattermost"]
      interval: 10s
      timeout: 5s
      retries: 5

  mattermost:
    image: mattermost/mattermost-team-edition:MM_VERSION_PLACEHOLDER
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      MM_SQLSETTINGS_DRIVERNAME: postgres
      MM_SQLSETTINGS_DATASOURCE: "postgres://mmuser:${POSTGRES_PASSWORD}@postgres:5432/mattermost?sslmode=disable&connect_timeout=10"
      MM_SERVICESETTINGS_SITEURL: https://${DOMAIN}
      MM_SERVICESETTINGS_ENABLELOCALMODE: "true"
    volumes:
      - mattermost-data:/mattermost/data
      - mattermost-config:/mattermost/config
      - mattermost-logs:/mattermost/logs
      - mattermost-plugins:/mattermost/plugins
      - mattermost-client-plugins:/mattermost/client/plugins
      - mattermost-bleve:/mattermost/bleve-indexes
    networks:
      - backend
      - frontend

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    depends_on:
      - mattermost
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - frontend

networks:
  backend:
  frontend:

volumes:
  postgres-data:
  mattermost-data:
  mattermost-config:
  mattermost-logs:
  mattermost-plugins:
  mattermost-client-plugins:
  mattermost-bleve:
  caddy-data:
  caddy-config:
YAML
# substitute the pinned version (kept out of the quoted heredoc on purpose)
sed -i "s/MM_VERSION_PLACEHOLDER/${MM_VERSION}/" docker-compose.yml

# Caddyfile — Caddy can't read .env, so the domain is written in literally
cat > Caddyfile <<EOF
${DOMAIN} {
    reverse_proxy mattermost:8065
}
EOF

# ---- 4. Launch -------------------------------------------------------------
echo "==> [4/4] Starting the stack"
docker compose up -d
echo
echo "Done. Watch it come up with:   cd ${INSTALL_DIR} && docker compose logs -f"
echo "Then open:   https://${DOMAIN}"
echo "The FIRST account you create becomes the system administrator."
echo
echo "Reminder: this is provided AS-IS with no warranty. You own this server now."
