Some checks failed
CI/CD Pipeline / Test (push) Failing after 22m19s
CI/CD Pipeline / Security Scan (push) Failing after 5m57s
CI/CD Pipeline / Build (amd64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (amd64, linux) (push) Has been skipped
CI/CD Pipeline / Build (amd64, windows) (push) Has been skipped
CI/CD Pipeline / Build (arm64, darwin) (push) Has been skipped
CI/CD Pipeline / Build (arm64, linux) (push) Has been skipped
CI/CD Pipeline / Build Docker Image (push) Has been skipped
CI/CD Pipeline / Create Release (push) Has been skipped
373 lines
8.3 KiB
Bash
Executable File
373 lines
8.3 KiB
Bash
Executable File
#!/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 "$@" |