docker-setup.sh 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #!/usr/bin/env bash
  2. # docker-setup.sh
  3. # Cross-platform installer for Open OSCAR Server Docker Setup
  4. # Compatible with Linux and macOS
  5. set -e
  6. set -u # Exit on undefined variables
  7. # ANSI color codes (fallback for POSIX shells that support it)
  8. RED='\033[0;31m'
  9. GREEN='\033[0;32m'
  10. YELLOW='\033[1;33m'
  11. CYAN='\033[0;36m'
  12. NC='\033[0m'
  13. log() { printf "%b\n" "${CYAN}[*] $1${NC}" >&2; }
  14. success(){ printf "%b\n" "${GREEN}[✔] $1${NC}" >&2; }
  15. warn() { printf "%b\n" "${YELLOW}[!] $1${NC}" >&2; }
  16. error() { printf "%b\n" "${RED}[✖] $1${NC}" >&2; return 1; }
  17. prompt() {
  18. local varname=$1
  19. local prompt_text=$2
  20. if [ -t 0 ] && [ -t 1 ]; then
  21. # Interactive shell with both stdin and stdout connected to terminal
  22. printf "%b" "$prompt_text"
  23. read -r "$varname"
  24. else
  25. # Non-interactive shell (like curl | bash) or output redirected
  26. printf "%b" "$prompt_text" >&2
  27. read -r "$varname" < /dev/tty
  28. fi
  29. # Use eval for POSIX-compatible indirect variable access
  30. local value
  31. eval "value=\$$varname"
  32. if [ -z "$value" ]; then
  33. printf "%b\n" "${RED}[✖] Input required but not provided.${NC}" >&2
  34. return 1
  35. fi
  36. }
  37. check_os() {
  38. case "$(uname -s)" in
  39. Linux|Darwin)
  40. : # supported
  41. ;;
  42. *)
  43. error "Unsupported OS: $(uname -s)"
  44. return 1
  45. ;;
  46. esac
  47. }
  48. check_prereqs() {
  49. log "Checking for required tools..."
  50. for cmd in git docker make; do
  51. if ! command -v "$cmd" >/dev/null 2>&1; then
  52. error "Missing required command: $cmd"
  53. return 1
  54. fi
  55. done
  56. success "All prerequisites are installed."
  57. }
  58. stop_existing_services() {
  59. log "Stopping any existing Docker Compose services..."
  60. if docker compose ps -q 2>/dev/null | grep -q .; then
  61. log "Found running services, stopping them..."
  62. docker compose down 2>/dev/null || true
  63. success "Stopped existing services."
  64. else
  65. log "No running services found."
  66. fi
  67. }
  68. resolve_repo_root() {
  69. SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
  70. # If this script is inside a Git repo already, use that
  71. if git -C "$SCRIPT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  72. REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)
  73. else
  74. TMP_DIR="open-oscar-server"
  75. if [ -d "$TMP_DIR/.git" ]; then
  76. warn "Directory '$TMP_DIR' is already a git repo. Using existing directory."
  77. else
  78. log "Cloning Open OSCAR Server repository..."
  79. if ! git clone https://github.com/mk6i/open-oscar-server.git "$TMP_DIR"; then
  80. error "Failed to clone repository"
  81. return 1
  82. fi
  83. fi
  84. REPO_ROOT=$(cd "$TMP_DIR" && pwd)
  85. fi
  86. if ! cd "$REPO_ROOT"; then
  87. error "Failed to enter repository directory"
  88. return 1
  89. fi
  90. }
  91. build_images() {
  92. log "Building Docker images..."
  93. if ! make docker-images; then
  94. error "Docker image build failed"
  95. return 1
  96. fi
  97. success "Docker images built successfully."
  98. }
  99. setup_ssl_cert() {
  100. if ! prompt OSCAR_HOST "Enter the OSCAR_HOST (e.g., ras.dev): "; then
  101. return 1
  102. fi
  103. # Validate OSCAR_HOST format (basic hostname validation)
  104. if ! echo "$OSCAR_HOST" | grep -qE '^[a-zA-Z0-9]([a-zA-Z0-9.-]*[a-zA-Z0-9])?$'; then
  105. error "Invalid hostname format: $OSCAR_HOST"
  106. return 1
  107. fi
  108. # Export OSCAR_HOST so docker-compose can use it
  109. export OSCAR_HOST
  110. log "SSL certificate options:"
  111. printf "%b\n" "${YELLOW}1) Generate self-signed certificate"
  112. printf "%b" "2) Use existing PEM certificate at certs/server.pem${NC}\n"
  113. if ! prompt cert_choice "${CYAN}Choose an option [1/2]: ${NC}"; then
  114. return 1
  115. fi
  116. case "$cert_choice" in
  117. 1)
  118. log "Generating self-signed SSL certificate for $OSCAR_HOST..."
  119. make clean-certs
  120. log "OSCAR_HOST set to ${OSCAR_HOST}"
  121. if ! make docker-cert OSCAR_HOST="$OSCAR_HOST"; then
  122. error "Failed to generate self-signed cert"
  123. return 1
  124. fi
  125. success "Self-signed certificate generated."
  126. ;;
  127. 2)
  128. if [ ! -f "certs/server.pem" ]; then
  129. error "certs/server.pem not found. Please place your PEM file there and rerun."
  130. return 1
  131. else
  132. success "Using existing certificate at certs/server.pem."
  133. fi
  134. ;;
  135. *)
  136. error "Invalid option for certificate setup."
  137. return 1
  138. ;;
  139. esac
  140. }
  141. generate_nss() {
  142. log "Generating NSS certificate database..."
  143. if ! make docker-nss; then
  144. error "Failed to generate NSS cert DB"
  145. return 1
  146. fi
  147. success "NSS certificate database created at certs/nss/"
  148. }
  149. start_server() {
  150. log "Starting Open OSCAR Server with hostname $OSCAR_HOST..."
  151. if ! make docker-run-bg OSCAR_HOST="$OSCAR_HOST"; then
  152. error "Failed to start server"
  153. return 1
  154. fi
  155. success "Open OSCAR Server is running."
  156. }
  157. final_steps() {
  158. printf "%b\n" "${GREEN}
  159. Open OSCAR Server setup complete!
  160. ===================================
  161. Next Steps:
  162. 1. Copy the NSS certs from 'certs/nss/' to each AIM 6.2+ client.
  163. 2. Ensure clients can resolve '${OSCAR_HOST}' to your server IP.
  164. Add the following to each client's hosts file if DNS isn't used:
  165. ${YELLOW}127.0.0.1 $OSCAR_HOST${NC}
  166. ${GREEN}3. For AIM 6.x client setup instructions, see:
  167. https://github.com/mk6i/open-oscar-server/blob/main/docs/AIM_6_7.md#aim-62-75-setup
  168. Enjoy!
  169. ${NC}" >&2
  170. }
  171. main() {
  172. check_os || return 1
  173. check_prereqs || return 1
  174. resolve_repo_root || return 1
  175. stop_existing_services || return 1
  176. build_images || return 1
  177. setup_ssl_cert || return 1
  178. generate_nss || return 1
  179. start_server || return 1
  180. final_steps
  181. }
  182. main "$@"