├── .github ├── dependabot.yml ├── linters │ ├── .dockerfilelintrc │ └── .hadolint.yaml └── workflows │ ├── chia-test.yml │ ├── dev-release.yml │ ├── latest-release.yml │ ├── main-release.yml │ ├── stale-issue.yml │ └── super-linter.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── docker-entrypoint.sh ├── docker-healthcheck.sh ├── docker-start.sh └── readme.md /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # This file is managed by the repo-content-updater project. Manual changes here will result in a PR to bring back 2 | # inline with the upstream template, unless you remove the dependabot managed file property from the repo 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "gomod" 7 | directory: / 8 | schedule: 9 | interval: "weekly" 10 | day: "tuesday" 11 | open-pull-requests-limit: 10 12 | rebase-strategy: auto 13 | labels: 14 | - dependencies 15 | - go 16 | - "Changed" 17 | reviewers: ["cmmarslender", "Starttoaster"] 18 | groups: 19 | global: 20 | patterns: 21 | - "*" 22 | 23 | - package-ecosystem: "pip" 24 | directory: / 25 | schedule: 26 | interval: "weekly" 27 | day: "tuesday" 28 | open-pull-requests-limit: 10 29 | rebase-strategy: auto 30 | labels: 31 | - dependencies 32 | - python 33 | - "Changed" 34 | reviewers: ["emlowe", "altendky"] 35 | 36 | - package-ecosystem: "github-actions" 37 | directories: ["/", ".github/actions/*"] 38 | schedule: 39 | interval: "weekly" 40 | day: "tuesday" 41 | open-pull-requests-limit: 10 42 | rebase-strategy: auto 43 | labels: 44 | - dependencies 45 | - github_actions 46 | - "Changed" 47 | reviewers: ["cmmarslender", "Starttoaster", "pmaslana"] 48 | 49 | - package-ecosystem: "npm" 50 | directory: / 51 | schedule: 52 | interval: "weekly" 53 | day: "tuesday" 54 | open-pull-requests-limit: 10 55 | rebase-strategy: auto 56 | labels: 57 | - dependencies 58 | - javascript 59 | - "Changed" 60 | reviewers: ["cmmarslender", "ChiaMineJP"] 61 | 62 | - package-ecosystem: cargo 63 | directory: / 64 | schedule: 65 | interval: "weekly" 66 | day: "tuesday" 67 | open-pull-requests-limit: 10 68 | rebase-strategy: auto 69 | labels: 70 | - dependencies 71 | - rust 72 | - "Changed" 73 | 74 | - package-ecosystem: swift 75 | directory: / 76 | schedule: 77 | interval: "weekly" 78 | day: "tuesday" 79 | open-pull-requests-limit: 10 80 | rebase-strategy: auto 81 | -------------------------------------------------------------------------------- /.github/linters/.dockerfilelintrc: -------------------------------------------------------------------------------- 1 | --- 2 | ########################### 3 | ########################### 4 | ## Dockerfile Lint rules ## 5 | ########################### 6 | ########################### 7 | 8 | ################################# 9 | # Default is 'on' for all rules # 10 | # You can disable as needed. # 11 | ################################# 12 | # Additional Info can be found at: 13 | # https://github.com/replicatedhq/dockerfilelint 14 | 15 | # Set the rules 16 | rules: 17 | # All commands in a Dockerfile require at least 1 argument 18 | required_params: on 19 | 20 | # For clarity and readability, all instructions in 21 | # a Dockerfile should be uppercase 22 | uppercase_commands: on 23 | 24 | # The first instruction in a Dockerfile must specify 25 | # the base image using a FROM 26 | from_first: on 27 | 28 | # This line is not a valid Dockerfile line 29 | invalid_line: on 30 | 31 | # Use of sudo is not allowed in a Dockerfile 32 | sudo_usage: off 33 | 34 | # Consider using a `--no-install-recommends` when `apt-get` 35 | # installing packages 36 | apt-get_missing_param: on 37 | 38 | # Consider using a `--no-install-recommends` when `apt-get` 39 | # installing packages 40 | apt-get_recommends: on 41 | 42 | # Use of `apt-get upgrade` is not allowed in a Dockerfile 43 | apt-get-upgrade: on 44 | 45 | # Use of `apt-get dist-upgrade` is not allowed in a Dockerfile 46 | apt-get-dist-upgrade: on 47 | 48 | # All instances of `apt-get update` should have the `apt-get install` 49 | # commands on the same line to reduce image size 50 | apt-get-update_require_install: on 51 | 52 | # Consider using a `--no-cache` (supported in alpine linux >= 3.3) or 53 | # `--update` followed by the command `rm -rf /var/cache/apk/*` 54 | # when `apk` adding packages. This will result in a smaller image size 55 | apkadd-missing_nocache_or_updaterm: on 56 | 57 | # Consider using a `--virtual` or `-t` switch to group multiple packages 58 | # for easy cleanup. This will help ensure future authors will continue 59 | # to clean up build dependencies and other temporary packages 60 | apkadd-missing-virtual: on 61 | 62 | # Exposing ports should only be valid port numbers 63 | invalid_port: on 64 | 65 | # Only valid commands are allowed in a Dockerfile 66 | invalid_command: on 67 | 68 | # Expose Only Container Port 69 | expose_host_port: on 70 | 71 | # Using LABEL should be in key=value format 72 | label_invalid: on 73 | 74 | # Base images should specify a tag to use 75 | missing_tag: on 76 | 77 | # Base images should not use the latest tag 78 | latest_tag: off 79 | 80 | # This command has extra arguments and will be ignored 81 | extra_args: on 82 | 83 | # This command requires additional arguments 84 | missing_args: on 85 | 86 | # All files referenced in an ADD command should 87 | # be part of the Docker build context 88 | add_src_invalid: on 89 | 90 | # When adding multiple files, the destination should be a directory 91 | add_dest_invalid: on 92 | 93 | # Using a WORKDIR parameter that has spaces should be escaped 94 | invalid_workdir: on 95 | 96 | # The arguments to this command are invalid 97 | invalid_format: on 98 | 99 | # Use of apt-get update should be paired with 100 | # rm -rf /var/lib/apt/lists/* in the same layer 101 | apt-get_missing_rm: on 102 | 103 | # This INSTRUCTION is deprecated as of Docker 1.13 104 | deprecated_in_1.13: on 105 | -------------------------------------------------------------------------------- /.github/linters/.hadolint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ########################## 3 | ## Hadolint config file ## 4 | ########################## 5 | ignored: 6 | - DL3003 # Use WORKDIR to switch to a directory. 7 | - DL3007 # :latest image tag 8 | - DL3008 # require apt specific versions 9 | -------------------------------------------------------------------------------- /.github/workflows/chia-test.yml: -------------------------------------------------------------------------------- 1 | name: Test official Chia Docker Image 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | docker_build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | 12 | - uses: actions/github-script@v7 13 | id: 'tag' 14 | with: 15 | github-token: ${{ secrets.GITHUB_TOKEN }} 16 | result-encoding: string 17 | script: | 18 | const release = await github.rest.repos.getLatestRelease({ 19 | owner: 'Chia-Network', 20 | repo: 'chia-blockchain', 21 | }); 22 | return release.data.tag_name; 23 | 24 | - run: docker build --build-arg BRANCH="${{ steps.tag.outputs.result }}" -t localtest:latest . 25 | 26 | - run: docker run -d --name=chia localtest:latest 27 | 28 | - timeout-minutes: 10 29 | run: | 30 | while true; do 31 | HEALTH_STATUS=$(docker inspect --format="{{.State.Health.Status}}" chia) 32 | if [ "$HEALTH_STATUS" == "starting" ]; then 33 | echo "Container chia is still starting. Waiting..." 34 | sleep 1 35 | elif [ "$HEALTH_STATUS" == "healthy" ]; then 36 | echo "Health check succeeded for container chia" 37 | break 38 | else 39 | echo "Health check failed for container chia" 40 | exit 1 41 | fi 42 | done 43 | -------------------------------------------------------------------------------- /.github/workflows/dev-release.yml: -------------------------------------------------------------------------------- 1 | name: Build Dev Container (ghcr only) 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | sha: 7 | description: "The SHA from chia-blockchain to use when building the image" 8 | required: true 9 | 10 | permissions: 11 | id-token: write 12 | contents: read 13 | packages: write 14 | 15 | concurrency: 16 | group: ${{ github.event.inputs.sha }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | docker_build_and_publish_dev: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Check out the repo 24 | uses: actions/checkout@v4 25 | 26 | - name: Set up QEMU 27 | uses: docker/setup-qemu-action@v3 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GitHub Container Registry 33 | uses: docker/login-action@v3 34 | with: 35 | registry: ghcr.io 36 | username: ${{ github.actor }} 37 | password: ${{ github.token }} 38 | 39 | - name: Docker meta 40 | id: meta 41 | uses: docker/metadata-action@v5 42 | with: 43 | images: | 44 | ghcr.io/chia-network/chia/dev 45 | tags: | 46 | type=raw,value=${{ github.event.inputs.sha }} 47 | 48 | - name: Build docker image and push to github packages 49 | uses: docker/build-push-action@v6 50 | with: 51 | context: . 52 | platforms: linux/amd64,linux/arm64 53 | no-cache: true 54 | push: true 55 | build-args: | 56 | "COMMIT=${{ github.event.inputs.sha }}" 57 | tags: ${{ steps.meta.outputs.tags }} 58 | labels: ${{ steps.meta.outputs.labels }} 59 | -------------------------------------------------------------------------------- /.github/workflows/latest-release.yml: -------------------------------------------------------------------------------- 1 | name: Build Latest Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | permissions: 10 | id-token: write 11 | contents: read 12 | packages: write 13 | 14 | concurrency: 15 | group: "latest" 16 | 17 | jobs: 18 | docker_build_and_publish_github: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out the repo 22 | uses: actions/checkout@v4 23 | 24 | - name: Set up QEMU 25 | uses: docker/setup-qemu-action@v3 26 | 27 | - name: Set up Docker Buildx 28 | uses: docker/setup-buildx-action@v3 29 | 30 | - name: Login to GitHub Container Registry 31 | uses: docker/login-action@v3 32 | with: 33 | registry: ghcr.io 34 | username: ${{ github.actor }} 35 | password: ${{ github.token }} 36 | 37 | - name: Login to DockerHub 38 | uses: docker/login-action@v3 39 | with: 40 | username: ${{ secrets.DOCKERHUB_USERNAME }} 41 | password: ${{ secrets.DOCKERHUB_PAT }} 42 | 43 | # Get the most recent release from chia-blockchain and build that 44 | - uses: actions/github-script@v7 45 | id: 'latest-tag' 46 | with: 47 | github-token: ${{ secrets.GITHUB_TOKEN }} 48 | result-encoding: string 49 | script: | 50 | const release = await github.rest.repos.getLatestRelease({ 51 | owner: 'Chia-Network', 52 | repo: 'chia-blockchain', 53 | }); 54 | return release.data.tag_name; 55 | 56 | - name: Docker meta 57 | id: meta 58 | uses: docker/metadata-action@v5 59 | with: 60 | images: | 61 | ghcr.io/chia-network/chia 62 | chianetwork/chia-docker 63 | tags: | 64 | type=raw,value=latest 65 | type=raw,value=${{ steps.latest-tag.outputs.result }} 66 | 67 | - name: Build docker image and push to github packages 68 | uses: docker/build-push-action@v6 69 | with: 70 | context: . 71 | platforms: linux/amd64,linux/arm64 72 | no-cache: true 73 | push: true 74 | build-args: | 75 | "BRANCH=${{ steps.latest-tag.outputs.result }}" 76 | tags: ${{ steps.meta.outputs.tags }} 77 | labels: ${{ steps.meta.outputs.labels }} 78 | 79 | - uses: Chia-Network/actions/github/glue@main 80 | with: 81 | json_data: '{"chia_ref":"${{ steps.latest-tag.outputs.result }}"}' 82 | glue_url: ${{ secrets.GLUE_API_URL }} 83 | glue_project: "docker-new-release" 84 | glue_path: "trigger" 85 | -------------------------------------------------------------------------------- /.github/workflows/main-release.yml: -------------------------------------------------------------------------------- 1 | name: Build Chia Main Branch 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | permissions: 10 | id-token: write 11 | contents: read 12 | packages: write 13 | 14 | concurrency: 15 | group: "main" 16 | 17 | jobs: 18 | docker_build_and_publish_github: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out the repo 22 | uses: actions/checkout@v4 23 | 24 | - name: Set up QEMU 25 | uses: docker/setup-qemu-action@v3 26 | 27 | - name: Set up Docker Buildx 28 | uses: docker/setup-buildx-action@v3 29 | 30 | - name: Login to GitHub Container Registry 31 | uses: docker/login-action@v3 32 | with: 33 | registry: ghcr.io 34 | username: ${{ github.actor }} 35 | password: ${{ github.token }} 36 | 37 | - name: Login to DockerHub 38 | uses: docker/login-action@v3 39 | with: 40 | username: ${{ secrets.DOCKERHUB_USERNAME }} 41 | password: ${{ secrets.DOCKERHUB_PAT }} 42 | 43 | - name: Docker meta 44 | id: meta 45 | uses: docker/metadata-action@v5 46 | with: 47 | images: | 48 | ghcr.io/chia-network/chia 49 | chianetwork/chia-docker 50 | tags: | 51 | type=raw,value=main 52 | 53 | - name: Build docker image and push to github packages 54 | uses: docker/build-push-action@v6 55 | with: 56 | context: . 57 | platforms: linux/amd64,linux/arm64 58 | no-cache: true 59 | push: true 60 | build-args: | 61 | "BRANCH=main" 62 | tags: ${{ steps.meta.outputs.tags }} 63 | labels: ${{ steps.meta.outputs.labels }} 64 | -------------------------------------------------------------------------------- /.github/workflows/stale-issue.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Close stale issues' 3 | on: 4 | schedule: 5 | - cron: '0 11 * * *' 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: chia-network/stale@main 12 | with: 13 | operations-per-run: 10000 14 | ascending: true 15 | days-before-issue-stale: 14 16 | days-before-issue-close: 7 17 | days-before-pr-stale: 60 18 | days-before-pr-close: -1 19 | exempt-all-pr-milestones: true 20 | exempt-all-issue-milestones: true 21 | exempt-all-assignees: true 22 | stale-issue-label: stale-issue 23 | stale-pr-label: stale-pr 24 | remove-stale-when-updated: true 25 | stale-issue-message: > 26 | 'This issue has been flagged as stale as there has been no 27 | activity on it in 14 days. If this issue is still affecting you 28 | and in need of review, please update it to keep it open.' 29 | close-issue-message: > 30 | 'This issue was automatically closed because it has been flagged 31 | as stale and subsequently passed 7 days with no further activity.' 32 | stale-pr-message: > 33 | 'This PR has been flagged as stale due to no activity for over 60 34 | days. It will not be automatically closed, but it has been given 35 | a stale-pr label and should be manually reviewed.' 36 | -------------------------------------------------------------------------------- /.github/workflows/super-linter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Code Base 3 | 4 | on: 5 | push: 6 | branches-ignore: 7 | - main 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | build: 14 | name: Lint Code Base 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout Code 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Lint Code Base 23 | uses: github/super-linter@v6 24 | env: 25 | VALIDATE_ALL_CODEBASE: true 26 | VALIDATE_NATURAL_LANGUAGE: false 27 | DEFAULT_BRANCH: main 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | VALIDATE_DOCKERFILE_HADOLINT: false # Breaks CI by trying to validate things that aren't dockerfiles 30 | VALIDATE_JSCPD: false 31 | VALIDATE_CHECKOV: false 32 | VALIDATE_SHELL_SHFMT: false 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | sim-root 3 | sim-keys 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # CHIA BUILD STEP 2 | FROM python:3.11-slim AS chia_build 3 | 4 | ARG BRANCH=latest 5 | ARG COMMIT="" 6 | 7 | RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ 8 | DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ 9 | lsb-release sudo git 10 | 11 | WORKDIR /chia-blockchain 12 | 13 | RUN echo "cloning ${BRANCH}" && \ 14 | if [ -z "$COMMIT" ]; then \ 15 | DEPTH_FLAG="--depth 1"; \ 16 | else \ 17 | DEPTH_FLAG=""; \ 18 | fi && \ 19 | git clone ${DEPTH_FLAG} --branch ${BRANCH} --recurse-submodules=mozilla-ca https://github.com/Chia-Network/chia-blockchain.git . && \ 20 | # If COMMIT is set, check out that commit, otherwise just continue 21 | ( [ ! -z "$COMMIT" ] && git fetch origin $COMMIT && git checkout $COMMIT ) || true && \ 22 | echo "running build-script" && \ 23 | /bin/sh ./install.sh -s 24 | 25 | # Get yq for chia config changes 26 | FROM mikefarah/yq:4 AS yq 27 | # Get chia-tools for a new experimental chia config management strategy 28 | FROM ghcr.io/chia-network/chia-tools:latest AS chia-tools 29 | 30 | # IMAGE BUILD 31 | FROM python:3.11-slim 32 | 33 | EXPOSE 8555 8444 34 | 35 | # CHIA_REPO allows changing to an alternate repo if running in the mode that builds from source on startup 36 | ENV CHIA_REPO=https://github.com/Chia-Network/chia-blockchain.git 37 | ENV CHIA_ROOT=/root/.chia/mainnet 38 | ENV keys="generate" 39 | ENV service="farmer" 40 | ENV plots_dir="/plots" 41 | ENV farmer_address= 42 | ENV farmer_port= 43 | ENV testnet="false" 44 | ENV TZ="UTC" 45 | ENV upnp="true" 46 | ENV log_to_file="true" 47 | ENV healthcheck="true" 48 | ENV chia_args= 49 | ENV full_node_peer= 50 | 51 | # Deprecated legacy options 52 | ENV harvester="false" 53 | ENV farmer="false" 54 | 55 | # Minimal list of software dependencies 56 | # sudo: Needed for alternative plotter install 57 | # tzdata: Setting the timezone 58 | # curl: Health-checks 59 | # netcat: Healthchecking the daemon 60 | # yq: changing config settings 61 | RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ 62 | DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y sudo tzdata curl netcat-traditional jq && \ 63 | rm -rf /var/lib/apt/lists/* && \ 64 | ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone && \ 65 | dpkg-reconfigure -f noninteractive tzdata 66 | 67 | COPY --from=yq /usr/bin/yq /usr/bin/yq 68 | COPY --from=chia-tools /chia-tools /usr/bin/chia-tools 69 | COPY --from=chia_build /chia-blockchain /chia-blockchain 70 | 71 | ENV PATH=/chia-blockchain/venv/bin:$PATH 72 | WORKDIR /chia-blockchain 73 | 74 | COPY docker-start.sh /usr/local/bin/ 75 | COPY docker-entrypoint.sh /usr/local/bin/ 76 | COPY docker-healthcheck.sh /usr/local/bin/ 77 | 78 | RUN chmod +x /usr/local/bin/docker-start.sh && \ 79 | chmod +x /usr/local/bin/docker-entrypoint.sh && \ 80 | chmod +x /usr/local/bin/docker-healthcheck.sh 81 | 82 | HEALTHCHECK --interval=1m --timeout=10s --start-period=20m \ 83 | CMD /bin/bash /usr/local/bin/docker-healthcheck.sh || exit 1 84 | 85 | ENTRYPOINT ["docker-entrypoint.sh"] 86 | CMD ["docker-start.sh"] 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2025 Chia Network Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # shellcheck disable=SC2154 4 | if [[ -n "${TZ}" ]]; then 5 | echo "Setting timezone to ${TZ}" 6 | ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime && echo "$TZ" > /etc/timezone 7 | fi 8 | 9 | # Install alternate version of chia if source mode is requested 10 | # Enables testing dev versions of chia-docker in the container even if the version is not published to the container registry 11 | if [[ -n ${source_ref} ]]; then 12 | echo "Installing chia from source:" 13 | echo " repo: ${CHIA_REPO}" 14 | echo " ref: ${source_ref}" 15 | 16 | cd / || exit 1 17 | DEBIAN_FRONTEND=noninteractive apt-get update 18 | DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y lsb-release sudo git 19 | 20 | rm -rf /chia-blockchain 21 | git clone --recurse-submodules=mozilla-ca "$CHIA_REPO" /chia-blockchain 22 | cd /chia-blockchain || exit 1 23 | git checkout "${source_ref}" 24 | /bin/sh ./install.sh -s 25 | fi 26 | 27 | cd /chia-blockchain || exit 1 28 | 29 | # shellcheck disable=SC1091 30 | . ./activate 31 | 32 | if [[ ${manual_config} == "true" ]]; then 33 | # Manual config mode skips everything below and lets you manage your config manually 34 | exec "$@" 35 | return 36 | fi 37 | 38 | # Set a few overrides if the service variable contains simulator 39 | if [ -z "${service##*simulator*}" ]; then 40 | echo "Setting up environment for simulator..." 41 | export CHIA_ROOT=/root/.chia/simulator/main 42 | export self_hostname="0.0.0.0" 43 | 44 | if [[ ${skip_sim_create} != 'true' ]]; then 45 | if [ -f /root/.chia/simulator/mnemonic ]; then 46 | echo "Using provided mnemonic from /root/.chia/simulator/mnemonic" 47 | # Use awk to trim leading and trailing whitespace while preserving internal spaces 48 | mnemonic=$(awk '{$1=$1};1' /root/.chia/simulator/mnemonic) 49 | fi 50 | 51 | if [ -n "$mnemonic" ]; then # Check if mnemonic is non-empty after trimming 52 | chia dev sim create --docker-mode --mnemonic "${mnemonic}" 53 | else 54 | chia dev sim create --docker-mode 55 | fi 56 | 57 | chia stop -d all 58 | chia keys show --show-mnemonic-seed --json | jq -r '.keys[0].mnemonic' > /root/.chia/simulator/mnemonic 59 | fi 60 | fi 61 | 62 | # shellcheck disable=SC2086 63 | chia ${chia_args} init --fix-ssl-permissions 64 | 65 | if [[ -n ${ca} ]]; then 66 | if ! openssl verify -CAfile "${ca}/private_ca.crt" "${CHIA_ROOT}/config/ssl/harvester/private_harvester.crt" &>/dev/null; then 67 | echo "initializing from new CA" 68 | # shellcheck disable=SC2086 69 | chia ${chia_args} init -c "${ca}" 70 | else 71 | echo "using existing CA" 72 | fi 73 | fi 74 | 75 | # Enables whatever the default testnet is for the version of chia that is running 76 | if [[ ${testnet} == 'true' ]]; then 77 | echo "configure testnet" 78 | chia configure --testnet true 79 | fi 80 | 81 | # Allows using another testnet that isn't the default testnet 82 | if [[ -n ${network} ]]; then 83 | echo "Setting network name to ${network}" 84 | yq -i ' 85 | .selected_network = env(network) | 86 | .seeder.selected_network = env(network) | 87 | .harvester.selected_network = env(network) | 88 | .pool.selected_network = env(network) | 89 | .farmer.selected_network = env(network) | 90 | .timelord.selected_network = env(network) | 91 | .full_node.selected_network = env(network) | 92 | .ui.selected_network = env(network) | 93 | .introducer.selected_network = env(network) | 94 | .wallet.selected_network = env(network) | 95 | .data_layer.selected_network = env(network) 96 | ' "$CHIA_ROOT/config/config.yaml" 97 | fi 98 | 99 | if [[ -n ${network_port} ]]; then 100 | echo "Setting network port to ${network_port}" 101 | yq -i ' 102 | .seeder.port = env(network_port) | 103 | .seeder.other_peers_port = env(network_port) | 104 | .farmer.full_node_peers[0].port = env(network_port) | 105 | .timelord.full_node_peers[0].port = env(network_port) | 106 | .full_node.port = env(network_port) | 107 | .full_node.introducer_peer.port = env(network_port) | 108 | .introducer.port = env(network_port) | 109 | .wallet.full_node_peers[0].port = env(network_port) | 110 | .wallet.introducer_peer.port = env(network_port) 111 | ' "$CHIA_ROOT/config/config.yaml" 112 | fi 113 | 114 | if [[ -n ${introducer_address} ]]; then 115 | echo "Setting introducer to ${introducer_address}" 116 | yq -i ' 117 | .full_node.introducer_peer.host = env(introducer_address) | 118 | .wallet.introducer_peer.host = env(introducer_address) 119 | ' "$CHIA_ROOT/config/config.yaml" 120 | fi 121 | 122 | if [[ -n ${dns_introducer_address} ]]; then 123 | echo "Setting dns introducer to ${dns_introducer_address}" 124 | yq -i ' 125 | .full_node.dns_servers = [env(dns_introducer_address)] | 126 | .wallet.dns_servers = [env(dns_introducer_address)] 127 | ' "$CHIA_ROOT/config/config.yaml" 128 | fi 129 | 130 | if [[ -n ${seeder_bootstrap_peers} ]]; then 131 | echo "Setting seeder.bootstrap_peers to ${seeder_bootstrap_peers}" 132 | yq -i ' 133 | .seeder.bootstrap_peers = (env(seeder_bootstrap_peers) | split(",")) 134 | ' "$CHIA_ROOT/config/config.yaml" 135 | fi 136 | 137 | if [[ -n ${seeder_minimum_height} ]]; then 138 | echo "Setting seeder.minimum_height to ${seeder_minimum_height}" 139 | yq -i ' 140 | .seeder.minimum_height = env(seeder_minimum_height) 141 | ' "$CHIA_ROOT/config/config.yaml" 142 | fi 143 | 144 | if [[ -n ${seeder_domain_name} ]]; then 145 | echo "Setting seeder.domain_name to ${seeder_domain_name}" 146 | yq -i ' 147 | .seeder.domain_name = env(seeder_domain_name) 148 | ' "$CHIA_ROOT/config/config.yaml" 149 | fi 150 | 151 | if [[ -n ${seeder_nameserver} ]]; then 152 | echo "Setting seeder.nameserver to ${seeder_nameserver}" 153 | yq -i ' 154 | .seeder.nameserver = env(seeder_nameserver) 155 | ' "$CHIA_ROOT/config/config.yaml" 156 | fi 157 | 158 | if [[ -n ${seeder_ttl} ]]; then 159 | echo "Setting seeder.ttl to ${seeder_ttl}" 160 | yq -i ' 161 | .seeder.ttl = env(seeder_ttl) 162 | ' "$CHIA_ROOT/config/config.yaml" 163 | fi 164 | 165 | if [[ -n ${seeder_soa_rname} ]]; then 166 | echo "Setting seeder.soa.rname to ${seeder_soa_rname}" 167 | yq -i ' 168 | .seeder.soa.rname = env(seeder_soa_rname) 169 | ' "$CHIA_ROOT/config/config.yaml" 170 | fi 171 | 172 | if [[ ${keys} == "persistent" ]]; then 173 | echo "Not touching key directories, key directory likely mounted by volume" 174 | elif [[ ${keys} == "none" ]]; then 175 | # This is technically redundant to 'keys=persistent', but from a user's readability perspective, it means two different things 176 | echo "Not touching key directories, no keys needed" 177 | elif [[ ${keys} == "copy" ]]; then 178 | echo "Setting the keys=copy environment variable has been deprecated. If you're seeing this message, you can simply change the value of the variable keys=none" 179 | elif [[ ${keys} == "generate" ]]; then 180 | echo "to use your own keys pass the mnemonic as a text file -v /path/to/keyfile:/path/in/container and -e keys=\"/path/in/container\"" 181 | chia keys generate -l "" 182 | else 183 | chia keys add -f "${keys}" -l "" 184 | fi 185 | 186 | for p in ${plots_dir//:/ }; do 187 | mkdir -p "${p}" 188 | if [[ ! $(ls -A "$p") ]]; then 189 | echo "Plots directory '${p}' appears to be empty, try mounting a plot directory with the docker -v command" 190 | fi 191 | chia plots add -d "${p}" 192 | done 193 | 194 | if [[ ${recursive_plot_scan} == 'true' ]]; then 195 | yq -i '.harvester.recursive_plot_scan = true' "$CHIA_ROOT/config/config.yaml" 196 | else 197 | yq -i '.harvester.recursive_plot_scan = false' "$CHIA_ROOT/config/config.yaml" 198 | fi 199 | 200 | chia configure --upnp "${upnp}" 201 | 202 | if [[ -n "${log_level}" ]]; then 203 | chia configure --log-level "${log_level}" 204 | fi 205 | 206 | if [[ -n "${peer_count}" ]]; then 207 | chia configure --set-peer-count "${peer_count}" 208 | fi 209 | 210 | if [[ -n "${outbound_peer_count}" ]]; then 211 | chia configure --set_outbound-peer-count "${outbound_peer_count}" 212 | fi 213 | 214 | if [[ -n ${farmer_address} && -n ${farmer_port} ]]; then 215 | chia configure --set-farmer-peer "${farmer_address}:${farmer_port}" 216 | fi 217 | 218 | if [[ -n ${crawler_db_path} ]]; then 219 | chia configure --crawler-db-path "${crawler_db_path}" 220 | fi 221 | 222 | if [[ -n ${crawler_minimum_version_count} ]]; then 223 | chia configure --crawler-minimum-version-count "${crawler_minimum_version_count}" 224 | fi 225 | 226 | if [[ -n ${self_hostname} ]]; then 227 | yq -i '.self_hostname = env(self_hostname)' "$CHIA_ROOT/config/config.yaml" 228 | else 229 | yq -i '.self_hostname = "127.0.0.1"' "$CHIA_ROOT/config/config.yaml" 230 | fi 231 | 232 | if [[ -n ${full_node_peer} ]]; then 233 | echo "Changing full_node_peer settings in config.yaml with value: $full_node_peer" 234 | full_node_peer_host=$(echo "$full_node_peer" | rev | cut -d ':' -f 2- | rev) \ 235 | full_node_peer_port=$(echo "$full_node_peer" | awk -F: '{print $NF}') \ 236 | yq -i ' 237 | .wallet.full_node_peers[0].host = env(full_node_peer_host) | 238 | .wallet.full_node_peers[0].port = env(full_node_peer_port) | 239 | .timelord.full_node_peers[0].host = env(full_node_peer_host) | 240 | .timelord.full_node_peers[0].port = env(full_node_peer_port) | 241 | .farmer.full_node_peers[0].host = env(full_node_peer_host) | 242 | .farmer.full_node_peers[0].port = env(full_node_peer_port) 243 | ' "$CHIA_ROOT/config/config.yaml" 244 | fi 245 | 246 | if [[ -n ${trusted_cidrs} ]]; then 247 | echo "Changing trusted cidr setting in config.yaml to value: $trusted_cidrs" 248 | yq -i ' 249 | .wallet.trusted_cidrs = env(trusted_cidrs) | 250 | .full_node.trusted_cidrs = env(trusted_cidrs) 251 | ' "$CHIA_ROOT/config/config.yaml" 252 | fi 253 | 254 | if [[ -n ${xch_spam_amount} ]]; then 255 | echo "Setting xch spam amount in config.yaml to value: $xch_spam_amount" 256 | yq -i ' 257 | .wallet.xch_spam_amount = env(xch_spam_amount) 258 | ' "$CHIA_ROOT/config/config.yaml" 259 | fi 260 | 261 | if [[ ${log_to_file} != 'true' ]]; then 262 | sed -i 's/log_stdout: false/log_stdout: true/g' "$CHIA_ROOT/config/config.yaml" 263 | else 264 | sed -i 's/log_stdout: true/log_stdout: false/g' "$CHIA_ROOT/config/config.yaml" 265 | fi 266 | 267 | # Compressed plot harvesting settings. 268 | if [[ -n "$parallel_decompressor_count" && "$parallel_decompressor_count" != 0 ]]; then 269 | yq -i '.harvester.parallel_decompressor_count = env(parallel_decompressor_count)' "$CHIA_ROOT/config/config.yaml" 270 | else 271 | yq -i '.harvester.parallel_decompressor_count = 0' "$CHIA_ROOT/config/config.yaml" 272 | fi 273 | 274 | if [[ -n "$decompressor_thread_count" && "$decompressor_thread_count" != 0 ]]; then 275 | yq -i '.harvester.decompressor_thread_count = env(decompressor_thread_count)' "$CHIA_ROOT/config/config.yaml" 276 | else 277 | yq -i '.harvester.decompressor_thread_count = 0' "$CHIA_ROOT/config/config.yaml" 278 | fi 279 | 280 | if [[ -n "$use_gpu_harvesting" && "$use_gpu_harvesting" == 'true' ]]; then 281 | yq -i '.harvester.use_gpu_harvesting = True' "$CHIA_ROOT/config/config.yaml" 282 | else 283 | yq -i '.harvester.use_gpu_harvesting = False' "$CHIA_ROOT/config/config.yaml" 284 | fi 285 | 286 | # Install timelord if service variable contains timelord substring 287 | if [ -z "${service##*timelord*}" ]; then 288 | arch=$(uname -m) 289 | echo "Info: detected CPU architecture $arch" 290 | if [ "$arch" != "x86_64" ]; then 291 | echo "Error: Unsupported CPU architecture for running the timelord component. Requires x86_64." 292 | exit 1 293 | fi 294 | 295 | echo "Installing timelord using install-timelord.sh" 296 | 297 | # install-timelord.sh relies on lsb-release for determining the cmake installation method, and git for building chiavdf 298 | DEBIAN_FRONTEND=noninteractive apt-get update 299 | DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y lsb-release git 300 | 301 | /bin/sh ./install-timelord.sh 302 | fi 303 | 304 | # Map deprecated legacy startup options. 305 | if [[ ${farmer} == "true" ]]; then 306 | service="farmer-only" 307 | elif [[ ${harvester} == "true" ]]; then 308 | service="harvester" 309 | fi 310 | 311 | if [[ ${service} == "harvester" ]]; then 312 | if [[ -z ${farmer_address} || -z ${farmer_port} || -z ${ca} ]]; then 313 | echo "A farmer peer address, port, and ca path are required." 314 | exit 315 | fi 316 | fi 317 | 318 | # Configure trusted peers if specified 319 | if [[ -n ${trusted_peers} ]]; then 320 | echo "Adding trusted peers from environment variable" 321 | IFS=',' read -ra TRUSTED_PEERS <<< "$trusted_peers" 322 | 323 | # Loop through each trusted node 324 | for peer in "${TRUSTED_PEERS[@]}"; do 325 | address="${peer%:*}" 326 | port="${peer#*:}" 327 | 328 | if [[ -n $address ]]; then 329 | echo "Adding trusted peer: $address:$port" 330 | /usr/bin/chia-tools config add-trusted-peer -y "$address" "$port" 331 | fi 332 | done 333 | fi 334 | 335 | # Check if any of the env vars start with "chia." or "chia__" and if so, process the config with chia-tools 336 | if env | grep -qE '^chia(\.|__)'; then 337 | echo "Found environment variables starting with 'chia.' or 'chia__' - Running chia-tools" 338 | /usr/bin/chia-tools config edit --config "$CHIA_ROOT/config/config.yaml" 339 | fi 340 | 341 | exec "$@" 342 | -------------------------------------------------------------------------------- /docker-healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck disable=SC2154 4 | if [[ ${healthcheck} != "true" ]]; then 5 | exit 0 6 | fi 7 | 8 | dt () { 9 | date +%FT%T.%3N 10 | } 11 | 12 | logger () { 13 | # shellcheck disable=SC2154 14 | if [[ ${log_to_file} != 'true' ]]; then 15 | echo "$1" >> /proc/1/fd/1 16 | else 17 | echo "$1" >> "${CHIA_ROOT}/log/debug.log" 18 | fi 19 | } 20 | 21 | # Set default to false for all components 22 | # Gets reset to true individually depending on ${service} variable 23 | node_check=false 24 | farmer_check=false 25 | harvester_check=false 26 | wallet_check=false 27 | timelord_check=false 28 | crawler_check=false 29 | 30 | # Determine which services to healthcheck based on ${service} 31 | # shellcheck disable=SC2154,SC2206 32 | services_array=($service) 33 | for option in "${services_array[@]}" 34 | do 35 | case "${option}" in 36 | all) 37 | node_check=true 38 | farmer_check=true 39 | harvester_check=true 40 | wallet_check=true 41 | timelord_check=true 42 | crawler_check=true 43 | ;; 44 | node) 45 | node_check=true 46 | ;; 47 | harvester) 48 | harvester_check=true 49 | ;; 50 | farmer) 51 | node_check=true 52 | farmer_check=true 53 | harvester_check=true 54 | wallet_check=true 55 | ;; 56 | farmer-no-wallet) 57 | node_check=true 58 | farmer_check=true 59 | harvester_check=true 60 | ;; 61 | farmer-only) 62 | farmer_check=true 63 | ;; 64 | timelord) 65 | timelord_check=true 66 | ;; 67 | timelord-only) 68 | timelord_check=true 69 | ;; 70 | crawler) 71 | crawler_check=true 72 | ;; 73 | seeder) 74 | crawler_check=true 75 | ;; 76 | wallet) 77 | wallet_check=true 78 | ;; 79 | esac 80 | done 81 | 82 | # Always check the daemon 83 | nc -z -v -w1 localhost 55400 84 | # shellcheck disable=SC2181 85 | if [[ "$?" -ne 0 ]]; then 86 | logger "$(dt) Daemon healthcheck failed" 87 | exit 1 88 | fi 89 | 90 | if [[ ${node_check} == "true" ]]; then 91 | curl -X POST --fail \ 92 | --cert "${CHIA_ROOT}/config/ssl/full_node/private_full_node.crt" \ 93 | --key "${CHIA_ROOT}/config/ssl/full_node/private_full_node.key" \ 94 | -d '{}' -k -H "Content-Type: application/json" https://localhost:8555/healthz 95 | 96 | # shellcheck disable=SC2181 97 | if [[ "$?" -ne 0 ]]; then 98 | logger "$(dt) Node healthcheck failed" 99 | exit 1 100 | fi 101 | fi 102 | 103 | if [[ ${farmer_check} == "true" ]]; then 104 | curl -X POST --fail \ 105 | --cert "${CHIA_ROOT}/config/ssl/farmer/private_farmer.crt" \ 106 | --key "${CHIA_ROOT}/config/ssl/farmer/private_farmer.key" \ 107 | -d '{}' -k -H "Content-Type: application/json" https://localhost:8559/healthz 108 | 109 | # shellcheck disable=SC2181 110 | if [[ "$?" -ne 0 ]]; then 111 | logger "$(dt) Farmer healthcheck failed" 112 | exit 1 113 | fi 114 | fi 115 | 116 | if [[ ${harvester_check} == "true" ]]; then 117 | curl -X POST --fail \ 118 | --cert "${CHIA_ROOT}/config/ssl/harvester/private_harvester.crt" \ 119 | --key "${CHIA_ROOT}/config/ssl/harvester/private_harvester.key" \ 120 | -d '{}' -k -H "Content-Type: application/json" https://localhost:8560/healthz 121 | 122 | # shellcheck disable=SC2181 123 | if [[ "$?" -ne 0 ]]; then 124 | logger "$(dt) Harvester healthcheck failed" 125 | exit 1 126 | fi 127 | fi 128 | 129 | if [[ ${timelord_check} == "true" ]]; then 130 | curl -X POST --fail \ 131 | --cert "${CHIA_ROOT}/config/ssl/timelord/private_timelord.crt" \ 132 | --key "${CHIA_ROOT}/config/ssl/timelord/private_timelord.key" \ 133 | -d '{}' -k -H "Content-Type: application/json" https://localhost:8557/healthz 134 | 135 | # shellcheck disable=SC2181 136 | if [[ "$?" -ne 0 ]]; then 137 | logger "$(dt) Timelord healthcheck failed" 138 | exit 1 139 | fi 140 | fi 141 | 142 | if [[ ${crawler_check} == "true" ]]; then 143 | curl -X POST --fail \ 144 | --cert "${CHIA_ROOT}/config/ssl/crawler/private_crawler.crt" \ 145 | --key "${CHIA_ROOT}/config/ssl/crawler/private_crawler.key" \ 146 | -d '{}' -k -H "Content-Type: application/json" https://localhost:8561/healthz 147 | 148 | # shellcheck disable=SC2181 149 | if [[ "$?" -ne 0 ]]; then 150 | logger "$(dt) Crawler healthcheck failed" 151 | exit 1 152 | fi 153 | fi 154 | 155 | if [[ ${wallet_check} == "true" ]]; then 156 | curl -X POST --fail \ 157 | --cert "${CHIA_ROOT}/config/ssl/wallet/private_wallet.crt" \ 158 | --key "${CHIA_ROOT}/config/ssl/wallet/private_wallet.key" \ 159 | -d '{}' -k -H "Content-Type: application/json" https://localhost:9256/healthz 160 | 161 | # shellcheck disable=SC2181 162 | if [[ "$?" -ne 0 ]]; then 163 | logger "$(dt) Wallet healthcheck failed" 164 | exit 1 165 | fi 166 | fi 167 | 168 | # shellcheck disable=SC2154 169 | if [[ ${log_level} == 'INFO' ]]; then 170 | logger "$(dt) Healthcheck(s) completed successfully" 171 | fi 172 | -------------------------------------------------------------------------------- /docker-start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # shellcheck disable=SC2154,SC2086 4 | chia ${chia_args} start ${service} 5 | 6 | trap "echo Shutting down ...; chia stop all -d; exit 0" SIGINT SIGTERM 7 | 8 | # shellcheck disable=SC2154 9 | if [[ ${log_to_file} == 'true' ]]; then 10 | # Ensures the log file actually exists, so we can tail successfully 11 | touch "$CHIA_ROOT/log/debug.log" 12 | tail -F "$CHIA_ROOT/log/debug.log" & 13 | fi 14 | 15 | tail -F /dev/null 16 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Official Chia Docker Container 2 | 3 | ## Quick Start 4 | 5 | These examples shows valid setups using Chia for both docker run and docker-compose. Note that you should read some documentation at some point, but this is a good place to start. 6 | 7 | ### Docker run 8 | Simple example: 9 | ```bash 10 | docker run --name chia --expose=8444 -v /path/to/plots:/plots -d ghcr.io/chia-network/chia:latest 11 | ``` 12 | Syntax 13 | ```bash 14 | docker run [--name ] [--expose=] [-v ] -d ghcr.io/chia-network/chia:latest 15 | ``` 16 | Optional Docker parameters: 17 | - Give the container a name: `--name=chia` 18 | - Accept incoming connections: `--expose=8444` 19 | - Volume mount plots: `-v /path/to/plots:/plots` 20 | 21 | 22 | ### Docker compose 23 | 24 | ```yaml 25 | version: "3.6" 26 | services: 27 | chia: 28 | container_name: chia 29 | restart: unless-stopped 30 | image: ghcr.io/chia-network/chia:latest 31 | ports: 32 | - 8444:8444 33 | volumes: 34 | - /path/to/plots:/plots 35 | ``` 36 | 37 | ## Configuration 38 | 39 | You can modify the behavior of your Chia container by setting specific environment variables. 40 | 41 | ### Timezone 42 | 43 | Set the timezone for the container (optional, defaults to UTC). 44 | Timezones can be configured using the `TZ` env variable. A list of supported time zones can be found [here](http://manpages.ubuntu.com/manpages/focal/man3/DateTime::TimeZone::Catalog.3pm.html) 45 | ```bash 46 | -e TZ="America/Chicago" 47 | ``` 48 | 49 | ### Add your custom keys 50 | 51 | To use your own keys pass a file with your mnemonic as arguments on startup 52 | ```bash 53 | -v /path/to/key/file:/path/in/container -e keys="/path/in/container" 54 | ``` 55 | or pass keys into the running container with your mnemonic 56 | ```bash 57 | docker exec -it venv/bin/chia keys add 58 | ``` 59 | alternatively you can pass in your local keychain, if you have previously deployed chia with these keys on the host machine 60 | ```bash 61 | -v ~/.local/share/python_keyring/:/root/.local/share/python_keyring/ 62 | ``` 63 | or if you would like to persist the entire mainnet subdirectory and not touch the key directories at all 64 | ```bash 65 | -v ~/.chia/mainnet:/root/.chia/mainnet -e keys="persistent" 66 | ``` 67 | 68 | 69 | ### Persist configuration, db, and keyring 70 | 71 | You can persist whole db and configuration, simply mount it to Host. 72 | ```bash 73 | -v ~/.chia:/root/.chia \ 74 | -v ~/.chia_keys:/root/.chia_keys 75 | ``` 76 | 77 | ### Farmer only 78 | 79 | To start a farmer only node pass 80 | ```bash 81 | -e service="farmer-only" 82 | ``` 83 | 84 | ### Harvester only 85 | 86 | To start a harvester only node pass 87 | ```bash 88 | -e service="harvester" -e farmer_address="addres.of.farmer" -e farmer_port="portnumber" -v /path/to/ssl/ca:/path/in/container -e ca="/path/in/container" -e keys="none" 89 | ``` 90 | 91 | ### Configure full_node peer 92 | 93 | To set the full_node peer's hostname and port, set the "full_node_peer" environment variable with the format `hostname:port` 94 | ```bash 95 | -e full_node_peer="node:8444" 96 | ``` 97 | This will configure the full_node peer hostname and port for the wallet, farmer, and timelord sections of the config.yaml file. 98 | 99 | ### Configure trusted full_nodes peers for wallets 100 | 101 | You can specify a list of trusted full_node peers for your wallet by setting the `trusted_peers` environment variable with a comma-separated list of address:port pairs. 102 | 103 | NOTE: You should only configure trusted full_nodes that you manage. 104 | 105 | ```bash 106 | -e trusted_peers=="1.2.3.4:8444,4.3.2.1:8444" 107 | ``` 108 | 109 | At this time, only IP addresses are supported. Domains will not be added to your config as a trusted peer. 110 | 111 | See the [trusted peer documentation](https://docs.chia.net/faq/?_highlight=trusted#what-are-trusted-peers-and-how-do-i-add-them) to understand what trusted nodes are. 112 | 113 | ### Plots 114 | 115 | The `plots_dir` environment variable can be used to specify the directory containing the plots, it supports PATH-style colon-separated directories. 116 | 117 | Or, you can simply mount `/plots` path to your host machine. 118 | 119 | Set the environment variable `recursive_plot_scan` to `true` to enable the recursive plot scan configuration option. 120 | 121 | ### Adding mounts while running 122 | 123 | By default, Docker requires a container restart to discover newly mounted filesystems under a configured bind-mount. Setting the bind-propagation option to `rslave` enables dynamic addition of sub-mounts while the container is running (Linux systems only). [See Docker Bind Mounts documentation for more information.](https://docs.docker.com/storage/bind-mounts/#configure-bind-propagation) 124 | ```bash 125 | -v /plotdrives:/plotdrives:rslave 126 | ``` 127 | 128 | ### Compressed Plots 129 | 130 | There are a few environment variables that control compressed plot settings for Harvesters ran with chia-docker. The default settings leave compressed plot harvesting disabled, but it can be enabled. 131 | 132 | See the [official documentation](https://docs.chia.net/farming-compressed-plots/#cli) for a description on what each of these settings do. 133 | 134 | Compressed plot farming can be enabled by setting the following: 135 | 136 | ```bash 137 | -e parallel_decompressor_count=1 138 | -e decompressor_thread_count=1 139 | ``` 140 | 141 | And to use an nvidia GPU for plot decompression, set: 142 | 143 | ```bash 144 | -e use_gpu_harvesting="true" 145 | ``` 146 | 147 | ### Log level 148 | To set the log level to one of CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET 149 | ```bash 150 | -e log_level="DEBUG" 151 | ``` 152 | 153 | ### Peer Count 154 | To set the peer_count and outbound_peer_count 155 | 156 | for example to set both to 20 use 157 | ```bash 158 | -e peer_count="20" 159 | ``` 160 | 161 | ```bash 162 | -e outbound_peer_count="20" 163 | ``` 164 | 165 | ### UPnP 166 | To disable UPnP support (enabled by default) 167 | ```bash 168 | -e upnp="false" 169 | ``` 170 | 171 | ### Log to file 172 | Log file can be used by external tools like chiadog, etc. Enabled by default. 173 | 174 | To disable log file generation, use 175 | ```bash 176 | -e log_to_file="false" 177 | ``` 178 | 179 | ### Docker Compose 180 | 181 | ```yaml 182 | version: "3.6" 183 | services: 184 | chia: 185 | container_name: chia 186 | restart: unless-stopped 187 | image: ghcr.io/chia-network/chia:latest 188 | ports: 189 | - 8444:8444 190 | environment: 191 | # Farmer Only 192 | # service: farmer-only 193 | # Harvester Only 194 | # service: harvester 195 | # farmer_address: 192.168.0.10 196 | # farmer_port: 8447 197 | # ca: /path/in/container 198 | # keys: generate 199 | # Harvester Only END 200 | # If you would like to add keys manually via mnemonic file 201 | # keys: /path/in/container 202 | # OR 203 | # Disable key generation on start 204 | # keys: 205 | TZ: ${TZ} 206 | # Enable UPnP 207 | # upnp: "true" 208 | # Enable log file generation 209 | # log_to_file: "true" 210 | volumes: 211 | - /path/to/plots:/plots 212 | - /home/user/.chia:/root/.chia 213 | # - /home/user/mnemonic:/path/in/container 214 | ``` 215 | 216 | ## CLI 217 | 218 | You can run commands externally with venv (this works for most chia [CLI commands](https://github.com/Chia-Network/chia-blockchain/wiki/CLI-Commands-Reference)) 219 | ```bash 220 | docker exec -it chia venv/bin/chia plots add -d /plots 221 | ``` 222 | 223 | ### Is it working? 224 | 225 | You can see status from outside the container 226 | ```bash 227 | $ docker exec -it chia venv/bin/chia farm summary 228 | Farming status: Farming 229 | Total chia farmed: xx 230 | User transaction fees: xx 231 | Block rewards: xx 232 | Last height farmed: xxxxxxx 233 | Local Harvester 234 | xxx plots of size: xx.xxx TiB 235 | Plot count for all harvesters: xxx 236 | Total size of plots: xx.xxx TiB 237 | Estimated network space: 30.638 EiB 238 | Expected time to win: x months and x weeks 239 | Note: log into your key using 'chia wallet show' to see rewards for each key 240 | ``` 241 | 242 | Or via `chia peer`. Note that you have to specify your component. 243 | 244 | ```bash 245 | docker exec -it chia venv/bin/chia peer -c {farmer|wallet|full_node|harvester|data_layer} 246 | ``` 247 | 248 | Or via `chia show -s`. 249 | 250 | ```bash 251 | $ docker exec -it chia venv/bin/chia show -s 252 | Network: mainnet Port: 8444 RPC Port: 8555 253 | Node ID: xxxxx 254 | Genesis Challenge: xxxxx 255 | Current Blockchain Status: Full Node Synced 256 | 257 | Peak: Hash: xxxxx 258 | Time: Fri Jan 19 2024 17:52:44 CET Height: 4823454 259 | 260 | Estimated network space: 30.639 EiB 261 | Current difficulty: 11136 262 | Current VDF sub_slot_iters: 574619648 263 | 264 | Height: | Hash: 265 | 4823454 | 7e66bd11e46801b25ac9237e300deff27a4750fc3bf4eb7e3c594b17faaf0b37 266 | 4823453 | 9f5b68a52364c1afec48bc87d26bbba912c355e7f51c970f7bf89d068c762530 267 | 4823452 | db3b5bb0e3d09fd398e2d9bd159c387f9ad280ec8719916ebb6c25c948834f9c 268 | 4823451 | 5dd056960ec14da1c54fe295f33487e280f3e3c39eddced158ebb520b8215894 269 | 4823450 | a3f5a3f61728b1f52e1ab7971b29d0c55b6bc8e2797ad826b780ada7a0f76a49 270 | 4823449 | 052075e6b9881049c95c3ceeabed9160e5bfbf55a2b3b0768a743542ce88a3a3 271 | 4823448 | 3e2b954d4eb782d1ce67eb7f17e9bf72843d17948ba181168dbc239c5e70acd2 272 | 4823447 | 69539a9474c239280b6a6b4ab5be994e892c1b75c7bfb8967517e75ee5a65b12 273 | 4823446 | 47ce031f46b2b0c9f90e90de4f9cab58054f356a7a3019b30c8f6292b86a5aae 274 | 4823445 | 8c5d0254db6e304696d240dc70bad803ad227b861d68e65a3dc30c0aeef298f6 275 | 276 | ``` 277 | 278 | ### Connect to testnet? 279 | 280 | ```bash 281 | docker run -d --expose=58444 -e testnet=true --name chia ghcr.io/chia-network/chia:latest 282 | ``` 283 | 284 | ### Connect remotely 285 | 286 | Sometimes you may want to access Chia RPCs from outside of the container, or connect a GUI to a remote Chia farm. In those instances, you may need to configure the `self_hostname` key in the Chia config file. 287 | 288 | By default this is set to `127.0.0.1` in chia-docker, but can be configured using the `self_hostname` environment variable, like so: 289 | 290 | ```bash 291 | docker run -d -e self_hostname="0.0.0.0" --name chia ghcr.io/chia-network/chia:latest 292 | ``` 293 | 294 | This sets self_hostname in the config to `0.0.0.0`, which will allow you to access the Chia RPC from outside of the container (you will still need a copy of the private cert/key for the component you're attempting to access.) 295 | 296 | #### Need a wallet? 297 | 298 | To get new wallet, execute command and follow the prompts: 299 | 300 | ```bash 301 | docker exec -it chia-farmer1 venv/bin/chia wallet show 302 | ``` 303 | 304 | ## Building 305 | 306 | ```bash 307 | docker build -t chia --build-arg BRANCH=latest . 308 | ``` 309 | 310 | ## Healthchecks 311 | 312 | The Dockerfile includes a HEALTHCHECK instruction that runs one or more curl commands against the Chia RPC API. In Docker, this can be disabled using an environment variable `-e healthcheck=false` as part of the `docker run` command. Or in docker-compose you can add it to your Chia service, like so: 313 | 314 | ```yaml 315 | version: "3.6" 316 | services: 317 | chia: 318 | ... 319 | environment: 320 | healthcheck: "false" 321 | ``` 322 | 323 | In Kubernetes, Docker healthchecks are disabled by default. Instead, readiness and liveness probes should be used, which can be configured in a Pod or Deployment manifest file like the following: 324 | 325 | ```yaml 326 | livenessProbe: 327 | exec: 328 | command: 329 | - /bin/sh 330 | - -c 331 | - '/usr/local/bin/docker-healthcheck.sh || exit 1' 332 | initialDelaySeconds: 60 333 | readinessProbe: 334 | exec: 335 | command: 336 | - /bin/sh 337 | - -c 338 | - '/usr/local/bin/docker-healthcheck.sh || exit 1' 339 | initialDelaySeconds: 60 340 | ``` 341 | 342 | See [Configure Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for more information about configuring readiness and liveness probes for Kubernetes clusters. The `initialDelaySeconds` parameter may need to be adjusted higher or lower depending on the speed to start up on the host the container is running on. 343 | 344 | ## Simulator 345 | 346 | `docker run -e service=simulator -v /local/path/to/simulator:/root/.chia/simulator ghcr.io/chia-network/chia:latest` 347 | 348 | Mounts the simulator root to the provided local path to make the test plots and the mnemonic persistent. Mnemonic will be available at /local/path/to/simulator/mnemonic 349 | --------------------------------------------------------------------------------