220 lines
7.6 KiB
Bash
220 lines
7.6 KiB
Bash
|
|
#!/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 <<EOF
|
||
|
|
[Unit]
|
||
|
|
Description=SonarQube
|
||
|
|
After=network.target postgresql.service
|
||
|
|
Requires=postgresql.service
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
Type=forking
|
||
|
|
User=${SONAR_USER}
|
||
|
|
Group=${SONAR_USER}
|
||
|
|
ExecStart=${SONAR_HOME}/bin/linux-x86-64/sonar.sh start
|
||
|
|
ExecStop=${SONAR_HOME}/bin/linux-x86-64/sonar.sh stop
|
||
|
|
LimitNOFILE=131072
|
||
|
|
LimitNPROC=8192
|
||
|
|
Restart=on-failure
|
||
|
|
RestartSec=10
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=multi-user.target
|
||
|
|
EOF
|
||
|
|
|
||
|
|
systemctl daemon-reload
|
||
|
|
systemctl enable sonarqube
|
||
|
|
systemctl start sonarqube
|
||
|
|
|
||
|
|
# --- Step 8: Wait for SonarQube and configure projects ---
|
||
|
|
echo "[8/8] Waiting for SonarQube to start (this can take 2-5 minutes)..."
|
||
|
|
SONAR_API="http://localhost:9000/api"
|
||
|
|
|
||
|
|
for i in $(seq 1 60); do
|
||
|
|
STATUS=$(curl -sf "${SONAR_API}/system/status" 2>/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=<cameleer3|cameleer3-server>"
|
||
|
|
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 "======================================================"
|