# operation_logs

created_at: 2026-01-16 23:16:40.943452455+08:00
updated_at: 2026-01-16 23:16:40.943452455+08:00
source: apps
ip: 171.34.209.241
node: local
path: /apps/install
method: post
status: Success
detail_zh: 安装应用[bitwarden]
detail_en: Installapp[bitwarden]
user_agent:
  Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36


# settings

created_at: 2026-01-16 23:14:31.877147742+08:00
updated_at: 2026-01-16 23:14:32.849349628+08:00
key: HideMenu
value:
  [{"id":"1","label":"Home-Menu","disabled":true,"isShow":true,"title":"menu.home","path":"/","sort":100},{"id":"2","label":"App-Menu","disabled":true,"isShow":true,"title":"menu.apps","path":"/apps/all","sort":200},{"id":"3","label":"Website-Menu","disabled":false,"isShow":true,"title":"menu.website","path":"/websites","sort":300,"children":[{"id":"31","label":"Website","disabled":false,"isShow":true,"title":"menu.website","path":"/websites","sort":100},{"id":"32","label":"SSL","disabled":false,"isShow":true,"title":"menu.ssl","path":"/websites/ssl","sort":200},{"id":"33","label":"PHP","disabled":false,"isShow":true,"title":"menu.runtime","path":"/websites/runtimes/php","sort":300}]},{"id":"4","label":"AI-Menu","disabled":false,"isShow":true,"title":"menu.aiTools","path":"/ai/model","sort":400,"children":[{"id":"41","label":"OllamaModel","disabled":false,"isShow":true,"title":"aiTools.model.model","path":"/ai/model","sort":100},{"id":"42","label":"MCPServer","disabled":false,"isShow":true,"title":"menu.mcp","path":"/ai/mcp","sort":200},{"id":"43","label":"GPU","disabled":false,"isShow":true,"title":"aiTools.gpu.gpu","path":"/ai/gpu","sort":300}]},{"id":"5","label":"Database-Menu","disabled":false,"isShow":true,"title":"menu.database","path":"/databases","sort":500},{"id":"6","label":"Container-Menu","disabled":false,"isShow":true,"title":"menu.container","path":"/containers","sort":600},{"id":"7","label":"System-Menu","disabled":false,"isShow":true,"title":"menu.system","path":"/hosts/files","sort":700,"children":[{"id":"71","label":"File","disabled":false,"isShow":true,"title":"menu.files","path":"/hosts/files","sort":100},{"id":"72","label":"Monitorx","disabled":false,"isShow":true,"title":"menu.monitor","path":"/hosts/monitor/monitor","sort":200},{"id":"74","label":"FirewallPort","disabled":false,"isShow":true,"title":"menu.firewall","path":"/hosts/firewall/port","sort":300},{"id":"75","label":"Process","disabled":false,"isShow":true,"title":"menu.processManage","path":"/hosts/process/process","sort":400},{"id":"76","label":"SSH","disabled":false,"isShow":true,"title":"menu.ssh","path":"/hosts/ssh/ssh","sort":500},{"id":"77","label":"Disk","disabled":false,"isShow":true,"title":"menu.disk","path":"/hosts/disk","sort":600}]},{"id":"8","label":"Terminal-Menu","disabled":false,"isShow":true,"title":"menu.terminal","path":"/hosts/terminal","sort":800},{"id":"10","label":"Cronjob-Menu","disabled":false,"isShow":true,"title":"menu.cronjob","path":"/cronjobs","sort":900},{"id":"9","label":"Toolbox-Menu","disabled":false,"isShow":true,"title":"menu.toolbox","path":"/toolbox","sort":1000},{"id":"11","label":"Xpack-Menu","disabled":false,"isShow":true,"title":"xpack.menu","sort":1100,"children":[{"id":"118","label":"XApp","disabled":false,"isShow":true,"title":"xpack.app.app","path":"/xpack/app","sort":100},{"id":"112","label":"Dashboard","disabled":false,"isShow":true,"title":"xpack.waf.name","path":"/xpack/waf/dashboard","sort":200},{"id":"111","label":"NodeDashboard","disabled":false,"isShow":true,"title":"xpack.node.nodeManagement","path":"/xpack/node/dashboard","sort":300},{"id":"119","label":"Upage","disabled":false,"isShow":true,"title":"xpack.upage","path":"/xpack/upage","sort":400},{"id":"113","label":"MonitorDashboard","disabled":false,"isShow":true,"title":"xpack.monitor.name","path":"/xpack/monitor/dashboard","sort":500},{"id":"114","label":"Tamper","disabled":false,"isShow":true,"title":"xpack.tamper.tamper","path":"/xpack/tamper","sort":600},{"id":"120","label":"Cluster","disabled":false,"isShow":true,"title":"xpack.cluster.cluster","path":"/xpack/cluster","sort":700},{"id":"115","label":"FileExange","disabled":false,"isShow":true,"title":"xpack.exchange.exchange","path":"/xpack/exchange/file","sort":800},{"id":"117","label":"XSetting","disabled":false,"isShow":true,"title":"xpack.setting.setting","path":"/xpack/setting","sort":900}]},{"id":"12","label":"Log-Menu","disabled":false,"isShow":true,"title":"menu.logs","path":"/logs","sort":1200},{"id":"13","label":"Setting-Menu","disabled":true,"isShow":true,"title":"menu.settings","path":"/settings","sort":1300}]


created_at: 2026-01-16 23:14:33.061855242+08:00
updated_at: 2026-01-16 23:14:33.061855242+08:00
key: PASSWORD_PRIVATE_KEY
value:
  -----BEGIN RSA PRIVATE KEY-----
  MIIEpAIBAAKCAQEA1Ax6Ch5ntmsMkmI4Cmw6wMVl/+G6pgGioA7tFeQ+IMXgGbGV
  IiWDDl+VLyQqGuoLxq5bUSheU+s1awIO68LZyBBMHZz+pb9FzuX282Y3PXXCStGn
  jdjPRd2nTjqBmBvMf034uW+0FJUzpoi1kkEt9huUTLfMUlNUpuv4B6aNJ+latCic
  QdqVqNGfpNo6l4fFAgnysi/G3llr9geYWsAK+oOfrLCz0MYV4BIdqBhn37+t3Nz4
  4Q1jF64dYg4Us6PiQt8syoTLc25FvZbxYZWNpSPKjtNYbkLJpsjj8NJOC5ZOL28W
  KmRrcrk5u7Xpt9RtgfmeTLEkazVeEmPNGH3K5QIDAQABAoIBABeqntJTS2sCLqCF
  4tBS/Qm33mb9OBpAE3j+wXpQg5ifzR/BAK6Tdjmb9GgTBroDRjYyDpITydde6JLd
  Y3HvyOO54ezqMUepfe6WHwZScbbj1kAIf0VnHdcj4oDqKb2i2KOavbhgnb4wWtfq
  6Sz+JlWSBW68ksrbbxbEPmYIMjfycOazR0i8YUxsFirjspvK+EB/PHLqW8CLQJQn
  3rgEp1E8RSsRHn/fXY4Y21dymDDnnFRYLVDASdvDnLNuINGUq3JUXZjtM7u2P8Cb
  vazfMnTJfDZP2hvqiJUKBlokpiRkifKy/xgau7BbGVw0y7rijWOSQadfbBPPGrcn
  RiYHjnECgYEA+EOgsHYuhoGWg6EyshWoSlbusqW2+5gg5UBfkS8ZhL2AAfVLsvTk
  G9tHmFfgtk1f4CDmbnOcwJegi4VDwAtuKvSycjHyPZtjk8uG5a/yvXUww3HsuB6w
  bwmYqwg8Y7eJU2t/DQqcA28Q8nwPYJVY4AxQp6/G3ISjk7JHLH28eGkCgYEA2qf2
  iS97wmhMSnD2AEGzGVHk/HXcSk52gU4zgNkuC9DYw2GIMUfBGP5+jsCedpk5NYZ3
  hhuOZcZv3ZlIhz2ja1uNB/fvJ+Cd/VIildA6xG2enDuuJACpWS0wGoYHSNdysTBv
  uBkWKexJEtO1TrcPlrHsVBc3ZyEQXQwP6YOmDx0CgYEAvoxBgE8lBI3f9WW7IF5p
  Da3NhYaVfGPWE78l2qwY3P4Jivc3w8IcdpkGSZJhYerfRIpb8rh/vn5iddOyHWto
  gkXP1MArGkfy1NQo1JAIMowJAmmlc+fyKTdnWxZ2K18KYuGl4V+cQTJ1Anhf4RSf
  407wdNQAQO75EfqKkEZtaskCgYEAsfqf+UCWS0McPke+Za0UvFplun2xJybA3TWr
  RIkDKwj/N+IOupY+fjrBBy+QjNbhs0jVx2psuTkR212mpLaua3ekz0Sn/VyfHRCb
  KDjLbRIRVfhaIeIL9pOKoTxRd6AvMj1L4p1A5jT3sgRzgzQM00vWIwiWxzIpoKNt
  3FSVeZ0CgYBzwbJek6Gpy+UCxuOOsef2AyvKvpX3gMIkS0JIlbN5Uw49FW1rwQ0D
  c+Mo35+jFYEI2xBBCQkvga0ncqSW7BK1ubcFhXg9rML9vkVv49l5AGE4SJXKitcD
  lkrj/3il4fBpBpHyWc2C83OlMi6cyj6ggKzxwW/xg4uFp7vf+HNTRg==
  -----END RSA PRIVATE KEY-----


created_at: 2026-01-16 23:14:33.075213304+08:00
updated_at: 2026-01-16 23:14:33.075213304+08:00
key: PASSWORD_PUBLIC_KEY
value:
  -----BEGIN PUBLIC KEY-----
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Ax6Ch5ntmsMkmI4Cmw6
  wMVl/+G6pgGioA7tFeQ+IMXgGbGVIiWDDl+VLyQqGuoLxq5bUSheU+s1awIO68LZ
  yBBMHZz+pb9FzuX282Y3PXXCStGnjdjPRd2nTjqBmBvMf034uW+0FJUzpoi1kkEt
  9huUTLfMUlNUpuv4B6aNJ+latCicQdqVqNGfpNo6l4fFAgnysi/G3llr9geYWsAK
  +oOfrLCz0MYV4BIdqBhn37+t3Nz44Q1jF64dYg4Us6PiQt8syoTLc25FvZbxYZWN
  pSPKjtNYbkLJpsjj8NJOC5ZOL28WKmRrcrk5u7Xpt9RtgfmeTLEkazVeEmPNGH3K
  5QIDAQAB
  -----END PUBLIC KEY-----


# script_libraries

created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Docker","es-es":"Instalar Docker","ja":"Dockerをインストール","ko":"Docker 설치","ms":"Pasang Docker","pt-br":"Instalar Docker","ru":"Установить Docker","tr":"Docker'ı Kur","zh":"安装 Docker","zh-hant":"安裝 Docker"}

script:
  #!/bin/bash

  country=$(curl -s ipinfo.io/country)
  echo "Current server location: $country"

  if [[ "$country" == "CN" ]]; then
    bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
  else
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
  fi

description:
  {"en":"Install Docker","es-es":"Instalar Docker","ja":"Dockerをインストール","ko":"Docker 설치","ms":"Pasang Docker","pt-br":"Instalar Docker","ru":"Установить Docker","tr":"Docker'ı Kur","zh":"安装 Docker","zh-hant":"安裝 Docker"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install ClamAV","es-es":"Instalar ClamAV","ja":"ClamAVをインストール","ko":"ClamAV 설치","ms":"Pasang ClamAV","pt-br":"Instalar ClamAV","ru":"Установить ClamAV","tr":"ClamAV Kur","zh":"安装 ClamAV","zh-hant":"安裝 ClamAV"}

script:
  #!/bin/bash

  # Install ClamAV
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color

  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_clamav() {
      echo -e "${GREEN}Detected system: $OS $VERSION${NC}"

      case "$OS" in
          ubuntu|debian)
              apt-get update
              apt-get install -y clamav clamav-daemon clamav-freshclam
              ;;
          centos|rhel|fedora)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  dnf install -y epel-release
                  dnf install -y clamav clamd clamav-update
              else
                  yum install -y epel-release
                  yum install -y clamav clamd clamav-update
              fi
              ;;
          alpine)
              apk add --no-cache clamav clamav-libunrar clamav-daemon clamav-freshclam
              ;;
          arch)
              pacman -Sy --noconfirm clamav
              ;;
          *)
              echo -e "${RED}Unsupported system${NC}"
              exit 1
              ;;
      esac
  }

  configure_clamd() {
      echo -e "${GREEN}Configure clamd...${NC}"
      
      CLAMD_CONF=""
      if [ -f "/etc/clamd.d/scan.conf" ]; then
          CLAMD_CONF="/etc/clamd.d/scan.conf"
      elif [ -f "/etc/clamav/clamd.conf" ]; then
          CLAMD_CONF="/etc/clamav/clamd.conf"
      else
          echo "clamd configuration file not found, please manually configure"
          exit 1
      fi
      cp "$CLAMD_CONF" "$CLAMD_CONF.bak"

      sed -i -E 's|^#\s?LogFileMaxSize\s+.*|LogFileMaxSize 2M|' "$CLAMD_CONF"
      sed -i -E 's|^#\s?PidFile\s+.*|PidFile /run/clamd.scan/clamd.pid|' "$CLAMD_CONF"
      sed -i -E 's|^#\s?DatabaseDirectory\s+.*|DatabaseDirectory /var/lib/clamav|' "$CLAMD_CONF"
      sed -i -E 's|^#\s?LocalSocket\s+.*|LocalSocket /run/clamd.scan/clamd.sock|' "$CLAMD_CONF"
  }

  configure_freshclam() {
      echo -e "${GREEN}Configure freshclam...${NC}"
      
      FRESHCLAM_CONF=""
      if [ -f "/etc/freshclam.conf" ]; then
          FRESHCLAM_CONF="/etc/freshclam.conf"
      elif [ -f "/etc/clamav/freshclam.conf" ]; then
          FRESHCLAM_CONF="/etc/clamav/freshclam.conf"
      else
          echo "freshclam configuration file not found, please manually configure"
          exit 1
      fi
      cp "$FRESHCLAM_CONF" "$FRESHCLAM_CONF.bak"

      sed -i -E 's|^#\s?DatabaseDirectory\s+.*|DatabaseDirectory /var/lib/clamav|' "$FRESHCLAM_CONF"
      sed -i -E 's|^#\s?PidFile\s+.*|PidFile /var/run/freshclam.pid|' "$FRESHCLAM_CONF"
      sed -i '/^DatabaseMirror/d' "$FRESHCLAM_CONF"
      echo "DatabaseMirror database.clamav.net" | sudo tee -a "$FRESHCLAM_CONF"
      sed -i -E 's|^#\s?Checks\s+.*|Checks 12|' "$FRESHCLAM_CONF"
  }

  download_database() {
      systemctl stop clamav-freshclam
      echo -e "${GREEN}The virus database starts to download...${NC}"
      
      MAX_RETRIES=5
      RETRY_DELAY=60
      ATTEMPT=1
      
      while [ $ATTEMPT -le $MAX_RETRIES ]; do
          echo -e "${YELLOW}Try $ATTEMPT/$MAX_RETRIES: run freshclam...${NC}"
          
          if freshclam --verbose; then
              echo -e "${GREEN}Download successfully${NC}"
              return 0
          fi
          
          if [ $ATTEMPT -lt $MAX_RETRIES ]; then
              echo -e "${YELLOW}Download failed, wait $RETRY_DELAY seconds and try again...${NC}"
              sleep $RETRY_DELAY
          fi
          
          ATTEMPT=$((ATTEMPT+1))
      done
      
      echo -e "${RED}Error: Unable to download virus database after $MAX_RETRIES attempt${NC}" >&2
      exit 1
  }

  start_services() {
      echo -e "${GREEN}Start ClamAV...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              systemctl enable --now clamav-daemon
              systemctl enable --now clamav-freshclam
              ;;
          centos|rhel|fedora)
              systemctl enable --now clamd@scan
              systemctl enable --now clamav-freshclam
              ;;
          alpine)
              rc-update add clamd boot
              rc-update add freshclam boot
              rc-service clamd start
              rc-service freshclam start
              ;;
          arch)
              systemctl enable --now clamav-daemon
              systemctl enable --now clamav-freshclam
              ;;
          *)
              echo -e "${YELLOW}The service cannot be started automatically. Please start manually!${NC}"
              ;;
      esac
      
     if ! command -v clamscan &> /dev/null; then
          echo -e "${RED}Install ClamAV failed${NC}"
          exit 1
      fi
      
      echo -e "${GREEN}ClamAV is installed and started${NC}"
  }

  main() {
      detect_os
      install_clamav
      configure_clamd
      configure_freshclam
      download_database
      start_services
  }

  main "$@"

description:
  {"en":"Install ClamAV","es-es":"Instalar ClamAV","ja":"ClamAVをインストール","ko":"ClamAV 설치","ms":"Pasang ClamAV","pt-br":"Instalar ClamAV","ru":"Установить ClamAV","tr":"ClamAV Kur","zh":"安装 ClamAV","zh-hant":"安裝 ClamAV"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Fail2ban","es-es":"Instalar Fail2ban","ja":"Fail2banをインストール","ko":"Fail2ban 설치","ms":"Pasang Fail2ban","pt-br":"Instalar Fail2ban","ru":"Установить Fail2ban","tr":"Fail2ban Kur","zh":"安装 Fail2ban","zh-hant":"安裝 Fail2ban"}

script:
  #!/bin/bash

  # Install Fail2ban
  # Support Ubuntu/Debian/CentOS/RHEL/Almalinux/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color


  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_fail2ban() {
      echo -e "${GREEN}Detected system: $OS $VERSION${NC}"

      case "$OS" in
          ubuntu|debian)
              apt-get update
              if ! command -v rsyslogd >/dev/null 2>&1; then
                  echo -e "${YELLOW}rsyslog not installed. installing rsyslog...${NC}"
                  apt-get install -y rsyslog
              else
                  echo -e "${GREEN}rsyslog is already installed.${NC}"
              fi
              apt-get install -y fail2ban
              ;;
          centos|rhel|fedora|almalinux)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  dnf install -y epel-release
                  dnf install -y fail2ban
              else
                  yum install -y epel-release
                  yum install -y fail2ban
              fi
              ;;
          alpine)
              apk add --no-cache fail2ban
              ;;
          arch)
              pacman -Sy --noconfirm fail2ban
              ;;
          *)
              echo -e "${RED}Unsupported system${NC}"
              exit 1
              ;;
      esac
  }

  configure_fail2ban() {
      echo -e "${GREEN}Configure Fail2ban...${NC}"
      
      FAIL2BAN_CONF="/etc/fail2ban/jail.local"
      LOG_FILE=""
      BAN_ACTION=""

      if systemctl is-active --quiet firewalld 2>/dev/null; then
          BAN_ACTION="firewallcmd-ipset"
      elif systemctl is-active --quiet ufw 2>/dev/null || service ufw status 2>/dev/null | grep -q "active"; then
          BAN_ACTION="ufw"
      else
          BAN_ACTION="iptables-allports"
      fi

      if [ -f /var/log/secure ]; then
          LOG_FILE="/var/log/secure"
      else
          LOG_FILE="/var/log/auth.log"
          [ -f "$LOG_FILE" ] || touch "$LOG_FILE"
      fi

      cat <<EOF > "$FAIL2BAN_CONF"
  #DEFAULT-START
  [DEFAULT]
  bantime = 600
  findtime = 300
  maxretry = 5
  banaction = $BAN_ACTION
  action = %(action_mwl)s
  #DEFAULT-END

  [sshd]
  ignoreip = 127.0.0.1/8
  enabled = true
  filter = sshd
  port = 22
  maxretry = 5
  findtime = 300
  bantime = 600
  banaction = $BAN_ACTION
  action = %(action_mwl)s
  logpath = $LOG_FILE
  EOF
  }

  start_service() {
      echo -e "${GREEN}Start Fail2ban...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              systemctl enable fail2ban
              systemctl restart fail2ban
              ;;
          centos|rhel|fedora|almalinux)
              systemctl enable fail2ban
              systemctl restart fail2ban
              ;;
          alpine)
              rc-update add fail2ban
              rc-service fail2ban start
              ;;
          arch)
              systemctl enable fail2ban
              systemctl restart fail2ban
              ;;
          *)
              echo -e "${YELLOW}The service cannot be started automatically. Please start manually!${NC}"
              ;;
      esac

      if command -v systemctl &> /dev/null; then
          systemctl status fail2ban || true
      else
          rc-service fail2ban status || true
      fi

      echo -e "${GREEN}Fail2ban is installed and started${NC}"
  }

  main() {
      detect_os
      install_fail2ban
      configure_fail2ban
      start_service
  }

  main "$@"

description:
  {"en":"Install Fail2ban","es-es":"Instalar Fail2ban","ja":"Fail2banをインストール","ko":"Fail2ban 설치","ms":"Pasang Fail2ban","pt-br":"Instalar Fail2ban","ru":"Установить Fail2ban","tr":"Fail2ban Kur","zh":"安装 Fail2ban","zh-hant":"安裝 Fail2ban"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Firewalld / UFW","ja":"Firewalld / UFWをインストール","ko":"Firewalld / UFW 설치","ms":"Pasang Firewalld / UFW","pt-br":"Instalar Firewalld / UFW","ru":"Установить Firewalld / UFW","zh":"安装 Firewalld / UFW","zh-hant":"安裝 Firewalld / UFW"}

script:
  #!/bin/bash

  # Install Firewalld | Ufw
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color

  FIREWALL=""


  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_firewall() {
      if [ "$OS" == "ubuntu" ] || [ "$OS" == "debian" ]; then
          echo -e "${GREEN}Detected system: $OS $VERSION, start to install ufw...${NC}"
          FIREWALL="ufw"
          apt-get update
          apt-get install -y ufw
      elif [ "$OS" == "centos" ] || [ "$OS" == "rhel" ] || [ "$OS_LIKE" == "rhel" ]; then
          echo -e "${GREEN}Detected system: $OS $VERSION, start to install firewall...${NC}"
          FIREWALL="firewalld"
          yum update
          yum install -y firewalld
      else
          echo -e "${RED}Unsupported system: $OS $VERSION${NC}"
          exit 1
      fi
  }

  start_with_init() {
      read -p "Please enter the ports to be allowed (separate multiple ports with spaces, e.g., 80 443 22): " PORTS

      if [ -z "$PORTS" ]; then
          echo -e "${RED}Error: No port was entered!${NC}"
          exit 1
      fi

      case $FIREWALL in
          firewalld)
              echo -e "${GREEN}Initialize and start firewalld...${NC}"
              systemctl start firewalld
              systemctl enable firewalld
              
              for port in $PORTS; do
                  firewall-cmd --zone=public --permanent --add-port="$port/tcp"
              done
              
              firewall-cmd --reload
              echo -e "${GREEN}The following TCP ports have been allowed: $PORTS ${NC}"
              ;;
              
          ufw)
              echo -e "${GREEN}Initialize and start ufw...${NC}"
              ufw --force enable
              
              for port in $PORTS; do
                  ufw allow "$port/tcp"
              done
              
              echo -e "${GREEN}The following TCP ports have been allowed: $PORTS ${NC}"
              ;;
      esac
  }

  check_install() {
      if [ "$FIREWALL" = "firewalld" ]; then
          if command -v firewall-cmd &> /dev/null; then
              systemctl status firewalld || true
          fi
      else 
          if command -v ufw &> /dev/null; then
              ufw status || true
          fi
      fi

      echo -e "${GREEN}$FIREWALL is installed and started${NC}"
  }

  main() {
      detect_os
      install_firewall
      start_with_init
      check_install
  }

  main "$@"

description:
  {"en":"Install Firewalld / UFW","ja":"Firewalld / UFWをインストール","ko":"Firewalld / UFW 설치","ms":"Pasang Firewalld / UFW","pt-br":"Instalar Firewalld / UFW","ru":"Установить Firewalld / UFW","zh":"安装 Firewalld / UFW","zh-hant":"安裝 Firewalld / UFW"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Pure-FTPd","es-es":"Instalar Pure-FTPd","ja":"Pure-FTPdをインストール","ko":"Pure-FTPd 설치","ms":"Pasang Pure-FTPd","pt-br":"Instalar Pure-FTPd","ru":"Установить Pure-FTPd","tr":"Pure-FTPd Kur","zh":"安装 Pure-FTPd","zh-hant":"安裝 Pure-FTPd"}

script:
  #!/bin/bash

  # Install Pure-FTPd
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color


  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_pureftpd() {
      echo -e "${GREEN}Detected system: $OS $VERSION${NC}"

      case "$OS" in
          ubuntu|debian)
              apt-get update
              apt-get install -y pure-ftpd
              ;;
          centos|rhel|fedora)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  dnf install -y epel-release
                  dnf install -y pure-ftpd
              else
                  yum install -y epel-release
                  yum install -y pure-ftpd
              fi
              ;;
          alpine)
              apk add --no-cache pure-ftpd
              ;;
          arch)
              pacman -Sy --noconfirm pure-ftpd
              ;;
          *)
              echo -e "${RED}Unsupported system${NC}"
              exit 1
              ;;
      esac

      if ! command -v pure-ftpd &> /dev/null; then
          echo -e "${RED}Install Pure-FTPd failed${NC}"
          exit 1
      fi
  }

  configure_pureftpd() {
      echo -e "${GREEN}Configure Pure-FTPd...${NC}"
      
      if [ ! -d "/etc/pure-ftpd/conf" ]; then
          PURE_FTPD_CONF="/etc/pure-ftpd/pure-ftpd.conf"
          cp "$PURE_FTPD_CONF" "$PURE_FTPD_CONF.bak"
          sed -i 's/^NoAnonymous[[:space:]]\+no$/NoAnonymous yes/' "$PURE_FTPD_CONF"
          sed -i 's/^PAMAuthentication[[:space:]]\+yes$/PAMAuthentication no/' "$PURE_FTPD_CONF"
          sed -i 's/^# PassivePortRange[[:space:]]\+30000 50000$/PassivePortRange 39000 40000/' "$PURE_FTPD_CONF"
          sed -i 's/^VerboseLog[[:space:]]\+no$/VerboseLog yes/' "$PURE_FTPD_CONF"
          sed -i 's/^# PureDB[[:space:]]\+\/etc\/pure-ftpd\/pureftpd\.pdb[[:space:]]*$/PureDB \/etc\/pure-ftpd\/pureftpd.pdb/' "$PURE_FTPD_CONF"
      else
          touch /etc/pure-ftpd/pureftpd.pdb
          chmod 644 /etc/pure-ftpd/pureftpd.pdb
          echo '/etc/pure-ftpd/pureftpd.pdb' > /etc/pure-ftpd/conf/PureDB
          echo yes > /etc/pure-ftpd/conf/VerboseLog 
          echo yes > /etc/pure-ftpd/conf/NoAnonymous
          echo '39000 40000' > /etc/pure-ftpd/conf/PassivePortRange
          echo 'no' > /etc/pure-ftpd/conf/PAMAuthentication
          echo 'no' > /etc/pure-ftpd/conf/UnixAuthentication
          echo 'clf:/var/log/pure-ftpd/transfer.log' > /etc/pure-ftpd/conf/AltLog
          ln -s /etc/pure-ftpd/conf/PureDB /etc/pure-ftpd/auth/50puredb
      fi
  }

  start_service() {
      echo -e "${GREEN}Start Pure-FTPd...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              systemctl enable pure-ftpd
              systemctl restart pure-ftpd
              ;;
          centos|rhel|fedora)
              systemctl enable pure-ftpd
              systemctl restart pure-ftpd
              ;;
          alpine)
              rc-update add pure-ftpd
              rc-service pure-ftpd start
              ;;
          arch)
              systemctl enable pure-ftpd
              systemctl restart pure-ftpd
              ;;
          *)
              echo -e "${YELLOW}The service cannot be started automatically. Please start manually!${NC}"
              ;;
      esac

      if command -v systemctl &> /dev/null; then
          systemctl status pure-ftpd || true
      else
          rc-service pure-ftpd status || true
      fi

      echo -e "${GREEN}Pure-FTPd is installed and started${NC}"
  }

  main() {
      detect_os
      install_pureftpd
      configure_pureftpd
      start_service
  }

  main "$@"

description:
  {"en":"Install Pure-FTPd","es-es":"Instalar Pure-FTPd","ja":"Pure-FTPdをインストール","ko":"Pure-FTPd 설치","ms":"Pasang Pure-FTPd","pt-br":"Instalar Pure-FTPd","ru":"Установить Pure-FTPd","tr":"Pure-FTPd Kur","zh":"安装 Pure-FTPd","zh-hant":"安裝 Pure-FTPd"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Supervisor","es-es":"Instalar Supervisor","ja":"Supervisorをインストール","ko":"Supervisor 설치","ms":"Pasang Supervisor","pt-br":"Instalar Supervisor","ru":"Установить Supervisor","tr":"Supervisor Kur","zh":"安装 Supervisor","zh-hant":"安裝 Supervisor"}

script:
  #!/bin/bash

  # Install Supervisor
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color

  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_supervisor() {
      echo -e "${GREEN}Detected system: $OS $VERSION${NC}"

      case "$OS" in
          ubuntu|debian)
              apt-get update
              apt-get install -y supervisor
              ;;
          centos|rhel|fedora)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  dnf install -y supervisor
              else
                  yum install -y supervisor
              fi
              ;;
          alpine)
              apk add --no-cache supervisor
              mkdir -p /etc/supervisor.d
              ;;
          arch)
              pacman -Sy --noconfirm supervisor
              ;;
          *)
              echo -e "${RED}Unsupported system${NC}"
              exit 1
              ;;
      esac
  }

  start_service() {
      echo -e "${GREEN}Start Supervisor...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              systemctl enable supervisor
              systemctl restart supervisor
              ;;
          centos|rhel|fedora)
              systemctl enable supervisor
              systemctl restart supervisor
              ;;
          alpine)
              rc-update add supervisor
              rc-service supervisor start
              ;;
          arch)
              systemctl enable supervisor
              systemctl restart supervisor
              ;;
          *)
              echo -e "${YELLOW}The service cannot be started automatically. Please start manually!${NC}"
              ;;
      esac

      if command -v systemctl &> /dev/null; then
          systemctl status supervisor || true
      else
          rc-service supervisor status || true
      fi

       echo -e "${GREEN}Supervisor is installed and started${NC}"
  }

  main() {
      detect_os
      install_supervisor
      start_service
  }

  main "$@"

description:
  {"en":"Install Supervisor","es-es":"Instalar Supervisor","ja":"Supervisorをインストール","ko":"Supervisor 설치","ms":"Pasang Supervisor","pt-br":"Instalar Supervisor","ru":"Установить Supervisor","tr":"Supervisor Kur","zh":"安装 Supervisor","zh-hant":"安裝 Supervisor"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install Rsync","es-es":"Instalar Rsync","ja":"Rsyncをインストール","ko":"Rsync 설치","ms":"Pasang Rsync","pt-br":"Instalar Rsync","ru":"Установить Rsync","tr":"Rsync Kur","zh":"安装 Rsync","zh-hant":"安裝 Rsync"}

script:
  #!/bin/bash
  # Install and Configure Rsync
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  BLUE='\033[0;34m'
  NC='\033[0m' # No Color

  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_rsync() {
      echo -e "${GREEN}Detected system: $OS $VERSION${NC}"
      
      # Check if rsync is already installed
      if command -v rsync >/dev/null 2>&1; then
          echo -e "${YELLOW}Rsync is already installed: $(rsync --version | head -n1)${NC}"
          return 0
      fi

      echo -e "${BLUE}Installing rsync...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              apt-get update
              apt-get install -y rsync
              ;;
          centos|rhel|fedora)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  dnf install -y rsync
              else
                  yum install -y rsync
              fi
              ;;
          alpine)
              apk add --no-cache rsync
              ;;
          arch)
              pacman -Sy --noconfirm rsync
              ;;
          *)
              echo -e "${RED}Unsupported system: $OS${NC}"
              exit 1
              ;;
      esac
      
      echo -e "${GREEN}Rsync installed successfully!${NC}"
  }

  configure_rsync() {
      echo -e "${GREEN}Configuring rsync...${NC}"
      
      RSYNCD_CONF="/etc/rsyncd.conf"
      RSYNCD_SECRETS="/etc/rsyncd.secrets"
      RSYNCD_MOTD="/etc/rsyncd.motd"
      
      # Create basic rsyncd.conf if it doesn't exist
      if [ ! -f "$RSYNCD_CONF" ]; then
          echo -e "${BLUE}Creating basic rsyncd.conf...${NC}"
          cat <<EOF > "$RSYNCD_CONF"
  # Rsync daemon configuration
  # Global settings
  uid = nobody
  gid = nobody
  use chroot = yes
  max connections = 4
  pid file = /var/run/rsyncd.pid
  exclude = lost+found/
  transfer logging = yes
  timeout = 600
  ignore nonreadable = yes
  dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

  # Example module (commented out)
  #[backup]
  #    path = /home/backup
  #    comment = Backup Directory
  #    read only = false
  #    list = yes
  #    uid = root
  #    gid = root
  #    auth users = backup
  #    secrets file = /etc/rsyncd.secrets

  EOF
          echo -e "${GREEN}Basic rsyncd.conf created at $RSYNCD_CONF${NC}"
      else
          echo -e "${YELLOW}rsyncd.conf already exists at $RSYNCD_CONF${NC}"
      fi
      
      # Create motd file
      if [ ! -f "$RSYNCD_MOTD" ]; then
          cat <<EOF > "$RSYNCD_MOTD"
  Welcome to this rsync server.
  EOF
          echo -e "${GREEN}Created rsyncd.motd at $RSYNCD_MOTD${NC}"
      fi
      
      # Create example secrets file (with restrictive permissions)
      if [ ! -f "$RSYNCD_SECRETS" ]; then
          cat <<EOF > "$RSYNCD_SECRETS"
  # Format: username:password
  # Example:
  # backup:your_secure_password_here
  EOF
          chmod 600 "$RSYNCD_SECRETS"
          echo -e "${GREEN}Created example rsyncd.secrets at $RSYNCD_SECRETS${NC}"
          echo -e "${YELLOW}Remember to set proper passwords in $RSYNCD_SECRETS${NC}"
      fi
  }

  setup_systemd_service() {
      echo -e "${BLUE}Setting up rsync daemon service...${NC}"
      
      if command -v systemctl >/dev/null 2>&1; then
          # Check if rsync service exists
          if systemctl list-unit-files | grep -q "^rsync.service"; then
              echo -e "${GREEN}Rsync systemd service already exists${NC}"
          else
              # Create systemd service file if it doesn't exist
              SYSTEMD_SERVICE="/etc/systemd/system/rsync.service"
              if [ ! -f "$SYSTEMD_SERVICE" ]; then
                  cat <<EOF > "$SYSTEMD_SERVICE"
  [Unit]
  Description=Rsync daemon
  After=network.target

  [Service]
  Type=notify
  ExecStart=/usr/bin/rsync --daemon --no-detach
  ExecReload=/bin/kill -HUP \$MAINPID
  KillMode=process
  Restart=on-failure
  RestartSec=1

  [Install]
  WantedBy=multi-user.target
  EOF
                  echo -e "${GREEN}Created systemd service file${NC}"
              fi
          fi
          
          # Reload systemd and enable service
          systemctl daemon-reload
          systemctl enable rsync
          echo -e "${GREEN}Rsync daemon service enabled${NC}"
      fi
  }

  setup_xinetd_service() {
      echo -e "${BLUE}Setting up rsync with xinetd...${NC}"
      
      # Install xinetd if not present
      case "$OS" in
          ubuntu|debian)
              if ! command -v xinetd >/dev/null 2>&1; then
                  apt-get install -y xinetd
              fi
              ;;
          centos|rhel|fedora)
              if ! command -v xinetd >/dev/null 2>&1; then
                  if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                      dnf install -y xinetd
                  else
                      yum install -y xinetd
                  fi
              fi
              ;;
          alpine)
              if ! command -v xinetd >/dev/null 2>&1; then
                  apk add --no-cache xinetd
              fi
              ;;
          arch)
              if ! command -v xinetd >/dev/null 2>&1; then
                  pacman -Sy --noconfirm xinetd
              fi
              ;;
      esac
      
      # Create xinetd configuration for rsync
      XINETD_RSYNC="/etc/xinetd.d/rsync"
      if [ ! -f "$XINETD_RSYNC" ]; then
          cat <<EOF > "$XINETD_RSYNC"
  service rsync
  {
          disable         = no
          socket_type     = stream
          wait            = no
          user            = root
          server          = /usr/bin/rsync
          server_args     = --daemon
          log_on_failure  += USERID
  }
  EOF
          echo -e "${GREEN}Created xinetd rsync configuration${NC}"
      fi
  }

  start_service() {
      echo -e "${GREEN}Starting rsync service...${NC}"
      
      case "$OS" in
          ubuntu|debian)
              if command -v systemctl >/dev/null 2>&1; then
                  systemctl start rsync 2>/dev/null || {
                      echo -e "${YELLOW}Systemd service failed, trying xinetd...${NC}"
                      setup_xinetd_service
                      systemctl enable xinetd
                      systemctl start xinetd
                  }
              else
                  setup_xinetd_service
                  service xinetd start
              fi
              ;;
          centos|rhel|fedora)
              if command -v systemctl >/dev/null 2>&1; then
                  systemctl start rsync 2>/dev/null || {
                      echo -e "${YELLOW}Systemd service failed, trying xinetd...${NC}"
                      setup_xinetd_service
                      systemctl enable xinetd
                      systemctl start xinetd
                  }
              else
                  setup_xinetd_service
                  service xinetd start
              fi
              ;;
          alpine)
              setup_xinetd_service
              rc-update add xinetd
              rc-service xinetd start
              ;;
          arch)
              if command -v systemctl >/dev/null 2>&1; then
                  systemctl start rsync 2>/dev/null || {
                      echo -e "${YELLOW}Systemd service failed, trying xinetd...${NC}"
                      setup_xinetd_service
                      systemctl enable xinetd
                      systemctl start xinetd
                  }
              fi
              ;;
          *)
              echo -e "${YELLOW}Service cannot be started automatically. Please start manually!${NC}"
              ;;
      esac
  }

  check_status() {
      echo -e "${BLUE}Checking rsync status...${NC}"
      
      # Check if rsync is installed
      if command -v rsync >/dev/null 2>&1; then
          echo -e "${GREEN}✓ Rsync version: $(rsync --version | head -n1)${NC}"
      else
          echo -e "${RED}✗ Rsync not found${NC}"
          return 1
      fi
      
      # Check if daemon is running
      if pgrep -x rsync >/dev/null; then
          echo -e "${GREEN}✓ Rsync daemon is running${NC}"
      else
          echo -e "${YELLOW}! Rsync daemon is not running${NC}"
      fi
      
      # Check listening ports
      if command -v ss >/dev/null 2>&1; then
          if ss -tlnp | grep -q ":873"; then
              echo -e "${GREEN}✓ Rsync daemon listening on port 873${NC}"
          else
              echo -e "${YELLOW}! Rsync daemon not listening on port 873${NC}"
          fi
      elif command -v netstat >/dev/null 2>&1; then
          if netstat -tlnp | grep -q ":873"; then
              echo -e "${GREEN}✓ Rsync daemon listening on port 873${NC}"
          else
              echo -e "${YELLOW}! Rsync daemon not listening on port 873${NC}"
          fi
      fi
      
      echo -e "${GREEN}Rsync installation completed!${NC}"
  }

  show_usage() {
      echo -e "${BLUE}Rsync Installation Script${NC}"
      echo ""
      echo "Usage: $0 [options]"
      echo ""
      echo "Options:"
      echo "  --daemon-only    Install rsync daemon service only"
      echo "  --client-only    Install rsync client only (no daemon)"
      echo "  --help          Show this help message"
      echo ""
  }

  main() {
      local daemon_only=false
      local client_only=false
      
      # Parse command line arguments
      while [[ $# -gt 0 ]]; do
          case $1 in
              --daemon-only)
                  daemon_only=true
                  shift
                  ;;
              --client-only)
                  client_only=true
                  shift
                  ;;
              --help|-h)
                  show_usage
                  exit 0
                  ;;
              *)
                  echo -e "${RED}Unknown option: $1${NC}"
                  show_usage
                  exit 1
                  ;;
          esac
      done
      
      echo -e "${BLUE}=== Rsync Installation Script ===${NC}"
      
      detect_os
      install_rsync
      
      if [ "$client_only" = false ]; then
          configure_rsync
          setup_systemd_service
          start_service
      fi
      
      check_status
  }

  main "$@"

description:
  {"en":"Install Rsync","es-es":"Instalar Rsync","ja":"Rsyncをインストール","ko":"Rsync 설치","ms":"Pasang Rsync","pt-br":"Instalar Rsync","ru":"Установить Rsync","tr":"Rsync Kur","zh":"安装 Rsync","zh-hant":"安裝 Rsync"}


created_at: 2026-01-16 23:14:33.725538339+08:00
updated_at: 2026-01-16 23:14:33.725538339+08:00
name:
  {"en":"Install FFmpeg","es-es":"Instalar FFmpeg","ja":"FFmpegをインストール","ko":"FFmpeg 설치","ms":"Pasang FFmpeg","pt-br":"Instalar FFmpeg","ru":"Установить FFmpeg","tr":"FFmpeg Kur","zh":"安装 FFmpeg","zh-hant":"安裝 FFmpeg"}

script:
  #!/bin/bash

  # Install FFmpeg
  # Support Ubuntu/Debian/CentOS/RHEL/Alpine/Arch Linux

  set -e

  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  NC='\033[0m' # No Color

  OS=""
  VERSION=""

  detect_os() {
      if [ -f /etc/os-release ]; then
          . /etc/os-release
          OS=$ID
          VERSION=$VERSION_ID
          if [ -n "$ID_LIKE" ]; then
              OS_LIKE=$ID_LIKE
          fi
      elif type lsb_release >/dev/null 2>&1; then
          OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
          VERSION=$(lsb_release -sr)
      elif [ -f /etc/redhat-release ]; then
          OS="rhel"
          VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release)
          OS_LIKE="rhel"
      elif [ -f /etc/alpine-release ]; then
          OS="alpine"
          VERSION=$(cat /etc/alpine-release)
      else
          OS=$(uname -s | tr '[:upper:]' '[:lower:]')
          VERSION=$(uname -r)
      fi
  }

  install_ffmpeg() {
      echo -e "${GREEN}Detected system: $OS $VERSION, start to install FFmpeg...${NC}"
      case "$OS" in
          ubuntu|debian)
              apt-get update
              apt-get install -y ffmpeg
              ;;
          centos|rhel|fedora)
              if [ "$OS" = "rhel" ] && [ "${VERSION%%.*}" -ge 8 ]; then
                  # CentOS 8 / RHEL 8+
                  dnf install -y epel-release
                  dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm
                  dnf install -y ffmpeg ffmpeg-devel
              else
                  # CentOS 7 / RHEL 7
                  yum install -y epel-release
                  yum install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm
                  yum install -y ffmpeg ffmpeg-devel || {
                      # fallback to Nux Dextop if still not available
                      rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
                      rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm
                      yum install -y ffmpeg ffmpeg-devel
                  }
              fi
              ;;
          alpine)
              apk update
              apk add ffmpeg
              ;;
          arch)
              pacman -Sy --noconfirm ffmpeg
              ;;
          *)
              echo -e "${RED}Unsupported system: $OS $VERSION${NC}"
              exit 1
              ;;
      esac
  }

  check_ffmpeg_install() {
      if command -v ffmpeg >/dev/null 2>&1; then
          echo -e "${GREEN}FFmpeg is installed. Version: $(ffmpeg -version | head -n 1)${NC}"
      else
          echo -e "${RED}FFmpeg installation failed or not found.${NC}"
          exit 1
      fi
  }

  main() {
      detect_os
      install_ffmpeg
      check_ffmpeg_install
  }

  main "$@"

description:
  {"en":"Install FFmpeg","es-es":"Instalar FFmpeg","ja":"FFmpegをインストール","ko":"FFmpeg 설치","ms":"Pasang FFmpeg","pt-br":"Instalar FFmpeg","ru":"Установить FFmpeg","tr":"FFmpeg Kur","zh":"安装 FFmpeg","zh-hant":"安裝 FFmpeg"}


