#!/bin/bash set -euo pipefail # ============================================================================= # SonarQube Community Edition Setup Script # Target: Debian 13 LXC container on Proxmox # Installs: PostgreSQL 17, Java 17, SonarQube 26.3.0 # ============================================================================= SONAR_VERSION="26.3.0.120487" SONAR_URL="https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONAR_VERSION}.zip" SONAR_HOME="/opt/sonarqube" SONAR_USER="sonar" DB_USER="sonarqube" DB_PASS="sq_$(head -c 16 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 20)" DB_NAME="sonarqube" ADMIN_PASS="CameleerSQ2026!" echo "==============================" echo " SonarQube Setup Starting" echo "==============================" echo "" # --- Step 1: Kernel parameters --- echo "[1/8] Configuring kernel parameters..." cat > /etc/sysctl.d/99-sonarqube.conf <<'SYSCTL' vm.max_map_count=524288 fs.file-max=131072 SYSCTL sysctl -p /etc/sysctl.d/99-sonarqube.conf cat > /etc/security/limits.d/99-sonarqube.conf <<'LIMITS' sonar - nofile 131072 sonar - nproc 8192 LIMITS # --- Step 2: Install packages --- echo "[2/8] Installing PostgreSQL and Java 17..." export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq postgresql openjdk-17-jre-headless unzip curl > /dev/null 2>&1 echo " PostgreSQL $(pg_config --version) installed" echo " Java $(java -version 2>&1 | head -1) installed" # --- Step 3: Configure PostgreSQL --- echo "[3/8] Configuring PostgreSQL database..." systemctl enable --now postgresql su - postgres -c "psql -c \"CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}';\"" 2>/dev/null || true su - postgres -c "psql -c \"CREATE DATABASE ${DB_NAME} OWNER ${DB_USER};\"" 2>/dev/null || true su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};\"" echo " Database '${DB_NAME}' ready" # --- Step 4: Create sonar user --- echo "[4/8] Creating sonar system user..." id ${SONAR_USER} &>/dev/null || useradd -r -m -d /home/${SONAR_USER} -s /bin/bash ${SONAR_USER} # --- Step 5: Download and install SonarQube --- echo "[5/8] Downloading SonarQube ${SONAR_VERSION} (~900MB, this may take a few minutes)..." cd /tmp if [ ! -f "sonarqube-${SONAR_VERSION}.zip" ]; then curl -# -L -o "sonarqube-${SONAR_VERSION}.zip" "${SONAR_URL}" fi echo " Extracting..." rm -rf /tmp/sonarqube-${SONAR_VERSION} unzip -q "sonarqube-${SONAR_VERSION}.zip" -d /tmp/ rm -rf ${SONAR_HOME} mv "/tmp/sonarqube-${SONAR_VERSION}" "${SONAR_HOME}" chown -R ${SONAR_USER}:${SONAR_USER} ${SONAR_HOME} # --- Step 6: Configure SonarQube --- echo "[6/8] Configuring SonarQube..." SONAR_CONF="${SONAR_HOME}/conf/sonar.properties" # Database sed -i 's|^#sonar.jdbc.username=.*|sonar.jdbc.username='"${DB_USER}"'|' "${SONAR_CONF}" sed -i 's|^#sonar.jdbc.password=.*|sonar.jdbc.password='"${DB_PASS}"'|' "${SONAR_CONF}" sed -i 's|^#sonar.jdbc.url=jdbc:postgresql.*|sonar.jdbc.url=jdbc:postgresql://localhost:5432/'"${DB_NAME}"'|' "${SONAR_CONF}" # Web server sed -i 's|^#sonar.web.host=.*|sonar.web.host=0.0.0.0|' "${SONAR_CONF}" sed -i 's|^#sonar.web.port=.*|sonar.web.port=9000|' "${SONAR_CONF}" # Elasticsearch (use temp dir inside sonar home) mkdir -p "${SONAR_HOME}/temp" chown -R ${SONAR_USER}:${SONAR_USER} "${SONAR_HOME}" # --- Step 7: Create systemd service --- echo "[7/8] Creating systemd service..." cat > /etc/systemd/system/sonarqube.service </dev/null | tr -d '{}' | tr ',' '\n' | grep '"status"' | cut -d'"' -f4 || echo "STARTING") if [ "${STATUS}" = "UP" ]; then break fi echo " ... ${STATUS} (attempt ${i}/60)" sleep 10 done STATUS=$(curl -sf "${SONAR_API}/system/status" 2>/dev/null | tr -d '{}' | tr ',' '\n' | grep '"status"' | cut -d'"' -f4 || echo "UNKNOWN") if [ "${STATUS}" != "UP" ]; then echo "ERROR: SonarQube did not start. Check: journalctl -u sonarqube" echo " Also check: ${SONAR_HOME}/logs/" exit 1 fi echo "" echo " SonarQube is UP!" echo "" # Change default admin password echo "Changing admin password..." curl -sf -u admin:admin -X POST "${SONAR_API}/users/change_password" \ -d "login=admin&previousPassword=admin&password=${ADMIN_PASS}" || echo " (password may already be changed)" # Create projects echo "Creating projects..." PROJECTS=("cameleer3:cameleer3:main" "cameleer3-server:cameleer3-server:main" "design-system:design-system:main" "cameleer-build-images:cameleer-build-images:main") for proj_info in "${PROJECTS[@]}"; do IFS=':' read -r key name branch <<< "${proj_info}" curl -sf -u admin:"${ADMIN_PASS}" -X POST "${SONAR_API}/projects/create" \ -d "project=${key}&name=${name}&mainBranch=${branch}" > /dev/null 2>&1 || true echo " Created project: ${name}" done # Generate a global analysis token echo "" echo "Generating analysis token..." TOKEN_RESPONSE=$(curl -sf -u admin:"${ADMIN_PASS}" -X POST "${SONAR_API}/user_tokens/generate" \ -d "name=cameleer-scanner&type=GLOBAL_ANALYSIS" 2>/dev/null || echo "") TOKEN=$(echo "${TOKEN_RESPONSE}" | tr ',' '\n' | grep '"token"' | cut -d'"' -f4) # Also enable SSH for future access echo "Enabling SSH root login..." sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config systemctl restart sshd 2>/dev/null || true # --- Done --- echo "" echo "======================================================" echo " SonarQube Setup Complete!" echo "======================================================" echo "" echo " URL: http://sonarqube.siegeln.internal:9000" echo " Admin user: admin" echo " Admin password: ${ADMIN_PASS}" echo "" echo " DB user: ${DB_USER}" echo " DB password: ${DB_PASS}" echo " DB name: ${DB_NAME}" echo "" if [ -n "${TOKEN}" ]; then echo " Scanner Token: ${TOKEN}" echo " (type: GLOBAL_ANALYSIS, name: cameleer-scanner)" fi echo "" echo " Projects created:" echo " - cameleer3 (Java)" echo " - cameleer3-server (Java)" echo " - design-system (TypeScript)" echo " - cameleer-build-images (Dockerfile)" echo "" echo " SSH root login has been enabled." echo "" echo "======================================================" echo "" echo " SCAN COMMANDS:" echo "" echo " Java (Maven) projects:" echo " mvn sonar:sonar \\" echo " -Dsonar.host.url=http://sonarqube.siegeln.internal:9000 \\" echo " -Dsonar.token=${TOKEN} \\" echo " -Dsonar.projectKey=" echo "" echo " TypeScript/JS projects:" echo " npx sonar-scanner \\" echo " -Dsonar.host.url=http://sonarqube.siegeln.internal:9000 \\" echo " -Dsonar.token=${TOKEN} \\" echo " -Dsonar.projectKey=design-system \\" echo " -Dsonar.sources=src" echo "" echo " Generic projects:" echo " npx sonar-scanner \\" echo " -Dsonar.host.url=http://sonarqube.siegeln.internal:9000 \\" echo " -Dsonar.token=${TOKEN} \\" echo " -Dsonar.projectKey=cameleer-build-images \\" echo " -Dsonar.sources=." echo "======================================================"