Initial commit: OpenClaw Mattermost Installer Wizard
This commit is contained in:
commit
b5719ca519
93
README.md
Normal file
93
README.md
Normal file
@ -0,0 +1,93 @@
|
||||
# 🦞 OpenClaw Mattermost Installer
|
||||
|
||||
One-command deployment of **Mattermost Team Edition** on Ubuntu/Debian, pre-configured for [OpenClaw](https://openclaw.dev) integration.
|
||||
|
||||
## What It Does
|
||||
|
||||
- Installs **Docker**, **Nginx**, and **Certbot** (if not present)
|
||||
- Deploys **Mattermost + PostgreSQL** via Docker Compose
|
||||
- Configures **Nginx reverse proxy** with WebSocket support
|
||||
- Obtains a free **Let's Encrypt SSL certificate**
|
||||
- Binds to `127.0.0.1` for secure OpenClaw localhost access
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Requirement | Details |
|
||||
|---|---|
|
||||
| **OS** | Ubuntu 20.04+ / Debian 11+ |
|
||||
| **Access** | Root (sudo) |
|
||||
| **Ports** | 80 and 443 open to the internet |
|
||||
| **DNS** | A record pointing your domain to this server's IP |
|
||||
| **RAM** | 2 GB minimum (4 GB recommended) |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Download the installer
|
||||
git clone https://github.com/openclaw/mattermost-installer.git
|
||||
cd mattermost-installer
|
||||
|
||||
# Run the wizard
|
||||
sudo bash install.sh
|
||||
```
|
||||
|
||||
The wizard will ask you for:
|
||||
1. **Domain name** (e.g. `chat.example.com`)
|
||||
2. **Email** (for Let's Encrypt SSL)
|
||||
3. **Port** (default: 8000)
|
||||
4. **Install directory** (default: `~/mattermost-docker`)
|
||||
|
||||
## OpenClaw Integration
|
||||
|
||||
After installation, create a Bot Account in Mattermost:
|
||||
|
||||
1. Go to **System Console → Integrations → Bot Accounts**
|
||||
2. Enable bot creation, then create a bot with `post:all` permission
|
||||
3. Copy the generated Bot Token
|
||||
|
||||
Then configure OpenClaw:
|
||||
|
||||
```bash
|
||||
openclaw config set channels.mattermost.accounts.default.baseUrl "https://YOUR_DOMAIN"
|
||||
openclaw config set channels.mattermost.accounts.default.botToken "YOUR_BOT_TOKEN"
|
||||
```
|
||||
|
||||
OpenClaw connects internally via `http://localhost:8000` for maximum speed and security.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Internet → Nginx (443/SSL) → 127.0.0.1:8000 → Mattermost Container (:8065)
|
||||
↕
|
||||
OpenClaw Gateway → localhost:8000 ──────────────→ PostgreSQL Container
|
||||
```
|
||||
|
||||
## Management
|
||||
|
||||
```bash
|
||||
cd ~/mattermost-docker
|
||||
|
||||
# Start / Stop / Restart
|
||||
docker compose up -d
|
||||
docker compose down
|
||||
docker compose restart
|
||||
|
||||
# View logs
|
||||
docker compose logs -f mattermost
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Fix |
|
||||
|---|---|
|
||||
| SSL cert failed | Verify DNS A record points to this server; check ports 80/443 are open |
|
||||
| Container won't start | Check logs: `docker compose logs mattermost` |
|
||||
| 502 Bad Gateway | Container may still be booting — wait 30s and refresh |
|
||||
| Permission denied | Run installer with `sudo` |
|
||||
|
||||
## License
|
||||
|
||||
MIT — use freely, contribute back. 🦞
|
||||
402
install.sh
Executable file
402
install.sh
Executable file
@ -0,0 +1,402 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================================
|
||||
# OpenClaw Mattermost Installer
|
||||
# Deploys Mattermost (Team Edition) via Docker with Nginx + Let's Encrypt SSL
|
||||
# Compatible with OpenClaw gateway via localhost
|
||||
#
|
||||
# Usage: sudo bash install.sh
|
||||
# GitHub: https://github.com/openclaw/mattermost-installer
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Colors ───────────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||
success() { echo -e "${GREEN}[ OK]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
||||
|
||||
banner() {
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}"
|
||||
echo " ┌──────────────────────────────────────────────┐"
|
||||
echo " │ 🦞 OpenClaw Mattermost Installer 🦞 │"
|
||||
echo " │ Docker + Nginx + Let's Encrypt │"
|
||||
echo " └──────────────────────────────────────────────┘"
|
||||
echo -e "${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Pre-flight checks ───────────────────────────────────────────────────────
|
||||
preflight() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
fail "This script must be run as root (sudo bash install.sh)"
|
||||
fi
|
||||
|
||||
if ! grep -qiE 'ubuntu|debian' /etc/os-release 2>/dev/null; then
|
||||
fail "This installer supports Ubuntu/Debian only."
|
||||
fi
|
||||
|
||||
if ss -tlnp | grep -qE ':80\b' 2>/dev/null; then
|
||||
warn "Port 80 is already in use. Nginx/Certbot may conflict."
|
||||
read -rp "Continue anyway? (y/N): " cont
|
||||
[[ "$cont" =~ ^[Yy]$ ]] || exit 1
|
||||
fi
|
||||
|
||||
if ss -tlnp | grep -qE ':443\b' 2>/dev/null; then
|
||||
warn "Port 443 is already in use. Nginx/Certbot may conflict."
|
||||
read -rp "Continue anyway? (y/N): " cont
|
||||
[[ "$cont" =~ ^[Yy]$ ]] || exit 1
|
||||
fi
|
||||
|
||||
success "Pre-flight checks passed."
|
||||
}
|
||||
|
||||
# ── Interactive prompts ──────────────────────────────────────────────────────
|
||||
gather_input() {
|
||||
echo -e "${BOLD}Step 1: Configuration${NC}"
|
||||
echo ""
|
||||
|
||||
# Domain
|
||||
while true; do
|
||||
read -rp " Enter your Mattermost domain (e.g. chat.example.com): " MM_DOMAIN
|
||||
if [[ -z "$MM_DOMAIN" ]]; then
|
||||
warn "Domain cannot be empty."
|
||||
elif [[ "$MM_DOMAIN" == *" "* ]]; then
|
||||
warn "Domain cannot contain spaces."
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Email for SSL
|
||||
while true; do
|
||||
read -rp " Enter your email (for Let's Encrypt SSL certificate): " MM_EMAIL
|
||||
if [[ -z "$MM_EMAIL" ]]; then
|
||||
warn "Email cannot be empty."
|
||||
elif [[ "$MM_EMAIL" != *"@"* ]]; then
|
||||
warn "Please enter a valid email address."
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Internal port
|
||||
read -rp " Internal proxy port [8000]: " MM_PORT
|
||||
MM_PORT=${MM_PORT:-8000}
|
||||
|
||||
# Install directory
|
||||
read -rp " Installation directory [~/mattermost-docker]: " INSTALL_DIR
|
||||
INSTALL_DIR=${INSTALL_DIR:-"$HOME/mattermost-docker"}
|
||||
# Expand tilde
|
||||
INSTALL_DIR="${INSTALL_DIR/#\~/$HOME}"
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD} Summary:${NC}"
|
||||
echo " Domain: https://${MM_DOMAIN}"
|
||||
echo " Email: ${MM_EMAIL}"
|
||||
echo " Port: 127.0.0.1:${MM_PORT} → :8065"
|
||||
echo " Directory: ${INSTALL_DIR}"
|
||||
echo ""
|
||||
read -rp " Proceed? (Y/n): " confirm
|
||||
[[ "$confirm" =~ ^[Nn]$ ]] && { info "Aborted."; exit 0; }
|
||||
}
|
||||
|
||||
# ── Install dependencies ────────────────────────────────────────────────────
|
||||
install_deps() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Step 2: Installing dependencies${NC}"
|
||||
echo ""
|
||||
|
||||
info "Updating package index..."
|
||||
apt-get update -qq
|
||||
|
||||
# Docker
|
||||
if command -v docker &>/dev/null; then
|
||||
success "Docker already installed: $(docker --version)"
|
||||
else
|
||||
info "Installing Docker..."
|
||||
apt-get install -y -qq ca-certificates curl gnupg lsb-release
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg 2>/dev/null || true
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
success "Docker installed."
|
||||
fi
|
||||
|
||||
# Docker Compose (detect v2 plugin vs v1 standalone)
|
||||
if docker compose version &>/dev/null; then
|
||||
COMPOSE_CMD="docker compose"
|
||||
success "Docker Compose (v2 plugin) available."
|
||||
elif command -v docker-compose &>/dev/null; then
|
||||
COMPOSE_CMD="docker-compose"
|
||||
success "Docker Compose (v1 standalone) available."
|
||||
else
|
||||
info "Installing Docker Compose plugin..."
|
||||
apt-get install -y -qq docker-compose-plugin
|
||||
COMPOSE_CMD="docker compose"
|
||||
success "Docker Compose installed."
|
||||
fi
|
||||
|
||||
# Nginx
|
||||
if command -v nginx &>/dev/null; then
|
||||
success "Nginx already installed."
|
||||
else
|
||||
info "Installing Nginx..."
|
||||
apt-get install -y -qq nginx
|
||||
systemctl enable nginx
|
||||
systemctl start nginx
|
||||
success "Nginx installed and started."
|
||||
fi
|
||||
|
||||
# Certbot
|
||||
if command -v certbot &>/dev/null; then
|
||||
success "Certbot already installed."
|
||||
else
|
||||
info "Installing Certbot..."
|
||||
apt-get install -y -qq certbot python3-certbot-nginx
|
||||
success "Certbot installed."
|
||||
fi
|
||||
|
||||
# UFW (optional — configure if present)
|
||||
if command -v ufw &>/dev/null; then
|
||||
info "Configuring firewall (UFW)..."
|
||||
ufw allow 'Nginx Full' >/dev/null 2>&1 || true
|
||||
ufw allow OpenSSH >/dev/null 2>&1 || true
|
||||
success "Firewall rules updated."
|
||||
fi
|
||||
|
||||
success "All dependencies ready."
|
||||
}
|
||||
|
||||
# ── Generate secure password ────────────────────────────────────────────────
|
||||
generate_password() {
|
||||
openssl rand -base64 24 | tr -d '/+=' | head -c 32
|
||||
}
|
||||
|
||||
# ── Create Docker stack ──────────────────────────────────────────────────────
|
||||
create_docker_stack() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Step 3: Creating Docker stack${NC}"
|
||||
echo ""
|
||||
|
||||
DB_PASS=$(generate_password)
|
||||
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
|
||||
cat > "${INSTALL_DIR}/docker-compose.yml" <<YAML
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=mmuser
|
||||
- POSTGRES_PASSWORD=${DB_PASS}
|
||||
- POSTGRES_DB=mattermost
|
||||
volumes:
|
||||
- ./volumes/db/var/lib/postgresql/data:/var/lib/postgresql/data
|
||||
|
||||
mattermost:
|
||||
image: mattermost/mattermost-team-edition:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:${MM_PORT}:8065"
|
||||
environment:
|
||||
- MM_SQLSETTINGS_DRIVERNAME=postgres
|
||||
- MM_SQLSETTINGS_DATASOURCE=postgres://mmuser:${DB_PASS}@postgres:5432/mattermost?sslmode=disable&connect_timeout=10
|
||||
- MM_SERVICESETTINGS_SITEURL=https://${MM_DOMAIN}
|
||||
volumes:
|
||||
- ./volumes/app/mattermost/config:/mattermost/config:rw
|
||||
- ./volumes/app/mattermost/data:/mattermost/data:rw
|
||||
- ./volumes/app/mattermost/logs:/mattermost/logs:rw
|
||||
- ./volumes/app/mattermost/plugins:/mattermost/plugins:rw
|
||||
- ./volumes/app/mattermost/client/plugins:/mattermost/client/plugins:rw
|
||||
- ./volumes/app/mattermost/bleve-indexes:/mattermost/bleve-indexes:rw
|
||||
depends_on:
|
||||
- postgres
|
||||
YAML
|
||||
|
||||
# Save credentials for reference
|
||||
cat > "${INSTALL_DIR}/.env" <<ENV
|
||||
# Auto-generated credentials — keep this file secure!
|
||||
MM_DOMAIN=${MM_DOMAIN}
|
||||
MM_PORT=${MM_PORT}
|
||||
DB_USER=mmuser
|
||||
DB_PASS=${DB_PASS}
|
||||
DB_NAME=mattermost
|
||||
ENV
|
||||
chmod 600 "${INSTALL_DIR}/.env"
|
||||
|
||||
success "Docker Compose file created at ${INSTALL_DIR}/docker-compose.yml"
|
||||
success "Credentials saved to ${INSTALL_DIR}/.env (chmod 600)"
|
||||
}
|
||||
|
||||
# ── Configure Nginx ──────────────────────────────────────────────────────────
|
||||
configure_nginx() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Step 4: Configuring Nginx reverse proxy${NC}"
|
||||
echo ""
|
||||
|
||||
NGINX_CONF="/etc/nginx/sites-available/mattermost-${MM_DOMAIN}"
|
||||
|
||||
cat > "${NGINX_CONF}" <<NGINX
|
||||
server {
|
||||
server_name ${MM_DOMAIN};
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:${MM_PORT};
|
||||
proxy_set_header Host \$http_host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
proxy_set_header X-Frame-Options SAMEORIGIN;
|
||||
|
||||
# WebSocket support (required for Mattermost real-time)
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
client_max_body_size 50M;
|
||||
}
|
||||
|
||||
listen 80;
|
||||
}
|
||||
NGINX
|
||||
|
||||
# Enable site
|
||||
ln -sf "${NGINX_CONF}" /etc/nginx/sites-enabled/
|
||||
# Remove default if it conflicts
|
||||
rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
|
||||
|
||||
nginx -t || fail "Nginx configuration test failed!"
|
||||
systemctl reload nginx
|
||||
|
||||
success "Nginx proxy configured for ${MM_DOMAIN}"
|
||||
}
|
||||
|
||||
# ── Obtain SSL certificate ───────────────────────────────────────────────────
|
||||
obtain_ssl() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Step 5: Obtaining SSL certificate${NC}"
|
||||
echo ""
|
||||
|
||||
info "Requesting Let's Encrypt certificate for ${MM_DOMAIN}..."
|
||||
info "Make sure your DNS A record points to this server's IP!"
|
||||
echo ""
|
||||
|
||||
certbot --nginx \
|
||||
-d "${MM_DOMAIN}" \
|
||||
--non-interactive \
|
||||
--agree-tos \
|
||||
--email "${MM_EMAIL}" \
|
||||
--redirect \
|
||||
|| {
|
||||
warn "Certbot failed. This usually means:"
|
||||
warn " 1. DNS is not yet pointing to this server"
|
||||
warn " 2. Ports 80/443 are blocked by a firewall"
|
||||
warn ""
|
||||
warn "You can retry later with:"
|
||||
warn " sudo certbot --nginx -d ${MM_DOMAIN}"
|
||||
warn ""
|
||||
warn "Continuing without SSL..."
|
||||
}
|
||||
|
||||
success "SSL certificate obtained (or skipped)."
|
||||
}
|
||||
|
||||
# ── Start the stack ──────────────────────────────────────────────────────────
|
||||
start_stack() {
|
||||
echo ""
|
||||
echo -e "${BOLD}Step 6: Starting Mattermost${NC}"
|
||||
echo ""
|
||||
|
||||
info "Pulling Docker images (this may take a few minutes)..."
|
||||
cd "${INSTALL_DIR}"
|
||||
$COMPOSE_CMD pull
|
||||
|
||||
info "Starting containers..."
|
||||
$COMPOSE_CMD up -d
|
||||
|
||||
# Wait for Mattermost to boot
|
||||
info "Waiting for Mattermost to start (up to 60s)..."
|
||||
for i in $(seq 1 12); do
|
||||
if curl -sI "http://127.0.0.1:${MM_PORT}" >/dev/null 2>&1; then
|
||||
success "Mattermost is responding on port ${MM_PORT}!"
|
||||
break
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Show container status
|
||||
echo ""
|
||||
$COMPOSE_CMD ps
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Print summary ───────────────────────────────────────────────────────────
|
||||
print_summary() {
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN}"
|
||||
echo " ┌──────────────────────────────────────────────┐"
|
||||
echo " │ ✅ Installation Complete! ✅ │"
|
||||
echo " └──────────────────────────────────────────────┘"
|
||||
echo -e "${NC}"
|
||||
echo ""
|
||||
echo -e "${BOLD} Access your Mattermost:${NC}"
|
||||
echo " 🌐 https://${MM_DOMAIN}"
|
||||
echo ""
|
||||
echo -e "${BOLD} Internal (localhost) access:${NC}"
|
||||
echo " 📡 http://127.0.0.1:${MM_PORT}"
|
||||
echo ""
|
||||
echo -e "${BOLD} Credentials:${NC}"
|
||||
echo " 📄 ${INSTALL_DIR}/.env"
|
||||
echo ""
|
||||
echo -e "${BOLD} Management commands:${NC}"
|
||||
echo " Start: cd ${INSTALL_DIR} && ${COMPOSE_CMD} up -d"
|
||||
echo " Stop: cd ${INSTALL_DIR} && ${COMPOSE_CMD} down"
|
||||
echo " Logs: cd ${INSTALL_DIR} && ${COMPOSE_CMD} logs -f"
|
||||
echo " Status: cd ${INSTALL_DIR} && ${COMPOSE_CMD} ps"
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN} ── OpenClaw Integration ──${NC}"
|
||||
echo ""
|
||||
echo " 1. Create a Bot Account in Mattermost:"
|
||||
echo " System Console → Integrations → Bot Accounts → Add Bot"
|
||||
echo " (Enable bot creation first, grant 'post:all')"
|
||||
echo ""
|
||||
echo " 2. Configure OpenClaw to connect:"
|
||||
echo -e " ${YELLOW}openclaw config set channels.mattermost.accounts.default.baseUrl \"https://${MM_DOMAIN}\"${NC}"
|
||||
echo -e " ${YELLOW}openclaw config set channels.mattermost.accounts.default.botToken \"<YOUR_BOT_TOKEN>\"${NC}"
|
||||
echo ""
|
||||
echo " OpenClaw will connect to Mattermost internally via localhost:${MM_PORT}"
|
||||
echo " for maximum speed and security. 🦞"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Main ─────────────────────────────────────────────────────────────────────
|
||||
main() {
|
||||
banner
|
||||
preflight
|
||||
gather_input
|
||||
install_deps
|
||||
create_docker_stack
|
||||
configure_nginx
|
||||
obtain_ssl
|
||||
start_stack
|
||||
print_summary
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
Reference in New Issue
Block a user