Publish deployment and backup scripts
This commit is contained in:
255
deploy-docker-mattermost.sh
Executable file
255
deploy-docker-mattermost.sh
Executable file
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# Mattermost Deployment Script (Docker Compose + Traefik)
|
||||
# ==============================================================================
|
||||
# Deploys Mattermost + PostgreSQL behind the shared Traefik reverse proxy.
|
||||
# ChatOps-optimized: bot accounts, webhooks, personal access tokens enabled.
|
||||
#
|
||||
# Usage: deploy-docker-mattermost.sh
|
||||
# deploy-docker-mattermost.sh --domain chat.us.an2.io
|
||||
# deploy-docker-mattermost.sh --remove [--purge] [--yes]
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/common.sh"
|
||||
|
||||
# --- Parse arguments ---
|
||||
parse_args "$@"
|
||||
|
||||
# --- Service config ---
|
||||
SERVICE_NAME="mattermost"
|
||||
BASE_DIR="/opt/${SERVICE_NAME}"
|
||||
CONFIG_NAME="${SERVICE_NAME}"
|
||||
UNIT_NAME="${SERVICE_NAME}-docker"
|
||||
CALLS_PORT="${CALLS_PORT:-8443}"
|
||||
|
||||
# --- Handle --remove ---
|
||||
if [[ "$ARG_REMOVE" == "1" ]]; then
|
||||
require_root
|
||||
do_remove "$SERVICE_NAME" "$CONFIG_NAME" "$UNIT_NAME" "$BASE_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Domain resolution: --domain > existing .env > default ---
|
||||
if [[ -n "$ARG_DOMAIN" ]]; then
|
||||
DOMAIN="$ARG_DOMAIN"
|
||||
elif [[ -f "${BASE_DIR}/.env" ]] && grep -q '^DOMAIN=' "${BASE_DIR}/.env"; then
|
||||
DOMAIN="$(grep '^DOMAIN=' "${BASE_DIR}/.env" | cut -d= -f2)"
|
||||
else
|
||||
DOMAIN="mm.an2.io"
|
||||
fi
|
||||
|
||||
# --- Detect current state for banner ---
|
||||
traefik_status="Not found — will deploy"
|
||||
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^traefik$'; then
|
||||
traefik_status="Running"
|
||||
elif [[ -f "${TRAEFIK_DIR}/docker-compose.yml" ]]; then
|
||||
traefik_status="Stopped — will start"
|
||||
fi
|
||||
|
||||
install_mode="Fresh install"
|
||||
if [[ -f "${BASE_DIR}/.env" ]]; then
|
||||
install_mode="Re-run (preserving data)"
|
||||
fi
|
||||
|
||||
# --- Print deployment plan ---
|
||||
echo ""
|
||||
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
||||
echo -e "${CYAN} Deploying Mattermost (Docker)${NC}"
|
||||
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
||||
echo -e " Domain: ${DOMAIN}"
|
||||
echo -e " Data: ${BASE_DIR}"
|
||||
echo -e " Calls Port: ${CALLS_PORT}"
|
||||
echo -e " Traefik: ${traefik_status}"
|
||||
echo -e " Mode: ${install_mode}"
|
||||
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
# --- Check if already deployed and running ---
|
||||
if [[ -f "${BASE_DIR}/docker-compose.yml" ]] && \
|
||||
docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^mm-app$'; then
|
||||
echo -e "${GREEN} Mattermost is already running — nothing to do.${NC}"
|
||||
echo ""
|
||||
echo -e " Logs: docker logs -f mm-app"
|
||||
echo -e " Backup: ${SCRIPT_DIR}/backup-mattermost.sh"
|
||||
echo -e " Remove: $0 --remove [--purge]"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Shared infrastructure ---
|
||||
require_root
|
||||
detect_os
|
||||
install_prerequisites
|
||||
ensure_docker_network
|
||||
ensure_traefik
|
||||
configure_firewall "${CALLS_PORT}/udp" "${CALLS_PORT}/tcp"
|
||||
|
||||
# --- Backup restore check ---
|
||||
if check_and_restore_backup "$SERVICE_NAME"; then
|
||||
saved_domain="$DOMAIN"
|
||||
# shellcheck source=/dev/null
|
||||
source "${BASE_DIR}/.env"
|
||||
DOMAIN="$saved_domain"
|
||||
else
|
||||
# --- Fresh install ---
|
||||
|
||||
if [[ -f "${BASE_DIR}/.env" ]]; then
|
||||
saved_domain="$DOMAIN"
|
||||
# shellcheck source=/dev/null
|
||||
source "${BASE_DIR}/.env"
|
||||
DOMAIN="$saved_domain"
|
||||
else
|
||||
POSTGRES_USER="mmuser"
|
||||
POSTGRES_PASSWORD="$(generate_password)"
|
||||
POSTGRES_DB="mattermost"
|
||||
fi
|
||||
|
||||
info "Creating directory layout..."
|
||||
mkdir -p "${BASE_DIR}"/{postgres/data,mattermost/{config,data,logs,plugins,client-plugins,bleve-indexes}}
|
||||
chown -R 2000:2000 "${BASE_DIR}/mattermost"
|
||||
|
||||
# --- Generate .env ---
|
||||
cat > "${BASE_DIR}/.env" <<DOTENV
|
||||
# Generated by deploy-docker-mattermost.sh on $(date -Iseconds)
|
||||
DOMAIN=${DOMAIN}
|
||||
TZ=UTC
|
||||
CALLS_PORT=${CALLS_PORT}
|
||||
|
||||
# PostgreSQL
|
||||
POSTGRES_USER=${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB=${POSTGRES_DB}
|
||||
|
||||
# Mattermost
|
||||
MM_SQLSETTINGS_DRIVERNAME=postgres
|
||||
MM_SQLSETTINGS_DATASOURCE=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@mm-postgres:5432/${POSTGRES_DB}?sslmode=disable&connect_timeout=10
|
||||
MM_BLEVESETTINGS_INDEXDIR=/mattermost/bleve-indexes
|
||||
MM_SERVICESETTINGS_SITEURL=https://${DOMAIN}
|
||||
|
||||
# ChatOps settings
|
||||
MM_SERVICESETTINGS_ENABLEBOTACCOUNTCREATION=true
|
||||
MM_SERVICESETTINGS_ENABLEOAUTHSERVICEPROVIDER=true
|
||||
MM_SERVICESETTINGS_ENABLEINCOMINGWEBHOOKS=true
|
||||
MM_SERVICESETTINGS_ENABLEOUTGOINGWEBHOOKS=true
|
||||
MM_SERVICESETTINGS_ENABLEPOSTUSERNAMEOVERRIDE=true
|
||||
MM_SERVICESETTINGS_ENABLEPOSTICONOVERRIDE=true
|
||||
MM_SERVICESETTINGS_ENABLECUSTOMEMOJI=true
|
||||
MM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS=true
|
||||
MM_PLUGINSETTINGS_ENABLEUPLOADS=true
|
||||
MM_TEAMSETTINGS_ENABLEOPENSERVER=false
|
||||
DOTENV
|
||||
chmod 600 "${BASE_DIR}/.env"
|
||||
ok ".env written."
|
||||
|
||||
# --- Generate docker-compose.yml ---
|
||||
cat > "${BASE_DIR}/docker-compose.yml" <<'COMPOSE'
|
||||
# Mattermost + PostgreSQL
|
||||
# Based on https://github.com/mattermost/docker
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: mm-postgres
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 4G
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /var/run/postgresql
|
||||
volumes:
|
||||
- ./postgres/data:/var/lib/postgresql
|
||||
environment:
|
||||
- TZ
|
||||
- POSTGRES_USER
|
||||
- POSTGRES_PASSWORD
|
||||
- POSTGRES_DB
|
||||
networks:
|
||||
- mm-internal
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "5"
|
||||
|
||||
mattermost:
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_started
|
||||
image: mattermost/mattermost-enterprise-edition:release-11.0
|
||||
container_name: mm-app
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
mem_limit: 4G
|
||||
tmpfs:
|
||||
- /tmp
|
||||
volumes:
|
||||
- ./mattermost/config:/mattermost/config:rw
|
||||
- ./mattermost/data:/mattermost/data:rw
|
||||
- ./mattermost/logs:/mattermost/logs:rw
|
||||
- ./mattermost/plugins:/mattermost/plugins:rw
|
||||
- ./mattermost/client-plugins:/mattermost/client/plugins:rw
|
||||
- ./mattermost/bleve-indexes:/mattermost/bleve-indexes:rw
|
||||
environment:
|
||||
- TZ
|
||||
- MM_SQLSETTINGS_DRIVERNAME
|
||||
- MM_SQLSETTINGS_DATASOURCE
|
||||
- MM_BLEVESETTINGS_INDEXDIR
|
||||
- MM_SERVICESETTINGS_SITEURL
|
||||
- MM_SERVICESETTINGS_ENABLEBOTACCOUNTCREATION
|
||||
- MM_SERVICESETTINGS_ENABLEOAUTHSERVICEPROVIDER
|
||||
- MM_SERVICESETTINGS_ENABLEINCOMINGWEBHOOKS
|
||||
- MM_SERVICESETTINGS_ENABLEOUTGOINGWEBHOOKS
|
||||
- MM_SERVICESETTINGS_ENABLEPOSTUSERNAMEOVERRIDE
|
||||
- MM_SERVICESETTINGS_ENABLEPOSTICONOVERRIDE
|
||||
- MM_SERVICESETTINGS_ENABLECUSTOMEMOJI
|
||||
- MM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS
|
||||
- MM_PLUGINSETTINGS_ENABLEUPLOADS
|
||||
- MM_TEAMSETTINGS_ENABLEOPENSERVER
|
||||
ports:
|
||||
- "${CALLS_PORT}:${CALLS_PORT}/udp"
|
||||
- "${CALLS_PORT}:${CALLS_PORT}/tcp"
|
||||
networks:
|
||||
- mm-internal
|
||||
- traefik-public
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "5"
|
||||
|
||||
networks:
|
||||
mm-internal:
|
||||
driver: bridge
|
||||
traefik-public:
|
||||
external: true
|
||||
COMPOSE
|
||||
ok "docker-compose.yml written."
|
||||
fi
|
||||
|
||||
# --- Always do these (fresh or restored) ---
|
||||
write_traefik_dynamic_config "$CONFIG_NAME" "$DOMAIN" "http://mm-app:8065"
|
||||
install_systemd_unit "$UNIT_NAME" "$BASE_DIR"
|
||||
(cd "$BASE_DIR" && docker compose up -d)
|
||||
wait_for_healthy "mm-app" "http://localhost:8443/api/v4/system/ping" 120
|
||||
|
||||
# --- Summary ---
|
||||
echo ""
|
||||
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
||||
echo -e "${GREEN} Mattermost deployed successfully${NC}"
|
||||
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
||||
echo -e " URL: https://${DOMAIN}"
|
||||
echo -e " Calls: Port ${CALLS_PORT} (UDP+TCP)"
|
||||
echo -e " Data: ${BASE_DIR}/"
|
||||
echo -e " Traefik: ${TRAEFIK_DYNAMIC_DIR}/${CONFIG_NAME}.yml"
|
||||
echo -e " Systemd: systemctl status ${UNIT_NAME}"
|
||||
echo -e " Logs: docker logs -f mm-app"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}Next: Open https://${DOMAIN} and create your admin account.${NC}"
|
||||
echo -e "${GREEN}══════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user