docker compose setup and .env generation in monorepo scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Executable
+240
@@ -0,0 +1,240 @@
|
||||
#!/bin/bash
|
||||
# Officer — Docker Compose service setup
|
||||
# Sets up Docker Compose services (Nginx Proxy Manager, PostgreSQL, Mailhog, Redis, SearXNG).
|
||||
# Outputs parseable key=value lines to stdout; all prompts go to stderr.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/setup-dockers.sh
|
||||
# eval "$(bash scripts/setup-dockers.sh)"
|
||||
#
|
||||
# Environment overrides:
|
||||
# SETUP_DOCKER_SERVICES="1 2 3" — pre-select services (or "all"/"none")
|
||||
# SETUP_DOCKER_NETWORK="services" — docker network name
|
||||
|
||||
set -e
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${CYAN}::${NC} $*" >&2; }
|
||||
ok() { echo -e " ${GREEN}✓${NC} $1" >&2; }
|
||||
warn() { echo -e " ${YELLOW}!${NC} $1" >&2; }
|
||||
fail() { echo -e " ${RED}✗${NC} $1" >&2; }
|
||||
|
||||
prompt_value() {
|
||||
local varname="$1" prompt="$2" default="$3"
|
||||
if [[ -n "$default" ]]; then
|
||||
echo -en " ${BOLD}${prompt}${NC} [${default}]: " >&2
|
||||
else
|
||||
echo -en " ${BOLD}${prompt}${NC}: " >&2
|
||||
fi
|
||||
read -r val
|
||||
if [[ -z "$val" ]]; then val="$default"; fi
|
||||
eval "$varname=\"\$val\""
|
||||
}
|
||||
|
||||
# ─── docker network ─────────────────────────────────────────────────────────
|
||||
DOCKER_NETWORK="${SETUP_DOCKER_NETWORK:-services}"
|
||||
|
||||
# Ensure network exists
|
||||
if ! docker network inspect "$DOCKER_NETWORK" &>/dev/null; then
|
||||
docker network create "$DOCKER_NETWORK" >/dev/null 2>&1
|
||||
ok "Created docker network '$DOCKER_NETWORK'"
|
||||
else
|
||||
ok "Docker network '$DOCKER_NETWORK' exists"
|
||||
fi
|
||||
|
||||
# ─── service selection ───────────────────────────────────────────────────────
|
||||
SERVICES="${SETUP_DOCKER_SERVICES:-}"
|
||||
|
||||
if [[ "$SERVICES" == "none" ]]; then
|
||||
info "Skipping Docker Compose services (SETUP_DOCKER_SERVICES=none)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$SERVICES" ]]; then
|
||||
info "Select Docker Compose services to include:"
|
||||
echo " [1] Nginx Proxy Manager (jc21/nginx-proxy-manager:latest)" >&2
|
||||
echo " [2] PostgreSQL 18 (postgres:18-alpine)" >&2
|
||||
echo " [3] Mailhog (mailhog/mailhog:latest)" >&2
|
||||
echo " [4] Redis (redis:alpine)" >&2
|
||||
echo " [5] SearXNG (searxng/searxng:latest)" >&2
|
||||
|
||||
prompt_value SERVICES "Enter numbers separated by spaces (e.g. '1 2 4'), or 'all'" "all"
|
||||
fi
|
||||
|
||||
if [[ "$SERVICES" == "all" ]]; then
|
||||
SERVICES="1 2 3 4 5"
|
||||
fi
|
||||
|
||||
# ─── compose directory ──────────────────────────────────────────────────────
|
||||
prompt_value COMPOSE_DIR "Docker Compose directory" "$HOME/.local/dockers"
|
||||
mkdir -p "$COMPOSE_DIR"
|
||||
|
||||
# ─── build compose file ─────────────────────────────────────────────────────
|
||||
cat > "$COMPOSE_DIR/docker-compose.yaml" <<'HEADER'
|
||||
services:
|
||||
HEADER
|
||||
|
||||
COMPOSE_SERVICES=()
|
||||
PG_PASSWORD=""
|
||||
MAILHOG_SELECTED=false
|
||||
|
||||
for svc in $SERVICES; do
|
||||
case "$svc" in
|
||||
1)
|
||||
COMPOSE_SERVICES+=("nginx-proxy-manager")
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<SVC
|
||||
nginx-proxy-manager:
|
||||
image: jc21/nginx-proxy-manager:latest
|
||||
container_name: nginx-proxy-manager
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "81:81"
|
||||
volumes:
|
||||
- ./npm_data:/data
|
||||
- ./npm_letsencrypt:/etc/letsencrypt
|
||||
networks:
|
||||
- $DOCKER_NETWORK
|
||||
|
||||
SVC
|
||||
;;
|
||||
2)
|
||||
COMPOSE_SERVICES+=("postgres")
|
||||
PG_DEFAULT_PASS=$(openssl rand -base64 36 | tr -d '/+=' | head -c 36)
|
||||
prompt_value PG_PASSWORD "PostgreSQL password" "$PG_DEFAULT_PASS"
|
||||
prompt_value PG_DATABASE "PostgreSQL database name" "officer_dev"
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<SVC
|
||||
postgres:
|
||||
image: postgres:18.3-alpine
|
||||
container_name: postgres
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:5432:5432"
|
||||
environment:
|
||||
POSTGRES_PASSWORD: $PG_PASSWORD
|
||||
PGDATA: /var/lib/postgresql/data
|
||||
volumes:
|
||||
- ./postgres_data:/var/lib/postgresql/data
|
||||
- ./db_dumps:/db_dumps
|
||||
networks:
|
||||
- $DOCKER_NETWORK
|
||||
|
||||
SVC
|
||||
;;
|
||||
3)
|
||||
COMPOSE_SERVICES+=("mailhog")
|
||||
MAILHOG_SELECTED=true
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<SVC
|
||||
mailhog:
|
||||
image: mailhog/mailhog:latest
|
||||
container_name: mailhog
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:1025:1025"
|
||||
- "127.0.0.1:8025:8025"
|
||||
networks:
|
||||
- $DOCKER_NETWORK
|
||||
|
||||
SVC
|
||||
;;
|
||||
4)
|
||||
COMPOSE_SERVICES+=("redis")
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<SVC
|
||||
redis:
|
||||
image: redis:alpine
|
||||
container_name: redis
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:6379:6379"
|
||||
volumes:
|
||||
- ./redis_data:/data
|
||||
networks:
|
||||
- $DOCKER_NETWORK
|
||||
|
||||
SVC
|
||||
;;
|
||||
5)
|
||||
COMPOSE_SERVICES+=("searxng")
|
||||
mkdir -p "$COMPOSE_DIR/searxng"
|
||||
SEARXNG_SECRET=$(openssl rand -hex 32)
|
||||
cat > "$COMPOSE_DIR/searxng/settings.yml" <<SEARXCFG
|
||||
use_default_settings: true
|
||||
|
||||
server:
|
||||
secret_key: "$SEARXNG_SECRET"
|
||||
limiter: false
|
||||
|
||||
search:
|
||||
formats:
|
||||
- html
|
||||
- json
|
||||
SEARXCFG
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<SVC
|
||||
searxng:
|
||||
image: searxng/searxng:latest
|
||||
container_name: searxng
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:8080:8080"
|
||||
volumes:
|
||||
- ./searxng:/etc/searxng
|
||||
environment:
|
||||
SEARXNG_BASE_URL: http://localhost:8080/
|
||||
networks:
|
||||
- $DOCKER_NETWORK
|
||||
|
||||
SVC
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Add networks block
|
||||
cat >> "$COMPOSE_DIR/docker-compose.yaml" <<FOOTER
|
||||
networks:
|
||||
$DOCKER_NETWORK:
|
||||
external: true
|
||||
FOOTER
|
||||
|
||||
# ─── start services ─────────────────────────────────────────────────────────
|
||||
info "Starting docker compose services..."
|
||||
(cd "$COMPOSE_DIR" && docker compose up -d) >&2
|
||||
|
||||
ok "Docker services: ${COMPOSE_SERVICES[*]}"
|
||||
|
||||
# ─── create database if PostgreSQL was selected ─────────────────────────────
|
||||
if [[ -n "$PG_PASSWORD" ]]; then
|
||||
info "Waiting for PostgreSQL to be ready..."
|
||||
for i in $(seq 1 15); do
|
||||
if docker exec postgres pg_isready -U postgres >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if docker exec postgres pg_isready -U postgres >/dev/null 2>&1; then
|
||||
# Create the database if it doesn't exist
|
||||
docker exec postgres psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = '$PG_DATABASE'" | grep -q 1 \
|
||||
|| docker exec postgres psql -U postgres -c "CREATE DATABASE $PG_DATABASE" >/dev/null 2>&1
|
||||
ok "Database '$PG_DATABASE' ready"
|
||||
else
|
||||
warn "PostgreSQL not ready after 15s — create database manually"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─── output parseable values to stdout ───────────────────────────────────────
|
||||
echo "COMPOSE_DIR=$COMPOSE_DIR"
|
||||
|
||||
if [[ -n "$PG_PASSWORD" ]]; then
|
||||
echo "POSTGRES_URL=postgresql://postgres:${PG_PASSWORD}@127.0.0.1:5432/${PG_DATABASE}"
|
||||
fi
|
||||
|
||||
if [[ "$MAILHOG_SELECTED" == true ]]; then
|
||||
echo "MAIL_TRANSPORT=smtp://127.0.0.1:1025"
|
||||
fi
|
||||
+76
-2
@@ -778,7 +778,81 @@ else
|
||||
warn "Skipping bun install (bun not found or not in project dir)"
|
||||
fi
|
||||
|
||||
# ─── 16. remote desktop (XFCE + VNC) ────────────────────────────────────────
|
||||
# ─── 16. environment (.env) ──────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Environment (.env) ──"
|
||||
|
||||
GENERATE_ENV=true
|
||||
|
||||
if [ -f "$PROJECT_DIR/.env" ]; then
|
||||
echo -n " .env already exists. Regenerate? (y/n) [n]: "
|
||||
read -r REGEN
|
||||
if [[ "$REGEN" != "y" && "$REGEN" != "Y" ]]; then
|
||||
GENERATE_ENV=false
|
||||
skip ".env (kept existing)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$GENERATE_ENV" = true ]; then
|
||||
# Run setup-dockers.sh and capture its stdout output
|
||||
echo " Setting up Docker Compose services..."
|
||||
DOCKER_OUTPUT=$(bash "$SCRIPT_DIR/setup-dockers.sh")
|
||||
|
||||
# Parse output from setup-dockers.sh
|
||||
COMPOSE_DIR=$(echo "$DOCKER_OUTPUT" | grep '^COMPOSE_DIR=' | cut -d= -f2-)
|
||||
POSTGRES_URL=$(echo "$DOCKER_OUTPUT" | grep '^POSTGRES_URL=' | cut -d= -f2-)
|
||||
DOCKER_MAIL_TRANSPORT=$(echo "$DOCKER_OUTPUT" | grep '^MAIL_TRANSPORT=' | cut -d= -f2-)
|
||||
|
||||
# Prompt for remaining values
|
||||
echo ""
|
||||
echo -n " PORT [9010]: "
|
||||
read -r ENV_PORT
|
||||
ENV_PORT="${ENV_PORT:-9010}"
|
||||
|
||||
echo -n " PUBLIC_URL (required): "
|
||||
read -r ENV_PUBLIC_URL
|
||||
while [ -z "$ENV_PUBLIC_URL" ]; do
|
||||
warn "PUBLIC_URL is required"
|
||||
echo -n " PUBLIC_URL: "
|
||||
read -r ENV_PUBLIC_URL
|
||||
done
|
||||
|
||||
echo -n " DATA_PATH [/mnt/data]: "
|
||||
read -r ENV_DATA_PATH
|
||||
ENV_DATA_PATH="${ENV_DATA_PATH:-/mnt/data}"
|
||||
|
||||
MAIL_DEFAULT="${DOCKER_MAIL_TRANSPORT:-smtp://127.0.0.1:1025}"
|
||||
echo -n " MAIL_TRANSPORT [$MAIL_DEFAULT]: "
|
||||
read -r ENV_MAIL_TRANSPORT
|
||||
ENV_MAIL_TRANSPORT="${ENV_MAIL_TRANSPORT:-$MAIL_DEFAULT}"
|
||||
|
||||
echo -n " DISCORD_BUG_REPORT_WEBHOOK []: "
|
||||
read -r ENV_DISCORD_WEBHOOK
|
||||
|
||||
if [ -z "$POSTGRES_URL" ]; then
|
||||
echo -n " POSTGRES_URL: "
|
||||
read -r POSTGRES_URL
|
||||
fi
|
||||
|
||||
# Auto-generate values
|
||||
JWT_SECRET=$(openssl rand -base64 48 | tr -d '/+=' | head -c 48)
|
||||
|
||||
# Write .env
|
||||
cat > "$PROJECT_DIR/.env" <<ENVFILE
|
||||
PORT=$ENV_PORT
|
||||
JWT_SECRET="$JWT_SECRET"
|
||||
MAIL_TRANSPORT="$ENV_MAIL_TRANSPORT"
|
||||
PUBLIC_URL=$ENV_PUBLIC_URL
|
||||
DATA_PATH=$ENV_DATA_PATH
|
||||
HOME_DIR=$HOME
|
||||
POSTGRES_URL="$POSTGRES_URL"
|
||||
DISCORD_BUG_REPORT_WEBHOOK="$ENV_DISCORD_WEBHOOK"
|
||||
ENVFILE
|
||||
|
||||
ok ".env written to $PROJECT_DIR/.env"
|
||||
fi
|
||||
|
||||
# ─── 17. remote desktop (XFCE + VNC) ────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Remote Desktop (XFCE + VNC) ──"
|
||||
|
||||
@@ -795,7 +869,7 @@ else
|
||||
esac
|
||||
fi
|
||||
|
||||
# ─── 17. PTY sidecar (systemd service) ──────────────────────────────────────
|
||||
# ─── 18. PTY sidecar (systemd service) ──────────────────────────────────────
|
||||
bash "$SCRIPT_DIR/setup-pty-sidecar.sh"
|
||||
|
||||
# ─── verification ─────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user