diff --git a/.dockerignore b/.dockerignore index 99bb78cc..54c76f70 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,22 @@ .git +.github +.vscode +.tmp +.idea db cert *.log Dockerfile docker-compose.yml -.tmp -.idea -.vscode LICENSE -README.* \ No newline at end of file +*.md +media +docs +windows_files +__pycache__ +.DS_Store +.env.example +.gitignore +x-ui.rc +x-ui.service.debian +x-ui.service.rhel \ No newline at end of file diff --git a/DockerEntrypoint.sh b/DockerEntrypoint.sh index 455c3211..7da8d58a 100644 --- a/DockerEntrypoint.sh +++ b/DockerEntrypoint.sh @@ -2,24 +2,8 @@ set -eu -: "${MAX_GEODATA_DIR_WAIT:=30}" -: "${WAIT_INTERVAL:=10}" -: "${GEODATA_DIR:?GEODATA_DIR is required}" - -FINISH_FILE="$GEODATA_DIR/cron-job-finished.txt" -ELAPSED=0 - -while [ ! -f "$FINISH_FILE" ] && [ "$ELAPSED" -lt "$MAX_GEODATA_DIR_WAIT" ]; do - echo "Waiting for geodata initialization... ($ELAPSED/$MAX_GEODATA_DIR_WAIT seconds)" - sleep $WAIT_INTERVAL - ELAPSED=$((ELAPSED + WAIT_INTERVAL)) -done - -if [ ! -f "$FINISH_FILE" ]; then - echo "ERROR: Geodata initialization timed out after $MAX_GEODATA_DIR_WAIT seconds" - echo "Container startup aborted." - exit 1 -fi +# /app/bin is shared volume +cp /tmp/xray/* /app/bin/ # Start fail2ban [ "$XUI_ENABLE_FAIL2BAN" = "true" ] && fail2ban-client -x start diff --git a/docker-compose.yml b/docker-compose.yml index 0fa748c1..08b2c7e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,55 +2,57 @@ services: 3x-ui: build: context: . + args: + XRAY_VERSION: "${XRAY_VERSION:-v25.10.15}" container_name: 3xui_app volumes: - $PWD/db/:/etc/x-ui/ - $PWD/cert/:/root/cert/ - $PWD/geodata/:/app/bin + environment: - TZ: "Asia/Tehran" + TZ: "UTC" XRAY_VMESS_AEAD_FORCED: "false" XUI_ENABLE_FAIL2BAN: "true" - GEODATA_DIR: "/app/bin" + XUI_MAIN_FOLDER: "/usr/local/x-ui" tty: true network_mode: host restart: unless-stopped - depends_on: - - geodata-cron - docker-proxy: - image: tecnativa/docker-socket-proxy - container_name: docker_proxy - restart: unless-stopped - environment: - - CONTAINERS=1 - - POST=1 - - ALLOW_RESTARTS=1 - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - networks: - - docker-internal - - geodata-cron: - build: - context: docker-cron-runner - args: - XRAY_VERSION: "${XRAY_VERSION:-v25.10.15}" - XRAY_BUILD_DIR: "/app/xray" - container_name: geodata_cron - restart: unless-stopped - depends_on: - - docker-proxy - environment: - TZ: "UTC" - DOCKER_PROXY_URL: "http://docker-proxy:2375" - TARGET_CONTAINER_NAME: "3xui_app" - CRON_SCHEDULE: "0 */6 * * *" - SHARED_VOLUME_PATH: "/app/bin" - volumes: - - $PWD/geodata/:/app/bin/ - networks: - - docker-internal +# If you don't need automatic geodata update, just disable `docker-proxy` and `geodata-cron` containers +# docker-proxy: +# image: tecnativa/docker-socket-proxy +# container_name: docker_proxy +# restart: unless-stopped +# environment: +# - CONTAINERS=1 +# - POST=1 +# - ALLOW_RESTARTS=1 +# volumes: +# - /var/run/docker.sock:/var/run/docker.sock:ro +# networks: +# - docker-internal +# +# geodata-cron: +# build: +# dockerfile: Dockerfile-cron-runner +# args: +# XRAY_VERSION: "${XRAY_VERSION:-v25.10.15}" +# XRAY_BUILD_DIR: "/app/xray" +# container_name: geodata_cron +# restart: unless-stopped +# depends_on: +# - docker-proxy +# environment: +# TZ: "UTC" +# DOCKER_PROXY_URL: "http://docker-proxy:2375" +# TARGET_CONTAINER_NAME: "3xui_app" +# CRON_SCHEDULE: "*/5 * * * *" #"0 */6 * * *" +# SHARED_VOLUME_PATH: "/app/bin" +# volumes: +# - $PWD/geodata/:/app/bin/ +# networks: +# - docker-internal networks: docker-internal: diff --git a/docker-cron-runner/Dockerfile b/docker-cron-runner/Dockerfile deleted file mode 100644 index 224dca41..00000000 --- a/docker-cron-runner/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM alpine:3.20 - -ARG TARGETARCH -ARG XRAY_VERSION -ARG XRAY_BUILD_DIR - -WORKDIR /app - -RUN apk add --no-cache \ - wget \ - unzip \ - curl \ - bash \ - ca-certificates \ - tzdata - - -COPY xray-tools.sh entrypoint.sh cron-job-script.sh ./ - -RUN chmod +x /app/xray-tools.sh /app/entrypoint.sh /app/cron-job-script.sh \ - && mkdir -p "$XRAY_BUILD_DIR" \ - && ./xray-tools.sh install_xray_core "$TARGETARCH" "$XRAY_BUILD_DIR" "$XRAY_VERSION" \ - && ./xray-tools.sh update_geodata_in_docker "$XRAY_BUILD_DIR" - -ENV XRAY_BUILD_DIR=${XRAY_BUILD_DIR} - -#CMD ["/app/entrypoint.sh"] \ -ENTRYPOINT ["/app/entrypoint.sh"] \ No newline at end of file diff --git a/lib/geo.sh b/lib/geo.sh index 0280d691..0437a970 100644 --- a/lib/geo.sh +++ b/lib/geo.sh @@ -5,65 +5,52 @@ [[ -n "${__X_UI_GEO_INCLUDED:-}" ]] && return 0 __X_UI_GEO_INCLUDED=1 -# Source dependencies -source "${LIB_DIR}/common.sh" -source "${LIB_DIR}/service.sh" - update_all_geofiles() { - update_geofiles "main" - update_geofiles "IR" - update_geofiles "RU" + target_folder="${1}" + update_geofiles "main" "${target_folder}" + update_geofiles "IR" "${target_folder}" + update_geofiles "RU" "${target_folder}" } update_geofiles() { + target_folder="${2}" case "${1}" in "main") dat_files=(geoip geosite); dat_source="Loyalsoldier/v2ray-rules-dat";; "IR") dat_files=(geoip_IR geosite_IR); dat_source="chocolate4u/Iran-v2ray-rules" ;; "RU") dat_files=(geoip_RU geosite_RU); dat_source="runetfreedom/russia-v2ray-rules-dat";; esac for dat in "${dat_files[@]}"; do - curl -fLRo ${xui_folder}/bin/${dat}.dat -z ${xui_folder}/bin/${dat}.dat \ - https://github.com/${dat_source}/releases/latest/download/${dat%%_}.dat + # Remove suffix for remote filename (e.g., geoip_IR -> geoip) + remote_file="${dat%%_*}" + curl -fLRo ${target_folder}/${dat}.dat -z ${target_folder}/${dat}.dat \ + https://github.com/${dat_source}/releases/latest/download/${remote_file}.dat done } -update_geo() { - echo -e "${green}\t1.${plain} Loyalsoldier (geoip.dat, geosite.dat)" - echo -e "${green}\t2.${plain} chocolate4u (geoip_IR.dat, geosite_IR.dat)" - echo -e "${green}\t3.${plain} runetfreedom (geoip_RU.dat, geosite_RU.dat)" - echo -e "${green}\t4.${plain} All" - echo -e "${green}\t0.${plain} Back to Main Menu" - read -rp "Choose an option: " choice +# CLI entrypoint when script is executed directly +if [[ "${0##*/}" = "geo.sh" ]]; then + cmd="${1:-}" + shift || true - case "$choice" in - 0) - show_menu - ;; - 1) - update_geofiles "main" - echo -e "${green}Loyalsoldier datasets have been updated successfully!${plain}" - restart - ;; - 2) - update_geofiles "IR" - echo -e "${green}chocolate4u datasets have been updated successfully!${plain}" - restart - ;; - 3) - update_geofiles "RU" - echo -e "${green}runetfreedom datasets have been updated successfully!${plain}" - restart - ;; - 4) - update_all_geofiles - echo -e "${green}All geo files have been updated successfully!${plain}" - restart - ;; - *) - echo -e "${red}Invalid option. Please select a valid number.${plain}\n" - update_geo - ;; + case "$cmd" in + update_all_geofiles) + update_all_geofiles "$@" + ;; + update_geofiles) + update_geofiles "$@" + ;; + "" | help | -h | --help) + echo "Usage:" + echo " $0 update_all_geofiles - Update geo files for all regions" + echo " $0 update_geofiles - Update geo files for specific region" + echo "" + echo "Available regions: main, IR, RU" + exit 0 + ;; + *) + echo "Unknown command: $cmd" >&2 + echo "Try: $0 help" >&2 + exit 1 + ;; esac - - before_show_menu -} +fi \ No newline at end of file diff --git a/lib/xray-tools.sh b/lib/xray-tools.sh new file mode 100755 index 00000000..f7a7d962 --- /dev/null +++ b/lib/xray-tools.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +install_xray_core() { + TARGETARCH="$1" + XRAYDIR="$2" + XRAY_VERSION="$3" + + OLD_DIR=$(pwd) + trap 'cd "$OLD_DIR"' EXIT + + echo "[$(date)] Running install_xray_core" + + case $1 in + amd64) + ARCH="64" + FNAME="amd64" + ;; + i386) + ARCH="32" + FNAME="i386" + ;; + armv8 | arm64 | aarch64) + ARCH="arm64-v8a" + FNAME="arm64" + ;; + armv7 | arm | arm32) + ARCH="arm32-v7a" + FNAME="arm32" + ;; + armv6) + ARCH="arm32-v6" + FNAME="armv6" + ;; + *) + ARCH="64" + FNAME="amd64" + ;; + esac + + if [ ! -d "$XRAYDIR" ]; then + mkdir -p "$XRAYDIR" + fi + cd "$XRAYDIR" + + wget -q "https://github.com/XTLS/Xray-core/releases/download/${XRAY_VERSION}/Xray-linux-${ARCH}.zip" + + # Validate the downloaded zip file + if [ ! -f "Xray-linux-${ARCH}.zip" ] || [ ! -s "Xray-linux-${ARCH}.zip" ]; then + echo "[ERR] Failed to download Xray-core zip or file is empty" + exit 1 + fi + + unzip -q "Xray-linux-${ARCH}.zip" -d ./xray-unzip + + # Validate the extracted xray binary + if [ -f "./xray-unzip/xray" ]; then + cp ./xray-unzip/xray ./"xray-linux-${FNAME}" + rm -r xray-unzip + rm "Xray-linux-${ARCH}.zip" + else + echo "[ERR] Failed to extract xray binary" + exit 1 + fi +} + +if [ "${0##*/}" = "xray-tools.sh" ]; then + cmd="$1" + shift || true + + case "$cmd" in + install_xray_core) + # args: TARGETARCH XRAYDIR XRAY_VERSION + install_xray_core "$@" + ;; +# update_geodata_in_docker) +# # args: XRAYDIR +# update_geodata_in_docker "$@" +# ;; + ""|help|-h|--help) + echo "Usage:" + echo " $0 install_xray_core TARGETARCH XRAYDIR XRAY_VERSION" +# echo " $0 update_geodata_in_docker XRAYDIR" + exit 0 + ;; + *) + echo "Unknown command: $cmd" >&2 + echo "Try: $0 help" >&2 + exit 1 + ;; + esac +fi \ No newline at end of file diff --git a/x-ui.sh b/x-ui.sh index 340d456a..b9c522dd 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -69,6 +69,47 @@ show_usage() { └────────────────────────────────────────────────────────────────┘" } +update_geo() { + echo -e "${green}\t1.${plain} Loyalsoldier (geoip.dat, geosite.dat)" + echo -e "${green}\t2.${plain} chocolate4u (geoip_IR.dat, geosite_IR.dat)" + echo -e "${green}\t3.${plain} runetfreedom (geoip_RU.dat, geosite_RU.dat)" + echo -e "${green}\t4.${plain} All" + echo -e "${green}\t0.${plain} Back to Main Menu" + read -rp "Choose an option: " choice + + case "$choice" in + 0) + show_menu + ;; + 1) + update_geofiles "main" "${xui_folder}"/bin + echo -e "${green}Loyalsoldier datasets have been updated successfully!${plain}" + restart + ;; + 2) + update_geofiles "IR" "${xui_folder}"/bin + echo -e "${green}chocolate4u datasets have been updated successfully!${plain}" + restart + ;; + 3) + update_geofiles "RU" "${xui_folder}"/bin + echo -e "${green}runetfreedom datasets have been updated successfully!${plain}" + restart + ;; + 4) + update_all_geofiles "${xui_folder}"/bin + echo -e "${green}All geo files have been updated successfully!${plain}" + restart + ;; + *) + echo -e "${red}Invalid option. Please select a valid number.${plain}\n" + update_geo + ;; + esac + + before_show_menu +} + show_menu() { echo -e " ╔────────────────────────────────────────────────╗ @@ -240,8 +281,9 @@ if [[ $# -gt 0 ]]; then "uninstall") check_install 0 && uninstall 0 ;; +# TODO: check "update-all-geofiles") - check_install 0 && update_all_geofiles 0 && restart 0 + check_install 0 && update_all_geofiles "${xui_folder}"/bin 0 && restart 0 ;; *) show_usage ;; esac