#!/bin/bash # SubConverter-Go Deployment Script # ================================== set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration PROJECT_NAME="subconverter-go" SERVICE_NAME="subconverter-go" SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" INSTALL_DIR="/opt/${PROJECT_NAME}" BINARY_NAME="${PROJECT_NAME}" CONFIG_FILE="config.yaml" USER="subconverter" GROUP="subconverter" # Helper 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_root() { if [[ $EUID -ne 0 ]]; then log_error "This script must be run as root" exit 1 fi } check_dependencies() { log_info "Checking dependencies..." # Check if Go is installed if ! command -v go &> /dev/null; then log_error "Go is not installed" exit 1 fi # Check if systemctl is available if ! command -v systemctl &> /dev/null; then log_warning "systemctl not found, service installation will be skipped" return 1 fi return 0 } create_user() { log_info "Creating user and group..." if ! getent group "$GROUP" &>/dev/null; then groupadd -r "$GROUP" log_success "Group $GROUP created" fi if ! getent passwd "$USER" &>/dev/null; then useradd -r -g "$GROUP" -d "$INSTALL_DIR" -s /bin/false "$USER" log_success "User $USER created" fi } install_binary() { log_info "Building and installing binary..." # Build the binary go build -ldflags="-w -s -X 'main.Version=1.0.0'" -o "$BINARY_NAME" main.go # Create installation directory mkdir -p "$INSTALL_DIR" # Copy binary cp "$BINARY_NAME" "$INSTALL_DIR/" chmod +x "$INSTALL_DIR/$BINARY_NAME" # Copy config file if [[ -f "$CONFIG_FILE" ]]; then cp "$CONFIG_FILE" "$INSTALL_DIR/" else log_warning "Config file not found, creating default..." cat > "$INSTALL_DIR/$CONFIG_FILE" << 'EOF' server: port: 25500 host: "0.0.0.0" read_timeout: 30 write_timeout: 30 max_request_size: 10485760 logging: level: "info" format: "json" output: "stdout" file: "logs/subconverter-go.log" max_size: 100 max_age: 7 max_backups: 3 compress: true security: access_tokens: [] cors_origins: ["*"] rate_limit: 60 timeout: 60 conversion: default_target: "clash" supported_targets: - "clash" - "surge" - "quantumult-x" - "loon" - "surfboard" - "v2ray" default_emoji: false default_udp: false max_nodes: 0 cache_timeout: 60 EOF fi # Create logs directory mkdir -p "$INSTALL_DIR/logs" # Set permissions chown -R "$USER:$GROUP" "$INSTALL_DIR" chmod 750 "$INSTALL_DIR" chmod 640 "$INSTALL_DIR/$CONFIG_FILE" log_success "Binary installed to $INSTALL_DIR" } create_service() { log_info "Creating systemd service..." cat > "$SERVICE_FILE" << EOF [Unit] Description=SubConverter-Go Service After=network.target [Service] Type=simple User=$USER Group=$GROUP WorkingDirectory=$INSTALL_DIR ExecStart=$INSTALL_DIR/$BINARY_NAME --config $INSTALL_DIR/$CONFIG_FILE Restart=always RestartSec=5 Environment=GIN_MODE=production Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Security settings NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=$INSTALL_DIR/logs ReadOnlyPaths=$INSTALL_DIR # Resource limits LimitNOFILE=65535 LimitNPROC=4096 [Install] WantedBy=multi-user.target EOF # Reload systemd systemctl daemon-reload # Enable service systemctl enable "$SERVICE_NAME" log_success "Service created and enabled" } configure_firewall() { log_info "Configuring firewall..." # Check if ufw is available if command -v ufw &> /dev/null; then ufw allow 25500/tcp log_success "Firewall configured with ufw" elif command -v firewall-cmd &> /dev/null; then firewall-cmd --permanent --add-port=25500/tcp firewall-cmd --reload log_success "Firewall configured with firewalld" else log_warning "No firewall tool found, manual configuration required" fi } start_service() { log_info "Starting service..." systemctl start "$SERVICE_NAME" # Wait for service to start sleep 2 # Check status if systemctl is-active --quiet "$SERVICE_NAME"; then log_success "Service started successfully" systemctl status "$SERVICE_NAME" --no-pager -l else log_error "Service failed to start" systemctl status "$SERVICE_NAME" --no-pager -l exit 1 fi } test_service() { log_info "Testing service..." # Test health endpoint if curl -s -f http://localhost:25500/health > /dev/null; then log_success "Health endpoint is accessible" else log_error "Health endpoint is not accessible" exit 1 fi # Test version endpoint if curl -s -f http://localhost:25500/version > /dev/null; then log_success "Version endpoint is accessible" else log_error "Version endpoint is not accessible" exit 1 fi log_success "All tests passed" } uninstall() { log_warning "Uninstalling $PROJECT_NAME..." # Stop and disable service if systemctl is-active --quiet "$SERVICE_NAME"; then systemctl stop "$SERVICE_NAME" fi if systemctl is-enabled --quiet "$SERVICE_NAME"; then systemctl disable "$SERVICE_NAME" fi # Remove service file if [[ -f "$SERVICE_FILE" ]]; then rm -f "$SERVICE_FILE" systemctl daemon-reload fi # Remove installation directory if [[ -d "$INSTALL_DIR" ]]; then rm -rf "$INSTALL_DIR" fi # Remove user and group if getent passwd "$USER" &>/dev/null; then userdel "$USER" fi if getent group "$GROUP" &>/dev/null; then groupdel "$GROUP" fi log_success "Uninstallation complete" } show_usage() { cat << EOF SubConverter-Go Deployment Script Usage: $0 [OPTIONS] OPTIONS: install Install the service uninstall Uninstall the service start Start the service stop Stop the service restart Restart the service status Show service status test Test the service logs Show service logs help Show this help message EXAMPLES: $0 install # Install and start the service $0 status # Check service status $0 logs # View service logs $0 uninstall # Remove the service EOF } # Main script logic main() { case "${1:-}" in "install") check_root if check_dependencies; then create_user install_binary create_service configure_firewall start_service test_service log_success "Installation completed successfully!" log_info "Service is running on http://localhost:25500" else log_info "Installing binary only (without service)..." install_binary log_success "Binary installed to $INSTALL_DIR" log_info "Run manually: $INSTALL_DIR/$BINARY_NAME --config $INSTALL_DIR/$CONFIG_FILE" fi ;; "uninstall") check_root uninstall ;; "start") check_root systemctl start "$SERVICE_NAME" log_success "Service started" ;; "stop") check_root systemctl stop "$SERVICE_NAME" log_success "Service stopped" ;; "restart") check_root systemctl restart "$SERVICE_NAME" log_success "Service restarted" ;; "status") systemctl status "$SERVICE_NAME" --no-pager -l ;; "test") test_service ;; "logs") journalctl -u "$SERVICE_NAME" -f ;; "help"|"-h"|"--help") show_usage ;; *) log_error "Unknown command: $1" show_usage exit 1 ;; esac } # Run main function main "$@"