Registry: docker-compose.yml now pulls argus-api/argus-ui/argus-proxy from git-cloud.weboria.eu/weboria (Gitea's built-in container registry) instead of ghcr.io. Built and pushed real production images from main (v3.73.0) before switching — verified anonymous `docker pull` works for all three with zero login required, matching the public installer's no-friction promise. install.sh's registry comment updated to match; no more "gap." Licensing: reworked per a full commercial-distribution review. Removed MaxMind/GeoLite2 entirely (confirmed geoip2-golang isn't even in go.mod — GeoIP is RIR-based, not MaxMind-based, and has been for a while). Clarified TimescaleDB's licensing story (embedded component distributed as part of the appliance, not a hosted DB service) rather than leaving it under a vague "reviewed before bundling" note. Added missing real dependencies grounded against the actual Dockerfiles (Alpine Linux, PostgreSQL, Go runtime, Node.js build-time-only, OpenSSL, curl, BusyBox). Renamed THIRD_PARTY_LICENSES -> THIRD_PARTY_LICENSES.md, added a "Weboria Proprietary Components" section. Removed the "pending legal review" section that was specifically about MaxMind/TimescaleDB, now resolved by the above -- LICENSE's own placeholder-pending-final-terms disclaimer stays, since drafting real commercial license text is separate legal work, not something to paper over. README: removed the internal "this repo contains no proprietary code" meta-description (customers don't need to see project scaffolding notes) and the "known gap" callout (both gaps closed above). Expanded the feature list with a dedicated ANIS Threat Intelligence section and richer detail on DNS Security, Bot/AI-crawler defense, and the Guided Security Policy Center. Stronger positioning copy up top.
165 lines
8.0 KiB
Bash
Executable File
165 lines
8.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# ARGUS Enterprise Web Security Platform — installer. Fetches the production
|
|
# compose stack, generates secrets, starts the platform, and prints your
|
|
# admin credentials.
|
|
#
|
|
# curl -fsSL https://git-cloud.weboria.eu/weboria/argus-installer/raw/branch/main/install.sh | bash
|
|
#
|
|
set -euo pipefail
|
|
|
|
REPO_RAW_BASE="https://git-cloud.weboria.eu/weboria/argus-installer/raw/branch/main"
|
|
INSTALL_DIR="${ARGUS_INSTALL_DIR:-/opt/argus}"
|
|
NETWORK_NAME="argus-network"
|
|
# Production images are pulled from Weboria's own registry, built into
|
|
# git-cloud.weboria.eu (Gitea's container registry) — docker-compose.yml's
|
|
# image: lines reference git-cloud.weboria.eu/weboria/argus-{api,ui,proxy}
|
|
# directly. Anonymous docker pull works with no login required.
|
|
|
|
# ── Output helpers ────────────────────────────────────────────────────────────
|
|
bold() { printf '\033[1m%s\033[0m\n' "$1"; }
|
|
info() { printf ' %s\n' "$1"; }
|
|
ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; }
|
|
warn() { printf ' \033[33m!\033[0m %s\n' "$1"; }
|
|
fail() { printf ' \033[31m✗\033[0m %s\n' "$1" >&2; exit 1; }
|
|
|
|
bold "ARGUS Installer"
|
|
echo
|
|
|
|
# ── 1. OS detection (informational — Linux is the supported target) ──────────
|
|
OS="$(uname -s)"
|
|
case "$OS" in
|
|
Linux) ok "Detected Linux" ;;
|
|
Darwin) warn "Detected macOS — supported for local evaluation via Docker Desktop, not for production deployment." ;;
|
|
*) warn "Unrecognized OS ($OS) — proceeding, but only Linux is officially supported." ;;
|
|
esac
|
|
|
|
# ── 2. Docker / Compose availability ──────────────────────────────────────────
|
|
command -v docker >/dev/null 2>&1 || fail "Docker is not installed. Install Docker first: https://docs.docker.com/engine/install/"
|
|
docker info >/dev/null 2>&1 || fail "Docker is installed but not running (or this user lacks permission). Start Docker / add your user to the docker group, then re-run."
|
|
docker compose version >/dev/null 2>&1 || fail "Docker Compose v2 (the 'docker compose' plugin) is required. See https://docs.docker.com/compose/install/"
|
|
ok "Docker and Docker Compose are available"
|
|
|
|
# ── 3. Fetch deployment files ──────────────────────────────────────────────────
|
|
mkdir -p "$INSTALL_DIR/docker-socket-proxy"
|
|
cd "$INSTALL_DIR"
|
|
|
|
fetch() {
|
|
curl -fsSL "$REPO_RAW_BASE/$1" -o "$2" || fail "Failed to download $1"
|
|
}
|
|
|
|
fetch "docker-compose.yml" "docker-compose.yml"
|
|
fetch "docker-socket-proxy/haproxy.cfg.template" "docker-socket-proxy/haproxy.cfg.template"
|
|
for script in update.sh uninstall.sh healthcheck.sh backup.sh restore.sh; do
|
|
fetch "$script" "$script"
|
|
chmod +x "$script"
|
|
done
|
|
if [ ! -f .env ]; then
|
|
fetch ".env.example" ".env"
|
|
ok "Fetched deployment files into $INSTALL_DIR"
|
|
else
|
|
ok "Fetched compose file (kept your existing .env)"
|
|
fi
|
|
|
|
# ── 4. Generate secrets (first install only — never overwrite an existing .env) ──
|
|
if grep -q '^DB_PASSWORD=change-me-in-production' .env 2>/dev/null; then
|
|
DB_PASSWORD="$(openssl rand -base64 24 | tr -d '\n')"
|
|
sed -i.bak "s#^DB_PASSWORD=.*#DB_PASSWORD=${DB_PASSWORD}#" .env && rm -f .env.bak
|
|
ok "Generated a secure database password"
|
|
fi
|
|
|
|
# ── 5. Docker network ─────────────────────────────────────────────────────────
|
|
if docker network inspect "$NETWORK_NAME" >/dev/null 2>&1; then
|
|
ok "Docker network '$NETWORK_NAME' already exists"
|
|
else
|
|
docker network create "$NETWORK_NAME" >/dev/null
|
|
ok "Created Docker network '$NETWORK_NAME'"
|
|
fi
|
|
|
|
# ── 6. Pull and start ──────────────────────────────────────────────────────────
|
|
bold "Pulling images and starting ARGUS..."
|
|
docker compose pull
|
|
docker compose up -d
|
|
echo
|
|
|
|
# ── 7. Wait for the API to become healthy ─────────────────────────────────────
|
|
API_HOST_PORT="$(grep -oP '^API_HOST_PORT=\K.*' .env 2>/dev/null || true)"
|
|
API_HOST_PORT="${API_HOST_PORT:-9080}"
|
|
bold "Waiting for ARGUS to finish starting (this can take a few minutes on first boot)..."
|
|
READY=false
|
|
for _ in $(seq 1 90); do
|
|
if curl -fsS "http://127.0.0.1:${API_HOST_PORT}/health" >/dev/null 2>&1; then
|
|
READY=true
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
if [ "$READY" != "true" ]; then
|
|
warn "ARGUS did not report healthy within 7.5 minutes."
|
|
warn "Check container status with: docker compose -f $INSTALL_DIR/docker-compose.yml ps"
|
|
warn "and logs with: docker compose -f $INSTALL_DIR/docker-compose.yml logs api"
|
|
exit 1
|
|
fi
|
|
ok "ARGUS is up"
|
|
|
|
# ── 8. Rotate the default admin credentials ───────────────────────────────────
|
|
ADMIN_USER="admin"
|
|
ADMIN_PASSWORD="Ax9!$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 20)"
|
|
API_BASE="http://127.0.0.1:${API_HOST_PORT}/api/v1"
|
|
|
|
LOGIN_RESP="$(curl -fsS -X POST "${API_BASE}/auth/login" \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"username":"admin","password":"admin"}' 2>/dev/null || true)"
|
|
TOKEN="$(printf '%s' "${LOGIN_RESP}" | grep -oP '"token"\s*:\s*"\K[^"]+' || true)"
|
|
|
|
CREDS_ROTATED=false
|
|
if [ -n "$TOKEN" ]; then
|
|
CHANGE_RESP="$(curl -fsS -o /dev/null -w '%{http_code}' -X POST "${API_BASE}/auth/change-credentials" \
|
|
-H 'Content-Type: application/json' \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
-d "{\"current_password\":\"admin\",\"new_username\":\"${ADMIN_USER}\",\"new_password\":\"${ADMIN_PASSWORD}\",\"new_password_confirm\":\"${ADMIN_PASSWORD}\"}" 2>/dev/null || echo "000")"
|
|
if [ "$CHANGE_RESP" = "200" ]; then
|
|
CREDS_ROTATED=true
|
|
ok "Rotated the default admin password"
|
|
fi
|
|
fi
|
|
if [ "$CREDS_ROTATED" != "true" ]; then
|
|
warn "Could not auto-rotate admin credentials (already changed on a prior run?). Log in with your existing credentials, or admin/admin on a genuinely fresh install."
|
|
fi
|
|
|
|
# ── 9. Summary ─────────────────────────────────────────────────────────────────
|
|
UI_PORT="$(grep -oP '^UI_PORT=\K.*' .env 2>/dev/null || true)"
|
|
UI_PORT="${UI_PORT:-81}"
|
|
|
|
echo
|
|
bold "ARGUS Enterprise Web Security Platform has been successfully installed."
|
|
echo
|
|
info "Access URL: https://$(hostname -I 2>/dev/null | awk '{print $1}' || echo localhost):${UI_PORT} (accept the self-signed certificate)"
|
|
if [ "$CREDS_ROTATED" = "true" ]; then
|
|
info "Username: ${ADMIN_USER}"
|
|
info "Password: ${ADMIN_PASSWORD}"
|
|
warn "Save this password now — it is not stored anywhere and cannot be recovered."
|
|
else
|
|
info "Log in with your existing admin credentials."
|
|
fi
|
|
echo
|
|
bold "Next steps:"
|
|
info "1. Open the administration panel at the Access URL above."
|
|
if [ "$CREDS_ROTATED" != "true" ]; then
|
|
info "2. Complete the first-run setup wizard (regional settings, guided protection checklist)."
|
|
info "3. Change the initial administrator password if you haven't already."
|
|
else
|
|
info "2. Complete the first-run setup wizard — regional settings and a guided review of every"
|
|
info " protection module (your admin password was already rotated above)."
|
|
fi
|
|
info "4. Configure domains and reverse proxy hosts under Proxy Hosts."
|
|
info "5. Review the ANIS threat intelligence connection under Threat Intel — enabled by"
|
|
info " default against the public Community Edition hub, no license key required."
|
|
info "6. Review security policies in the Security Policy Center."
|
|
echo
|
|
info "Configuration: ${INSTALL_DIR}/.env and ${INSTALL_DIR}/docker-compose.yml"
|
|
info "Upgrade: cd ${INSTALL_DIR} && docker compose pull && docker compose up -d"
|
|
info "Backup: cd ${INSTALL_DIR} && ./backup.sh"
|
|
info "Docs/support: see README.md in this directory"
|
|
echo
|