install_casdoor.sh 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #!/usr/bin/env bash
  2. # =============================================================================
  3. # FranklinWH Toolbox - Casdoor 安装脚本(Docker 方式)
  4. # =============================================================================
  5. # 作用:以 Docker Compose 部署 Casdoor(casbin/casdoor),并:
  6. # 1. 在本地 PostgreSQL 中创建 casdoor 角色与 casdoor 数据库
  7. # 2. 生成 docker-compose.yml 与 conf/app.conf
  8. # 3. 首次启动时用 --createDatabase=true 让 Casdoor 建表并写入初始数据
  9. # 4. 常规启动容器(端口 8010->8000,与线上一致)
  10. #
  11. # 前置条件:
  12. # - Docker + docker compose 插件已安装(可用 install_deps.sh docker)
  13. # - PostgreSQL 已安装并运行(本机 :5432)
  14. #
  15. # 环境变量:
  16. # CASDOOR_DIR Casdoor 部署目录 (默认 /home/$USER/docker/casdoor)
  17. # CASDOOR_PORT 对外端口(->容器8000) (默认 8010)
  18. # CASDOOR_PG_HOST PG 主机(容器内视角) (默认 host.docker.internal)
  19. # CASDOOR_PG_PORT PG 端口 (默认 5432)
  20. # CASDOOR_PG_USER Casdoor 使用的 PG 角色 (默认 casdoor)
  21. # CASDOOR_PG_PASSWORD Casdoor PG 角色密码 (默认 casdoor)
  22. # CASDOOR_DB_NAME Casdoor 数据库名 (默认 casdoor)
  23. # CASDOOR_ORIGIN Casdoor 对外访问地址 (默认 http://localhost:8010)
  24. # =============================================================================
  25. set -euo pipefail
  26. CASDOOR_DIR="${CASDOOR_DIR:-$HOME/docker/casdoor}"
  27. # TODO: [确认] Casdoor 对外端口(默认 8010,需与反向代理 /casdoor 一致)
  28. CASDOOR_PORT="${CASDOOR_PORT:-8010}"
  29. CASDOOR_PG_HOST="${CASDOOR_PG_HOST:-host.docker.internal}"
  30. CASDOOR_PG_PORT="${CASDOOR_PG_PORT:-5432}"
  31. CASDOOR_PG_USER="${CASDOOR_PG_USER:-casdoor}"
  32. # TODO: [必填] Casdoor 数据库口令——请通过环境变量传入强口令,勿使用默认 casdoor
  33. CASDOOR_PG_PASSWORD="${CASDOOR_PG_PASSWORD:-casdoor}"
  34. CASDOOR_DB_NAME="${CASDOOR_DB_NAME:-casdoor}"
  35. # TODO: [必填] Casdoor 对外访问地址(origin)——填成实际域名,如 https://<域名>/casdoor
  36. CASDOOR_ORIGIN="${CASDOOR_ORIGIN:-http://localhost:${CASDOOR_PORT}}"
  37. c_reset='\033[0m'; c_blue='\033[1;34m'; c_green='\033[1;32m'; c_yellow='\033[1;33m'; c_red='\033[1;31m'
  38. info() { echo -e "${c_blue}[INFO]${c_reset} $*"; }
  39. ok() { echo -e "${c_green}[ OK ]${c_reset} $*"; }
  40. warn() { echo -e "${c_yellow}[WARN]${c_reset} $*"; }
  41. err() { echo -e "${c_red}[FAIL]${c_reset} $*" >&2; }
  42. # docker compose 命令探测(插件 or 独立二进制)
  43. compose() {
  44. if docker compose version >/dev/null 2>&1; then
  45. docker compose "$@"
  46. elif command -v docker-compose >/dev/null 2>&1; then
  47. docker-compose "$@"
  48. else
  49. err "未找到 docker compose,请先安装(install_deps.sh docker)"; return 1
  50. fi
  51. }
  52. # ---------------------------------------------------------------------------
  53. # 1. PostgreSQL:建角色 + 建库
  54. # ---------------------------------------------------------------------------
  55. provision_pg() {
  56. info "在 PostgreSQL 中准备 Casdoor 角色与数据库 ..."
  57. command -v psql >/dev/null 2>&1 || { err "未找到 psql,请先安装 PostgreSQL"; return 1; }
  58. # 角色(幂等)
  59. sudo -u postgres psql -v ON_ERROR_STOP=1 \
  60. -v role="${CASDOOR_PG_USER}" -v pwd="${CASDOOR_PG_PASSWORD}" <<'SQL'
  61. SELECT format('CREATE ROLE %I LOGIN PASSWORD %L', :'role', :'pwd')
  62. WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = :'role')
  63. \gexec
  64. SQL
  65. # 数据库(幂等,owner=角色)
  66. sudo -u postgres psql -v ON_ERROR_STOP=1 \
  67. -v db="${CASDOOR_DB_NAME}" -v role="${CASDOOR_PG_USER}" <<'SQL'
  68. SELECT format('CREATE DATABASE %I OWNER %I ENCODING ''UTF8''', :'db', :'role')
  69. WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = :'db')
  70. \gexec
  71. SQL
  72. ok "PostgreSQL:角色 ${CASDOOR_PG_USER} / 数据库 ${CASDOOR_DB_NAME} 就绪"
  73. # 允许容器经 host-gateway 连接本机 PG:确保监听地址与 pg_hba 允许
  74. warn "请确认 PostgreSQL 允许来自 Docker 网段的连接(listen_addresses 与 pg_hba.conf)。"
  75. warn "常见做法:postgresql.conf 设 listen_addresses='*';pg_hba.conf 增加 host ${CASDOOR_DB_NAME} ${CASDOOR_PG_USER} 172.16.0.0/12 scram-sha-256,然后 systemctl reload postgresql。"
  76. }
  77. # ---------------------------------------------------------------------------
  78. # 2. 生成 compose 与 app.conf
  79. # ---------------------------------------------------------------------------
  80. write_files() {
  81. info "生成 Casdoor 部署文件到 ${CASDOOR_DIR} ..."
  82. mkdir -p "${CASDOOR_DIR}/conf"
  83. # 数据源:Casdoor postgres driver 使用 keyword=value DSN;末尾 dbname 由 dbName 指定
  84. local dsn="user=${CASDOOR_PG_USER} password=${CASDOOR_PG_PASSWORD} host=${CASDOOR_PG_HOST} port=${CASDOOR_PG_PORT} sslmode=disable dbname="
  85. cat > "${CASDOOR_DIR}/docker-compose.yml" <<EOF
  86. services:
  87. casdoor:
  88. restart: always
  89. image: casbin/casdoor:latest
  90. entrypoint: /bin/sh -c './server'
  91. ports:
  92. - "${CASDOOR_PORT}:8000"
  93. environment:
  94. RUNNING_IN_DOCKER: "true"
  95. extra_hosts:
  96. - "host.docker.internal:host-gateway"
  97. volumes:
  98. - ./conf:/conf/
  99. EOF
  100. cat > "${CASDOOR_DIR}/conf/app.conf" <<EOF
  101. appname = casdoor
  102. httpport = 8000
  103. runmode = prod
  104. copyrequestbody = true
  105. driverName = postgres
  106. dataSourceName = ${dsn}
  107. dbName = ${CASDOOR_DB_NAME}
  108. tableNamePrefix =
  109. showSql = false
  110. redisEndpoint =
  111. defaultStorageProvider =
  112. isCloudIntranet = false
  113. authState = "casdoor"
  114. verificationCodeTimeout = 10
  115. initScore = 0
  116. logPostOnly = true
  117. isUsernameLowered = false
  118. origin = ${CASDOOR_ORIGIN}
  119. originFrontend =
  120. staticBaseUrl = "https://cdn.casbin.org"
  121. isDemoMode = false
  122. batchSize = 100
  123. enableGzip = true
  124. ldapServerPort = 389
  125. radiusServerPort = 1812
  126. radiusDefaultOrganization = "built-in"
  127. quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
  128. logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
  129. initDataNewOnly = false
  130. initDataFile = "./init_data.json"
  131. frontendBaseDir = "../cc_0"
  132. EOF
  133. ok "已生成 docker-compose.yml 与 conf/app.conf"
  134. }
  135. # ---------------------------------------------------------------------------
  136. # 3. 首次建表 + 启动
  137. # ---------------------------------------------------------------------------
  138. start_casdoor() {
  139. cd "${CASDOOR_DIR}"
  140. # 首次:让 Casdoor 建表并写入初始数据(--createDatabase=true)
  141. info "首次初始化 Casdoor 数据表(--createDatabase=true)..."
  142. docker run --rm \
  143. --add-host host.docker.internal:host-gateway \
  144. -v "${CASDOOR_DIR}/conf:/conf/" \
  145. casbin/casdoor:latest \
  146. /bin/sh -c './server --createDatabase=true' || \
  147. warn "初始化返回非零(若为“表已存在”可忽略)"
  148. info "启动 Casdoor 容器 ..."
  149. compose up -d
  150. sleep 3
  151. compose ps
  152. ok "Casdoor 已启动:${CASDOOR_ORIGIN}(默认管理员 admin/123)"
  153. }
  154. main() {
  155. info "== 安装 Casdoor(Docker)=="
  156. command -v docker >/dev/null 2>&1 || { err "未找到 docker,请先安装(install_deps.sh docker)"; exit 1; }
  157. provision_pg
  158. write_files
  159. start_casdoor
  160. cat <<EOF
  161. ${c_green}Casdoor 部署完成${c_reset}
  162. 目录 : ${CASDOOR_DIR}
  163. 访问地址 : ${CASDOOR_ORIGIN}
  164. 管理员 : admin / 123(首次登录后请立即修改)
  165. 后续配置 : 见 deploy/DEPLOYMENT.md 的《Casdoor 配置》章节
  166. (创建组织 organization_franklinwh_toolbox、应用 app-franklinwh-toolbox,
  167. 取得 clientId/clientSecret/证书,并配置反向代理 /casdoor)
  168. EOF
  169. }
  170. main "$@"