mockapi/fix_waitress_port.sh
2026-03-16 18:05:02 +00:00

262 lines
No EOL
7.5 KiB
Bash

#!/bin/bash
# Comprehensive fix for Waitress port parsing issue on VPS
set -e
echo "=== Fixing Waitress Port Parsing Issue ==="
echo
APP_DIR="/opt/mockapi"
SERVICE_FILE="/etc/systemd/system/mockapi.service"
ENV_FILE="${APP_DIR}/.env"
print_status() {
echo -e "\033[0;32m[+]\033[0m $1"
}
print_warning() {
echo -e "\033[1;33m[!]\033[0m $1"
}
print_error() {
echo -e "\033[0;31m[!]\033[0m $1"
}
# Step 1: Check environment
print_status "Step 1: Checking environment"
if [[ ! -d "$APP_DIR" ]]; then
print_error "Application directory not found: $APP_DIR"
exit 1
fi
if [[ ! -f "$SERVICE_FILE" ]]; then
print_error "Service file not found: $SERVICE_FILE"
exit 1
fi
cd "$APP_DIR"
# Step 2: Read current port from .env
print_status "Step 2: Reading current configuration"
PORT="8000"
HOST="0.0.0.0"
if [[ -f "$ENV_FILE" ]]; then
if grep -q "^PORT=" "$ENV_FILE"; then
PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2)
print_status "Found PORT in .env: $PORT"
# Validate PORT is numeric
if [[ ! "$PORT" =~ ^[0-9]+$ ]]; then
print_error "PORT is not numeric: '$PORT'. Setting to 8000."
PORT="8000"
sudo sed -i "s/^PORT=.*/PORT=8000/" "$ENV_FILE"
fi
else
print_warning "PORT not found in .env, adding PORT=8000"
echo "PORT=8000" | sudo tee -a "$ENV_FILE" > /dev/null
fi
if grep -q "^HOST=" "$ENV_FILE"; then
HOST=$(grep "^HOST=" "$ENV_FILE" | cut -d'=' -f2)
print_status "Found HOST in .env: $HOST"
else
print_warning "HOST not found in .env, adding HOST=0.0.0.0"
echo "HOST=0.0.0.0" | sudo tee -a "$ENV_FILE" > /dev/null
fi
else
print_error ".env file not found: $ENV_FILE"
exit 1
fi
# Step 3: Backup service file
print_status "Step 3: Backing up service file"
BACKUP_FILE="${SERVICE_FILE}.backup.$(date +%s)"
sudo cp "$SERVICE_FILE" "$BACKUP_FILE"
print_status "Backup created: $BACKUP_FILE"
# Step 4: Fix service file - OPTION 1: Use shell expansion
print_status "Step 4: Fixing service file ExecStart command"
print_warning "Current issue: Waitress receives literal string '\$PORT' instead of expanded value"
print_status "Solution 1: Use /bin/sh -c to enable shell variable expansion"
# Get the virtual environment path
VENV_DIR="${APP_DIR}/venv"
if [[ ! -d "$VENV_DIR" ]]; then
print_error "Virtual environment not found: $VENV_DIR"
exit 1
fi
# Read current service file to get other settings
CURRENT_USER=$(grep "^User=" "$SERVICE_FILE" | cut -d'=' -f2)
CURRENT_GROUP=$(grep "^Group=" "$SERVICE_FILE" | cut -d'=' -f2)
CURRENT_WORKDIR=$(grep "^WorkingDirectory=" "$SERVICE_FILE" | cut -d'=' -f2)
print_status "Current service settings:"
print_status " User: $CURRENT_USER"
print_status " Group: $CURRENT_GROUP"
print_status " WorkingDirectory: $CURRENT_WORKDIR"
# Create new service file with fixed ExecStart
print_status "Creating fixed service file..."
sudo tee "$SERVICE_FILE" > /dev/null << EOF
[Unit]
Description=Mock API Service
After=network.target
Wants=network.target
[Service]
Type=simple
User=$CURRENT_USER
Group=$CURRENT_GROUP
WorkingDirectory=$CURRENT_WORKDIR
Environment="PATH=$VENV_DIR/bin"
Environment="PYTHONPATH=$APP_DIR"
EnvironmentFile=$APP_DIR/.env
# Use shell to expand environment variables
ExecStart=/bin/sh -c "$VENV_DIR/bin/waitress-serve --host=\$HOST --port=\$PORT wsgi:wsgi_app"
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=mockapi
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=$APP_DIR
[Install]
WantedBy=multi-user.target
EOF
print_status "Service file updated with shell expansion."
# Step 5: Alternative simpler fix - hardcode port based on .env value
print_status "Alternative approach available: Hardcode port in service file"
print_warning "Would you like to hardcode port $PORT in service file instead? (y/N)"
read -p "Choice: " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_status "Hardcoding port $PORT in service file..."
sudo tee "$SERVICE_FILE" > /dev/null << EOF
[Unit]
Description=Mock API Service
After=network.target
Wants=network.target
[Service]
Type=simple
User=$CURRENT_USER
Group=$CURRENT_GROUP
WorkingDirectory=$CURRENT_WORKDIR
Environment="PATH=$VENV_DIR/bin"
Environment="PYTHONPATH=$APP_DIR"
EnvironmentFile=$APP_DIR/.env
# Hardcoded port based on .env value
ExecStart=$VENV_DIR/bin/waitress-serve --host=$HOST --port=$PORT wsgi:wsgi_app
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=mockapi
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=$APP_DIR
[Install]
WantedBy=multi-user.target
EOF
print_status "Service file updated with hardcoded port $PORT."
print_warning "Note: If you change PORT in .env, you must update service file manually."
fi
# Step 6: Reload and restart
print_status "Step 5: Reloading systemd daemon..."
sudo systemctl daemon-reload
print_status "Step 6: Restarting service..."
sudo systemctl restart mockapi
sleep 3
# Step 7: Verify
print_status "Step 7: Verifying service status..."
if sudo systemctl is-active --quiet mockapi; then
print_status "✓ Service is running!"
echo
print_status "Testing health endpoint on port $PORT..."
if curl -f -s --max-time 10 http://localhost:$PORT/health > /dev/null 2>&1; then
print_status "✓ Health check passed!"
echo
echo "=== Service Fixed Successfully ==="
echo "MockAPI is now running on:"
echo " URL: http://localhost:$PORT"
echo " Admin: http://localhost:$PORT/admin/login"
echo " Docs: http://localhost:$PORT/docs"
echo " Health: http://localhost:$PORT/health"
else
print_warning "Health check failed (might be starting up). Checking logs..."
sleep 2
if curl -f -s --max-time 5 http://localhost:$PORT/health > /dev/null 2>&1; then
print_status "✓ Health check passed on second attempt!"
else
print_warning "Service running but health check failing. Checking logs..."
sudo journalctl -u mockapi -n 20 --no-pager
fi
fi
else
print_error "Service failed to start after fix."
echo
print_warning "Checking service logs..."
sudo journalctl -u mockapi -n 30 --no-pager
echo
print_warning "Trying alternative approach with simplified service file..."
# Try a simpler approach - just hardcode common values
print_status "Creating minimal service file..."
sudo tee "$SERVICE_FILE" > /dev/null << EOF
[Unit]
Description=Mock API Service
After=network.target
[Service]
Type=simple
User=$CURRENT_USER
Group=$CURRENT_GROUP
WorkingDirectory=$APP_DIR
Environment="PATH=$VENV_DIR/bin"
ExecStart=$VENV_DIR/bin/waitress-serve --host=0.0.0.0 --port=8000 wsgi:wsgi_app
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl restart mockapi
sleep 3
if sudo systemctl is-active --quiet mockapi; then
print_status "✓ Service started with hardcoded values!"
print_warning "Running on default port 8000. Update .env to match."
sudo sed -i "s/^PORT=.*/PORT=8000/" "$ENV_FILE"
else
print_error "All fixes failed. Please check manual configuration."
sudo journalctl -u mockapi -n 30 --no-pager
fi
fi
echo
print_status "=== Fix script completed ==="
echo "Backup service file: $BACKUP_FILE"
echo "Current .env PORT: $PORT"
echo "Current .env HOST: $HOST"