| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- #!/usr/bin/env bash
- #
- # smoke-firstboot.sh — verify the first-boot per-instance credential script.
- #
- # Installs the released x-ui binary into a container WITHOUT a database, runs
- # x-ui-firstboot.sh, and asserts:
- # * fresh random credentials are generated (no admin/admin)
- # * /etc/x-ui/credentials.txt (600) and /etc/motd are written
- # * the sentinel is created and a second run is a no-op (creds unchanged)
- #
- # Requires Docker and network access. Usage: bash deploy/test/smoke-firstboot.sh
- set -euo pipefail
- REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
- IMAGE="${SMOKE_IMAGE:-ubuntu:24.04}"
- if ! command -v docker > /dev/null 2>&1; then
- echo "ERROR: docker is required for this smoke test." >&2
- exit 1
- fi
- echo "== first-boot credential smoke test (image: $IMAGE) =="
- docker run --rm \
- -v "${REPO_ROOT}/deploy/firstboot/x-ui-firstboot.sh:/root/x-ui-firstboot.sh:ro" \
- -e DEBIAN_FRONTEND=noninteractive \
- "$IMAGE" bash -euo pipefail -c '
- apt-get update -qq
- apt-get install -y -qq curl tar openssl ca-certificates jq > /dev/null
- echo "--- installing released x-ui binary (no DB, no systemd) ---"
- REPO=MHSanaei/3x-ui
- ARCH=$(dpkg --print-architecture) # amd64 | arm64
- echo "container arch: $ARCH"
- VER=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | jq -r .tag_name)
- [ -n "$VER" ] && [ "$VER" != "null" ] || { echo "FAIL: cannot resolve version"; exit 1; }
- tmp=$(mktemp -d)
- curl -fL4 -o "${tmp}/x.tar.gz" \
- "https://github.com/${REPO}/releases/download/${VER}/x-ui-linux-${ARCH}.tar.gz"
- tar -xzf "${tmp}/x.tar.gz" -C /usr/local/
- chmod +x /usr/local/x-ui/x-ui
- install -m 755 /root/x-ui-firstboot.sh /usr/local/x-ui/x-ui-firstboot.sh
- # Guarantee a clean slate (the image must never ship a DB).
- rm -f /etc/x-ui/x-ui.db /etc/x-ui/.firstboot-done
- echo "--- run 1: generate per-instance credentials ---"
- /usr/local/x-ui/x-ui-firstboot.sh
- test -f /etc/x-ui/.firstboot-done || { echo "FAIL: sentinel not created"; exit 1; }
- test -f /etc/x-ui/credentials.txt || { echo "FAIL: credentials.txt missing"; exit 1; }
- perms=$(stat -c %a /etc/x-ui/credentials.txt)
- [ "$perms" = "600" ] || { echo "FAIL: credentials.txt perms=$perms (want 600)"; exit 1; }
- grep -q "3x-ui" /etc/motd || { echo "FAIL: motd not written"; exit 1; }
- # shellcheck disable=SC1090
- . /etc/x-ui/credentials.txt
- [ -n "${XUI_USERNAME:-}" ] && [ "$XUI_USERNAME" != "admin" ] \
- || { echo "FAIL: username missing or still admin"; exit 1; }
- first_user="$XUI_USERNAME"
- /usr/local/x-ui/x-ui setting -show | grep -q "hasDefaultCredential: false" \
- || { echo "FAIL: hasDefaultCredential is not false"; exit 1; }
- echo "--- run 2: must be a no-op (sentinel honored) ---"
- /usr/local/x-ui/x-ui-firstboot.sh
- # shellcheck disable=SC1090
- . /etc/x-ui/credentials.txt
- [ "$XUI_USERNAME" = "$first_user" ] \
- || { echo "FAIL: credentials changed on re-run"; exit 1; }
- echo "SMOKE_PASS: firstboot user=$first_user (stable across re-run)"
- '
- echo "== first-boot smoke test PASSED =="
|