entrypoint.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #!/bin/bash
  2. echo "Setting up docker env..."
  3. echo "MODE: $MODE"
  4. echo "USE_NEW_DESIGN: $USE_NEW_DESIGN"
  5. echo "SERVER_LIST_URL: $SERVER_LIST_URL"
  6. echo "WEBPORT: $WEBPORT"
  7. echo "REDACT_IP_ADDRESSES: $REDACT_IP_ADDRESSES"
  8. echo "DB_TYPE: $DB_TYPE"
  9. echo "ENABLE_ID_OBFUSCATION: $ENABLE_ID_OBFUSCATION"
  10. echo "GDPR_EMAIL: $GDPR_EMAIL"
  11. set -e
  12. #set -x
  13. is_alpine() {
  14. [ -f /etc/alpine-release ]
  15. }
  16. html_escape() {
  17. printf '%s' "$1" | sed \
  18. -e 's/&/\&/g' \
  19. -e 's/</\&lt;/g' \
  20. -e 's/>/\&gt;/g' \
  21. -e 's/"/\&quot;/g' \
  22. -e "s/'/\&#39;/g"
  23. }
  24. sed_escape() {
  25. printf '%s\n' "$1" | sed 's/[&/\\]/\\&/g; s/\$/\\$/g'
  26. }
  27. # Cleanup
  28. rm -rf /var/www/html/*
  29. # Copy frontend files
  30. cp /speedtest/*.js /var/www/html/
  31. cp /speedtest/stability.html /var/www/html/
  32. # Copy design switch files
  33. cp /speedtest/config.json /var/www/html/
  34. cp /speedtest/design-switch.js /var/www/html/
  35. # Copy PWA metadata and icons
  36. cp /speedtest/favicon.ico /var/www/html/
  37. cp /speedtest/manifest.webmanifest /var/www/html/
  38. cp -r /speedtest/images /var/www/html/
  39. # Set custom webroot on alpine
  40. if is_alpine; then
  41. echo "ALPINE IMAGE"
  42. sed -i "s#\"/var/www/localhost/htdocs\"#\"/var/www/html\"#g" /etc/apache2/httpd.conf
  43. else
  44. echo "DEBIAN IMAGE"
  45. fi
  46. # Copy servers.json for stability page (frontend/dual modes)
  47. if [[ "$MODE" == "frontend" || "$MODE" == "dual" ]] && [ -f /servers.json ]; then
  48. cp /servers.json /var/www/html/servers.json
  49. fi
  50. # Set up backend side for standlone modes
  51. if [[ "$MODE" == "standalone" || "$MODE" == "dual" ]]; then
  52. cp -r /speedtest/backend/ /var/www/html/backend
  53. if [ ! -z "$IPINFO_APIKEY" ]; then
  54. sed -i s/\$IPINFO_APIKEY\ =\ \'\'/\$IPINFO_APIKEY\ =\ \'$IPINFO_APIKEY\'/g /var/www/html/backend/getIP_ipInfo_apikey.php
  55. fi
  56. fi
  57. if [ "$MODE" == "backend" ]; then
  58. cp -r /speedtest/backend/* /var/www/html
  59. if [ ! -z "$IPINFO_APIKEY" ]; then
  60. sed -i s/\$IPINFO_APIKEY\ =\ \'\'/\$IPINFO_APIKEY\ =\ \'$IPINFO_APIKEY\'/g /var/www/html/getIP_ipInfo_apikey.php
  61. fi
  62. fi
  63. # Set up index.php for frontend-only or standalone modes
  64. if [[ "$MODE" == "frontend" || "$MODE" == "dual" || "$MODE" == "standalone" ]]; then
  65. # Copy design files (switcher + both designs)
  66. cp /speedtest/index.html /var/www/html/
  67. cp /speedtest/index-classic.html /var/www/html/
  68. cp /speedtest/index-modern.html /var/www/html/
  69. cp /speedtest/stability.html /var/www/html/
  70. # Keep the frontend assets under frontend/, which is where the HTML looks for
  71. # them and where they sit in the repository
  72. cp -a /speedtest/frontend /var/www/html/
  73. # Copy frontend config files
  74. cp /speedtest/settings.json /var/www/html/settings.json 2>/dev/null || true
  75. if [ -f /servers.json ]; then
  76. echo "using mounted /servers.json for server-list.json"
  77. cp /servers.json /var/www/html/server-list.json
  78. elif [ -n "$SERVER_LIST_URL" ]; then
  79. echo "no /servers.json found, relying on SERVER_LIST_URL"
  80. elif [ "$MODE" == "frontend" ]; then
  81. echo "ERROR: /servers.json not found and SERVER_LIST_URL is not set" >&2
  82. exit 1
  83. else
  84. echo "no /servers.json found, create one for local host"
  85. # generate config for just the local server
  86. echo '[{"name":"local","server":"/backend", "dlURL": "garbage.php", "ulURL": "empty.php", "pingURL": "empty.php", "getIpURL": "getIP.php", "sponsorName": "", "sponsorURL": "", "id":1 }]' > /var/www/html/server-list.json
  87. fi
  88. if [ ! -z "$SERVER_LIST_URL" ]; then
  89. echo "using SERVER_LIST_URL for frontend server list"
  90. SERVER_LIST_URL_ESCAPED=$(printf '%s\n' "$SERVER_LIST_URL" | sed 's/[&/\\]/\\&/g; s/\$/\\$/g')
  91. sed -i "s/var SPEEDTEST_SERVERS = \"server-list.json\";/var SPEEDTEST_SERVERS = \"$SERVER_LIST_URL_ESCAPED\";/" /var/www/html/index-modern.html
  92. sed -i "/var SPEEDTEST_SERVERS = \\[/,/^[[:space:]]*];/c\\\t\tvar SPEEDTEST_SERVERS = \"$SERVER_LIST_URL_ESCAPED\";" /var/www/html/index-classic.html
  93. sed -i "s/var SPEEDTEST_SERVERS = \"server-list.json\";/var SPEEDTEST_SERVERS = \"$SERVER_LIST_URL_ESCAPED\";/" /var/www/html/stability.html
  94. fi
  95. # The stability page reads the same local server list as the main UI when present.
  96. if [ -f /var/www/html/server-list.json ]; then
  97. cp /var/www/html/server-list.json /var/www/html/servers.json
  98. fi
  99. # Replace title placeholders if TITLE is set
  100. if [ ! -z "$TITLE" ]; then
  101. TITLE_ONE_LINE=${TITLE//$'\r'/}
  102. TITLE_ONE_LINE=${TITLE_ONE_LINE//$'\n'/ }
  103. TITLE_HTML_ESCAPED=$(html_escape "$TITLE_ONE_LINE")
  104. TITLE_ESCAPED=$(sed_escape "$TITLE_HTML_ESCAPED")
  105. sed -i "s/<title>LibreSpeed<\\/title>/<title>$TITLE_ESCAPED<\\/title>/g; s/<h1>LibreSpeed<\\/h1>/<h1>$TITLE_ESCAPED<\\/h1>/g" /var/www/html/index-classic.html
  106. sed -i "s/<title>LibreSpeed<\\/title>/<title>$TITLE_ESCAPED<\\/title>/g" /var/www/html/index.html
  107. sed -i "s/<title>LibreSpeed - Free and Open Source Speedtest<\\/title>/<title>$TITLE_ESCAPED - Free and Open Source Speedtest<\\/title>/g; s/<h1>Free and Open Source Speedtest\\.<\\/h1>/<h1>$TITLE_ESCAPED<\\/h1>/g" /var/www/html/index-modern.html
  108. fi
  109. # Replace modern page tagline if TAGLINE is set
  110. if [ -n "$TAGLINE" ]; then
  111. TAGLINE_ONE_LINE=${TAGLINE//$'\r'/}
  112. TAGLINE_ONE_LINE=${TAGLINE_ONE_LINE//$'\n'/ }
  113. TAGLINE_HTML_ESCAPED=$(html_escape "$TAGLINE_ONE_LINE")
  114. TAGLINE_ESCAPED=$(sed_escape "$TAGLINE_HTML_ESCAPED")
  115. sed -i "s/<p class=\"tagline\">No Flash, No Java, No Websockets, No Bullsh\\*t<\\/p>/<p class=\"tagline\">$TAGLINE_ESCAPED<\\/p>/g" /var/www/html/index-modern.html
  116. fi
  117. # Support legacy EMAIL env var as fallback for GDPR_EMAIL
  118. if [ -z "$GDPR_EMAIL" ] && [ ! -z "$EMAIL" ]; then
  119. echo "WARNING: EMAIL env var is deprecated, please use GDPR_EMAIL instead" >&2
  120. GDPR_EMAIL="$EMAIL"
  121. echo "GDPR_EMAIL: $GDPR_EMAIL"
  122. fi
  123. # Replace GDPR email placeholder if GDPR_EMAIL is set
  124. if [ ! -z "$GDPR_EMAIL" ]; then
  125. # Escape special sed characters: & (replacement), / (delimiter), \ (escape), $ (variable)
  126. GDPR_EMAIL_ESCAPED=$(printf '%s\n' "$GDPR_EMAIL" | sed 's/[&/\\]/\\&/g; s/\$/\\$/g')
  127. for html_file in /var/www/html/index-modern.html /var/www/html/index-classic.html; do
  128. if [ -f "$html_file" ]; then
  129. sed -i "s/TO BE FILLED BY DEVELOPER/$GDPR_EMAIL_ESCAPED/g; s/PUT@YOUR_EMAIL.HERE/$GDPR_EMAIL_ESCAPED/g" "$html_file"
  130. fi
  131. done
  132. fi
  133. fi
  134. # Configure design preference via config.json
  135. if [ "$USE_NEW_DESIGN" == "true" ]; then
  136. sed -i 's/"useNewDesign": false/"useNewDesign": true/' /var/www/html/config.json
  137. fi
  138. # Apply Telemetry settings when running in standalone or frontend mode and telemetry is enabled
  139. if [[ "$TELEMETRY" == "true" && ("$MODE" == "frontend" || "$MODE" == "standalone" || "$MODE" == "dual") ]]; then
  140. cp -r /speedtest/results /var/www/html/results
  141. sed -i 's/telemetry_level": ".*"/telemetry_level": "basic"/' /var/www/html/settings.json
  142. if [ "$MODE" == "frontend" ]; then
  143. mkdir /var/www/html/backend
  144. cp /speedtest/backend/getIP_util.php /var/www/html/backend
  145. fi
  146. if [ "$DB_TYPE" == "mysql" ]; then
  147. sed -i 's/$db_type = '\''.*'\''/$db_type = '\'$DB_TYPE\''/g' /var/www/html/results/telemetry_settings.php
  148. sed -i 's/$MySql_username = '\''.*'\''/$MySql_username = '\'$DB_USERNAME\''/g' /var/www/html/results/telemetry_settings.php
  149. sed -i 's/$MySql_password = '\''.*'\''/$MySql_password = '\'$DB_PASSWORD\''/g' /var/www/html/results/telemetry_settings.php
  150. sed -i 's/$MySql_hostname = '\''.*'\''/$MySql_hostname = '\'$DB_HOSTNAME\''/g' /var/www/html/results/telemetry_settings.php
  151. sed -i 's/$MySql_databasename = '\''.*'\''/$MySql_databasename = '\'$DB_NAME\''/g' /var/www/html/results/telemetry_settings.php
  152. if [ "$DB_PORT" != "" ]; then
  153. sed -i 's/$MySql_port = '\''.*'\''/$MySql_port = '\'$DB_PORT\''/g' /var/www/html/results/telemetry_settings.php
  154. fi
  155. elif [ "$DB_TYPE" == "postgresql" ]; then
  156. sed -i 's/$db_type = '\''.*'\''/$db_type = '\'$DB_TYPE\''/g' /var/www/html/results/telemetry_settings.php
  157. sed -i 's/$PostgreSql_username = '\''.*'\''/$PostgreSql_username = '\'$DB_USERNAME\''/g' /var/www/html/results/telemetry_settings.php
  158. sed -i 's/$PostgreSql_password = '\''.*'\''/$PostgreSql_password = '\'$DB_PASSWORD\''/g' /var/www/html/results/telemetry_settings.php
  159. sed -i 's/$PostgreSql_hostname = '\''.*'\''/$PostgreSql_hostname = '\'$DB_HOSTNAME\''/g' /var/www/html/results/telemetry_settings.php
  160. sed -i 's/$PostgreSql_databasename = '\''.*'\''/$PostgreSql_databasename = '\'$DB_NAME\''/g' /var/www/html/results/telemetry_settings.php
  161. else
  162. sed -i s/\$db_type\ =\ \'.*\'/\$db_type\ =\ \'sqlite\'\/g /var/www/html/results/telemetry_settings.php
  163. fi
  164. # Override SQLite database path for Docker environment
  165. # In Docker, we use /database/db.sql which is outside the web-accessible directory
  166. sed -i s/\$Sqlite_db_file\ =\ .*\'/\$Sqlite_db_file=\'\\\/database\\\/db.sql\'/g /var/www/html/results/telemetry_settings.php
  167. sed -i s/\$stats_password\ =\ \'.*\'/\$stats_password\ =\ \'$PASSWORD\'/g /var/www/html/results/telemetry_settings.php
  168. if [ "$ENABLE_ID_OBFUSCATION" == "true" ]; then
  169. sed -i s/\$enable_id_obfuscation\ =\ .*\;/\$enable_id_obfuscation\ =\ true\;/g /var/www/html/results/telemetry_settings.php
  170. if [ ! -z "$OBFUSCATION_SALT" ]; then
  171. if [[ "$OBFUSCATION_SALT" =~ ^0x[0-9a-fA-F]+$ ]]; then
  172. echo "<?php" > /var/www/html/results/idObfuscation_salt.php
  173. echo "\$OBFUSCATION_SALT = $OBFUSCATION_SALT;" >> /var/www/html/results/idObfuscation_salt.php
  174. else
  175. echo "WARNING: Invalid OBFUSCATION_SALT format. It must be a hex string (e.g., 0x1234abcd). Using random salt." >&2
  176. fi
  177. fi
  178. fi
  179. if [ "$REDACT_IP_ADDRESSES" == "true" ]; then
  180. sed -i s/\$redact_ip_addresses\ =\ .*\;/\$redact_ip_addresses\ =\ true\;/g /var/www/html/results/telemetry_settings.php
  181. fi
  182. mkdir -p /database/
  183. if is_alpine; then
  184. chown -R apache /database/
  185. else
  186. chown -R www-data /database/
  187. fi
  188. fi
  189. if is_alpine; then
  190. chown -R apache /var/www/html/*
  191. else
  192. chown -R www-data /var/www/html/*
  193. fi
  194. # Allow selection of Apache port for network_mode: host
  195. if [ "$WEBPORT" != "80" ]; then
  196. if is_alpine; then
  197. sed -i "s/^Listen 80\$/Listen $WEBPORT/g" /etc/apache2/httpd.conf
  198. else
  199. sed -i "s/^Listen 80\$/Listen $WEBPORT/g" /etc/apache2/ports.conf
  200. sed -i "s/*:80>/*:$WEBPORT>/g" /etc/apache2/sites-available/000-default.conf
  201. fi
  202. fi
  203. echo "Done, Starting APACHE"
  204. # This runs apache
  205. if is_alpine; then
  206. exec httpd -DFOREGROUND
  207. else
  208. exec apache2-foreground
  209. fi