From b5d2ddf23ba96c9db1dec28420f1e48190aaf9a4 Mon Sep 17 00:00:00 2001 From: elAgala Date: Sun, 17 Aug 2025 05:32:26 -0300 Subject: [PATCH] refactor: read templates from local files --- CLAUDE.md | 94 +++++++++++++++++++ Dockerfile | 7 ++ Makefile | 17 ++++ images/caddy_full/Dockerfile | 4 +- index.sh | 6 +- monitoring/install_prometheus.sh | 33 ------- {docker => src/docker}/create_networks.sh | 0 {docker => src/docker}/install_docker.sh | 0 install.sh => src/install.sh | 30 ++++-- src/monitoring/install_prometheus.sh | 39 ++++++++ {user => src/user}/create_deploy_user.sh | 0 {user => src/user}/create_user.sh | 0 {user => src/user}/ssh_config.sh | 0 {utils => src/utils}/install_make.sh | 0 {utils => src/utils}/install_vim.sh | 0 {utils => src/utils}/install_zsh.sh | 0 src/web/install_caddy.sh | 107 ++++++++++++++++++++++ {web => src/web}/setup_ufw.sh | 0 web/install_caddy.sh | 96 ------------------- 19 files changed, 289 insertions(+), 144 deletions(-) create mode 100644 CLAUDE.md create mode 100644 Dockerfile delete mode 100644 monitoring/install_prometheus.sh rename {docker => src/docker}/create_networks.sh (100%) rename {docker => src/docker}/install_docker.sh (100%) rename install.sh => src/install.sh (57%) mode change 100644 => 100755 create mode 100644 src/monitoring/install_prometheus.sh rename {user => src/user}/create_deploy_user.sh (100%) rename {user => src/user}/create_user.sh (100%) rename {user => src/user}/ssh_config.sh (100%) rename {utils => src/utils}/install_make.sh (100%) rename {utils => src/utils}/install_vim.sh (100%) rename {utils => src/utils}/install_zsh.sh (100%) create mode 100644 src/web/install_caddy.sh rename {web => src/web}/setup_ufw.sh (100%) delete mode 100644 web/install_caddy.sh diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..213ba4f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,94 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Server-initializer is a Docker-based server setup automation tool that provisions Ubuntu/Debian servers with a complete web infrastructure stack including: +- Caddy web server with WAF (Coraza) and CrowdSec protection +- Prometheus, Loki, Grafana monitoring stack +- User management and SSH configuration +- Docker containers with proper networking + +## Common Commands + +### Development and Testing +```bash +# Build and test setup script in development mode +make dev + +# Build and keep container alive for testing +make dev-keep-alive + +# Build Docker test container +make build + +# Clean up test containers and images +make clean + +# Build custom Caddy image with WAF and CrowdSec +make build-caddy +``` + +### Caddy Management (from deployed server) +```bash +# Restart Caddy with config reload +make caddy:restart + +# Generate new CrowdSec API key +make caddy:crowdsec-key + +# Generate password hash for authentication +make caddy:generate-password + +# View Caddy logs +make caddy:logs +``` + +## Architecture + +### Entry Points +- `index.sh` - Main entry point that clones repo and runs `install.sh` +- `install.sh` - Master installer that orchestrates all component installations + +### Component Structure +- `user/` - User creation, SSH configuration, deploy user setup +- `web/` - Caddy installation and UFW firewall setup +- `docker/` - Docker installation and network creation +- `monitoring/` - Prometheus stack setup +- `utils/` - System utilities (vim, zsh, make) +- `templates/` - Configuration templates for services + +### Docker Networks +The system creates two external networks: +- `caddy_net` - For web services +- `monitoring_net` - For monitoring stack + +### Templates Directory +- `templates/caddy/full/` - Complete Caddy setup with WAF, CrowdSec, and authentication +- `templates/monitoring/` - Prometheus, Loki, Grafana, Node Exporter, cAdvisor stack +- `templates/nginx-certbot/` - Alternative nginx setup + +### Key Files +- `templates/caddy/full/docker-compose.yml` - Main Caddy service definition +- `templates/monitoring/docker-compose.yml` - Monitoring stack services +- `web/install_caddy.sh:33` - Caddy installation with password setup +- `monitoring/install_prometheus.sh:25` - Monitoring stack deployment + +## Installation Flow + +1. Server update and package installation +2. Docker installation and network creation +3. Caddy installation with security features +4. User and SSH configuration +5. Monitoring stack deployment +6. System utilities installation + +The installer prompts for Prometheus and Loki passwords during setup, which are encrypted using Caddy's hash-password function. + +## Custom Caddy Image + +The project builds a custom Caddy image (`ghcr.io/elagala/server-initializer/caddy-waf-crowdsec:latest`) that includes: +- Coraza WAF module +- CrowdSec bouncer integration +- Basic authentication support \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..724dbe4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM ubuntu:22.04 + +RUN apt-get update && apt-get install -y sudo + +COPY . /server-initializer + +CMD ["/bin/bash"] diff --git a/Makefile b/Makefile index dd3b5b9..aa1ecc3 100644 --- a/Makefile +++ b/Makefile @@ -2,3 +2,20 @@ build-caddy: @echo "Building Caddy FULL image" docker build -t ghcr.io/elagala/server-initializer/caddy-waf-crowdsec:latest -f images/caddy_full/Dockerfile . docker push ghcr.io/elagala/server-initializer/caddy-waf-crowdsec:latest + +dev: clean build + echo "Running container and testing install script..." + docker run -it --rm server-initializer /bin/bash -c "cd /server-initializer/src && ./install.sh agala --development" + +dev-keep-alive: clean build + echo "Running install script and keeping container alive for testing..." + docker run -it --name server-initializer-test server-initializer /bin/bash -c "cd /server-initializer/src && ./install.sh agala --development && echo 'Setup complete! Starting interactive shell...' && exec /bin/bash" + +build: + echo "Building Ubuntu test container..." + docker build -t server-initializer . + +clean: + echo "Cleaning up containers and images..." + docker rm -f server-initializer-test 2>/dev/null || true + docker rmi server-initializer 2>/dev/null || true diff --git a/images/caddy_full/Dockerfile b/images/caddy_full/Dockerfile index b70592a..2483d1a 100644 --- a/images/caddy_full/Dockerfile +++ b/images/caddy_full/Dockerfile @@ -1,5 +1,5 @@ # Build stage with xcaddy -FROM caddy:builder AS builder +FROM caddy:2.10.0-builder AS builder # Install xcaddy and build Caddy with plugins RUN xcaddy build \ @@ -15,7 +15,7 @@ RUN apk add --no-cache git && \ mv /coreruleset/crs-setup.conf.example /coreruleset/crs-setup.conf # Final stage -FROM caddy:latest +FROM caddy:2.10.0 # Copy custom Caddy binary COPY --from=builder /usr/bin/caddy /usr/bin/caddy diff --git a/index.sh b/index.sh index 325a255..887201b 100644 --- a/index.sh +++ b/index.sh @@ -13,13 +13,9 @@ if [ ! -d "$TARGET_DIR" ]; then git clone "$REPO_URL" "$TARGET_DIR" fi -cd "$TARGET_DIR" || exit 1 +cd "$TARGET_DIR/src" || exit 1 echo "[ INITIALIZER ]: Starting initialization" -echo "[ INITIALIZER ]: Updating server" -sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade -y && sudo apt autoremove -y - -echo "[ INITIALIZER ]: Server updated. Starting set up" chmod +x ./install.sh ./install.sh "$1" diff --git a/monitoring/install_prometheus.sh b/monitoring/install_prometheus.sh deleted file mode 100644 index 5c581cc..0000000 --- a/monitoring/install_prometheus.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -function install_prometheus() { - REPO_URL="https://raw.githubusercontent.com/elAgala/server-initializer/master" - TEMPLATE_PATH="/templates/monitoring" - username="$1" - monitoring_dir="/home/$username/monitoring" - - echo "[ MONITOR ]: Starting monitoring setup" - mkdir -p "$monitoring_dir" - mkdir -p "$monitoring_dir/loki" - mkdir -p "$monitoring_dir/promtail" - - # Download main monitoring files - wget "$REPO_URL/$TEMPLATE_PATH/docker-compose.yml" -O "$monitoring_dir/docker-compose.yml" - wget "$REPO_URL/$TEMPLATE_PATH/prometheus.yml" -O "$monitoring_dir/prometheus.yml" - - # Download Loki configuration - wget "$REPO_URL/$TEMPLATE_PATH/loki/loki.yml" -O "$monitoring_dir/loki/loki.yml" - - # Download Promtail configuration - wget "$REPO_URL/$TEMPLATE_PATH/promtail/promtail.yml" -O "$monitoring_dir/promtail/promtail.yml" - - cd "$monitoring_dir" - echo "[ MONITOR ]: Monitoring stack installed. Starting containers" - sudo docker compose up -d - echo "[ MONITOR ]: Monitoring stack running:" - echo " - Prometheus: http://localhost:9090 (internal)" - echo " - Prometheus API: https://YOUR_SERVER_IP/prometheus/ (external)" - echo " - Loki: http://localhost:3100 (internal)" - echo " - Node Exporter: http://localhost:9100 (internal)" - echo " - cAdvisor: http://localhost:8080 (internal)" -} diff --git a/docker/create_networks.sh b/src/docker/create_networks.sh similarity index 100% rename from docker/create_networks.sh rename to src/docker/create_networks.sh diff --git a/docker/install_docker.sh b/src/docker/install_docker.sh similarity index 100% rename from docker/install_docker.sh rename to src/docker/install_docker.sh diff --git a/install.sh b/src/install.sh old mode 100644 new mode 100755 similarity index 57% rename from install.sh rename to src/install.sh index c9e11c3..550d8af --- a/install.sh +++ b/src/install.sh @@ -1,5 +1,9 @@ #!/bin/bash +echo "[ INSTALL ]: Updating server packages" +sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade -y && sudo apt autoremove -y +echo "[ INSTALL ]: Server updated. Starting component installation" + source ./user/create_user.sh source ./user/create_deploy_user.sh source ./user/ssh_config.sh @@ -21,17 +25,19 @@ chmod +x ./utils/install_zsh.sh chmod +x ./monitoring/install_prometheus.sh if [ -z "$1" ]; then - echo "Usage: $0 " + echo "Usage: $0 [--development]" exit 1 fi -# Docker -install_docker -create_networks +# Check for development flag +DEVELOPMENT_MODE=false +if [ "$2" = "--development" ]; then + DEVELOPMENT_MODE=true + echo "[ INSTALL ]: Running in development mode - Docker operations will be skipped" +fi -# Web -install_caddy $1 -setup_ufw +# Get the repository directory (parent of src/) +REPO_DIR="$(dirname "$PWD")" # User create_user $1 @@ -41,10 +47,18 @@ config_ssh $1 create_deploy_user config_ssh "deploy" +# Docker +install_docker +create_networks + +# Web +install_caddy $1 "$REPO_DIR" "$DEVELOPMENT_MODE" +setup_ufw + # Utils install_vim install_zsh $1 install_make # Monitoring -install_prometheus $1 +install_prometheus $1 "$REPO_DIR" "$DEVELOPMENT_MODE" diff --git a/src/monitoring/install_prometheus.sh b/src/monitoring/install_prometheus.sh new file mode 100644 index 0000000..73ab9ad --- /dev/null +++ b/src/monitoring/install_prometheus.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +function install_prometheus() { + username="$1" + repo_dir="$2" + development_mode="$3" + template_path="$repo_dir/templates/monitoring" + monitoring_dir="/home/$username/monitoring" + + echo "[ MONITOR ]: Starting monitoring setup" + mkdir -p "$monitoring_dir" + mkdir -p "$monitoring_dir/loki" + mkdir -p "$monitoring_dir/promtail" + + # Copy main monitoring files from local repo + cp "$template_path/docker-compose.yml" "$monitoring_dir/docker-compose.yml" + cp "$template_path/prometheus.yml" "$monitoring_dir/prometheus.yml" + + # Copy Loki configuration + cp "$template_path/loki/loki.yml" "$monitoring_dir/loki/loki.yml" + + # Copy Promtail configuration + cp "$template_path/promtail/promtail.yml" "$monitoring_dir/promtail/promtail.yml" + + cd "$monitoring_dir" + if [ "$development_mode" = "true" ]; then + echo "[ MONITOR ]: Development mode - skipping Docker operations" + echo "[ MONITOR ]: Monitoring stack files copied successfully" + else + echo "[ MONITOR ]: Monitoring stack installed. Starting containers" + sudo docker compose up -d + echo "[ MONITOR ]: Monitoring stack running:" + echo " - Prometheus: http://localhost:9090 (internal)" + echo " - Prometheus API: https://YOUR_SERVER_IP/prometheus/ (external)" + echo " - Loki: http://localhost:3100 (internal)" + echo " - Node Exporter: http://localhost:9100 (internal)" + echo " - cAdvisor: http://localhost:8080 (internal)" + fi +} diff --git a/user/create_deploy_user.sh b/src/user/create_deploy_user.sh similarity index 100% rename from user/create_deploy_user.sh rename to src/user/create_deploy_user.sh diff --git a/user/create_user.sh b/src/user/create_user.sh similarity index 100% rename from user/create_user.sh rename to src/user/create_user.sh diff --git a/user/ssh_config.sh b/src/user/ssh_config.sh similarity index 100% rename from user/ssh_config.sh rename to src/user/ssh_config.sh diff --git a/utils/install_make.sh b/src/utils/install_make.sh similarity index 100% rename from utils/install_make.sh rename to src/utils/install_make.sh diff --git a/utils/install_vim.sh b/src/utils/install_vim.sh similarity index 100% rename from utils/install_vim.sh rename to src/utils/install_vim.sh diff --git a/utils/install_zsh.sh b/src/utils/install_zsh.sh similarity index 100% rename from utils/install_zsh.sh rename to src/utils/install_zsh.sh diff --git a/src/web/install_caddy.sh b/src/web/install_caddy.sh new file mode 100644 index 0000000..df2e43e --- /dev/null +++ b/src/web/install_caddy.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +function install_caddy() { + + username="$1" + repo_dir="$2" + development_mode="$3" + template_path="$repo_dir/templates/caddy/full" + caddy_dir="/home/$username/web-server" + + echo "[ WEB ]: Starting Caddy setup" + mkdir -p "$caddy_dir" + mkdir -p "$caddy_dir/crowdsec" + mkdir -p "$caddy_dir/caddy" + mkdir -p "$caddy_dir/caddy/coraza" + mkdir -p "$caddy_dir/caddy/sites-enabled" + + chown -R "$username:$username" "$caddy_dir" + + # Copy configuration files from local repo + cp "$template_path/docker-compose.yml" "$caddy_dir/docker-compose.yml" + cp "$template_path/Makefile" "$caddy_dir/Makefile" + cp "$template_path/caddy/Caddyfile" "$caddy_dir/caddy/Caddyfile" + cp "$template_path/caddy/coraza/coraza.conf" "$caddy_dir/caddy/coraza/coraza.conf" + cp "$template_path/crowdsec/acquis.yaml" "$caddy_dir/crowdsec/acquis.yaml" + cp "$template_path/caddy/sites-enabled/prometheus.Caddyfile" "$caddy_dir/caddy/sites-enabled/prometheus.Caddyfile" + cp "$template_path/caddy/sites-enabled/examples.Caddyfile" "$caddy_dir/caddy/sites-enabled/examples.Caddyfile" + + if [ "$development_mode" = "true" ]; then + echo "[ WEB ]: Development mode - skipping Docker operations" + echo "[ WEB ]: Creating placeholder .env file..." + cd "$caddy_dir" + cat >"$caddy_dir/.env" <"$caddy_dir/.env" </dev/null 2>&1; then + echo "[ WEB ]: CrowdSec is ready!" + break + fi + echo "[ WEB ]: Waiting for CrowdSec... ($i/30)" + sleep 2 + done + + # Check if CrowdSec is ready + if ! sudo docker exec crowdsec cscli version >/dev/null 2>&1; then + echo "[ WEB ]: ERROR: CrowdSec failed to start properly. Check logs with: docker compose logs crowdsec" + return 1 + fi + + # Generate CrowdSec API key + echo "[ WEB ]: Generating CrowdSec API key..." + CROWDSEC_API_KEY=$(sudo docker exec crowdsec cscli bouncers add caddy-bouncer -o raw) + + # Encrypt passwords using Caddy + echo "[ WEB ]: Encrypting Prometheus password..." + PROMETHEUS_PASSWORD=$(sudo docker exec caddy caddy hash-password --plaintext "$prometheus_plain_password") + echo "[ WEB ]: Encrypting Loki password..." + LOKI_PASSWORD=$(sudo docker exec caddy caddy hash-password --plaintext "$loki_plain_password") + + # Update .env file with real API key and encrypted passwords + cat >"$caddy_dir/.env" < "$caddy_dir/.env" </dev/null 2>&1; then - echo "[ WEB ]: CrowdSec is ready!" - break - fi - echo "[ WEB ]: Waiting for CrowdSec... ($i/30)" - sleep 2 - done - - # Check if CrowdSec is ready - if ! sudo docker exec crowdsec cscli version >/dev/null 2>&1; then - echo "[ WEB ]: ERROR: CrowdSec failed to start properly. Check logs with: docker compose logs crowdsec" - return 1 - fi - - # Generate CrowdSec API key - echo "[ WEB ]: Generating CrowdSec API key..." - CROWDSEC_API_KEY=$(sudo docker exec crowdsec cscli bouncers add caddy-bouncer -o raw) - - # Encrypt passwords using Caddy - echo "[ WEB ]: Encrypting Prometheus password..." - PROMETHEUS_PASSWORD=$(sudo docker exec caddy caddy hash-password --plaintext "$prometheus_plain_password") - echo "[ WEB ]: Encrypting Loki password..." - LOKI_PASSWORD=$(sudo docker exec caddy caddy hash-password --plaintext "$loki_plain_password") - - # Update .env file with real API key and encrypted passwords - cat > "$caddy_dir/.env" <