diff --git a/Dockerfile b/Dockerfile index b402ce9..7704234 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,40 +3,41 @@ ARG GO_VERSION=1.24.1 FROM --platform=$BUILDPLATFORM golang:$GO_VERSION AS psiphon_builder WORKDIR /go LABEL stage=builder -ARG BUILDOS -ARG BUILDARCH ARG TARGETS ARG PSIPHON_VERSION -ENV DIR=/go/src/github.com/Psiphon-Labs/psiphon-tunnel-core -ENV GO111MODULE=off -ENV CGO_ENABLED=0 -SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ADD build.sh latest_version.sh /go/ RUN <<__SCRIPT__ -TARGET_PALTFORMS=${TARGETS:-"$BUILDOS/$BUILDARCH"} -TARGET_PALTFORMS=${TARGET_PALTFORMS//,/ } -mkdir -p ${DIR} -curl -sL https://github.com/Psiphon-Labs/psiphon-tunnel-core/archive/refs/tags/v${PSIPHON_VERSION}.tar.gz | tar xz -C ${DIR} --strip-components=1 -for PLATFORM in $TARGET_PALTFORMS -do - OS=${PLATFORM%%/*} - ARCH=${PLATFORM#*/} - ARCH=${ARCH%/*} - VERSION=${PLATFORM##*/} - TARGETVARIANT=${VERSION/$ARCH/} - VERSION=${TARGETVER/v/} - GOOS=${OS} GOARCH=${ARCH} go install -a -tags netgo -ldflags '-w -extldflags "-static"' github.com/Psiphon-Labs/psiphon-tunnel-core/ConsoleClient - BINARY=$(find /go/bin/* -name "ConsoleClient*") - mv ${BINARY} /go/psiphon_${OS}_${ARCH}_${TARGETVARIANT} -done +ARGS="" +if [ -n "${TARGETS}" ]; then + ARGS="${ARGS} --targets ${TARGETS}" +fi +if [ -n "${PSIPHON_VERSION}" ]; then + ARGS="${ARGS} --version ${PSIPHON_VERSION}" +fi +/go/build.sh ${ARGS} __SCRIPT__ -FROM swarupsengupta2007/alpine-s6:3.16.0 +FROM alpine:3.22.0 ARG TARGETOS ARG TARGETARCH ARG TARGETVARIANT -COPY base/ / -COPY psiphon.config ${DEF_DEFAULTS} -COPY --from=psiphon_builder /go/psiphon_${TARGETOS}_${TARGETARCH}_${TARGETVARIANT} ${DEF_APP}/psiphon -EXPOSE 8080 1080 -HEALTHCHECK --interval=30s --timeout=5s --start-period=2m --retries=3 CMD netstat -ltn|grep 1080 || exit 1 -VOLUME /config +RUN --mount=type=bind,from=psiphon_builder,source=/go/dist,target=/tmp/psiphon \ + --mount=type=bind,source=./assets,target=/tmp/assets \ + <<__SCRIPT__ + apk add --no-cache tini + cp /tmp/assets/start-psiphon /usr/local/bin/start-psiphon + cp /tmp/assets/healtcheck /usr/local/bin/healtcheck + mkdir -p /etc/psiphon + cp /tmp/assets/psiphon.config /etc/psiphon/psiphon.config + if [ -z "${TARGETVARIANT}" ]; then + cp /tmp/psiphon/psiphon_${TARGETOS}_${TARGETARCH} /usr/local/bin/psiphon + else + cp /tmp/psiphon/psiphon_${TARGETOS}_${TARGETARCH}_${TARGETVARIANT} /usr/local/bin/psiphon + fi + chmod +x /usr/local/bin/start-psiphon + chmod +x /usr/local/bin/healtcheck + chmod +x /usr/local/bin/psiphon +__SCRIPT__ +ENTRYPOINT ["/sbin/tini", "--"] +CMD ["/usr/local/bin/start-psiphon"] +HEALTHCHECK --interval=30s --timeout=5s --start-period=2m --retries=3 CMD healtcheck diff --git a/build.sh b/build.sh index dc54b80..861a323 100755 --- a/build.sh +++ b/build.sh @@ -43,28 +43,24 @@ while [[ $# -gt 0 ]]; do esac done -source ./lastest_version.sh +MYPATH=$(dirname "$(readlink -f "$0")") +source "${MYPATH}/latest_version.sh" if [[ -z "${PSIPHON_VERSION}" ]]; then PSIPHON_VERSION=$(get_latest_version) else - if ! validate_version_format "$PSIPHON_VERSION"; then + if ! validate_version_format "${PSIPHON_VERSION}"; then echo "Invalid Psiphon version format. Please use 'X.Y.Z' or 'vX.Y.Z' format." exit 1 fi fi -PSIPHON_VERSION=$(normalize_version "$PSIPHON_VERSION") +PSIPHON_VERSION=$(normalize_version "${PSIPHON_VERSION}") ALL_TARGETS="linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6,windows/amd64,windows/386,darwin/amd64,darwin/arm64" CURRENT_TARGET="$(go env GOOS)/$(go env GOARCH)" TARGETS=${TARGETS:-"current"} -if [[ "${TARGETS}" == "current" ]]; then - TARGETS="${CURRENT_TARGET}" -elif [[ "${TARGETS}" == "all" ]]; then - TARGETS="${ALL_TARGETS}" -fi - +TARGETS=$(decipher_targets "${TARGETS}") TARGETS=${TARGETS//,/ } BUILD_DIR=$(pwd)/tmp_build_$$ @@ -79,20 +75,23 @@ mkdir -p "${BIN_DIR}" curl -sL https://github.com/Psiphon-Labs/psiphon-tunnel-core/archive/refs/tags/${PSIPHON_VERSION}.tar.gz | tar xz --strip-components=1 -C "${BUILD_DIR}" pushd "${BUILD_DIR}/ConsoleClient" > /dev/null +export CGO_ENABLED=0 + for PLATFORM in ${TARGETS} do IFS='/' read -r OS ARCH VARIANT <<< "${PLATFORM}" + + export GOOS=${OS} + export GOARCH=${ARCH} + if [[ -n "${VARIANT}" ]]; then + export GOARM=${VARIANT#v} + fi GOEXT="" if [[ "${OS}" == "windows" ]]; then GOEXT=".exe" fi - - GOARM_ENV="" - if [[ -n "${VARIANT}" ]]; then - GOARM_ENV="GOARM=${VARIANT#v}" - fi - - CGO_ENABLED=0 GOOS=${OS} GOARCH=${ARCH} ${GOARM_ENV} ${GO} build -a -tags netgo -ldflags "-s -w -extldflags '-static'" -o "${BIN_DIR}/psiphon_${PLATFORM//\//_}${GOEXT}" + ${GO} build -a -tags netgo -ldflags "-s -w -extldflags '-static'" -o "${BIN_DIR}/psiphon_${PLATFORM//\//_}${GOEXT}" + unset GOOS GOARCH GOARM done popd > /dev/null diff --git a/latest_version.sh b/latest_version.sh index 7f2ab66..3657d1b 100644 --- a/latest_version.sh +++ b/latest_version.sh @@ -11,34 +11,53 @@ fi function validate_version_format() { local v="$1" - [[ "$v" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]] + [[ "${v}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]] } function get_latest_version() { local json version json="$(curl -fsSL https://api.github.com/repos/Psiphon-Labs/psiphon-tunnel-core/releases/latest)" if command -v jq >/dev/null 2>&1; then - version="$(printf '%s' "$json" | jq -r .tag_name)" + version="$(printf '%s' "${json}" | jq -r .tag_name)" else - version="$(printf '%s' "$json" \ + version="$(printf '%s' "${json}" \ | grep -m1 '"tag_name":' \ | sed -E 's/.*"tag_name": ?"([^"]+)".*/\1/')" fi - if ! validate_version_format "$version"; then + if ! validate_version_format "${version}"; then echo "I tried to get the latest version of Psiphon without jq but it didn't work." >&2 echo "Please install jq or specify the version manually." >&2 exit 1 fi - printf '%s\n' "$version" + printf '%s\n' "${version}" } function normalize_version() { local v="$1" - if [[ "$v" =~ ^v ]]; then - echo "$v" + if [[ "${v}" =~ ^v ]]; then + echo "${v}" else - echo "v$v" + echo "v${v}" + fi +} + +function get_supported_targets() { + echo "linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6" +} + +function get_current_target() { + echo "$(go env GOOS)/$(go env GOARCH)" +} + +function decipher_targets() { + local targets="$1" + if [[ "${targets}" == "current" ]]; then + echo "$(get_current_target)" + elif [[ "${targets}" == "all" ]]; then + echo "$(get_supported_targets)" + else + echo "${targets}" fi } \ No newline at end of file diff --git a/make.bash b/make.bash index 225e29b..c60cd1a 100755 --- a/make.bash +++ b/make.bash @@ -1,13 +1,109 @@ -#!/bin/bash +#!/usr/bin/env bash -MK_TARGETS=${TARGETS:-"linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6"} -MK_VERSION=${VERSION:-2.0.32} -MK_GO_VERSION=${GO_VERSION:-1.23.7} +set -euo pipefail +IFS=$'\n\t' + +function help_message() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --targets, -t Comma-separated list of target platforms (default: current, use 'all' for all supported targets)" + echo " --version, -v Psiphon version to build (default: 2.0.32)" + echo " --go, -g Go version to use (default: 1.22.7)" + echo " --help, -h Show this help message and exit" + echo " --supported-targets Show supported targets and exit" + exit ${1:-1} +} + +EXTRA_BUILD_ARGS="" +VERSION="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + help_message 0 + ;; + --targets=*) + TARGETS="${1#*=}" + shift + ;; + -t | --targets) + TARGETS="$2" + shift 2 + ;; + --version=*) + VERSION="${1#*=}" + shift + ;; + -v | --version) + VERSION="$2" + shift 2 + ;; + --go=*) + GO_VERSION="${1#*=}" + shift + ;; + -g | --go) + GO_VERSION="$2" + shift 2 + ;; + --supported-targets) + echo "Supported targets: $(get_supported_targets)" + exit 0 + ;; + --current-target) + echo "Current target: $(get_current_target)" + exit 0 + ;; + -l | --load) + if [[ -n ${EXTRA_BUILD_ARGS} && ${EXTRA_BUILD_ARGS} == *"--push"* ]]; then + echo "Error: --load and --push cannot be used together." >&2 + exit 1 + fi + EXTRA_BUILD_ARGS="--load" + shift + ;; + -p | --push) + if [[ -n ${EXTRA_BUILD_ARGS} && ${EXTRA_BUILD_ARGS} == *"--load"* ]]; then + echo "Error: --load and --push cannot be used together." >&2 + exit 1 + fi + EXTRA_BUILD_ARGS="--push" + shift + ;; + *) + echo "Error: Unknown option '$1'" >&2 + help_message + ;; + esac +done + +TARGETS=${TARGETS:-"current"} +GO_VERSION=${GO_VERSION:-1.22.7} + +MYPATH=$(dirname "$(readlink -f "$0")") +source "${MYPATH}/latest_version.sh" + +DOCKER_BUILD_ARGS=() + +if [[ -n "${TARGETS}" ]]; then + DOCKER_BUILD_ARGS+=(--build-arg TARGETS=${TARGETS}) +fi +if [[ -z "${VERSION}" ]]; then + VERSION=$(get_latest_version) +fi +if [[ -n "${VERSION}" ]]; then + VERSION=$(normalize_version "${VERSION}") + DOCKER_BUILD_ARGS+=(--build-arg PSIPHON_VERSION=${VERSION}) +fi +if [[ -n "${GO_VERSION}" ]]; then + DOCKER_BUILD_ARGS+=(--build-arg GO_VERSION=${GO_VERSION}) +fi + +DECIPHERED_TARGETS=$(decipher_targets "${TARGETS}") docker buildx build \ - --build-arg TARGETS=${MK_TARGETS} \ - --build-arg PSIPHON_VERSION=${MK_VERSION} \ - --build-arg GO_VERSION=${MK_GO_VERSION} \ - -t swarupsengupta2007/psiphon:${MK_VERSION} \ + "${DOCKER_BUILD_ARGS[@]}" \ + -t swarupsengupta2007/psiphon:"${VERSION#v}" \ -t swarupsengupta2007/psiphon:latest \ - --platform ${MK_TARGETS} . $1 + --platform "${DECIPHERED_TARGETS}" . \ + ${EXTRA_BUILD_ARGS}