diff --git a/.dockerignore b/.dockerignore index 0516eeb..1120e95 100644 --- a/.dockerignore +++ b/.dockerignore @@ -16,7 +16,6 @@ target/ *.pem *.key !public_key.pem -!data/public_key.pem # Database files *.db @@ -51,7 +50,6 @@ update_codebase.txt .idea/ # Misc -Cargo.lock generate_random_ascii.sh test/ invalid_txs/ diff --git a/Dockerfile b/Dockerfile index 7195d1c..b312094 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,9 +11,8 @@ FROM rust:1.95-bookworm AS builder RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ libssl-dev \ - libsodium-dev \ libzmq5-dev \ - cmake \ + libsqlite3-dev \ && rm -rf /var/lib/apt/lists/* WORKDIR /build @@ -27,12 +26,14 @@ RUN mkdir -p src/bin && \ echo '' > src/db.rs && \ echo '' > src/xpub.rs && \ echo '' > src/validation.rs && \ - cargo build --release --bin bal-server --bin bal-pusher 2>/dev/null || true && \ + cargo build --release --bin bal-server --no-default-features --features server 2>/dev/null || true && \ + cargo build --release --bin bal-pusher --no-default-features --features pusher 2>/dev/null || true && \ rm -rf src target/release/.fingerprint target/release/deps/*bal_server* -# Copy real source and build +# Copy real source and build each binary with only its required features COPY src/ src/ -RUN cargo build --release --bin bal-server --bin bal-pusher && \ +RUN cargo build --release --bin bal-server --no-default-features --features server && \ + cargo build --release --bin bal-pusher --no-default-features --features pusher && \ strip target/release/bal-server target/release/bal-pusher # --------------------------------------------------------------------------- @@ -43,7 +44,6 @@ FROM debian:bookworm-slim AS runtime # Install runtime dependencies + tini for PID 1 RUN apt-get update && apt-get install -y --no-install-recommends \ libssl3 \ - libsodium23 \ libzmq5 \ libsqlite3-0 \ ca-certificates \ diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 0000000..e3b56f0 --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,100 @@ +# ============================================================================= +# Dockerfile.release — Downloads the latest pre-built release from Gitea +# No Rust toolchain needed. Fast builds, minimal image. +# ============================================================================= + +FROM debian:bookworm-slim AS runtime + +ARG GITEA_API="https://bitcoin-after.life/gitea/api/v1/repos/bitcoinafterlife/bal-server" +ARG BAL_VERSION="" + +# Install runtime dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + libssl3 \ + libzmq5 \ + libsqlite3-0 \ + ca-certificates \ + curl \ + jq \ + tini \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +WORKDIR /tmp/bal-install + +# Download and verify release +# If BAL_VERSION is set, fetch that specific tag; otherwise fetch latest +RUN set -eux; \ + if [ -n "$BAL_VERSION" ]; then \ + URL="${GITEA_API}/releases/tags/${BAL_VERSION}"; \ + else \ + URL="${GITEA_API}/releases/latest"; \ + fi; \ + echo "==> Fetching release metadata from $URL"; \ + RELEASE_JSON=$(curl -sfL "$URL") || { echo "ERROR: Failed to fetch release metadata"; exit 1; }; \ + TAG=$(echo "$RELEASE_JSON" | jq -r '.tag_name // empty'); \ + if [ -z "$TAG" ]; then echo "ERROR: Could not determine release tag"; exit 1; fi; \ + echo "==> Release tag: $TAG"; \ + TARBALL_URL=$(echo "$RELEASE_JSON" | jq -r \ + '.assets[] | select(.name | test("\\.tar\\.gz$")) | .browser_download_url' | head -1); \ + if [ -z "$TARBALL_URL" ]; then echo "ERROR: No .tar.gz asset found"; exit 1; fi; \ + ASSET_NAME=$(basename "$TARBALL_URL"); \ + echo "==> Downloading $ASSET_NAME"; \ + curl -sfL -o "$ASSET_NAME" "$TARBALL_URL" || { echo "ERROR: Download failed"; exit 1; }; \ + echo "==> Downloading checksum"; \ + curl -sfL -o "${ASSET_NAME}.sha256" "${TARBALL_URL}.sha256" 2>/dev/null || true; \ + if [ -f "${ASSET_NAME}.sha256" ]; then \ + echo "==> Verifying SHA-256 checksum"; \ + sha256sum -c "${ASSET_NAME}.sha256" || { echo "ERROR: SHA-256 verification failed"; exit 1; }; \ + echo "==> Checksum OK"; \ + else \ + echo "WARNING: No .sha256 file available — skipping checksum verification"; \ + fi; \ + echo "==> Extracting tarball"; \ + tar -xzf "$ASSET_NAME"; \ + EXTRACTED="$(basename "$ASSET_NAME" .tar.gz)"; \ + for bin in bal-server bal-pusher; do \ + if [ ! -f "$EXTRACTED/$bin" ]; then \ + echo "ERROR: Binary '$bin' not found in archive"; \ + exit 1; \ + fi; \ + echo "==> Installing $bin"; \ + install -m 0755 -o root -g root "$EXTRACTED/$bin" /usr/local/bin/; \ + done; \ + echo "==> Cleanup"; \ + rm -rf /tmp/bal-install + +# Create dedicated non-root user +RUN groupadd -g 1000 bal && \ + useradd -u 1000 -g bal -s /usr/sbin/nologin -M bal && \ + mkdir -p /var/bal /var/bal/.bitcoin && \ + chown -R bal:bal /var/bal && \ + chmod 700 /var/bal + +# Copy entrypoint +COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Use tini as PID 1 for proper signal handling +ENTRYPOINT ["/usr/bin/tini", "--"] +CMD ["/usr/local/bin/entrypoint.sh"] + +# Data directory (mount as volume) +VOLUME ["/var/bal"] + +# bal-server port +EXPOSE 9137 + +# Default environment (override at runtime) +ENV RUST_LOG=info \ + BAL_SERVER_BIND_ADDRESS=127.0.0.1 \ + BAL_SERVER_BIND_PORT=9137 \ + BAL_SERVER_DB_FILE=/var/bal/bal.db \ + BAL_PUSHER_DB_FILE=/var/bal/bal.db \ + BAL_SERVER_URL=http://127.0.0.1:9137 \ + BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \ + SSL_KEY_PATH=/var/bal/private_key.pem + +# Health check +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD curl -sf http://127.0.0.1:9137/ || exit 1 diff --git a/README.md b/README.md index d23c291..f8e48ee 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,15 @@ sudo cp target/release/bal-server target/release/bal-pusher /usr/local/bin ## Docker -### Build +### Quick Start (release download) + +Download the latest pre-built release — no Rust toolchain needed: + +```bash +docker build -f Dockerfile.release -t bal-server . +``` + +### Build from source ```bash docker build -t bal-server . @@ -37,6 +45,12 @@ docker run -d \ bal-server ``` +### Pin a specific version + +```bash +docker build -f Dockerfile.release --build-arg BAL_VERSION=v0.3.2 -t bal-server:0.3.2 . +``` + ### Docker environment variables | Variable | Description | Default | @@ -48,6 +62,7 @@ docker run -d \ > **Note:** The container runs as a non-root `bal` user (uid 1000) with `tini` as PID 1. > The `/var/bal` volume stores the database. Mount Bitcoin Core's cookie file as read-only. > When using `--network host`, ensure only `127.0.0.1` is used for internal services. +> `Dockerfile.release` fetches the latest release from the Gitea server and verifies its SHA-256 checksum. ## Configuration (bal-server) @@ -111,7 +126,7 @@ The `bal-server` application can be configured using environment variables. zmqpubhashblock=tcp://127.0.0.1:28332 ``` - **Rust and Cargo**: [Rust Installation](https://www.rust-lang.org/tools/install) -- **Libraries**: `libssl-dev`, `libsodium-dev`, `libzmq5-dev`, `libsqlite3-dev` +- **Libraries**: `libssl-dev`, `libzmq5-dev`, `libsqlite3-dev` ## Running diff --git a/docs/01_project_overview.md b/docs/01_project_overview.md index 7e1c2f1..46a6ebb 100644 --- a/docs/01_project_overview.md +++ b/docs/01_project_overview.md @@ -39,7 +39,12 @@ The project uses Cargo feature flags to build each binary independently: ## Docker Support -The project includes a multi-stage `Dockerfile` using `rust:1.95-bookworm` as the builder and `debian:bookworm-slim` as the runtime. The container runs as a non-root `bal` user (uid 1000) with `tini` as PID 1 and includes a healthcheck endpoint. +Two Dockerfiles are provided: + +- **`Dockerfile.release`** (recommended for production): Downloads the latest pre-built release from the Gitea server. No Rust toolchain needed. Verifies SHA-256 checksum. Supports pinning a specific version via `BAL_VERSION` build arg. +- **`Dockerfile`** (for development/custom builds): Multi-stage build using `rust:1.95-bookworm` as the builder and `debian:bookworm-slim` as the runtime. Each binary is compiled with only its required features (`--no-default-features --features server` / `--features pusher`). + +Both run as a non-root `bal` user (uid 1000) with `tini` as PID 1 and include a healthcheck endpoint. ## Mapping to Existing Documentation diff --git a/docs/07_deployment_and_ops.md b/docs/07_deployment_and_ops.md index f2c7fab..5a7176c 100644 --- a/docs/07_deployment_and_ops.md +++ b/docs/07_deployment_and_ops.md @@ -93,17 +93,38 @@ Default ports per network: ## Docker -The project includes a multi-stage `Dockerfile`: +The project provides two Dockerfiles: -- **Builder stage:** `rust:1.95-bookworm` with full build. +### `Dockerfile.release` — Download pre-built release (recommended for production) + +Downloads the latest release from the Gitea server. No Rust toolchain needed. Fast builds. + +```bash +# Latest release +docker build -f Dockerfile.release -t bal-server . + +# Specific version +docker build -f Dockerfile.release --build-arg BAL_VERSION=v0.3.2 -t bal-server:0.3.2 . +``` + +- Fetches `.tar.gz` from `https://bitcoin-after.life/gitea/api/v1/repos/bitcoinafterlife/bal-server/releases/latest`. +- Verifies SHA-256 checksum if available. +- Single-stage image (`debian:bookworm-slim`), minimal size. +- `BAL_VERSION` build arg: set to a tag (e.g., `v0.3.2`) to pin a specific release. + +### `Dockerfile` — Build from source + +Multi-stage build with the Rust toolchain. Use for development or custom builds. + +- **Builder stage:** `rust:1.95-bookworm` with full build. Each binary is compiled with only its required features (`--no-default-features --features server` / `--features pusher`). - **Runtime stage:** `debian:bookworm-slim` with minimal runtime. - **User:** Non-root `bal` user (uid 1000). - **PID 1:** `tini` for proper signal handling. - **Healthcheck:** `curl -f http://localhost:9137/ || exit 1`. -Build and run: +### Run (both Dockerfiles) + ```bash -docker build -t bal-server . docker run -d \ --name bal-server \ -v /var/bal:/var/bal \ diff --git a/docs/09_references_and_links.md b/docs/09_references_and_links.md index e88adb7..3860096 100644 --- a/docs/09_references_and_links.md +++ b/docs/09_references_and_links.md @@ -29,7 +29,8 @@ | Contrib (install bitcoind) | `contrib/download_and_install_bitcoincore.sh` | Bitcoind download, GPG verify, systemd, config | | Contrib (install Tor) | `contrib/install_tor.sh` | Tor repository, `ControlPort 9051` | | Nginx template | `contrib/nginx/bal-server.conf` | TLS termination, security headers, rate limiting | -| Dockerfile | `Dockerfile` | Multi-stage build, non-root user, tini, healthcheck | +| Dockerfile | `Dockerfile` | Multi-stage build from source, non-root user, tini, healthcheck | +| Dockerfile.release | `Dockerfile.release` | Download latest release from Gitea, SHA-256 verification | | Systemd Service | File | Purpose | |---|---|---|