refactor: read templates from local files

This commit is contained in:
2025-08-17 05:32:26 -03:00
parent 2dd0edbd49
commit b5d2ddf23b
19 changed files with 289 additions and 144 deletions

94
CLAUDE.md Normal file
View File

@@ -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

7
Dockerfile Normal file
View File

@@ -0,0 +1,7 @@
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y sudo
COPY . /server-initializer
CMD ["/bin/bash"]

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)"
}

30
install.sh → src/install.sh Normal file → Executable file
View File

@@ -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 <username>"
echo "Usage: $0 <username> [--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"

View File

@@ -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
}

107
src/web/install_caddy.sh Normal file
View File

@@ -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" <<EOF
CROWDSEC_API_KEY=dev-placeholder-key
PROMETHEUS_PASSWORD=dev-placeholder-password
LOKI_PASSWORD=dev-placeholder-password
EOF
else
echo "[ WEB ]: Starting containers to generate keys..."
cd "$caddy_dir"
# Prompt user for passwords and encrypt them using Caddy
echo "[ WEB ]: Setting up authentication passwords..."
echo -n "Enter password for Prometheus access: "
read -s prometheus_plain_password
echo
echo -n "Enter password for Loki access: "
read -s loki_plain_password
echo
# Create .env file with placeholder
cat >"$caddy_dir/.env" <<EOF
CROWDSEC_API_KEY=PLACEHOLDER_WILL_BE_REPLACED
PROMETHEUS_PASSWORD=PLACEHOLDER_WILL_BE_REPLACED
LOKI_PASSWORD=PLACEHOLDER_WILL_BE_REPLACED
EOF
# Start containers
sudo docker compose up -d
# Wait for CrowdSec to be ready with health check
echo "[ WEB ]: Waiting for CrowdSec to be ready..."
for i in {1..30}; do
if sudo docker exec crowdsec cscli version >/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" <<EOF
CROWDSEC_API_KEY=$CROWDSEC_API_KEY
PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD
LOKI_PASSWORD=$LOKI_PASSWORD
EOF
# Restart containers with new API key
echo "[ WEB ]: Restarting containers with generated keys..."
sudo docker compose down
sudo docker compose up -d
fi
echo "[ WEB ]: Caddy setup completed successfully!"
echo "[ WEB ]: Configuration location: $caddy_dir"
echo "[ WEB ]: CrowdSec API key: $CROWDSEC_API_KEY"
echo "[ WEB ]: Prometheus password: [ENCRYPTED AND STORED IN .env]"
echo "[ WEB ]: Loki password: [ENCRYPTED AND STORED IN .env]"
echo "[ WEB ]: Add your site configurations to: $caddy_dir/caddy/sites-enabled/"
}

View File

@@ -1,96 +0,0 @@
#!/bin/bash
function install_caddy() {
REPO_URL="https://raw.githubusercontent.com/elAgala/server-initializer/master"
TEMPLATE_PATH="templates/caddy/full"
username="$1"
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"
# Download configuration files
wget "$REPO_URL/$TEMPLATE_PATH/docker-compose.yml" -O "$caddy_dir/docker-compose.yml"
wget "$REPO_URL/$TEMPLATE_PATH/Makefile" -O "$caddy_dir/Makefile"
wget "$REPO_URL/$TEMPLATE_PATH/caddy/Caddyfile" -O "$caddy_dir/caddy/Caddyfile"
wget "$REPO_URL/$TEMPLATE_PATH/caddy/coraza/coraza.conf" -O "$caddy_dir/caddy/coraza/coraza.conf"
wget "$REPO_URL/$TEMPLATE_PATH/crowdsec/acquis.yaml" -O "$caddy_dir/crowdsec/acquis.yaml"
wget "$REPO_URL/$TEMPLATE_PATH/caddy/sites-enabled/prometheus.Caddyfile" -O "$caddy_dir/caddy/sites-enabled/prometheus.Caddyfile"
wget "$REPO_URL/$TEMPLATE_PATH/caddy/sites-enabled/examples.Caddyfile" -O "$caddy_dir/caddy/sites-enabled/examples.Caddyfile"
echo "[ WEB ]: Starting containers to generate keys..."
cd "$caddy_dir"
# Prompt user for passwords and encrypt them using Caddy
echo "[ WEB ]: Setting up authentication passwords..."
echo -n "Enter password for Prometheus access: "
read -s prometheus_plain_password
echo
echo -n "Enter password for Loki access: "
read -s loki_plain_password
echo
# Create .env file with placeholder
cat > "$caddy_dir/.env" <<EOF
CROWDSEC_API_KEY=PLACEHOLDER_WILL_BE_REPLACED
PROMETHEUS_PASSWORD=PLACEHOLDER_WILL_BE_REPLACED
LOKI_PASSWORD=PLACEHOLDER_WILL_BE_REPLACED
EOF
# Start containers
sudo docker compose up -d
# Wait for CrowdSec to be ready with health check
echo "[ WEB ]: Waiting for CrowdSec to be ready..."
for i in {1..30}; do
if sudo docker exec crowdsec cscli version >/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" <<EOF
CROWDSEC_API_KEY=$CROWDSEC_API_KEY
PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD
LOKI_PASSWORD=$LOKI_PASSWORD
EOF
# Restart containers with new API key
echo "[ WEB ]: Restarting containers with generated keys..."
sudo docker compose down
sudo docker compose up -d
echo "[ WEB ]: Caddy setup completed successfully!"
echo "[ WEB ]: Configuration location: $caddy_dir"
echo "[ WEB ]: CrowdSec API key: $CROWDSEC_API_KEY"
echo "[ WEB ]: Prometheus password: [ENCRYPTED AND STORED IN .env]"
echo "[ WEB ]: Loki password: [ENCRYPTED AND STORED IN .env]"
echo "[ WEB ]: Add your site configurations to: $caddy_dir/caddy/sites-enabled/"
}