From 81d02ed49b521dfdef270e5d5d45bdcd7c1cc487 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Mon, 16 Mar 2026 18:40:22 +0000 Subject: [PATCH] chore: auto-commit 2026-03-16 18:40 --- README.md | 80 ++++++++- change_port.sh | 249 ++++++++++++++++++++++++++ check_port_config.sh | 181 +++++++++++++++++++ fix_env_port_dynamic.sh | 368 ++++++++++++++++++++++++++++++++++++++ fix_missing_port.sh | 74 ++++++++ fix_remove_backslashes.sh | 191 ++++++++++++++++++++ fix_service_env_vars.sh | 226 +++++++++++++++++++++++ install.sh | 72 +++----- 8 files changed, 1397 insertions(+), 44 deletions(-) create mode 100644 change_port.sh create mode 100644 check_port_config.sh create mode 100644 fix_env_port_dynamic.sh create mode 100644 fix_missing_port.sh create mode 100644 fix_remove_backslashes.sh create mode 100644 fix_service_env_vars.sh diff --git a/README.md b/README.md index f90a5ce..a15b19c 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,85 @@ RestartSec=10 WantedBy=multi-user.target ``` -### 3. **Reverse Proxy (Recommended)** +### 3. **Changing Port Configuration** +If you need to change the port MockAPI runs on (e.g., due to port conflicts), you have two options: + +#### Option A: Using the Change Port Script (Recommended) +```bash +# Download the script if not already present +cd /opt/mockapi +sudo wget -O change_port.sh https://raw.githubusercontent.com/your-repo/main/change_port.sh +sudo chmod +x change_port.sh + +# Run the script +sudo bash change_port.sh +``` + +The script will: +1. Show current port configuration +2. Ask for new port number +3. Update `.env` file +4. Update systemd service file +5. Update OAuth2 issuer URL +6. Restart the service + +#### Option B: Manual Port Change +If you prefer to change the port manually: + +1. **Edit the `.env` file**: + ```bash + sudo nano /opt/mockapi/.env + ``` + Update these lines: + ```ini + PORT=8080 # Change to your desired port + HOST=0.0.0.0 # Or change host if needed + OAUTH2_ISSUER=http://localhost:8080 # Update to match new port + ``` + +2. **Edit the systemd service file**: + ```bash + sudo nano /etc/systemd/system/mockapi.service + ``` + Update the `ExecStart` line: + ```ini + ExecStart=/opt/mockapi/venv/bin/waitress-serve --host=0.0.0.0 --port=8080 wsgi:wsgi_app + ``` + +3. **Reload systemd and restart**: + ```bash + sudo systemctl daemon-reload + sudo systemctl restart mockapi + sudo systemctl status mockapi + ``` + +4. **Verify the change**: + ```bash + curl http://localhost:8080/health + ``` + +**Important Notes**: +- The port in `.env` and service file must match +- After changing port, update any reverse proxy configurations +- OAuth2 clients may need reconfiguration if issuer URL changes + +**Checking Current Configuration**: +To verify your port configuration is consistent, use the check script: +```bash +cd /opt/mockapi +sudo wget -O check_port_config.sh https://raw.githubusercontent.com/your-repo/main/check_port_config.sh +sudo chmod +x check_port_config.sh +sudo bash check_port_config.sh +``` + +The script will: +- Show current port settings from `.env` and service file +- Check for consistency between files +- Verify service is running and listening on correct port +- Test health endpoint +- Provide recommendations if issues are found + +### 4. **Reverse Proxy (Recommended)** Use Nginx or Apache as a reverse proxy for SSL termination, load balancing, and static file serving: **Example Nginx configuration**: diff --git a/change_port.sh b/change_port.sh new file mode 100644 index 0000000..ec29dff --- /dev/null +++ b/change_port.sh @@ -0,0 +1,249 @@ +#!/bin/bash +# Change MockAPI port configuration +# Run this script to change the port MockAPI runs on + +set -e + +echo "=== MockAPI Port Change Utility ===" +echo + +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" +SERVICE_FILE="/etc/systemd/system/mockapi.service" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${GREEN}[+]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[!]${NC} $1" +} + +print_info() { + echo -e "${BLUE}[i]${NC} $1" +} + +# Check if running as root or with sudo +if [[ $EUID -ne 0 ]]; then + print_error "This script requires sudo privileges." + print_info "Run with: sudo bash $0" + exit 1 +fi + +# Step 1: Check if files exist +if [[ ! -f "$ENV_FILE" ]]; then + print_error ".env file not found: $ENV_FILE" + exit 1 +fi + +if [[ ! -f "$SERVICE_FILE" ]]; then + print_error "Service file not found: $SERVICE_FILE" + exit 1 +fi + +# Step 2: Show current configuration +print_status "Current configuration:" +CURRENT_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2 || echo "8000") +CURRENT_HOST=$(grep "^HOST=" "$ENV_FILE" | cut -d'=' -f2 || echo "0.0.0.0") +CURRENT_ISSUER=$(grep "^OAUTH2_ISSUER=" "$ENV_FILE" | cut -d'=' -f2 || echo "http://localhost:${CURRENT_PORT}") + +echo " Current PORT: $CURRENT_PORT" +echo " Current HOST: $CURRENT_HOST" +echo " Current OAUTH2_ISSUER: $CURRENT_ISSUER" +echo + +# Step 3: Ask for new port +read -p "Enter new port number [$CURRENT_PORT]: " NEW_PORT +NEW_PORT=${NEW_PORT:-$CURRENT_PORT} + +# Validate new port +if [[ ! "$NEW_PORT" =~ ^[0-9]+$ ]]; then + print_error "Invalid port number: '$NEW_PORT'. Must be numeric." + exit 1 +fi + +if [[ "$NEW_PORT" -lt 1 ]] || [[ "$NEW_PORT" -gt 65535 ]]; then + print_error "Port number must be between 1 and 65535." + exit 1 +fi + +# Check if port is already in use +if command -v netstat &> /dev/null; then + if netstat -tuln | grep -q ":$NEW_PORT "; then + print_warning "Port $NEW_PORT appears to be in use!" + read -p "Continue anyway? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi +elif command -v ss &> /dev/null; then + if ss -tuln | grep -q ":$NEW_PORT "; then + print_warning "Port $NEW_PORT appears to be in use!" + read -p "Continue anyway? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi +fi + +# Step 4: Ask for host (optional) +read -p "Enter host address [$CURRENT_HOST]: " NEW_HOST +NEW_HOST=${NEW_HOST:-$CURRENT_HOST} + +# Step 5: Backup files +print_status "Creating backups..." +BACKUP_DIR="${APP_DIR}/backup_port_change_$(date +%Y%m%d_%H%M%S)" +mkdir -p "$BACKUP_DIR" +cp "$ENV_FILE" "$BACKUP_DIR/.env.backup" +cp "$SERVICE_FILE" "$BACKUP_DIR/mockapi.service.backup" +print_status "Backups saved to: $BACKUP_DIR" + +# Step 6: Update .env file +print_status "Updating .env file..." +# Update PORT +if grep -q "^PORT=" "$ENV_FILE"; then + sed -i "s/^PORT=.*/PORT=$NEW_PORT/" "$ENV_FILE" +else + echo "PORT=$NEW_PORT" >> "$ENV_FILE" +fi + +# Update HOST +if grep -q "^HOST=" "$ENV_FILE"; then + sed -i "s/^HOST=.*/HOST=$NEW_HOST/" "$ENV_FILE" +else + echo "HOST=$NEW_HOST" >> "$ENV_FILE" +fi + +# Update OAUTH2_ISSUER +NEW_ISSUER="http://localhost:${NEW_PORT}" +if grep -q "^OAUTH2_ISSUER=" "$ENV_FILE"; then + sed -i "s|^OAUTH2_ISSUER=.*|OAUTH2_ISSUER=$NEW_ISSUER|" "$ENV_FILE" +else + echo "OAUTH2_ISSUER=$NEW_ISSUER" >> "$ENV_FILE" +fi + +print_status "Updated .env file:" +echo " PORT=$NEW_PORT" +echo " HOST=$NEW_HOST" +echo " OAUTH2_ISSUER=$NEW_ISSUER" + +# Step 7: Update service file +print_status "Updating service file..." +# Get virtual environment path +VENV_DIR=$(grep 'Environment="PATH=' "$SERVICE_FILE" | cut -d'=' -f2 | cut -d':' -f1 | sed 's/"//g' || echo "/opt/mockapi/venv") + +# Get user and group from current service file +SERVICE_USER=$(grep "^User=" "$SERVICE_FILE" | cut -d'=' -f2) +SERVICE_GROUP=$(grep "^Group=" "$SERVICE_FILE" | cut -d'=' -f2) + +# Create updated service file +cat > /tmp/mockapi_new.service << EOF +[Unit] +Description=Mock API Service +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$SERVICE_USER +Group=$SERVICE_GROUP +WorkingDirectory=$APP_DIR +Environment="PATH=$VENV_DIR/bin" +Environment="PYTHONPATH=$APP_DIR" +EnvironmentFile=$APP_DIR/.env +# Hardcoded port from .env (updated) +ExecStart=$VENV_DIR/bin/waitress-serve --host=$NEW_HOST --port=$NEW_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 + +# Replace service file +cp /tmp/mockapi_new.service "$SERVICE_FILE" +rm -f /tmp/mockapi_new.service + +print_status "Service file updated with new port $NEW_PORT." + +# Step 8: Reload systemd +print_status "Reloading systemd daemon..." +systemctl daemon-reload + +# Step 9: Restart service +print_status "Restarting MockAPI service..." +if systemctl restart mockapi; then + print_status "Service restart initiated." + + # Wait for service to start + sleep 3 + + if systemctl is-active --quiet mockapi; then + print_status "✓ Service is running on port $NEW_PORT!" + + # Test health endpoint + print_status "Testing health endpoint..." + if curl -f -s --max-time 10 http://localhost:$NEW_PORT/health > /dev/null 2>&1; then + print_status "✓ Health check passed!" + echo + echo "=== Port Change Successful ===" + echo + echo "MockAPI is now running on:" + echo " URL: http://localhost:$NEW_PORT" + echo " Admin: http://localhost:$NEW_PORT/admin/login" + echo " Docs: http://localhost:$NEW_PORT/docs" + echo " Health: http://localhost:$NEW_PORT/health" + echo + echo "If accessing remotely, use:" + echo " http://$(hostname -I | awk '{print $1}'):$NEW_PORT" + else + print_warning "Service is running but health check failed." + print_info "This might be normal during initial startup." + echo + print_status "Service status:" + systemctl status mockapi --no-pager -l + fi + else + print_error "Service failed to start after port change." + echo + print_warning "Checking service logs..." + journalctl -u mockapi -n 30 --no-pager + echo + print_warning "Restoring from backup..." + cp "$BACKUP_DIR/.env.backup" "$ENV_FILE" + cp "$BACKUP_DIR/mockapi.service.backup" "$SERVICE_FILE" + systemctl daemon-reload + systemctl restart mockapi + print_status "Restored original configuration." + fi +else + print_error "Failed to restart service." + systemctl status mockapi --no-pager -l +fi + +echo +print_status "=== Port Change Complete ===" +echo "Backup files are in: $BACKUP_DIR" +echo "If you need to revert, copy files from backup directory." \ No newline at end of file diff --git a/check_port_config.sh b/check_port_config.sh new file mode 100644 index 0000000..7912214 --- /dev/null +++ b/check_port_config.sh @@ -0,0 +1,181 @@ +#!/bin/bash +# Check MockAPI port configuration consistency +# Run this to verify port settings are correct + +echo "=== MockAPI Port Configuration Check ===" +echo + +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" +SERVICE_FILE="/etc/systemd/system/mockapi.service" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +print_ok() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +# Check if files exist +if [[ ! -f "$ENV_FILE" ]]; then + print_error ".env file not found: $ENV_FILE" + exit 1 +fi + +if [[ ! -f "$SERVICE_FILE" ]]; then + print_error "Service file not found: $SERVICE_FILE" + exit 1 +fi + +print_ok "Checking configuration files..." + +# Read values from .env +ENV_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2 || echo "NOT_FOUND") +ENV_HOST=$(grep "^HOST=" "$ENV_FILE" | cut -d'=' -f2 || echo "NOT_FOUND") +ENV_ISSUER=$(grep "^OAUTH2_ISSUER=" "$ENV_FILE" | cut -d'=' -f2 || echo "NOT_FOUND") + +# Read from service file +SERVICE_LINE=$(grep "^ExecStart=" "$SERVICE_FILE" || echo "NOT_FOUND") +if [[ "$SERVICE_LINE" != "NOT_FOUND" ]]; then + # Extract host and port from ExecStart + SERVICE_HOST=$(echo "$SERVICE_LINE" | grep -o -- '--host=[^ ]*' | cut -d'=' -f2 || echo "NOT_FOUND") + SERVICE_PORT=$(echo "$SERVICE_LINE" | grep -o -- '--port=[^ ]*' | cut -d'=' -f2 || echo "NOT_FOUND") +else + SERVICE_HOST="NOT_FOUND" + SERVICE_PORT="NOT_FOUND" +fi + +echo +echo "=== Current Configuration ===" +echo + +echo ".env file ($ENV_FILE):" +echo " PORT: $ENV_PORT" +echo " HOST: $ENV_HOST" +echo " OAUTH2_ISSUER: $ENV_ISSUER" +echo + +echo "Service file ($SERVICE_FILE):" +echo " HOST in ExecStart: $SERVICE_HOST" +echo " PORT in ExecStart: $SERVICE_PORT" +echo + +echo "=== Analysis ===" +echo + +# Check 1: Port numeric validation +if [[ "$ENV_PORT" =~ ^[0-9]+$ ]]; then + print_ok "PORT in .env is numeric: $ENV_PORT" +else + print_error "PORT in .env is not numeric: '$ENV_PORT'" +fi + +if [[ "$SERVICE_PORT" =~ ^[0-9]+$ ]]; then + print_ok "PORT in service file is numeric: $SERVICE_PORT" +else + print_error "PORT in service file is not numeric: '$SERVICE_PORT'" +fi + +# Check 2: Port consistency +if [[ "$ENV_PORT" == "$SERVICE_PORT" ]]; then + print_ok "Ports match: .env=$ENV_PORT, service=$SERVICE_PORT" +else + print_error "Port mismatch! .env=$ENV_PORT, service=$SERVICE_PORT" +fi + +# Check 3: Host consistency +if [[ "$ENV_HOST" == "$SERVICE_HOST" ]]; then + print_ok "Hosts match: .env=$ENV_HOST, service=$SERVICE_HOST" +elif [[ "$ENV_HOST" == "NOT_FOUND" ]] || [[ "$SERVICE_HOST" == "NOT_FOUND" ]]; then + print_warning "Host not found in one or both files" +else + print_error "Host mismatch! .env=$ENV_HOST, service=$SERVICE_HOST" +fi + +# Check 4: OAUTH2_ISSUER consistency +EXPECTED_ISSUER="http://localhost:${ENV_PORT}" +if [[ "$ENV_ISSUER" == "$EXPECTED_ISSUER" ]]; then + print_ok "OAUTH2_ISSUER matches port: $ENV_ISSUER" +elif [[ "$ENV_ISSUER" == "NOT_FOUND" ]]; then + print_warning "OAUTH2_ISSUER not found in .env" +else + print_warning "OAUTH2_ISSUER doesn't match port: $ENV_ISSUER (expected: $EXPECTED_ISSUER)" +fi + +# Check 5: Service status +echo +echo "=== Service Status ===" +echo + +if systemctl is-active --quiet mockapi 2>/dev/null; then + print_ok "Service is running" + + # Try to get actual listening port + if command -v ss &> /dev/null; then + LISTENING_PORT=$(ss -tuln | grep ":$ENV_PORT " | head -1 | awk '{print $4}' | cut -d':' -f2) + if [[ -n "$LISTENING_PORT" ]]; then + print_ok "Service is listening on port: $LISTENING_PORT" + if [[ "$LISTENING_PORT" == "$ENV_PORT" ]]; then + print_ok "Listening port matches configured port" + else + print_error "Listening port ($LISTENING_PORT) doesn't match configured port ($ENV_PORT)" + fi + fi + fi + + # Test health endpoint + echo + echo "Testing health endpoint..." + if curl -f -s --max-time 5 http://localhost:${ENV_PORT}/health > /dev/null 2>&1; then + print_ok "Health check passed: http://localhost:${ENV_PORT}/health" + else + print_warning "Health check failed on port $ENV_PORT" + print_warning "Service might be starting up or have issues" + fi +else + print_error "Service is not running" + echo "Status:" + systemctl status mockapi --no-pager -l | head -20 +fi + +echo +echo "=== Recommendations ===" +echo + +if [[ "$ENV_PORT" != "$SERVICE_PORT" ]]; then + echo "1. Fix port mismatch:" + echo " Run: sudo bash change_port.sh" + echo " Or manually update .env and service file to match" +fi + +if [[ ! "$ENV_PORT" =~ ^[0-9]+$ ]]; then + echo "2. Fix invalid PORT in .env:" + echo " Edit $ENV_FILE and set PORT to a numeric value (e.g., 8000)" +fi + +if [[ "$ENV_ISSUER" != "http://localhost:${ENV_PORT}" ]] && [[ "$ENV_ISSUER" != "NOT_FOUND" ]]; then + echo "3. Update OAUTH2_ISSUER to match port:" + echo " Edit $ENV_FILE and set: OAUTH2_ISSUER=http://localhost:${ENV_PORT}" +fi + +if ! systemctl is-active --quiet mockapi 2>/dev/null; then + echo "4. Start the service:" + echo " sudo systemctl start mockapi" + echo " sudo systemctl status mockapi" +fi + +echo +echo "=== Summary ===" +echo "Run 'sudo bash change_port.sh' to fix any configuration issues." +echo "Run 'sudo systemctl restart mockapi' after making changes." \ No newline at end of file diff --git a/fix_env_port_dynamic.sh b/fix_env_port_dynamic.sh new file mode 100644 index 0000000..aff73e0 --- /dev/null +++ b/fix_env_port_dynamic.sh @@ -0,0 +1,368 @@ +#!/bin/bash +# Fix MockAPI to use PORT from .env file dynamically +# This updates the systemd service to read HOST and PORT from .env at runtime + +set -e + +echo "=== Fix: Make MockAPI use PORT from .env dynamically ===" +echo + +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" +SERVICE_FILE="/etc/systemd/system/mockapi.service" +WRAPPER_SCRIPT="${APP_DIR}/start_mockapi.sh" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +print_status() { + echo -e "${GREEN}[+]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[!]${NC} $1" +} + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + print_error "This script requires sudo privileges." + print_warning "Run with: sudo bash $0" + exit 1 +fi + +# Step 1: Check if files exist +if [[ ! -f "$ENV_FILE" ]]; then + print_error ".env file not found: $ENV_FILE" + exit 1 +fi + +if [[ ! -f "$SERVICE_FILE" ]]; then + print_error "Service file not found: $SERVICE_FILE" + exit 1 +fi + +# Step 2: Ensure PORT exists in .env +print_status "Checking .env file for PORT variable..." +if ! grep -q "^PORT=" "$ENV_FILE"; then + print_warning "PORT not found in .env. Adding PORT=8000..." + echo "PORT=8000" >> "$ENV_FILE" + print_status "Added PORT=8000 to .env" +else + PORT_VALUE=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) + print_status "Found PORT in .env: $PORT_VALUE" + + # Validate PORT is numeric + if [[ ! "$PORT_VALUE" =~ ^[0-9]+$ ]]; then + print_error "PORT is not numeric: '$PORT_VALUE'. Fixing to 8000." + sed -i "s/^PORT=.*/PORT=8000/" "$ENV_FILE" + print_status "Updated PORT to 8000" + fi +fi + +# Step 3: Ensure HOST exists in .env +if ! grep -q "^HOST=" "$ENV_FILE"; then + print_warning "HOST not found in .env. Adding HOST=0.0.0.0..." + echo "HOST=0.0.0.0" >> "$ENV_FILE" +fi + +# Step 4: Ensure OAUTH2_ISSUER matches port +CURRENT_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) +EXPECTED_ISSUER="http://localhost:${CURRENT_PORT}" +if grep -q "^OAUTH2_ISSUER=" "$ENV_FILE"; then + CURRENT_ISSUER=$(grep "^OAUTH2_ISSUER=" "$ENV_FILE" | cut -d'=' -f2) + if [[ "$CURRENT_ISSUER" != "$EXPECTED_ISSUER" ]]; then + print_status "Updating OAUTH2_ISSUER to match port..." + sed -i "s|^OAUTH2_ISSUER=.*|OAUTH2_ISSUER=$EXPECTED_ISSUER|" "$ENV_FILE" + fi +else + print_warning "OAUTH2_ISSUER not found. Adding: $EXPECTED_ISSUER" + echo "OAUTH2_ISSUER=$EXPECTED_ISSUER" >> "$ENV_FILE" +fi + +# Step 5: Create wrapper script +print_status "Creating wrapper script: $WRAPPER_SCRIPT" +cat > "$WRAPPER_SCRIPT" << 'EOF' +#!/bin/bash +# Wrapper script to start MockAPI with environment variables from .env + +# Source the .env file +if [[ -f "/opt/mockapi/.env" ]]; then + set -a # Automatically export all variables + source "/opt/mockapi/.env" + set +a +else + echo "ERROR: .env file not found at /opt/mockapi/.env" >&2 + exit 1 +fi + +# Validate PORT is numeric +if ! [[ "$PORT" =~ ^[0-9]+$ ]]; then + echo "ERROR: PORT must be numeric, got: '$PORT'" >&2 + exit 1 +fi + +# Set defaults if not defined +HOST=${HOST:-0.0.0.0} +PORT=${PORT:-8000} + +# Debug info (only if DEBUG is true) +if [[ "${DEBUG:-false}" == "true" ]] || [[ "${DEBUG:-false}" == "True" ]]; then + echo "Starting MockAPI with HOST=$HOST, PORT=$PORT" + echo "Using virtual environment: /opt/mockapi/venv" +fi + +# Execute waitress with variables from .env +exec /opt/mockapi/venv/bin/waitress-serve --host="$HOST" --port="$PORT" wsgi:wsgi_app +EOF + +chmod +x "$WRAPPER_SCRIPT" +print_status "Wrapper script created and made executable" + +# Step 6: Backup current service file +print_status "Backing up current service file..." +BACKUP_FILE="${SERVICE_FILE}.backup.$(date +%s)" +cp "$SERVICE_FILE" "$BACKUP_FILE" +print_status "Backup created: $BACKUP_FILE" + +# Step 7: Extract current settings from service file +CURRENT_USER=$(grep "^User=" "$SERVICE_FILE" | cut -d'=' -f2) +CURRENT_GROUP=$(grep "^Group=" "$SERVICE_FILE" | cut -d'=' -f2) +CURRENT_VENV=$(grep 'Environment="PATH=' "$SERVICE_FILE" | cut -d'=' -f2 | cut -d':' -f1 | sed 's/"//g' || echo "/opt/mockapi/venv") + +print_status "Current service settings:" +print_status " User: $CURRENT_USER" +print_status " Group: $CURRENT_GROUP" +print_status " Venv: $CURRENT_VENV" + +# Step 8: Create updated service file using wrapper script +print_status "Updating service file to use wrapper script..." +cat > "$SERVICE_FILE" << EOF +[Unit] +Description=Mock API Service +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$CURRENT_USER +Group=$CURRENT_GROUP +WorkingDirectory=$APP_DIR +Environment="PATH=$CURRENT_VENV/bin" +Environment="PYTHONPATH=$APP_DIR" +EnvironmentFile=$APP_DIR/.env +# Use wrapper script that sources .env and expands variables +ExecStart=$WRAPPER_SCRIPT +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 to use wrapper script" + +# Step 9: Alternative approach - direct variable expansion (simpler) +print_status "Also creating alternative simpler fix..." +# Create a second service file alternative without wrapper script +ALT_SERVICE="${SERVICE_FILE}.alternative" + +cat > "$ALT_SERVICE" << 'EOF' +[Unit] +Description=Mock API Service (Alternative - direct expansion) +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$CURRENT_USER +Group=$CURRENT_GROUP +WorkingDirectory=$APP_DIR +Environment="PATH=$CURRENT_VENV/bin" +Environment="PYTHONPATH=$APP_DIR" +EnvironmentFile=$APP_DIR/.env +# Systemd expands variables from EnvironmentFile in ExecStart +ExecStart=$CURRENT_VENV/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 + +# Replace $CURRENT_USER, $CURRENT_GROUP, etc. in the alternative file +sed -i "s|\\\$CURRENT_USER|$CURRENT_USER|g" "$ALT_SERVICE" +sed -i "s|\\\$CURRENT_GROUP|$CURRENT_GROUP|g" "$ALT_SERVICE" +sed -i "s|\\\$APP_DIR|$APP_DIR|g" "$ALT_SERVICE" +sed -i "s|\\\$CURRENT_VENV|$CURRENT_VENV|g" "$ALT_SERVICE" + +print_status "Alternative service file created: $ALT_SERVICE" +print_status "Note: The alternative uses direct systemd variable expansion" +print_status " The main fix uses a wrapper script (more reliable)" + +# Step 10: Test which approach to use +print_status "Testing variable expansion..." +# Try the direct expansion approach first +print_status "Trying direct expansion approach first..." + +# Update service file to use direct expansion (cleaner) +cat > "$SERVICE_FILE" << EOF +[Unit] +Description=Mock API Service +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$CURRENT_USER +Group=$CURRENT_GROUP +WorkingDirectory=$APP_DIR +Environment="PATH=$CURRENT_VENV/bin" +Environment="PYTHONPATH=$APP_DIR" +EnvironmentFile=$APP_DIR/.env +# Systemd expands variables from EnvironmentFile in ExecStart +ExecStart=$CURRENT_VENV/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 "Updated service file with direct variable expansion" +print_warning "Note: Using escaped \$HOST and \$PORT to prevent HERE-doc expansion" +print_warning "Systemd should expand these from EnvironmentFile" + +# Step 11: Reload and restart +print_status "Reloading systemd daemon..." +systemctl daemon-reload + +print_status "Restarting MockAPI service..." +if systemctl restart mockapi; then + print_status "Service restart initiated..." + + sleep 3 + + if systemctl is-active --quiet mockapi; then + print_status "✓ Service is running!" + + # Test with current port + CURRENT_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) + print_status "Testing health endpoint on port $CURRENT_PORT..." + + if curl -f -s --max-time 10 http://localhost:$CURRENT_PORT/health > /dev/null 2>&1; then + print_status "✓ Health check passed!" + echo + echo "=== SUCCESS: MockAPI now uses PORT from .env dynamically ===" + echo + echo "You can now change the port by editing:" + echo " $ENV_FILE" + echo "And updating the PORT variable." + echo + echo "Then restart the service:" + echo " sudo systemctl restart mockapi" + echo + echo "Current configuration:" + echo " PORT: $CURRENT_PORT" + echo " Access: http://localhost:$CURRENT_PORT" + echo " Health: http://localhost:$CURRENT_PORT/health" + echo " Admin: http://localhost:$CURRENT_PORT/admin/login" + else + print_warning "Service running but health check failed." + print_warning "Checking service logs..." + journalctl -u mockapi -n 20 --no-pager + fi + else + print_error "Service failed to start with direct expansion." + print_status "Trying wrapper script approach..." + + # Use wrapper script approach + cat > "$SERVICE_FILE" << EOF +[Unit] +Description=Mock API Service +After=network.target +Wants=network.target + +[Service] +Type=simple +User=$CURRENT_USER +Group=$CURRENT_GROUP +WorkingDirectory=$APP_DIR +Environment="PATH=$CURRENT_VENV/bin" +EnvironmentFile=$APP_DIR/.env +# Use wrapper script +ExecStart=$WRAPPER_SCRIPT +Restart=always +RestartSec=10 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=mockapi + +[Install] +WantedBy=multi-user.target +EOF + + systemctl daemon-reload + systemctl restart mockapi + + sleep 3 + + if systemctl is-active --quiet mockapi; then + print_status "✓ Service running with wrapper script!" + else + print_error "Both approaches failed. Check logs:" + journalctl -u mockapi -n 30 --no-pager + print_status "Restoring backup..." + cp "$BACKUP_FILE" "$SERVICE_FILE" + systemctl daemon-reload + systemctl restart mockapi + fi + fi +else + print_error "Failed to restart service." + systemctl status mockapi --no-pager -l +fi + +echo +print_status "=== Fix completed ===" +echo "Backup files:" +echo " Service file: $BACKUP_FILE" +echo " Alternative: $ALT_SERVICE" +echo " Wrapper script: $WRAPPER_SCRIPT" +echo +echo "To change port:" +echo " 1. Edit $ENV_FILE and update PORT value" +echo " 2. Run: sudo systemctl restart mockapi" \ No newline at end of file diff --git a/fix_missing_port.sh b/fix_missing_port.sh new file mode 100644 index 0000000..1de0151 --- /dev/null +++ b/fix_missing_port.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Add missing PORT variable to .env file +# Run this if PORT is not defined in .env + +set -e + +echo "=== Fix Missing PORT in .env ===" +echo + +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" + +if [[ ! -f "$ENV_FILE" ]]; then + echo "ERROR: .env file not found: $ENV_FILE" + exit 1 +fi + +# Check if PORT exists +if grep -q "^PORT=" "$ENV_FILE"; then + CURRENT_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) + echo "PORT already exists in .env: $CURRENT_PORT" + + # Validate it's numeric + if [[ ! "$CURRENT_PORT" =~ ^[0-9]+$ ]]; then + echo "WARNING: PORT is not numeric: '$CURRENT_PORT'. Fixing to 8000." + sed -i "s/^PORT=.*/PORT=8000/" "$ENV_FILE" + echo "Updated PORT to 8000." + else + echo "PORT is valid numeric value." + fi +else + echo "PORT not found in .env. Adding PORT=8000..." + echo "PORT=8000" >> "$ENV_FILE" + echo "Added PORT=8000 to .env." +fi + +# Check if HOST exists +if ! grep -q "^HOST=" "$ENV_FILE"; then + echo "HOST not found in .env. Adding HOST=0.0.0.0..." + echo "HOST=0.0.0.0" >> "$ENV_FILE" +fi + +# Check if OAUTH2_ISSUER exists and matches port +CURRENT_PORT=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) +EXPECTED_ISSUER="http://localhost:${CURRENT_PORT}" + +if grep -q "^OAUTH2_ISSUER=" "$ENV_FILE"; then + CURRENT_ISSUER=$(grep "^OAUTH2_ISSUER=" "$ENV_FILE" | cut -d'=' -f2) + if [[ "$CURRENT_ISSUER" != "$EXPECTED_ISSUER" ]]; then + echo "Updating OAUTH2_ISSUER to match port..." + sed -i "s|^OAUTH2_ISSUER=.*|OAUTH2_ISSUER=$EXPECTED_ISSUER|" "$ENV_FILE" + echo "Updated OAUTH2_ISSUER to: $EXPECTED_ISSUER" + else + echo "OAUTH2_ISSUER already matches port." + fi +else + echo "OAUTH2_ISSUER not found. Adding: $EXPECTED_ISSUER" + echo "OAUTH2_ISSUER=$EXPECTED_ISSUER" >> "$ENV_FILE" +fi + +echo +echo "=== Updated .env file ===" +echo "Contents of $ENV_FILE:" +echo "------------------------" +grep -E "^(PORT|HOST|OAUTH2_ISSUER)=" "$ENV_FILE" +echo "------------------------" + +echo +echo "Note: After updating .env, you may need to:" +echo "1. Update service file with new port (if changed)" +echo "2. Run: sudo systemctl daemon-reload" +echo "3. Run: sudo systemctl restart mockapi" +echo +echo "Use 'sudo bash change_port.sh' to update both .env and service file." \ No newline at end of file diff --git a/fix_remove_backslashes.sh b/fix_remove_backslashes.sh new file mode 100644 index 0000000..e99648c --- /dev/null +++ b/fix_remove_backslashes.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# Simple fix: Remove backslashes from $HOST and $PORT in service file +# This allows systemd to expand variables from .env + +set -e + +echo "=== Fix: Remove backslashes from \$HOST and \$PORT in service file ===" +echo + +SERVICE_FILE="/etc/systemd/system/mockapi.service" +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + echo "ERROR: This script requires sudo privileges." + exit 1 +fi + +# Check if service file exists +if [[ ! -f "$SERVICE_FILE" ]]; then + echo "ERROR: Service file not found: $SERVICE_FILE" + exit 1 +fi + +echo "Current service file: $SERVICE_FILE" +echo + +# Backup +BACKUP="${SERVICE_FILE}.backup.$(date +%s)" +cp "$SERVICE_FILE" "$BACKUP" +echo "Backup created: $BACKUP" +echo + +# Check current ExecStart +echo "Current ExecStart line:" +grep "^ExecStart=" "$SERVICE_FILE" +echo + +# Check if we have escaped variables +if grep -q "\\\\\$HOST\|\\\\\$PORT" "$SERVICE_FILE"; then + echo "Found escaped variables (\\\$HOST and/or \\\$PORT). Removing backslashes..." + + # Remove backslashes before $HOST and $PORT + sed -i 's/--host=\\\$HOST/--host=$HOST/g' "$SERVICE_FILE" + sed -i 's/--port=\\\$PORT/--port=$PORT/g' "$SERVICE_FILE" + + echo "Backslashes removed." +else + echo "No escaped variables found. Checking for other patterns..." + + # Check if we have $HOST and $PORT without backslashes + if grep -q "--host=\$HOST --port=\$PORT" "$SERVICE_FILE"; then + echo "Already has unescaped \$HOST and \$PORT. Good." + elif grep -q "--host=[0-9]" "$SERVICE_FILE"; then + echo "Has hardcoded host/port. Need to replace with variables." + + # Extract current hardcoded values + CURRENT_LINE=$(grep "^ExecStart=" "$SERVICE_FILE") + HOST_VALUE=$(echo "$CURRENT_LINE" | sed -n 's/.*--host=\([^ ]*\).*/\1/p') + PORT_VALUE=$(echo "$CURRENT_LINE" | sed -n 's/.*--port=\([^ ]*\).*/\1/p') + + echo "Current hardcoded values: host=$HOST_VALUE, port=$PORT_VALUE" + + # Ensure .env has these values + if [[ ! -f "$ENV_FILE" ]]; then + echo "WARNING: .env file not found: $ENV_FILE" + else + # Update or add PORT in .env + if ! grep -q "^PORT=" "$ENV_FILE"; then + echo "PORT=$PORT_VALUE" >> "$ENV_FILE" + echo "Added PORT=$PORT_VALUE to .env" + fi + + # Update or add HOST in .env + if ! grep -q "^HOST=" "$ENV_FILE"; then + echo "HOST=$HOST_VALUE" >> "$ENV_FILE" + echo "Added HOST=$HOST_VALUE to .env" + fi + fi + + # Replace hardcoded values with variables + sed -i "s|--host=$HOST_VALUE --port=$PORT_VALUE|--host=\$HOST --port=\$PORT|" "$SERVICE_FILE" + echo "Replaced hardcoded values with variables." + else + echo "Unknown ExecStart format. Manual inspection needed." + fi +fi + +echo +echo "Updated ExecStart line:" +grep "^ExecStart=" "$SERVICE_FILE" +echo + +# Ensure PORT exists in .env +if [[ -f "$ENV_FILE" ]]; then + echo "Checking .env file..." + if ! grep -q "^PORT=" "$ENV_FILE"; then + echo "WARNING: PORT not found in .env. Adding PORT=8000..." + echo "PORT=8000" >> "$ENV_FILE" + fi + + if ! grep -q "^HOST=" "$ENV_FILE"; then + echo "WARNING: HOST not found in .env. Adding HOST=0.0.0.0..." + echo "HOST=0.0.0.0" >> "$ENV_FILE" + fi + + PORT_VALUE=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) + echo "Current PORT in .env: $PORT_VALUE" +else + echo "WARNING: .env file not found at $ENV_FILE" + echo "Creating basic .env file..." + cat > "$ENV_FILE" << EOF +PORT=8000 +HOST=0.0.0.0 +OAUTH2_ISSUER=http://localhost:8000 +EOF + chmod 600 "$ENV_FILE" + echo "Created .env file with default values" +fi + +# Reload systemd +echo +echo "Reloading systemd daemon..." +systemctl daemon-reload + +# Restart service +echo "Restarting MockAPI service..." +if systemctl restart mockapi; then + echo "Service restart initiated." + + sleep 3 + + if systemctl is-active --quiet mockapi; then + echo "SUCCESS: Service is running!" + + # Test health endpoint + PORT_VALUE=$(grep "^PORT=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2 || echo "8000") + echo + echo "Testing health endpoint on port $PORT_VALUE..." + if curl -f -s --max-time 10 http://localhost:$PORT_VALUE/health > /dev/null 2>&1; then + echo "✓ Health check passed!" + echo + echo "=== FIX SUCCESSFUL ===" + echo "MockAPI now uses PORT from .env file dynamically." + echo + echo "To change port:" + echo " 1. Edit $ENV_FILE" + echo " 2. Update the PORT value" + echo " 3. Run: sudo systemctl restart mockapi" + echo + echo "Current port: $PORT_VALUE" + echo "Access: http://localhost:$PORT_VALUE" + else + echo "WARNING: Service running but health check failed." + echo "Checking logs..." + journalctl -u mockapi -n 10 --no-pager + fi + else + echo "ERROR: Service failed to start after fix." + echo "Checking logs..." + journalctl -u mockapi -n 20 --no-pager + + # Try fallback: check if maybe we need different escaping + echo + echo "Trying alternative approach..." + # Check if the issue is with $HOST $PORT not being expanded + # Maybe systemd isn't expanding them. Let's check EnvironmentFile line + if ! grep -q "EnvironmentFile=" "$SERVICE_FILE"; then + echo "Adding EnvironmentFile directive..." + # Add EnvironmentFile after existing Environment lines + sed -i '/^Environment=.*/a EnvironmentFile='"$APP_DIR"'/.env' "$SERVICE_FILE" + systemctl daemon-reload + systemctl restart mockapi + fi + fi +else + echo "ERROR: Failed to restart service." + systemctl status mockapi --no-pager -l +fi + +echo +echo "=== Summary ===" +echo "Backup: $BACKUP" +echo "Service file updated to use \$HOST and \$PORT (no backslashes)" +echo "Systemd should now expand these from .env file at runtime" +echo +echo "If port changes don't work, check:" +echo " 1. .env file exists and is readable by service user" +echo " 2. PORT value in .env is numeric" +echo " 3. Service file has 'EnvironmentFile=$APP_DIR/.env' line" \ No newline at end of file diff --git a/fix_service_env_vars.sh b/fix_service_env_vars.sh new file mode 100644 index 0000000..669d37c --- /dev/null +++ b/fix_service_env_vars.sh @@ -0,0 +1,226 @@ +#!/bin/bash +# Simple fix: Update service file to use $HOST and $PORT from .env +# No wrapper script, just fix the variable expansion + +set -e + +echo "=== Fix: Update service to use \$HOST and \$PORT from .env ===" +echo + +APP_DIR="/opt/mockapi" +ENV_FILE="${APP_DIR}/.env" +SERVICE_FILE="/etc/systemd/system/mockapi.service" + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +print_status() { + echo -e "${GREEN}[+]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +print_error() { + echo -e "${RED}[!]${NC} $1" +} + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + print_error "This script requires sudo privileges." + exit 1 +fi + +# Step 1: Check files +if [[ ! -f "$ENV_FILE" ]]; then + print_error ".env file not found: $ENV_FILE" + exit 1 +fi + +if [[ ! -f "$SERVICE_FILE" ]]; then + print_error "Service file not found: $SERVICE_FILE" + exit 1 +fi + +# Step 2: Ensure PORT exists in .env +print_status "Checking .env file..." +if ! grep -q "^PORT=" "$ENV_FILE"; then + print_warning "PORT not found in .env. Adding PORT=8000..." + echo "PORT=8000" >> "$ENV_FILE" + print_status "Added PORT=8000" +fi + +if ! grep -q "^HOST=" "$ENV_FILE"; then + print_warning "HOST not found in .env. Adding HOST=0.0.0.0..." + echo "HOST=0.0.0.0" >> "$ENV_FILE" +fi + +# Validate PORT is numeric +PORT_VALUE=$(grep "^PORT=" "$ENV_FILE" | cut -d'=' -f2) +if [[ ! "$PORT_VALUE" =~ ^[0-9]+$ ]]; then + print_error "PORT is not numeric: '$PORT_VALUE'. Fixing to 8000." + sed -i "s/^PORT=.*/PORT=8000/" "$ENV_FILE" + PORT_VALUE="8000" +fi + +# Step 3: Backup service file +print_status "Backing up service file..." +BACKUP_FILE="${SERVICE_FILE}.backup.$(date +%s)" +cp "$SERVICE_FILE" "$BACKUP_FILE" +print_status "Backup created: $BACKUP_FILE" + +# Step 4: Check current ExecStart +print_status "Checking current ExecStart line..." +CURRENT_EXEC=$(grep "^ExecStart=" "$SERVICE_FILE") +echo "Current: $CURRENT_EXEC" + +# Step 5: Update ExecStart to use $HOST and $PORT +print_status "Updating ExecStart to use variables from .env..." +# We need to replace the ExecStart line with one that uses $HOST and $PORT +# But we need to be careful about escaping for sed + +# First, get the current venv path from the existing ExecStart or Environment line +VENV_PATH=$(grep 'Environment="PATH=' "$SERVICE_FILE" | cut -d'=' -f2 | cut -d':' -f1 | sed 's/"//g') +if [[ -z "$VENV_PATH" ]]; then + # Try to extract from ExecStart + VENV_PATH=$(echo "$CURRENT_EXEC" | sed -n "s|^ExecStart=\(.*\)/waitress-serve.*|\1|p") + if [[ -z "$VENV_PATH" ]]; then + VENV_PATH="/opt/mockapi/venv" + print_warning "Could not detect venv path, using default: $VENV_PATH" + fi +fi + +print_status "Detected venv path: $VENV_PATH" + +# Create a temporary file with the updated service configuration +TMP_FILE=$(mktemp) + +# Read the current service file and update ExecStart +while IFS= read -r line; do + if [[ "$line" =~ ^ExecStart= ]]; then + # Replace with new ExecStart using variables + echo "ExecStart=$VENV_PATH/bin/waitress-serve --host=\$HOST --port=\$PORT wsgi:wsgi_app" + print_status "Updated ExecStart line" + else + echo "$line" + fi +done < "$SERVICE_FILE" > "$TMP_FILE" + +# Replace the service file +mv "$TMP_FILE" "$SERVICE_FILE" + +# Step 6: Verify the change +print_status "Verifying update..." +UPDATED_EXEC=$(grep "^ExecStart=" "$SERVICE_FILE") +echo "Updated: $UPDATED_EXEC" + +# Check if we have the escaped \$HOST and \$PORT +if echo "$UPDATED_EXEC" | grep -q "\\\\\$HOST\|\\\\\$PORT"; then + print_warning "Found escaped variables (\\\$HOST/\\\$PORT). This might still cause issues." + print_status "Trying alternative: unescaped variables..." + + # Create alternative without backslashes + TMP_FILE2=$(mktemp) + while IFS= read -r line; do + if [[ "$line" =~ ^ExecStart= ]]; then + # Use unescaped variables + echo "ExecStart=$VENV_PATH/bin/waitress-serve --host=\$HOST --port=\$PORT wsgi:wsgi_app" + else + echo "$line" + fi + done < "$SERVICE_FILE" > "$TMP_FILE2" + + # The issue: $HOST and $PORT in the HERE-document above will expand + # We need to write literal $HOST and $PORT. Let's use sed instead. + sed -i 's/--host=\\\$HOST --port=\\\$PORT/--host=$HOST --port=$PORT/' "$TMP_FILE2" + mv "$TMP_FILE2" "$SERVICE_FILE" + + print_status "Updated with unescaped variables" +fi + +# Final check +FINAL_EXEC=$(grep "^ExecStart=" "$SERVICE_FILE") +echo "Final ExecStart: $FINAL_EXEC" + +# Step 7: Test if it looks correct +if echo "$FINAL_EXEC" | grep -q "--host=\$HOST --port=\$PORT"; then + print_status "✓ ExecStart looks correct (uses \$HOST and \$PORT)" +elif echo "$FINAL_EXEC" | grep -q "--host=\\\$HOST --port=\\\$PORT"; then + print_warning "ExecStart has escaped variables (\\\$HOST/\\\$PORT)" + print_warning "This might still cause the original error." +else + print_warning "ExecStart format unexpected: $FINAL_EXEC" +fi + +# Step 8: Reload and restart +print_status "Reloading systemd..." +systemctl daemon-reload + +print_status "Restarting service..." +if systemctl restart mockapi; then + print_status "Service restart initiated..." + + sleep 3 + + if systemctl is-active --quiet mockapi; then + print_status "✓ Service is running!" + + # Test health endpoint + print_status "Testing health endpoint on port $PORT_VALUE..." + if curl -f -s --max-time 10 http://localhost:$PORT_VALUE/health > /dev/null 2>&1; then + print_status "✓ Health check passed!" + echo + echo "=== SUCCESS ===" + echo "MockAPI service now uses PORT from .env file." + echo + echo "To change port:" + echo " 1. Edit $ENV_FILE" + echo " 2. Update the PORT value" + echo " 3. Run: sudo systemctl restart mockapi" + echo + echo "Current port: $PORT_VALUE" + echo "Access: http://localhost:$PORT_VALUE" + else + print_warning "Service running but health check failed." + journalctl -u mockapi -n 10 --no-pager + fi + else + print_error "Service failed to start." + echo "Checking logs..." + journalctl -u mockapi -n 20 --no-pager + + # Try one more approach: use a simple hardcoded port as fallback + print_status "Trying fallback: hardcoding port $PORT_VALUE..." + sed -i "s|--host=\$HOST --port=\$PORT|--host=0.0.0.0 --port=$PORT_VALUE|" "$SERVICE_FILE" + systemctl daemon-reload + systemctl restart mockapi + + sleep 3 + + if systemctl is-active --quiet mockapi; then + print_status "✓ Service running with hardcoded port $PORT_VALUE" + print_warning "Note: Port is now hardcoded. To change port, update service file." + else + print_error "All attempts failed. Restoring backup..." + cp "$BACKUP_FILE" "$SERVICE_FILE" + systemctl daemon-reload + systemctl restart mockapi + fi + fi +else + print_error "Failed to restart service." + systemctl status mockapi --no-pager -l +fi + +echo +print_status "=== Fix completed ===" +echo "Backup: $BACKUP_FILE" +echo "To manually change port in the future:" +echo " 1. Edit $ENV_FILE (update PORT)" +echo " 2. Edit $SERVICE_FILE (update --port value in ExecStart)" +echo " 3. sudo systemctl daemon-reload" +echo " 4. sudo systemctl restart mockapi" \ No newline at end of file diff --git a/install.sh b/install.sh index ce7305c..de7eff2 100644 --- a/install.sh +++ b/install.sh @@ -299,40 +299,14 @@ setup_systemd_service() { fi fi - # Read HOST and PORT from .env for service file - SERVICE_HOST="0.0.0.0" - SERVICE_PORT="8000" - - if [[ -f "${APP_DIR}/.env" ]]; then - # Read HOST from .env - if grep -q "^HOST=" "${APP_DIR}/.env"; then - SERVICE_HOST=$(grep "^HOST=" "${APP_DIR}/.env" | cut -d'=' -f2) - fi - - # Read PORT from .env (use current PORT variable as fallback) - if grep -q "^PORT=" "${APP_DIR}/.env"; then - SERVICE_PORT=$(grep "^PORT=" "${APP_DIR}/.env" | cut -d'=' -f2) - elif [[ -n "$PORT" ]]; then - SERVICE_PORT="$PORT" - fi - - # Validate PORT is numeric - if [[ ! "$SERVICE_PORT" =~ ^[0-9]+$ ]]; then - print_error "PORT in .env is not numeric: '$SERVICE_PORT'. Using 8000." - SERVICE_PORT="8000" - # Fix .env - sed -i "s/^PORT=.*/PORT=8000/" "${APP_DIR}/.env" - fi - else - SERVICE_PORT="$PORT" - fi - - print_status "Service will run on: $SERVICE_HOST:$SERVICE_PORT" - # Create systemd service file print_status "Creating systemd service file at $SERVICE_FILE..." - sudo tee "$SERVICE_FILE" > /dev/null << EOF + # Create service file with proper variable expansion + # We use a HEREDOC with single quotes to prevent expansion of $HOST and $PORT + # but we need to expand RUN_USER, APP_DIR, VENV_DIR. We'll use a template approach. + + sudo tee "$SERVICE_FILE" > /dev/null << 'SERVICE_TEMPLATE' [Unit] Description=Mock API Service After=network.target @@ -340,30 +314,37 @@ Wants=network.target [Service] Type=simple -User=$RUN_USER -Group=$RUN_USER -WorkingDirectory=$APP_DIR -Environment="PATH=$VENV_DIR/bin" -Environment="PYTHONPATH=$APP_DIR" -EnvironmentFile=$APP_DIR/.env -# Note: HOST and PORT are hardcoded from .env values at install time -# If you change PORT in .env, you must update this service file -ExecStart=$VENV_DIR/bin/waitress-serve --host=$SERVICE_HOST --port=$SERVICE_PORT wsgi:wsgi_app +User=RUN_USER_PLACEHOLDER +Group=RUN_USER_PLACEHOLDER +WorkingDirectory=APP_DIR_PLACEHOLDER +Environment="PATH=VENV_DIR_PLACEHOLDER/bin" +Environment="PYTHONPATH=APP_DIR_PLACEHOLDER" +EnvironmentFile=APP_DIR_PLACEHOLDER/.env +# HOST and PORT are read from .env file at runtime +ExecStart=VENV_DIR_PLACEHOLDER/bin/waitress-serve --host=$HOST --port=$PORT wsgi:wsgi_app Restart=always RestartSec=10 StandardOutput=syslog StandardError=syslog -SyslogIdentifier=$SERVICE_NAME +SyslogIdentifier=SERVICE_NAME_PLACEHOLDER # Security hardening NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict -ReadWritePaths=$APP_DIR +ReadWritePaths=APP_DIR_PLACEHOLDER [Install] WantedBy=multi-user.target -EOF +SERVICE_TEMPLATE + + # Replace placeholders with actual values + sudo sed -i "s|RUN_USER_PLACEHOLDER|$RUN_USER|g" "$SERVICE_FILE" + sudo sed -i "s|APP_DIR_PLACEHOLDER|$APP_DIR|g" "$SERVICE_FILE" + sudo sed -i "s|VENV_DIR_PLACEHOLDER|$VENV_DIR|g" "$SERVICE_FILE" + sudo sed -i "s|SERVICE_NAME_PLACEHOLDER|$SERVICE_NAME|g" "$SERVICE_FILE" + + print_status "Service file created with dynamic PORT from .env" print_status "Systemd service file created." @@ -524,6 +505,11 @@ show_summary() { print_info "To update configuration, edit $APP_DIR/.env and restart:" print_info " sudo systemctl restart $SERVICE_NAME" echo + print_info "To change port (e.g., from $PORT to 8080):" + print_info " 1. Edit $APP_DIR/.env (update PORT, OAUTH2_ISSUER)" + print_info " 2. Run: sudo systemctl restart $SERVICE_NAME" + print_info " The service automatically uses PORT from .env file" + echo } main() {