You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

749 lines
21 KiB

  1. # -*- mode: shell-script -*-
  2. get_domain() {
  3. local cfg="$1"
  4. e "$cfg" | cfg-get-value domain 2>/dev/null && return 0
  5. ## is service name a regex ?
  6. if [[ "$BASE_SERVICE_NAME" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then
  7. echo "$BASE_SERVICE_NAME"
  8. return 0
  9. fi
  10. err "You must specify a ${WHITE}domain$NORMAL option in relation. (${FUNCNAME[@]})"
  11. return 1
  12. }
  13. ##
  14. ## Master entrypoints
  15. ##
  16. apache_proxy_dir() {
  17. local cfg="$1" domain
  18. apache_vhost_create web_proxy "$cfg" || return 1
  19. }
  20. export -f apache_proxy_dir
  21. apache_publish_dir() {
  22. local cfg="$1" domain
  23. apache_vhost_create publish_dir "$cfg" || return 1
  24. apache_code_dir "$cfg" || return 1
  25. apache_data_dirs "$cfg"
  26. }
  27. export -f apache_publish_dir
  28. ##
  29. ## Simple functions
  30. ##
  31. apache_vhost_create() {
  32. local type="$1" cfg="$2" custom_rules vhost_statement creds
  33. export APACHE_CONFIG_LOCATION="$SERVICE_CONFIGSTORE/etc/apache2/sites-enabled"
  34. protocols=$(__vhost_cfg_normalize_protocol "$cfg") || return 1
  35. if is_protocol_enabled https "$protocols"; then
  36. read-0 ssl_plugin_fun ssl_cfg_value ssl_cfg_options < <(ssl_get_plugin_fun "$cfg") || return 1
  37. "$ssl_plugin_fun"_vars "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
  38. redirect=$(e "$cfg" | cfg-get-value 'redirect-to-ssl' 2>/dev/null) || true
  39. if is_protocol_enabled http "$protocols"; then
  40. redirect=${redirect:-true}
  41. else
  42. redirect=false
  43. fi
  44. if [ "$redirect" == "true" ]; then
  45. custom_rules=$(_get_custom_rules "$cfg") || return 1
  46. if [[ "$custom_rules" != *"## Auto-redirection from http to https"* ]]; then
  47. redirect_rule="- |
  48. ## Auto-redirection from http to https
  49. RewriteEngine On
  50. RewriteCond %{HTTPS} off
  51. RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
  52. "
  53. relation-set apache-custom-rules "$redirect_rule
  54. $(if [ "$custom_rules" ]; then
  55. echo "- |"$'\n'"$(echo "$custom_rules" | prefix " ")"
  56. fi)"
  57. cfg=$(merge_yaml_str "$cfg" "$(yaml_key_val_str "apache-custom-rules" "$redirect_rule
  58. $(if [ "$custom_rules" ]; then
  59. echo "- |"$'\n'"$(echo "$custom_rules" | prefix " ")"
  60. fi)")")
  61. fi
  62. relation-set protocol https
  63. else
  64. ## Both services are available and different, don't do anything then ?
  65. #relation-set protocol https
  66. :
  67. fi
  68. else
  69. relation-set protocol http
  70. fi
  71. vhost_statement=$(apache_vhost_statement "$type" "$protocols" "$cfg") || {
  72. err "Failed to get vhost statement for type $type on ${protocols:1:-1}"
  73. return 1
  74. }
  75. domain=$(get_domain "$cfg") || return 1
  76. relation-set domain "$domain"
  77. echo "$vhost_statement"| file_put "$APACHE_CONFIG_LOCATION/$prefix$domain.conf" || return 1
  78. creds=$(e "$cfg" | cfg-get-value creds 2>/dev/null) || true
  79. if [ "$creds" ]; then
  80. apache_passwd_file "$cfg" || return 1
  81. fi
  82. if is_protocol_enabled https "$protocols"; then
  83. "$ssl_plugin_fun"_prepare "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
  84. fi
  85. }
  86. is_protocol_enabled() {
  87. local protocol="$1" protocols="$2"
  88. [[ "$protocols" == *",$protocol,"* ]]
  89. }
  90. export -f is_protocol_enabled
  91. _get_ssl_option_value() {
  92. local cfg="$1" target_relation rn ts rc td
  93. e "$cfg" | cfg-get-value ssl 2>/dev/null && return 0
  94. target_relation="cert-provider"
  95. while read-0 rn ts rc td; do
  96. [ "$rn" == "${target_relation}" ] || continue
  97. info "A cert-provider '$ts' declared as 'ssl' value"
  98. echo "$ts"
  99. return 0
  100. done < <(get_service_relations "$SERVICE_NAME")
  101. return 1
  102. }
  103. __vhost_cfg_normalize_protocol() {
  104. local cfg="$1" protocol
  105. ## XXXvlab: can't cache if libcharm is not able to give me some checksums
  106. ## indeed, ``_get_ssl_option_value`` depends on relations calculations...
  107. # local cfg="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(p0 "$@" | md5_compat)" \
  108. # protocol
  109. # if [ -e "$cache_file" ]; then
  110. # #debug "$FUNCNAME: STATIC cache hit $1"
  111. # cat "$cache_file" &&
  112. # touch "$cache_file" || return 1
  113. # return 0
  114. # fi
  115. if protocol=$(e "$cfg" | cfg-get-value protocol 2>/dev/null); then
  116. protocol=${protocol:-auto}
  117. else
  118. protocol=auto
  119. fi
  120. case "$protocol" in
  121. auto)
  122. if _get_ssl_option_value "$cfg" >/dev/null 2>&1; then
  123. protocol="http,https"
  124. else
  125. protocol="http"
  126. fi
  127. ;;
  128. both)
  129. protocol="https,http"
  130. ;;
  131. ssl|https)
  132. protocol="https"
  133. ;;
  134. http)
  135. protocol="http"
  136. ;;
  137. *)
  138. err "Invalid value '$protocol' for ${WHITE}protocol$NORMAL option (use one of: http, https, both, auto)."
  139. return 1
  140. esac
  141. echo ",$protocol,"
  142. #| tee "$cache_file"
  143. }
  144. ## ssl_plugin_* and ssl_fallback should :
  145. ## - do anything to ensure that
  146. ## - issue config-add to add volumes if necessary
  147. ## - output 3 vars of where to find the 3 files from within the docker apache
  148. ssl_get_plugin_fun() {
  149. # from ssl conf, return the function that should manage SSL code creation
  150. local master_cfg="$1" cfg type keys
  151. cfg=$(_get_ssl_option_value "$master_cfg")
  152. [ "$cfg" ] || return 0
  153. type="$(echo "$cfg" | shyaml -y get-type 2>/dev/null)" || return 1
  154. if [[ "$type" == "bool" ]]; then
  155. printf "%s\0" "ssl_fallback" "" "$cfg"
  156. echo ssl_fallback
  157. return 0
  158. fi
  159. if ! [[ "$type" == "str" || "$type" == "struct" ]]; then
  160. err "Invalid ${WHITE}ssl${NORMAL} value type '$type': please provide a string or a struct."
  161. return 1
  162. fi
  163. if [ -z "$NO_CERT_PROVIDER" ]; then
  164. if [[ "$type" == "str" ]]; then
  165. keys=("$cfg")
  166. else
  167. keys=($(echo "$cfg" | shyaml keys 2>/dev/null))
  168. fi
  169. for key in "${keys[@]}"; do
  170. target_relation="cert-provider"
  171. fun="ssl_plugin_${target_relation}"
  172. while read-0 relation_name target_service relation_config tech_dep; do
  173. [ "$relation_name" == "${target_relation}" ] || continue
  174. [ "$target_service" == "$key" ] || continue
  175. verb "Corresponding plugin ${DARKGREEN}found${NORMAL}" \
  176. "in ${DARKBLUE}$relation_name${NORMAL}/${DARKYELLOW}$key${NORMAL}"
  177. ssl_cfg=$(printf "%s" "$cfg" | shyaml get-value "$key" 2>/dev/null) || true
  178. merged_config=$(merge_yaml_str "$relation_config" "$ssl_cfg") || return 1
  179. printf "%s\0" "$fun" "$key" "$merged_config"
  180. return 0
  181. done < <(get_service_relations "$SERVICE_NAME") || return 1
  182. case "$key" in
  183. cert|ca-cert|key)
  184. :
  185. ;;
  186. *)
  187. err "Invalid key '$key' in ${WHITE}ssl${NORMAL}:" \
  188. "no corresponding services declared in ${DARKBLUE}${target_relation}$NORMAL"
  189. return 1
  190. ;;
  191. esac
  192. done
  193. fi
  194. ## No key of the struct seem to be declared cert-provider, so fallback
  195. printf "%s\0" "ssl_fallback" "" "$cfg"
  196. echo ssl_fallback
  197. }
  198. ssl_fallback_vars() {
  199. local cfg="$1" ssl_cfg="$2" cert key ca_cert domain
  200. domain=$(get_domain "$cfg") || return 1
  201. if __vhost_cfg_ssl_cert=$(echo "$ssl_cfg" | shyaml get-value cert 2>/dev/null); then
  202. __vhost_cfg_SSL_CERT_LOCATION=/etc/ssl/certs/${domain}.pem
  203. fi
  204. if __vhost_cfg_ssl_key=$(echo "$ssl_cfg" | shyaml get-value key 2>/dev/null); then
  205. __vhost_cfg_SSL_KEY_LOCATION=/etc/ssl/private/${domain}.key
  206. fi
  207. if __vhost_cfg_ssl_ca_cert=$(echo "$ssl_cfg" | shyaml get-value ca-cert 2>/dev/null); then
  208. __vhost_cfg_SSL_CA_CERT_LOCATION=/etc/ssl/certs/${domain}-ca.pem
  209. fi
  210. }
  211. ssl_fallback_prepare() {
  212. local cfg="$1" cert key ca_cert
  213. dst="$CONFIGSTORE/$BASE_SERVICE_NAME"
  214. volumes=""
  215. for label in cert key ca_cert; do
  216. content="$(eval echo "\"\$__vhost_cfg_ssl_$label\"")"
  217. if [ "$content" ]; then
  218. location="$(eval echo "\$__vhost_cfg_SSL_${label^^}_LOCATION")"
  219. echo "$content" | file_put "$dst$location"
  220. config_hash=$(printf "%s\0" "$config_hash" "$label" "$content" | md5_compat)
  221. volumes="$volumes
  222. - $dst$location:$location:ro"
  223. fi
  224. done
  225. if [ "$volumes" ]; then
  226. config-add "\
  227. services:
  228. $MASTER_TARGET_SERVICE_NAME:
  229. volumes:
  230. $volumes
  231. "
  232. fi
  233. }
  234. ssl_plugin_cert-provider_vars() {
  235. local cfg="$1" ssl_cfg="$2"
  236. domain=$(get_domain "$cfg") || return 1
  237. __vhost_cfg_SSL_CERT_LOCATION=/etc/letsencrypt/live/${domain}/cert.pem
  238. __vhost_cfg_SSL_KEY_LOCATION=/etc/letsencrypt/live/${domain}/privkey.pem
  239. __vhost_cfg_SSL_CHAIN=/etc/letsencrypt/live/${domain}/chain.pem
  240. }
  241. ssl_plugin_cert-provider_prepare() {
  242. local cfg="$1" ssl_cfg="$2" service="$3" options domain server_aliases
  243. domain=$(get_domain "$cfg") || return 1
  244. options=$(yaml_key_val_str "options" "$ssl_cfg") || return 1
  245. service_config=$(yaml_key_val_str "$service" "$options")
  246. server_aliases=$(e "$cfg" | cfg-get-value server-aliases 2>/dev/null) || true
  247. [ "$server_aliases" == None ] && server_aliases=""
  248. if [ "$server_aliases" ]; then
  249. server_aliases=($(echo "$server_aliases" | shyaml get-values)) || return 1
  250. else
  251. server_aliases=()
  252. fi
  253. compose --debug --add-compose-content "$service_config" run --rm --service-ports "$service" \
  254. crt create "$domain" "${server_aliases[@]}" || {
  255. err "Failed to launch letsencrypt for certificate creation."
  256. return 1
  257. }
  258. config-add "\
  259. services:
  260. $MASTER_TARGET_SERVICE_NAME:
  261. volumes:
  262. - $DATASTORE/$service/etc/letsencrypt:/etc/letsencrypt:ro
  263. " || return 1
  264. }
  265. apache_passwd_file() {
  266. local cfg="$1" creds
  267. include parse || true
  268. ## XXXvlab: called twice... no better way to do this ?
  269. creds=$(e "$cfg" | cfg-get-value creds 2>/dev/null) || true
  270. password_path=$(password-path-get "$cfg")
  271. first=
  272. if ! [ -e "$CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_path" ]; then
  273. debug "No file $CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_path, creating password file." || true
  274. first=c
  275. fi
  276. while read-0 login password; do
  277. debug "htpasswd -b$first '${password_path}' '$login' '$password'"
  278. echo "htpasswd -b$first '${password_path}' '$login' '$password'"
  279. if [ "$first" ]; then
  280. first=
  281. fi
  282. done < <(e "$creds" | shyaml key-values-0 2>/dev/null) |
  283. docker run -i --entrypoint "/bin/bash" \
  284. -v "$APACHE_CONFIG_LOCATION:/etc/apache2/sites-enabled" \
  285. "$DOCKER_BASE_IMAGE" || return 1
  286. }
  287. ## Produce the full statements depending on relation-get informations
  288. apache_vhost_statement() {
  289. local type="$1" protocols="$2" cfg="$3" \
  290. vhost_statement
  291. if is_protocol_enabled http "$protocols"; then
  292. __vhost_full_vhost_statement "$type" http "$cfg" || return 1
  293. fi
  294. if is_protocol_enabled https "$protocols"; then
  295. read-0 ssl_plugin_fun ssl_cfg_value ssl_cfg_options < <(ssl_get_plugin_fun "$cfg") || return 1
  296. "$ssl_plugin_fun"_vars "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
  297. vhost_statement=$(__vhost_full_vhost_statement "$type" https "$cfg") || return 1
  298. cat <<EOF
  299. <IfModule mod_ssl.c>
  300. $(echo "$vhost_statement" | prefix " ")
  301. </IfModule>
  302. EOF
  303. fi
  304. }
  305. export -f apache_vhost_statement
  306. apache_code_dir() {
  307. local cfg="$1" www_data_gid local_path
  308. www_data_gid=$(cached_cmd_on_base_image apache 'id -g www-data') || {
  309. debug "Failed to query for www-data gid in ${DARKYELLOW}apache${NORMAL} base image."
  310. return 1
  311. }
  312. domain=$(get_domain "$cfg") || return 1
  313. local_path="/var/www/${domain}"
  314. host_path=$(e "$cfg" | cfg-get-value location 2>/dev/null) ||
  315. host_path="$DATASTORE/$BASE_SERVICE_NAME${local_path}"
  316. mkdir -p "$host_path" || return 1
  317. setfacl -R -m g:"$www_data_gid":rx "$host_path"
  318. info "Set permission for read and traversal on '$host_path'."
  319. config-add "
  320. $MASTER_BASE_SERVICE_NAME:
  321. volumes:
  322. - $host_path:$local_path
  323. "
  324. }
  325. apache_data_dirs() {
  326. local cfg="$1" data_dirs dst data dirs
  327. data_dirs=$(e "$cfg" | cfg-get-value data-dirs 2>/dev/null | shyaml get-values 2>/dev/null) || true
  328. if [ -z "$data_dirs" ]; then
  329. return 0
  330. fi
  331. domain=$(get_domain "$cfg") || return 1
  332. local_path="/var/www/${domain}"
  333. dst=$DATASTORE/$BASE_SERVICE_NAME$local_path
  334. data=()
  335. while IFS="," read -ra addr; do
  336. for dir in "${addr[@]}"; do
  337. data+=($dir)
  338. done
  339. done <<< "$data_dirs"
  340. www_data_gid=$(cached_cmd_on_base_image apache 'id -g www-data') || {
  341. debug "Failed to query for www-data gid in ${DARKYELLOW}apache${NORMAL} base image."
  342. return 1
  343. }
  344. info "www-data gid from ${DARKYELLOW}apache${NORMAL} is '$www_data_gid'"
  345. dirs=()
  346. for d in "${data[@]}"; do
  347. dirs+=("$dst/$d")
  348. done
  349. mkdir -p "${dirs[@]}"
  350. setfacl -R -m g:"$www_data_gid":rwx "${dirs[@]}"
  351. setfacl -R -d -m g:"$www_data_gid":rwx "${dirs[@]}"
  352. config-add "
  353. $MASTER_BASE_SERVICE_NAME:
  354. volumes:
  355. $(
  356. for d in "${data[@]}"; do
  357. echo " - $dst/$d:$local_path/$d"
  358. done
  359. )"
  360. }
  361. deploy_files() {
  362. local src="$1" dst="$2"
  363. if ! [ -d "$dst" ]; then
  364. err "Destination '$dst' does not exist or is not a directory"
  365. return 1
  366. fi
  367. (
  368. cd "$dst" && info "In $dst:" &&
  369. get_file "$src" | tar xv
  370. )
  371. }
  372. export -f deploy_files
  373. apache_core_rules_add() {
  374. local conf="$1" dst="/etc/apache2/conf-enabled/$BASE_SERVICE_NAME.conf"
  375. debug "Adding core rule."
  376. echo "$conf" | file_put "$CONFIGSTORE/$BASE_SERVICE_NAME$dst"
  377. config_hash=$(printf "%s\0" "$config_hash" "$conf" | md5_compat)
  378. config-add "
  379. $MASTER_BASE_SERVICE_NAME:
  380. volumes:
  381. - $CONFIGSTORE/$BASE_SERVICE_NAME$dst:$dst:ro
  382. "
  383. }
  384. __vhost_ssl_statement() {
  385. ## defaults
  386. __vhost_cfg_SSL_CERT_LOCATION=${__vhost_cfg_SSL_CERT_LOCATION:-/etc/ssl/certs/ssl-cert-snakeoil.pem}
  387. __vhost_cfg_SSL_KEY_LOCATION=${__vhost_cfg_SSL_KEY_LOCATION:-/etc/ssl/private/ssl-cert-snakeoil.key}
  388. cat <<EOF
  389. ##
  390. ## SSL Configuration
  391. ##
  392. SSLEngine On
  393. SSLCertificateFile $__vhost_cfg_SSL_CERT_LOCATION
  394. SSLCertificateKeyFile $__vhost_cfg_SSL_KEY_LOCATION
  395. $([ -z "$__vhost_cfg_SSL_CA_CERT_LOCATION" ] || echo "SSLCACertificateFile $__vhost_cfg_SSL_CA_CERT_LOCATION")
  396. $([ -z "$__vhost_cfg_SSL_CHAIN" ] || echo "SSLCertificateChainFile $__vhost_cfg_SSL_CHAIN")
  397. SSLVerifyClient None
  398. EOF
  399. }
  400. password-path-get() {
  401. local cfg="$1" domain
  402. domain=$(get_domain "$cfg") || return 1
  403. echo /etc/apache2/sites-enabled/${domain}.passwd
  404. }
  405. __vhost_creds_statement() {
  406. local cfg="$1" password_path
  407. password_path=$(password-path-get "$cfg") || return 1
  408. if ! e "$cfg" | cfg-get-value creds >/dev/null 2>&1; then
  409. echo "Allow from all"
  410. return 0
  411. fi
  412. cat <<EOF
  413. AuthType basic
  414. AuthName "private"
  415. AuthUserFile ${password_path}
  416. Require valid-user
  417. EOF
  418. }
  419. __vhost_head_statement() {
  420. local cfg="$1" protocol="$2" server_aliases admin_mail
  421. domain=$(get_domain "$cfg") || return 1
  422. admin_mail=$(e "$1" | cfg-get-value "admin-mail" 2>/dev/null) || true
  423. server_aliases=$(e "$cfg" | cfg-get-value server-aliases 2>/dev/null) || true
  424. [ "$server_aliases" == None ] && server_aliases=""
  425. if [ "$server_aliases" ]; then
  426. server_aliases=($(e "$server_aliases" | shyaml get-values)) || return 1
  427. if [ -z "$domain" ]; then
  428. err "You can't specify server aliases if you don't have a domain."
  429. return 1
  430. fi
  431. else
  432. server_aliases=()
  433. fi
  434. if [ "$protocol" == "https" ]; then
  435. prefix="s-"
  436. else
  437. prefix=
  438. fi
  439. cat <<EOF
  440. ServerAdmin ${admin_mail:-contact@$domain}
  441. ServerName ${domain}
  442. $(
  443. for alias in "${server_aliases[@]}"; do
  444. [ "$alias" ] || continue
  445. echo "ServerAlias $alias"
  446. done
  447. )
  448. ServerSignature Off
  449. CustomLog /var/log/apache2/${prefix}${domain}_access.log combined
  450. ErrorLog /var/log/apache2/${prefix}${domain}_error.log
  451. ErrorLog syslog:local2
  452. EOF
  453. }
  454. _get_custom_rules() {
  455. local cfg="$1" custom_rules type elt value first
  456. custom_rules=$(e "$cfg" | cfg-get-value apache-custom-rules 2>/dev/null) || true
  457. if [ -z "$custom_rules" ]; then
  458. return 0
  459. fi
  460. type=$(echo "$custom_rules" | shyaml get-type)
  461. value=
  462. case "$type" in
  463. "sequence")
  464. first=1
  465. while read-0 elt; do
  466. elt="$(echo "$elt" | yaml_get_interpret)" || return 1
  467. [ "$elt" ] || continue
  468. if [ "$first" ]; then
  469. first=
  470. else
  471. value+=$'\n'$'\n'
  472. fi
  473. first=
  474. value+="$elt"
  475. done < <(echo "$custom_rules" | shyaml -y get-values-0)
  476. ;;
  477. "struct")
  478. while read-0 _key val; do
  479. value+=$'\n'"$(echo "$val" | yaml_get_interpret)" || return 1
  480. done < <(echo "$custom_rules" | shyaml -y key-values-0)
  481. ;;
  482. "str")
  483. value+=$(echo "$custom_rules")
  484. ;;
  485. *)
  486. value+=$(echo "$custom_rules")
  487. ;;
  488. esac
  489. printf "%s" "$value"
  490. }
  491. __vhost_custom_rules() {
  492. local cfg="$1" custom_rules
  493. custom_rules=$(_get_custom_rules "$cfg") || return 1
  494. if [ "$custom_rules" ]; then
  495. cat <<EOF
  496. ##
  497. ## Custom rules
  498. ##
  499. $custom_rules
  500. EOF
  501. fi
  502. }
  503. __vhost_content_statement() {
  504. local type="$1"
  505. shift
  506. case "$type" in
  507. "web_proxy")
  508. __vhost_proxy_statement "$@" || return 1
  509. ;;
  510. "publish_dir")
  511. __vhost_publish_dir_statement "$@" || return 1
  512. ;;
  513. esac
  514. }
  515. target-get() {
  516. local cfg="$1" target first_exposed_port base_image
  517. target=$(e "$cfg" | cfg-get-value target 2>/dev/null) || true
  518. if [ -z "$target" ]; then
  519. ## First exposed port:
  520. base_image=$(service_base_docker_image "$BASE_SERVICE_NAME") || return 1
  521. if ! docker_has_image "$base_image"; then
  522. docker pull "$base_image" >&2
  523. fi
  524. first_exposed_port=$(image_exposed_ports_0 "$base_image" | tr '\0' '\n' | head -n 1 | cut -f 1 -d /) || return 1
  525. if [ -z "$first_exposed_port" ]; then
  526. err "Failed to get first exposed port of image '$base_image'."
  527. return 1
  528. fi
  529. target=$MASTER_BASE_SERVICE_NAME:$first_exposed_port
  530. info "No target was specified, introspection found: $target"
  531. fi
  532. echo "$target"
  533. }
  534. __vhost_proxy_statement() {
  535. local protocol="$1" cfg="$2"
  536. target=$(target-get "$cfg") || return 1
  537. cat <<EOF
  538. ##
  539. ## Proxy declaration towards $target
  540. ##
  541. <IfModule mod_proxy.c>
  542. ProxyRequests Off
  543. <Proxy *>
  544. Order deny,allow
  545. Allow from all
  546. </Proxy>
  547. ProxyVia On
  548. ProxyPass / http://$target/ retry=0
  549. <Location / >
  550. $(__vhost_creds_statement "$cfg" | prefix " ")
  551. ProxyPassReverse /
  552. </Location>
  553. $([ "$protocol" == "https" ] && echo " SSLProxyEngine On")
  554. </IfModule>
  555. RequestHeader set "X-Forwarded-Proto" "$protocol"
  556. ## Fix IE problem (httpapache proxy dav error 408/409)
  557. SetEnv proxy-nokeepalive 1
  558. EOF
  559. }
  560. __vhost_full_vhost_statement() {
  561. local type="$1" protocol="$2" cfg="$3" head_statement custom_rules content_statement
  562. head_statement=$(__vhost_head_statement "$cfg" "$protocol") || return 1
  563. custom_rules=$(__vhost_custom_rules "$cfg") || return 1
  564. content_statement=$(__vhost_content_statement "$type" "$protocol" "$cfg") || return 1
  565. case "$protocol" in
  566. https)
  567. PORT=443
  568. ;;
  569. http)
  570. PORT=80
  571. ;;
  572. esac
  573. cat <<EOF
  574. <VirtualHost *:$PORT>
  575. $(echo "$head_statement" | prefix " ")
  576. $(echo "$custom_rules" | prefix " ")
  577. $(echo "$content_statement" | prefix " ")
  578. ## Forbid any cache, this is only usefull on dev server.
  579. #Header set Cache-Control "no-cache"
  580. #Header set Access-Control-Allow-Origin "*"
  581. #Header set Access-Control-Allow-Methods "POST, GET, OPTIONS"
  582. #Header set Access-Control-Allow-Headers "origin, content-type, accept"
  583. $([ "$protocol" == "https" ] && __vhost_ssl_statement | prefix " " && echo )
  584. </VirtualHost>
  585. EOF
  586. }
  587. __vhost_publish_dir_statement() {
  588. local protocol="$1" cfg="$2"
  589. domain=$(get_domain "$cfg") || return 1
  590. local_path="/var/www/${domain}"
  591. cat <<EOF
  592. ##
  593. ## Publish directory $local_path
  594. ##
  595. DocumentRoot $local_path
  596. <Directory />
  597. Options FollowSymLinks
  598. AllowOverride None
  599. </Directory>
  600. <Directory $local_path>
  601. Options Indexes FollowSymLinks MultiViews
  602. AllowOverride all
  603. $(__vhost_creds_statement "$cfg" | prefix " ")
  604. </Directory>
  605. EOF
  606. }
  607. apache_config_hash() {
  608. debug "Adding config hash to enable recreating upon config change."
  609. config_hash=$({
  610. printf "%s\0" "$config_hash"
  611. find "$SERVICE_CONFIGSTORE/etc/apache2/sites-enabled" \
  612. -name \*.conf -exec md5sum {} \;
  613. } | md5_compat) || exit 1
  614. init-config-add "
  615. $MASTER_BASE_SERVICE_NAME:
  616. labels:
  617. - compose.config_hash=$config_hash
  618. "
  619. }