480 lines
12 KiB
Bash
Executable File
480 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Stoatchat Setup Script
|
|
# Automated deployment of Revolt chat backend for st.vish.gg
|
|
|
|
set -euo pipefail
|
|
|
|
# Configuration
|
|
STOATCHAT_DIR="/opt/stoatchat"
|
|
DOMAIN="st.vish.gg"
|
|
REPO_URL="https://github.com/stoatchat/stoatchat.git"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Check if running as root
|
|
check_root() {
|
|
if [[ $EUID -eq 0 ]]; then
|
|
log_error "This script should not be run as root"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Check system requirements
|
|
check_requirements() {
|
|
log_info "Checking system requirements..."
|
|
|
|
# Check OS
|
|
if [[ ! -f /etc/os-release ]]; then
|
|
log_error "Cannot determine OS version"
|
|
exit 1
|
|
fi
|
|
|
|
source /etc/os-release
|
|
if [[ "$ID" != "ubuntu" && "$ID" != "debian" ]]; then
|
|
log_warning "This script is designed for Ubuntu/Debian. Proceeding anyway..."
|
|
fi
|
|
|
|
# Check available memory
|
|
local mem_gb=$(free -g | awk '/^Mem:/{print $2}')
|
|
if [[ $mem_gb -lt 4 ]]; then
|
|
log_warning "Less than 4GB RAM detected. Stoatchat may not perform well."
|
|
fi
|
|
|
|
# Check available disk space
|
|
local disk_gb=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
|
|
if [[ $disk_gb -lt 20 ]]; then
|
|
log_error "Less than 20GB free disk space. Cannot proceed."
|
|
exit 1
|
|
fi
|
|
|
|
log_success "System requirements check passed"
|
|
}
|
|
|
|
# Install system dependencies
|
|
install_dependencies() {
|
|
log_info "Installing system dependencies..."
|
|
|
|
sudo apt update
|
|
sudo apt install -y \
|
|
curl \
|
|
wget \
|
|
git \
|
|
build-essential \
|
|
pkg-config \
|
|
libssl-dev \
|
|
ca-certificates \
|
|
gnupg \
|
|
lsb-release \
|
|
jq
|
|
|
|
# Install Docker if not present
|
|
if ! command -v docker &> /dev/null; then
|
|
log_info "Installing Docker..."
|
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
sudo sh get-docker.sh
|
|
sudo usermod -aG docker $USER
|
|
rm get-docker.sh
|
|
log_success "Docker installed"
|
|
else
|
|
log_info "Docker already installed"
|
|
fi
|
|
|
|
# Install Docker Compose if not present
|
|
if ! command -v docker-compose &> /dev/null; then
|
|
log_info "Installing Docker Compose..."
|
|
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
sudo chmod +x /usr/local/bin/docker-compose
|
|
log_success "Docker Compose installed"
|
|
else
|
|
log_info "Docker Compose already installed"
|
|
fi
|
|
|
|
# Install mise (Rust toolchain manager)
|
|
if ! command -v mise &> /dev/null; then
|
|
log_info "Installing mise..."
|
|
curl https://mise.run | sh
|
|
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
log_success "mise installed"
|
|
else
|
|
log_info "mise already installed"
|
|
fi
|
|
|
|
log_success "Dependencies installed"
|
|
}
|
|
|
|
# Clone and setup stoatchat
|
|
setup_stoatchat() {
|
|
log_info "Setting up Stoatchat..."
|
|
|
|
# Create directory
|
|
sudo mkdir -p $STOATCHAT_DIR
|
|
sudo chown $USER:$USER $STOATCHAT_DIR
|
|
|
|
# Clone repository
|
|
if [[ ! -d "$STOATCHAT_DIR/.git" ]]; then
|
|
log_info "Cloning Stoatchat repository..."
|
|
git clone $REPO_URL $STOATCHAT_DIR
|
|
else
|
|
log_info "Updating Stoatchat repository..."
|
|
cd $STOATCHAT_DIR
|
|
git pull origin main
|
|
fi
|
|
|
|
cd $STOATCHAT_DIR
|
|
|
|
# Setup LiveKit configuration
|
|
if [[ ! -f "livekit.yml" ]]; then
|
|
log_info "Creating LiveKit configuration..."
|
|
cp livekit.example.yml livekit.yml
|
|
|
|
# Update LiveKit config with domain
|
|
sed -i "s/localhost:7880/voice.$DOMAIN/g" livekit.yml
|
|
sed -i "s/redis_host: localhost/redis_host: localhost/g" livekit.yml
|
|
sed -i "s/redis_port: 6379/redis_port: 6380/g" livekit.yml
|
|
fi
|
|
|
|
# Create production configuration
|
|
log_info "Creating production configuration..."
|
|
cat > Revolt.overrides.toml << EOF
|
|
[api]
|
|
url = "https://api.$DOMAIN"
|
|
|
|
[events]
|
|
url = "wss://events.$DOMAIN"
|
|
|
|
[autumn]
|
|
url = "https://files.$DOMAIN"
|
|
|
|
[january]
|
|
url = "https://proxy.$DOMAIN"
|
|
|
|
[livekit]
|
|
url = "wss://voice.$DOMAIN"
|
|
|
|
[database]
|
|
mongodb = "mongodb://localhost:27017/revolt"
|
|
|
|
[redis]
|
|
url = "redis://localhost:6380"
|
|
|
|
[s3]
|
|
endpoint = "http://localhost:14009"
|
|
access_key_id = "minioadmin"
|
|
secret_access_key = "minioadmin"
|
|
bucket = "revolt-files"
|
|
region = "us-east-1"
|
|
|
|
[rabbitmq]
|
|
url = "amqp://guest:guest@localhost:5672"
|
|
|
|
[email]
|
|
smtp_host = "smtp.gmail.com"
|
|
smtp_port = 587
|
|
smtp_username = "your-email@example.com"
|
|
smtp_password = "REDACTED_PASSWORD"
|
|
from_address = "your-email@example.com"
|
|
smtp_tls = true
|
|
|
|
[features]
|
|
registration = true
|
|
email_verification = false
|
|
invite_only = false
|
|
EOF
|
|
|
|
log_success "Stoatchat setup completed"
|
|
}
|
|
|
|
# Start supporting services
|
|
start_infrastructure() {
|
|
log_info "Starting supporting services..."
|
|
|
|
cd $STOATCHAT_DIR
|
|
|
|
# Start Docker services
|
|
docker-compose up -d
|
|
|
|
# Wait for services to be ready
|
|
log_info "Waiting for services to be ready..."
|
|
sleep 30
|
|
|
|
# Check service health
|
|
local services=("database" "redis" "minio" "rabbitmq")
|
|
for service in "${services[@]}"; do
|
|
if docker-compose ps | grep -q "stoatchat-$service.*Up"; then
|
|
log_success "$service is running"
|
|
else
|
|
log_error "$service failed to start"
|
|
docker-compose logs stoatchat-$service
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
log_success "Infrastructure services started"
|
|
}
|
|
|
|
# Build stoatchat
|
|
build_stoatchat() {
|
|
log_info "Building Stoatchat..."
|
|
|
|
cd $STOATCHAT_DIR
|
|
|
|
# Activate mise environment
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
eval "$(mise activate bash)"
|
|
|
|
# Build the project
|
|
if mise run build; then
|
|
log_success "Stoatchat built successfully"
|
|
else
|
|
log_error "Failed to build Stoatchat"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Start stoatchat services
|
|
start_stoatchat_services() {
|
|
log_info "Starting Stoatchat services..."
|
|
|
|
cd $STOATCHAT_DIR
|
|
|
|
# Create logs directory
|
|
mkdir -p logs
|
|
|
|
# Start services in background
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
eval "$(mise activate bash)"
|
|
|
|
mise service:api > logs/api.log 2>&1 &
|
|
echo $! > logs/api.pid
|
|
|
|
mise service:events > logs/events.log 2>&1 &
|
|
echo $! > logs/events.pid
|
|
|
|
mise service:files > logs/files.log 2>&1 &
|
|
echo $! > logs/files.pid
|
|
|
|
mise service:proxy > logs/proxy.log 2>&1 &
|
|
echo $! > logs/proxy.pid
|
|
|
|
mise service:gifbox > logs/gifbox.log 2>&1 &
|
|
echo $! > logs/gifbox.pid
|
|
|
|
mise service:pushd > logs/pushd.log 2>&1 &
|
|
echo $! > logs/pushd.pid
|
|
|
|
mise service:crond > logs/crond.log 2>&1 &
|
|
echo $! > logs/crond.pid
|
|
|
|
# Wait for services to start
|
|
sleep 10
|
|
|
|
# Check if services are running
|
|
local ports=(14702 14703 14704 14705 14706)
|
|
for port in "${ports[@]}"; do
|
|
if ss -tlnp | grep -q ":$port "; then
|
|
log_success "Service on port $port is running"
|
|
else
|
|
log_warning "Service on port $port may not be ready yet"
|
|
fi
|
|
done
|
|
|
|
log_success "Stoatchat services started"
|
|
}
|
|
|
|
# Test the installation
|
|
test_installation() {
|
|
log_info "Testing installation..."
|
|
|
|
# Test API endpoint
|
|
if curl -s http://localhost:14702/0.8/ | jq -e '.revolt' > /dev/null; then
|
|
log_success "API is responding correctly"
|
|
else
|
|
log_error "API is not responding"
|
|
return 1
|
|
fi
|
|
|
|
# Test file service
|
|
if curl -s http://localhost:14704/ | jq -e '.autumn' > /dev/null; then
|
|
log_success "File service is responding correctly"
|
|
else
|
|
log_error "File service is not responding"
|
|
return 1
|
|
fi
|
|
|
|
log_success "Installation test passed"
|
|
}
|
|
|
|
# Create systemd services
|
|
create_systemd_services() {
|
|
log_info "Creating systemd services..."
|
|
|
|
# Create stoatchat user service
|
|
sudo tee /etc/systemd/system/stoatchat.service > /dev/null << EOF
|
|
[Unit]
|
|
Description=Stoatchat (Revolt Chat Backend)
|
|
After=network.target docker.service
|
|
Requires=docker.service
|
|
|
|
[Service]
|
|
Type=forking
|
|
User=$USER
|
|
WorkingDirectory=$STOATCHAT_DIR
|
|
Environment=PATH=$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin
|
|
ExecStart=$STOATCHAT_DIR/scripts/start-services.sh
|
|
ExecStop=$STOATCHAT_DIR/scripts/stop-services.sh
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Create start script
|
|
cat > $STOATCHAT_DIR/scripts/start-services.sh << 'EOF'
|
|
#!/bin/bash
|
|
cd /opt/stoatchat
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
eval "$(mise activate bash)"
|
|
|
|
# Start infrastructure
|
|
docker-compose up -d
|
|
|
|
# Wait for infrastructure
|
|
sleep 30
|
|
|
|
# Start stoatchat services
|
|
mkdir -p logs
|
|
mise service:api > logs/api.log 2>&1 &
|
|
echo $! > logs/api.pid
|
|
mise service:events > logs/events.log 2>&1 &
|
|
echo $! > logs/events.pid
|
|
mise service:files > logs/files.log 2>&1 &
|
|
echo $! > logs/files.pid
|
|
mise service:proxy > logs/proxy.log 2>&1 &
|
|
echo $! > logs/proxy.pid
|
|
mise service:gifbox > logs/gifbox.log 2>&1 &
|
|
echo $! > logs/gifbox.pid
|
|
mise service:pushd > logs/pushd.log 2>&1 &
|
|
echo $! > logs/pushd.pid
|
|
mise service:crond > logs/crond.log 2>&1 &
|
|
echo $! > logs/crond.pid
|
|
EOF
|
|
|
|
# Create stop script
|
|
cat > $STOATCHAT_DIR/scripts/stop-services.sh << 'EOF'
|
|
#!/bin/bash
|
|
cd /opt/stoatchat
|
|
|
|
# Stop stoatchat services
|
|
if [[ -f logs/api.pid ]]; then kill $(cat logs/api.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/events.pid ]]; then kill $(cat logs/events.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/files.pid ]]; then kill $(cat logs/files.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/proxy.pid ]]; then kill $(cat logs/proxy.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/gifbox.pid ]]; then kill $(cat logs/gifbox.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/pushd.pid ]]; then kill $(cat logs/pushd.pid) 2>/dev/null || true; fi
|
|
if [[ -f logs/crond.pid ]]; then kill $(cat logs/crond.pid) 2>/dev/null || true; fi
|
|
|
|
# Stop infrastructure
|
|
docker-compose down
|
|
EOF
|
|
|
|
# Make scripts executable
|
|
chmod +x $STOATCHAT_DIR/scripts/*.sh
|
|
|
|
# Enable service
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable stoatchat.service
|
|
|
|
log_success "Systemd services created"
|
|
}
|
|
|
|
# Print final instructions
|
|
print_final_instructions() {
|
|
log_success "Stoatchat installation completed!"
|
|
|
|
echo ""
|
|
echo "🎉 Installation Summary:"
|
|
echo " • Stoatchat installed in: $STOATCHAT_DIR"
|
|
echo " • Domain configured for: $DOMAIN"
|
|
echo " • Services running on ports: 14702-14706"
|
|
echo ""
|
|
echo "🔧 Next Steps:"
|
|
echo " 1. Set up Gmail App Password:"
|
|
echo " - Go to Google Account settings"
|
|
echo " - Enable 2-Factor Authentication"
|
|
echo " - Generate App Password for 'Mail'"
|
|
echo " - Update GMAIL_APP_PASSWORD_REQUIRED in Revolt.overrides.toml"
|
|
echo ""
|
|
echo " 2. Configure Cloudflare Tunnel for external access:"
|
|
echo " - api.$DOMAIN → localhost:14702"
|
|
echo " - events.$DOMAIN → localhost:14703"
|
|
echo " - files.$DOMAIN → localhost:14704"
|
|
echo " - proxy.$DOMAIN → localhost:14705"
|
|
echo ""
|
|
echo " 3. Set up the web client at $DOMAIN"
|
|
echo ""
|
|
echo " 4. Configure LiveKit for voice chat (optional)"
|
|
echo ""
|
|
echo "📊 Service Management:"
|
|
echo " • Start: sudo systemctl start stoatchat"
|
|
echo " • Stop: sudo systemctl stop stoatchat"
|
|
echo " • Status: sudo systemctl status stoatchat"
|
|
echo " • Logs: journalctl -u stoatchat -f"
|
|
echo ""
|
|
echo "🔍 Manual Service Management:"
|
|
echo " • View logs: tail -f $STOATCHAT_DIR/logs/*.log"
|
|
echo " • Test API: curl http://localhost:14702/0.8/"
|
|
echo " • Check ports: ss -tlnp | grep revolt"
|
|
echo ""
|
|
echo "📚 Documentation: $STOATCHAT_DIR/README.md"
|
|
echo ""
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
log_info "Starting Stoatchat installation for $DOMAIN"
|
|
|
|
check_root
|
|
check_requirements
|
|
install_dependencies
|
|
setup_stoatchat
|
|
start_infrastructure
|
|
build_stoatchat
|
|
start_stoatchat_services
|
|
|
|
if test_installation; then
|
|
create_systemd_services
|
|
print_final_instructions
|
|
else
|
|
log_error "Installation test failed. Please check the logs."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|