diff --git a/setup-sonarqube.sh b/setup-sonarqube.sh new file mode 100644 index 0000000..26ea5cb --- /dev/null +++ b/setup-sonarqube.sh @@ -0,0 +1,219 @@ +#!/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 "======================================================"