Sanitized mirror from private repository - 2026-04-20 01:32:01 UTC
This commit is contained in:
479
scripts/setup-stoatchat.sh
Executable file
479
scripts/setup-stoatchat.sh
Executable file
@@ -0,0 +1,479 @@
|
||||
#!/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 "$@"
|
||||
Reference in New Issue
Block a user