From ae710732aa5ced7d1910ddd63aabdbc3780c2911 Mon Sep 17 00:00:00 2001 From: Wang Defa Date: Mon, 8 Dec 2025 10:11:41 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/ci.yaml | 218 +++++++++++++++++++++++++++++++++++++++ .gitignore | 6 ++ debian/build-deb.sh | 85 +++++++++++++++ debian/control.template | 18 ++++ debian/p2pool.service | 26 +++++ debian/postinst | 61 +++++++++++ debian/postrm | 34 ++++++ debian/prerm | 10 ++ docker/Dockerfile.alpine | 44 ++++++++ docker/Dockerfile.ubuntu | 44 ++++++++ 10 files changed, 546 insertions(+) create mode 100644 .gitea/workflows/ci.yaml create mode 100644 .gitignore create mode 100755 debian/build-deb.sh create mode 100644 debian/control.template create mode 100644 debian/p2pool.service create mode 100755 debian/postinst create mode 100755 debian/postrm create mode 100755 debian/prerm create mode 100644 docker/Dockerfile.alpine create mode 100644 docker/Dockerfile.ubuntu diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..877d952 --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,218 @@ +# .gitea/workflows/ci.yaml +name: Build and Release + +on: + push: + branches: [main, develop] + tags: ['*'] + +env: + DOCKER_BUILDKIT: "1" + PRODUCT_NAME: "p2pool" + PACKAGE_VERSION: "v4.12" + BUILDX_NO_DEFAULT_ATTESTATIONS: "1" + +jobs: + build-and-test: + runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest-amd64' || 'ubuntu-latest-arm64' }} + strategy: + matrix: + arch: [amd64, arm64] + distro: [ubuntu, alpine] + steps: + - uses: actions/checkout@v4 + + - name: Setup Docker Buildx + run: | + # 创建 buildx builder(原生构建不需要 QEMU) + docker buildx create --use --name native-builder \ + --driver docker-container \ + --driver-opt network=host \ + --driver-opt env.BUILDKIT_STEP_LOG_MAX_SIZE=50000000 \ + --driver-opt env.BUILDKIT_STEP_LOG_MAX_SPEED=10000000 \ + || true + docker buildx inspect --bootstrap + + - name: Build binaries + run: | + P2POOL_VERSION=${PACKAGE_VERSION} + PLATFORM="linux/${{ matrix.arch }}" + + echo "🏗️ Building ${PLATFORM} on native ${{ matrix.arch }} runner" + echo "📦 Distribution: ${{ matrix.distro }}" + + # 设置 BuildKit 优化参数 + export BUILDKIT_PROGRESS=plain + + docker buildx build --pull \ + --platform ${PLATFORM} \ + --build-arg P2POOL_VERSION=${P2POOL_VERSION} \ + --output type=local,dest=./output \ + -f docker/Dockerfile.${{ matrix.distro }} . + + - name: Package and test + run: | + DIR="./output/linux_${{ matrix.arch }}" + + if [ ! -d "$DIR" ]; then + echo "❌ 构建输出目录不存在: $DIR" + exit 1 + fi + + TARGZ="${PRODUCT_NAME}-${{ matrix.arch }}-${{ matrix.distro }}-${PACKAGE_VERSION}.tar.gz" + tar -czf "${TARGZ}" -C "$DIR" . + + echo "📦 Created package: ${TARGZ}" + ls -lh "${TARGZ}" + + # 快速验证 + mkdir -p test && tar -xzf "${TARGZ}" -C test + test/p2pool --help 2>/dev/null || echo "⚠️ Help displayed" + rm -rf test + + - name: Build Debian package + if: matrix.distro == 'ubuntu' + run: | + # 安装 dpkg-deb(如果需要) + sudo apt-get update && sudo apt-get install -y dpkg-dev + + TARGZ="${PRODUCT_NAME}-${{ matrix.arch }}-${{ matrix.distro }}-${PACKAGE_VERSION}.tar.gz" + + echo "📦 Building Debian package for ${{ matrix.arch }}..." + chmod +x debian/build-deb.sh + ./debian/build-deb.sh ${{ matrix.arch }} ${PACKAGE_VERSION} "${TARGZ}" + + ls -lh *.deb + + - uses: https://github.com/ChristopherHX/gitea-upload-artifact@v4 + with: + name: binaries-${{ matrix.arch }}-${{ matrix.distro }} + path: | + *.tar.gz + *.deb + retention-days: 1 + + release: + runs-on: ubuntu-latest-amd64 + needs: build-and-test + if: startsWith(github.ref, 'refs/tags/') + steps: + - uses: https://github.com/ChristopherHX/gitea-download-artifact@v4 + with: + pattern: binaries-* + path: ./packages + merge-multiple: true + + - name: Upload packages and create release + env: + TOKEN: ${{ secrets.BUILD_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + cd packages + + # 提取仓库信息(移除 https:// 前缀和仓库路径) + REGISTRY=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||') + OWNER="${{ gitea.repository_owner }}" + REPO_NAME=$(echo "${{ gitea.repository }}" | cut -d'/' -f2) + + echo "📦 上传包到 Generic Package Registry..." + echo " Registry: ${REGISTRY}" + echo " Owner: ${OWNER}" + echo " Package: ${PRODUCT_NAME}" + echo " Version: ${TAG}" + + # 上传所有 tar.gz 包到 Generic Package Registry + for file in *.tar.gz; do + [ ! -f "$file" ] && continue + echo " ⬆️ $file" + curl -fsSL -X PUT \ + -H "Authorization: token ${TOKEN}" \ + --upload-file "$file" \ + "https://${REGISTRY}/api/packages/${OWNER}/generic/${PRODUCT_NAME}/${TAG}/$file" || { + echo "❌ 上传失败: $file" + exit 1 + } + done + + # 上传 Debian 包到 Debian Package Registry (支持多个发行版) + echo "" + echo "📦 上传 Debian 包到 Debian Package Registry..." + for file in *.deb; do + [ ! -f "$file" ] && continue + + # 上传到 bookworm (Debian 12) + echo " ⬆️ $file → bookworm" + curl -fsSL -X PUT \ + -H "Authorization: token ${TOKEN}" \ + --upload-file "$file" \ + "https://${REGISTRY}/api/packages/${OWNER}/debian/pool/bookworm/main/upload" || { + echo "❌ Debian 包上传失败: $file (bookworm)" + exit 1 + } + + # 上传到 trixie (Debian 13) + echo " ⬆️ $file → trixie" + curl -fsSL -X PUT \ + -H "Authorization: token ${TOKEN}" \ + --upload-file "$file" \ + "https://${REGISTRY}/api/packages/${OWNER}/debian/pool/trixie/main/upload" || { + echo "❌ Debian 包上传失败: $file (trixie)" + exit 1 + } + done + + # 生成 Release JSON payload + echo "" + echo "📝 生成 Release..." + + export REGISTRY OWNER TAG + RELEASE_DATA=$(python3 -c 'import json,glob,os;r=os.environ["REGISTRY"];o=os.environ["OWNER"];p=os.environ["PRODUCT_NAME"];t=os.environ["TAG"];b=["## Release "+t,"","### 📥 下载方式","","#### 方式 1: 直接下载(推荐)","","点击下面 **Assets** 部分的文件名直接下载。","","#### 方式 2: Generic Package Registry",""]+[f"- [`{f}`](https://{r}/api/packages/{o}/generic/{p}/{t}/{f})" for f in sorted(glob.glob("*.tar.gz"))]+["","#### 方式 3: Debian Repository","","**Debian 12 (bookworm):**","","```bash","# Download GPG key",f"sudo curl https://{r}/api/packages/{o}/debian/repository.key -o /etc/apt/keyrings/gitea-{o}.asc","","# Add repository",f"echo \"deb [signed-by=/etc/apt/keyrings/gitea-{o}.asc] https://{r}/api/packages/{o}/debian bookworm main\" | sudo tee -a /etc/apt/sources.list.d/{o}.list","","# Update and install","sudo apt-get update",f"sudo apt-get install {p}","```","","**Debian 13 (trixie):**","","```bash","# Download GPG key",f"sudo curl https://{r}/api/packages/{o}/debian/repository.key -o /etc/apt/keyrings/gitea-{o}.asc","","# Add repository",f"echo \"deb [signed-by=/etc/apt/keyrings/gitea-{o}.asc] https://{r}/api/packages/{o}/debian trixie main\" | sudo tee -a /etc/apt/sources.list.d/{o}.list","","# Update and install","sudo apt-get update",f"sudo apt-get install {p}","```"];print(json.dumps({"tag_name":t,"name":f"Release {t}","body":"\n".join(b),"draft":False,"prerelease":False}))') + + # 创建 Release + echo "" + echo "🎉 创建 Release..." + RESPONSE=$(curl -fsSL -w "\n%{http_code}" -X POST \ + -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + "https://${REGISTRY}/api/v1/repos/${{ gitea.repository }}/releases" \ + -d "${RELEASE_DATA}") + + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + RESPONSE_BODY=$(echo "$RESPONSE" | head -n-1) + + if [ "$HTTP_CODE" = "201" ]; then + echo "✅ Release 创建成功" + RELEASE_ID=$(echo "$RESPONSE_BODY" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) + echo " Release ID: ${RELEASE_ID}" + elif [ "$HTTP_CODE" = "409" ]; then + echo "⚠️ Release 已存在,获取现有 Release ID..." + RELEASE_ID=$(curl -fsSL \ + -H "Authorization: token ${TOKEN}" \ + "https://${REGISTRY}/api/v1/repos/${{ gitea.repository }}/releases/tags/${TAG}" | \ + grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) + echo " Release ID: ${RELEASE_ID}" + else + echo "❌ 创建 Release 失败 (HTTP ${HTTP_CODE})" + echo "$RESPONSE_BODY" + exit 1 + fi + + # 上传文件作为 Release 附件 + echo "" + echo "📎 上传文件作为 Release 附件..." + for file in *.tar.gz *.deb; do + [ ! -f "$file" ] && continue + echo " ⬆️ $file" + + # 使用 multipart/form-data 上传附件 + curl -fsSL -X POST \ + -H "Authorization: token ${TOKEN}" \ + -F "attachment=@${file}" \ + "https://${REGISTRY}/api/v1/repos/${{ gitea.repository }}/releases/${RELEASE_ID}/assets?name=${file}" || { + echo " ⚠️ 附件上传失败: $file(可能已存在)" + } + done + + echo "" + echo "✅ Release 创建完成!" + echo "🔗 访问: https://${REGISTRY}/${{ gitea.repository }}/releases/tag/${TAG}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78b8f8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +.vscode/ +.claude/ +CLAUDE.md +docs/ +example/ diff --git a/debian/build-deb.sh b/debian/build-deb.sh new file mode 100755 index 0000000..917353a --- /dev/null +++ b/debian/build-deb.sh @@ -0,0 +1,85 @@ +#!/bin/bash +set -e + +# 参数检查 +if [ $# -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 amd64 v4.12 p2pool-amd64-ubuntu-v4.12.tar.gz" + exit 1 +fi + +ARCH=$1 +VERSION=$2 +TARGZ_FILE=$3 +PKG_NAME="p2pool" +DEB_FILE="${PKG_NAME}_${VERSION}_${ARCH}.deb" + +# 转换架构名称(Docker 使用的架构名到 Debian 架构名) +case "$ARCH" in + amd64) + DEB_ARCH="amd64" + ;; + arm64) + DEB_ARCH="arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; +esac + +echo "📦 Building Debian package: ${DEB_FILE}" +echo " Architecture: ${DEB_ARCH}" +echo " Version: ${VERSION}" +echo " Source: ${TARGZ_FILE}" + +# 创建临时目录 +BUILD_DIR=$(mktemp -d) +trap "rm -rf $BUILD_DIR" EXIT + +# 创建包目录结构 +PKG_DIR="${BUILD_DIR}/${PKG_NAME}_${VERSION}_${DEB_ARCH}" +mkdir -p "${PKG_DIR}/DEBIAN" +mkdir -p "${PKG_DIR}/usr/local/bin" +mkdir -p "${PKG_DIR}/lib/systemd/system" +mkdir -p "${PKG_DIR}/etc/p2pool" + +# 解压二进制文件 +echo "📂 Extracting binaries..." +tar -xzf "${TARGZ_FILE}" -C "${PKG_DIR}/usr/local/bin" + +# 生成 control 文件 +echo "📝 Generating control file..." +sed -e "s/{{VERSION}}/${VERSION}/" \ + -e "s/{{ARCH}}/${DEB_ARCH}/" \ + debian/control.template > "${PKG_DIR}/DEBIAN/control" + +# 复制维护脚本 +echo "📋 Copying maintainer scripts..." +cp debian/postinst "${PKG_DIR}/DEBIAN/postinst" +cp debian/prerm "${PKG_DIR}/DEBIAN/prerm" +cp debian/postrm "${PKG_DIR}/DEBIAN/postrm" +chmod 755 "${PKG_DIR}/DEBIAN/postinst" +chmod 755 "${PKG_DIR}/DEBIAN/prerm" +chmod 755 "${PKG_DIR}/DEBIAN/postrm" + +# 复制 systemd service 文件 +echo "🔧 Installing systemd service..." +cp debian/p2pool.service "${PKG_DIR}/lib/systemd/system/" + +# 设置权限 +chmod 755 "${PKG_DIR}/usr/local/bin/p2pool" +chmod 644 "${PKG_DIR}/lib/systemd/system/p2pool.service" + +# 构建 deb 包 +echo "🔨 Building package..." +dpkg-deb --build --root-owner-group "${PKG_DIR}" "${DEB_FILE}" + +# 检查包 +echo "✅ Package built successfully!" +echo "📦 Package: $(pwd)/${DEB_FILE}" +echo "📊 Package info:" +dpkg-deb --info "${DEB_FILE}" + +echo "" +echo "🎉 Done!" diff --git a/debian/control.template b/debian/control.template new file mode 100644 index 0000000..fd77d9d --- /dev/null +++ b/debian/control.template @@ -0,0 +1,18 @@ +Package: p2pool +Version: {{VERSION}} +Section: net +Priority: optional +Architecture: {{ARCH}} +Depends: libc6, libuv1, libzmq5, libcurl4 +Maintainer: P2Pool Team +Homepage: https://github.com/SChernykh/p2pool +Description: Decentralized pool for Monero mining + P2Pool is a decentralized Monero mining pool that runs on a sidechain. + . + Key features: + - 0% fee + - No central administrator + - Trustless - funds are never in custody + - Supports regular payouts similar to traditional pools + - Permissionless - no one decides who can mine + - Supports merge mining diff --git a/debian/p2pool.service b/debian/p2pool.service new file mode 100644 index 0000000..0a55b8c --- /dev/null +++ b/debian/p2pool.service @@ -0,0 +1,26 @@ +[Unit] +Description=P2Pool - Decentralized Monero Mining Pool +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=p2pool +Group=p2pool +WorkingDirectory=/var/lib/p2pool +ExecStart=/usr/local/bin/p2pool --host 127.0.0.1 --rpc-port 18081 --wallet YOUR_MONERO_WALLET_ADDRESS +Restart=on-failure +RestartSec=10s +StandardOutput=journal +StandardError=journal +SyslogIdentifier=p2pool + +# Security hardening +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/p2pool /var/log/p2pool + +[Install] +WantedBy=multi-user.target diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 0000000..e17a18d --- /dev/null +++ b/debian/postinst @@ -0,0 +1,61 @@ +#!/bin/sh +set -e + +# Create user and group if they don't exist +if ! getent group p2pool >/dev/null; then + addgroup --system p2pool +fi + +if ! getent passwd p2pool >/dev/null; then + adduser --system --ingroup p2pool --no-create-home \ + --home /var/lib/p2pool --shell /usr/sbin/nologin \ + --gecos "P2Pool Service" p2pool +fi + +# Create data directory +mkdir -p /var/lib/p2pool +chown p2pool:p2pool /var/lib/p2pool +chmod 750 /var/lib/p2pool + +# Create log directory +mkdir -p /var/log/p2pool +chown p2pool:p2pool /var/log/p2pool +chmod 750 /var/log/p2pool + +# Set binary permissions +chown root:root /usr/local/bin/p2pool +chmod 755 /usr/local/bin/p2pool + +# Reload systemd +if [ -d /run/systemd/system ]; then + systemctl daemon-reload +fi + +echo "" +echo "✅ P2Pool installed successfully!" +echo "" +echo "📋 Before starting P2Pool, you MUST:" +echo "" +echo "1. Edit the systemd service file to set your Monero wallet address:" +echo " sudo systemctl edit --full p2pool.service" +echo "" +echo " Replace 'YOUR_MONERO_WALLET_ADDRESS' with your actual Monero wallet address" +echo " and configure --host and --rpc-port to point to your Monero node" +echo "" +echo "2. Start P2Pool:" +echo " sudo systemctl enable p2pool.service" +echo " sudo systemctl start p2pool.service" +echo "" +echo "3. Check status:" +echo " sudo systemctl status p2pool.service" +echo " sudo journalctl -u p2pool -f" +echo "" +echo "Data directory: /var/lib/p2pool" +echo "Log directory: /var/log/p2pool" +echo "Binary: /usr/local/bin/p2pool" +echo "" +echo "For help:" +echo " p2pool --help" +echo "" + +exit 0 diff --git a/debian/postrm b/debian/postrm new file mode 100755 index 0000000..4f5beea --- /dev/null +++ b/debian/postrm @@ -0,0 +1,34 @@ +#!/bin/sh +set -e + +case "$1" in + purge) + # Remove user and group + if getent passwd p2pool >/dev/null; then + deluser --system p2pool 2>/dev/null || true + fi + if getent group p2pool >/dev/null; then + delgroup --system p2pool 2>/dev/null || true + fi + + # Remove data directories (only on purge) + rm -rf /var/lib/p2pool + rm -rf /var/log/p2pool + ;; + + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + # Do nothing + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# Reload systemd +if [ -d /run/systemd/system ]; then + systemctl daemon-reload +fi + +exit 0 diff --git a/debian/prerm b/debian/prerm new file mode 100755 index 0000000..c9b7e7b --- /dev/null +++ b/debian/prerm @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +# Stop service if running +if [ -d /run/systemd/system ] && systemctl is-active --quiet p2pool.service; then + echo "Stopping P2Pool service..." + systemctl stop p2pool.service +fi + +exit 0 diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine new file mode 100644 index 0000000..5a58b41 --- /dev/null +++ b/docker/Dockerfile.alpine @@ -0,0 +1,44 @@ +FROM alpine:3.21 AS base + +ARG TARGETARCH + +RUN apk update && apk add --no-cache \ + git \ + cmake \ + gcc \ + g++ \ + make \ + linux-headers \ + libuv-dev \ + zeromq-dev \ + curl-dev + +FROM base AS build + +ARG P2POOL_VERSION +ARG TARGETARCH +ARG BUILDPLATFORM +ARG TARGETPLATFORM + +RUN git clone --recursive https://github.com/SChernykh/p2pool /src/p2pool + +WORKDIR /src/p2pool + +RUN git checkout ${P2POOL_VERSION} + +# Determine parallel jobs based on cross-compilation +RUN mkdir build && cd build && \ + if [ "$BUILDPLATFORM" != "$TARGETPLATFORM" ]; then \ + MAKE_JOBS="-j2"; \ + else \ + MAKE_JOBS="-j$(nproc)"; \ + fi && \ + echo "Building with parallel jobs: $MAKE_JOBS (cross-compile: $([ "$BUILDPLATFORM" != "$TARGETPLATFORM" ] && echo yes || echo no))" && \ + cmake .. -DCMAKE_BUILD_TYPE=Release -DWITH_MERGE_MINING_DONATION=OFF && \ + make $MAKE_JOBS + +FROM scratch + +ARG TARGETARCH + +COPY --from=build /src/p2pool/build/p2pool /linux_${TARGETARCH}/p2pool diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu new file mode 100644 index 0000000..2f6aa2d --- /dev/null +++ b/docker/Dockerfile.ubuntu @@ -0,0 +1,44 @@ +FROM ubuntu:24.04 AS base + +ARG TARGETARCH + +RUN apt-get update && apt-get install -y \ + git \ + cmake \ + gcc \ + g++ \ + make \ + libuv1-dev \ + libzmq3-dev \ + libcurl4-openssl-dev \ + && rm -rf /var/lib/apt/lists/* + +FROM base AS build + +ARG P2POOL_VERSION +ARG TARGETARCH +ARG BUILDPLATFORM +ARG TARGETPLATFORM + +RUN git clone --recursive https://github.com/SChernykh/p2pool /src/p2pool + +WORKDIR /src/p2pool + +RUN git checkout ${P2POOL_VERSION} + +# Determine parallel jobs based on cross-compilation +RUN mkdir build && cd build && \ + if [ "$BUILDPLATFORM" != "$TARGETPLATFORM" ]; then \ + MAKE_JOBS="-j2"; \ + else \ + MAKE_JOBS="-j$(nproc)"; \ + fi && \ + echo "Building with parallel jobs: $MAKE_JOBS (cross-compile: $([ "$BUILDPLATFORM" != "$TARGETPLATFORM" ] && echo yes || echo no))" && \ + cmake .. -DCMAKE_BUILD_TYPE=Release -DWITH_MERGE_MINING_DONATION=OFF && \ + make $MAKE_JOBS + +FROM scratch + +ARG TARGETARCH + +COPY --from=build /src/p2pool/build/p2pool /linux_${TARGETARCH}/p2pool