├── .eth ├── README.md ├── charon │ └── .empty ├── dkg_output │ └── .empty ├── ethdo │ ├── README.md │ └── create-withdrawal-change.sh ├── exit_messages │ └── .empty ├── lido-ejector │ └── .empty └── validator_keys │ └── .empty ├── .github ├── actions │ └── test_client_stack │ │ └── action.yml ├── check-service.sh ├── helper.sh ├── pull_request_template.md ├── test-ethd-config.exp └── workflows │ ├── build-besu.yml │ ├── build-deposit.yml │ ├── build-erigon.yml │ ├── build-fluffy.yml │ ├── build-geth.yml │ ├── build-grandine.yml │ ├── build-lighthouse.yml │ ├── build-lodestar.yml │ ├── build-nethermind.yml │ ├── build-nimbus-el.yml │ ├── build-nimbus-gnosis.yml │ ├── build-nimbus-slottime.yml │ ├── build-nimbus.yml │ ├── build-prysm.yml │ ├── build-reth.yml │ ├── build-teku.yml │ ├── lint.yml │ ├── test-ethd.yml │ ├── test-fluffy.yml │ ├── test-grafana.yml │ ├── test-grandine-nimbus.yml │ ├── test-lighthouse-reth.yml │ ├── test-lodestar-erigon.yml │ ├── test-nimbus-nethermind.yml │ ├── test-prysm-geth.yml │ ├── test-teku-besu.yml │ ├── test-update.yml │ └── test-vero.yml ├── .gitignore ├── .motd ├── .pre-commit-config.yaml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── allin1-keyapi-shared.yml ├── bash-completion ├── besu.yml ├── besu ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── caplin-shared.yml ├── caplin-traefik.yml ├── central-metrics.yml ├── cl-shared.yml ├── cl-traefik.yml ├── commit-boost-pbs.yml ├── commit-boost └── cb-config.toml.sample ├── contributoor.yml ├── default.env ├── deposit-cli.yml ├── ee-shared.yml ├── ee-traefik.yml ├── el-shared.yml ├── el-traefik.yml ├── erigon.yml ├── erigon ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── ethd ├── ethdo.yml ├── ethdo ├── Dockerfile └── docker-entrypoint.sh ├── ethstaker-deposit-cli ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── ext-network.yml ├── flashbots ├── Dockerfile.binary └── Dockerfile.source ├── fluffy.yml ├── fluffy ├── Dockerfile.binary └── Dockerfile.source ├── geth.yml ├── geth ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── grafana-cloud.yml ├── grafana-rootless.yml ├── grafana-shared.yml ├── grafana.yml ├── grafana ├── Dockerfile ├── dashboard.yml ├── datasource.yml ├── default-alerts │ ├── cpu.yml │ ├── crit_disk_space.yml │ ├── disk_space.yml │ ├── memory.yml │ └── oom.yml └── provision.sh ├── grandine-allin1.yml ├── grandine-cl-only.yml ├── grandine ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── keyapi-shared.yml ├── lido-obol.yml ├── lighthouse-cl-only.yml ├── lighthouse-vc-only.yml ├── lighthouse.yml ├── lighthouse ├── Dockerfile.binary ├── Dockerfile.source ├── docker-entrypoint-vc.sh ├── docker-entrypoint.sh └── validator-exit.sh ├── lodestar-cl-only.yml ├── lodestar-vc-only.yml ├── lodestar.yml ├── lodestar ├── Dockerfile.binary ├── Dockerfile.source ├── docker-entrypoint-vc.sh └── docker-entrypoint.sh ├── loki └── loki.yml ├── mev-boost.yml ├── nethermind.yml ├── nethermind ├── Dockerfile.binary ├── Dockerfile.dev ├── Dockerfile.source └── docker-entrypoint.sh ├── nimbus-allin1.yml ├── nimbus-cl-only.yml ├── nimbus-el.yml ├── nimbus-el ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── nimbus-stats.yml ├── nimbus-vc-only.yml ├── nimbus.yml ├── nimbus ├── Dockerfile.binary ├── Dockerfile.source ├── Dockerfile.sourcegnosis ├── Dockerfile.sourceslottime ├── docker-entrypoint-vc.sh ├── docker-entrypoint.sh └── validator-exit.sh ├── portal-shared.yml ├── prometheus-shared.yml ├── prometheus-traefik.yml ├── prometheus ├── .gitignore ├── Dockerfile ├── base-config.yml ├── blackbox.yml ├── conf.d │ ├── coingecko.yml │ └── ping.yml ├── custom-prom.yml.sample ├── docker-entrypoint.sh ├── json.yml ├── obol-prom.yml ├── rootless-base-config.yml └── rootless │ ├── besu-prom.yml │ ├── erigon-prom.yml │ ├── geth-prom.yml │ ├── lh-prom.yml │ ├── lhcc-prom.yml │ ├── lido-obol-prom.yml │ ├── ls-prom.yml │ ├── lscc-prom.yml │ ├── nethermind-prom.yml │ ├── nimbus-prom.yml │ ├── prysm-prom.yml │ ├── prysmcc-prom.yml │ ├── reth-prom.yml │ ├── ssv-prom.yml │ ├── teku-prom.yml │ ├── traefik-prom.yml │ └── web3signer-prom.yml ├── promtail ├── custom-lokiurl.yml.sample ├── entrypoint.sh └── global.yml ├── prysm-cl-only.yml ├── prysm-stats.yml ├── prysm-vc-only.yml ├── prysm-web-shared.yml ├── prysm.yml ├── prysm ├── Dockerfile.binary ├── Dockerfile.source ├── create-wallet.sh ├── docker-entrypoint-vc.sh └── docker-entrypoint.sh ├── reth.yml ├── reth ├── Dockerfile.binary ├── Dockerfile.source └── docker-entrypoint.sh ├── siren-shared.yml ├── siren.yml ├── siren └── docker-entrypoint.sh ├── ssv-config ├── config-sample.yaml └── dkg-config-sample.yaml ├── ssv-dkg.yml ├── ssv-pulse.yml ├── ssv.yml ├── teku-allin1.yml ├── teku-cl-only.yml ├── teku-vc-only.yml ├── teku.yml ├── teku ├── Dockerfile.binary ├── Dockerfile.source ├── docker-entrypoint-vc.sh └── docker-entrypoint.sh ├── traefik-aws.yml ├── traefik-cf.yml ├── traefik ├── Dockerfile └── Dockerfile.jq ├── vc-utils ├── Dockerfile └── keymanager.sh ├── vero-vc-only.yml ├── vero ├── Dockerfile.binary ├── Dockerfile.real ├── Dockerfile.source └── docker-entrypoint.sh ├── web3signer.yml └── web3signer ├── Dockerfile.binary └── docker-entrypoint.sh /.eth/README.md: -------------------------------------------------------------------------------- 1 | The directory `validator_keys` will contain the `deposit_data-TIMESTAMP.json` and `keystore-m_ID.json` 2 | files created by staking-deposit-cli. 3 | 4 | Use `deposit_data-TIMESTAMP.json` for your initial deposit. After that, it can be disposed of. 5 | 6 | Use `keystore-m_ID.json` files to import your validator secret keys into the validator 7 | instance of the client you are running. 8 | -------------------------------------------------------------------------------- /.eth/charon/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-educators/eth-docker/f016af5f4e484ea07fa4476fd226677c33cd6370/.eth/charon/.empty -------------------------------------------------------------------------------- /.eth/dkg_output/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-educators/eth-docker/f016af5f4e484ea07fa4476fd226677c33cd6370/.eth/dkg_output/.empty -------------------------------------------------------------------------------- /.eth/exit_messages/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-educators/eth-docker/f016af5f4e484ea07fa4476fd226677c33cd6370/.eth/exit_messages/.empty -------------------------------------------------------------------------------- /.eth/lido-ejector/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-educators/eth-docker/f016af5f4e484ea07fa4476fd226677c33cd6370/.eth/lido-ejector/.empty -------------------------------------------------------------------------------- /.eth/validator_keys/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eth-educators/eth-docker/f016af5f4e484ea07fa4476fd226677c33cd6370/.eth/validator_keys/.empty -------------------------------------------------------------------------------- /.github/actions/test_client_stack/action.yml: -------------------------------------------------------------------------------- 1 | name: "Test Client Stack" 2 | description: "A custom action to test CL, VC and EL" 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Start client combo 8 | run: ./ethd up 9 | shell: bash 10 | - name: Pause for 30 seconds 11 | run: sleep 30 12 | shell: bash 13 | - name: Test CL 14 | run: ./.github/check-service.sh consensus 15 | shell: bash 16 | - name: Test VC 17 | run: ./.github/check-service.sh validator 18 | shell: bash 19 | - name: Test EL 20 | run: ./.github/check-service.sh execution 21 | shell: bash 22 | -------------------------------------------------------------------------------- /.github/check-service.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | __service=$1 4 | 5 | __containerID=$(docker compose ps -q "${__service}") 6 | 7 | __restart_count=$(docker inspect --format '{{ .RestartCount }}' "$__containerID") 8 | __is_running=$(docker inspect --format '{{ .State.Running }}' "$__containerID") 9 | 10 | if [ "$__is_running" != "true" ] || [ "$__restart_count" -gt 1 ]; then 11 | echo "$__service is either not running or continuously restarting" 12 | docker compose ps "${__service}" 13 | docker compose logs "${__service}" 14 | exit 1 15 | else 16 | echo "$__service is running" 17 | docker compose ps "${__service}" 18 | exit 0 19 | fi 20 | -------------------------------------------------------------------------------- /.github/helper.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set_value_in_env() { 4 | # Assumes that "var" has been set to the name of the variable to be changed 5 | if [ "${!var+x}" ]; then 6 | if ! grep -qF "${var}" .env 2>/dev/null ; then 7 | echo "${var}=${!var}" >> .env 8 | else 9 | sed -i'.original' -e "s~^\(${var}\s*=\s*\).*$~\1${!var}~" .env 10 | fi 11 | fi 12 | } 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | **What I did** 2 | 3 | **Related issue** 4 | 5 | 6 | **(not mandatory) A picture of a cute animal, if possible in relation to what you did** 7 | -------------------------------------------------------------------------------- /.github/workflows/build-besu.yml: -------------------------------------------------------------------------------- 1 | name: Source build Besu 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-besu: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Teku/Besu 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=teku.yml:besu.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | BESU_DOCKERFILE=Dockerfile.source 32 | var=BESU_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Teku/Besu w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=teku-cl-only.yml:teku-vc-only.yml:besu.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-deposit.yml: -------------------------------------------------------------------------------- 1 | name: Source build ethstaker-deposit-cli 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-deposit-cli: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set ethstaker-deposit-cli 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=deposit-cli.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | DEPCLI_DOCKERFILE=Dockerfile.source 29 | var=DEPCLI_DOCKERFILE 30 | set_value_in_env 31 | - name: Build clients 32 | run: ./ethd update --non-interactive 33 | -------------------------------------------------------------------------------- /.github/workflows/build-erigon.yml: -------------------------------------------------------------------------------- 1 | name: Source build Erigon 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-erigon: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Lodestar/Erigon 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=lodestar.yml:erigon.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | ERIGON_DOCKERFILE=Dockerfile.source 32 | var=ERIGON_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Lodestar/Erigon w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=lodestar-cl-only.yml:lodestar-vc-only.yml:erigon.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-fluffy.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nimbus Fluffy 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nimbus: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nimbus/Fluffy 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nimbus-el.yml:fluffy.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | FLUFFY_DOCKERFILE=Dockerfile.source 32 | var=FLUFFY_DOCKERFILE 33 | set_value_in_env 34 | NETWORK=mainnet 35 | var=NETWORK 36 | set_value_in_env 37 | PORTAL=true 38 | var=PORTAL 39 | set_value_in_env 40 | EL_MINIMAL_NODE=true 41 | var=EL_MINIMAL_NODE 42 | set_value_in_env 43 | - name: Build clients 44 | run: ./ethd update --non-interactive 45 | - name: Test Nimbus Fluffy 46 | run: ./.github/check-service.sh portal 47 | -------------------------------------------------------------------------------- /.github/workflows/build-geth.yml: -------------------------------------------------------------------------------- 1 | name: Source build Geth 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-geth: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Prysm/Geth 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=prysm.yml:geth.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | CL_NODE=consensus:4000 32 | var=CL_NODE 33 | set_value_in_env 34 | GETH_DOCKERFILE=Dockerfile.source 35 | var=GETH_DOCKERFILE 36 | set_value_in_env 37 | - name: Build clients 38 | run: ./ethd update --non-interactive 39 | - name: Test the stack 40 | uses: ./.github/actions/test_client_stack 41 | - name: Set Prysm/Geth w/ VC 42 | run: | 43 | source ./.github/helper.sh 44 | COMPOSE_FILE=prysm-cl-only.yml:prysm-vc-only.yml:geth.yml 45 | var=COMPOSE_FILE 46 | set_value_in_env 47 | - name: Test the stack 48 | uses: ./.github/actions/test_client_stack 49 | -------------------------------------------------------------------------------- /.github/workflows/build-grandine.yml: -------------------------------------------------------------------------------- 1 | name: Source build Grandine 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-grandine: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Create .env file 18 | run: cp default.env .env 19 | - name: Set Grandine/Reth 20 | run: | 21 | source ./.github/helper.sh 22 | COMPOSE_FILE=grandine-allin1.yml:reth.yml 23 | var=COMPOSE_FILE 24 | set_value_in_env 25 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 26 | var=FEE_RECIPIENT 27 | set_value_in_env 28 | GRANDINE_DOCKERFILE=Dockerfile.source 29 | var=GRANDINE_DOCKERFILE 30 | set_value_in_env 31 | - name: Build Grandine 32 | run: ./ethd update --non-interactive 33 | - name: Start Grandine/Reth 34 | run: ./ethd up 35 | - name: Pause for 30 seconds 36 | run: sleep 30 37 | - name: Test Reth 38 | run: ./.github/check-service.sh execution 39 | - name: Test Grandine CL 40 | run: ./.github/check-service.sh consensus 41 | # - name: Test Grandine VC 42 | # run: ./.github/check-service.sh validator 43 | - name: Set Grandine/Reth w/ Lighthouse VC 44 | run: | 45 | source ./.github/helper.sh 46 | COMPOSE_FILE=grandine-cl-only.yml:lighthouse-vc-only.yml:reth.yml 47 | var=COMPOSE_FILE 48 | set_value_in_env 49 | - name: Test the stack 50 | uses: ./.github/actions/test_client_stack 51 | -------------------------------------------------------------------------------- /.github/workflows/build-lighthouse.yml: -------------------------------------------------------------------------------- 1 | name: Source build Lighthouse 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-lighthouse: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Lighthouse/Reth 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=lighthouse.yml:reth.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | LH_DOCKERFILE=Dockerfile.source 32 | var=LH_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Lighthouse/Reth w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=lighthouse-cl-only.yml:lighthouse-vc-only.yml:reth.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-lodestar.yml: -------------------------------------------------------------------------------- 1 | name: Source build Lodestar 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-lodestar: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Lodestar/Erigon 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=lodestar.yml:erigon.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | LS_DOCKERFILE=Dockerfile.source 32 | var=LS_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Lodestar/Erigon w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=lodestar-cl-only.yml:lodestar-vc-only.yml:erigon.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-nethermind.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nethermind 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nethermind: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nethermind 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nethermind.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | NM_DOCKERFILE=Dockerfile.source 32 | var=NM_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Nimbus/Nethermind w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nethermind.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-nimbus-el.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nimbus EL 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nimbus: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nimbus 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nimbus-el.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | NIMEL_DOCKERFILE=Dockerfile.source 32 | var=NIMEL_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Nimbus/Nimbus w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nimbus-el.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/build-nimbus-gnosis.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nimbus on Gnosis 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nimbus: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nethermind 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nethermind.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | NIM_DOCKERFILE=Dockerfile.sourcegnosis 32 | var=NIM_DOCKERFILE 33 | set_value_in_env 34 | NETWORK=gnosis 35 | var=NETWORK 36 | set_value_in_env 37 | - name: Build clients 38 | run: ./ethd update --non-interactive 39 | - name: Start Nimbus/Nethermind 40 | run: ./ethd up 41 | - name: Pause for 30 seconds 42 | run: sleep 30 43 | - name: Test Nimbus CL 44 | run: ./.github/check-service.sh consensus 45 | - name: Test Nimbus VC 46 | run: ./.github/check-service.sh validator 47 | - name: Test Nethermind 48 | run: ./.github/check-service.sh execution 49 | - name: Set Nimbus/Nethermind w/ VC 50 | run: | 51 | source ./.github/helper.sh 52 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nethermind.yml 53 | var=COMPOSE_FILE 54 | set_value_in_env 55 | - name: Start Nimbus/Nethermind 56 | run: ./ethd up 57 | - name: Pause for 30 seconds 58 | run: sleep 30 59 | - name: Test Nimbus CL 60 | run: ./.github/check-service.sh consensus 61 | - name: Test Nimbus VC 62 | run: ./.github/check-service.sh validator 63 | - name: Test Nethermind 64 | run: ./.github/check-service.sh execution 65 | -------------------------------------------------------------------------------- /.github/workflows/build-nimbus-slottime.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nimbus with Ethereum slot time 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nimbus: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nethermind 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nethermind.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | NIM_DOCKERFILE=Dockerfile.sourceslottime 32 | var=NIM_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Start Nimbus/Nethermind 37 | run: ./ethd up 38 | - name: Pause for 30 seconds 39 | run: sleep 30 40 | - name: Test Nimbus CL 41 | run: ./.github/check-service.sh consensus 42 | - name: Test Nimbus VC 43 | run: ./.github/check-service.sh validator 44 | - name: Test Nethermind 45 | run: ./.github/check-service.sh execution 46 | - name: Set Nimbus/Nethermind w/ VC 47 | run: | 48 | source ./.github/helper.sh 49 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nethermind.yml 50 | var=COMPOSE_FILE 51 | set_value_in_env 52 | - name: Start Nimbus/Nethermind 53 | run: ./ethd up 54 | - name: Pause for 30 seconds 55 | run: sleep 30 56 | - name: Test Nimbus CL 57 | run: ./.github/check-service.sh consensus 58 | - name: Test Nimbus VC 59 | run: ./.github/check-service.sh validator 60 | - name: Test Nethermind 61 | run: ./.github/check-service.sh execution 62 | -------------------------------------------------------------------------------- /.github/workflows/build-nimbus.yml: -------------------------------------------------------------------------------- 1 | name: Source build Nimbus 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-nimbus: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Nimbus/Nethermind 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=nimbus.yml:nethermind.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | NIM_DOCKERFILE=Dockerfile.source 32 | var=NIM_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Start Nimbus/Nethermind 37 | run: ./ethd up 38 | - name: Pause for 30 seconds 39 | run: sleep 30 40 | - name: Test Nimbus CL 41 | run: ./.github/check-service.sh consensus 42 | - name: Test Nimbus VC 43 | run: ./.github/check-service.sh validator 44 | - name: Test Nethermind 45 | run: ./.github/check-service.sh execution 46 | - name: Set Nimbus/Nethermind w/ VC 47 | run: | 48 | source ./.github/helper.sh 49 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nethermind.yml 50 | var=COMPOSE_FILE 51 | set_value_in_env 52 | - name: Start Nimbus/Nethermind 53 | run: ./ethd up 54 | - name: Pause for 30 seconds 55 | run: sleep 30 56 | - name: Test Nimbus CL 57 | run: ./.github/check-service.sh consensus 58 | - name: Test Nimbus VC 59 | run: ./.github/check-service.sh validator 60 | - name: Test Nethermind 61 | run: ./.github/check-service.sh execution 62 | -------------------------------------------------------------------------------- /.github/workflows/build-prysm.yml: -------------------------------------------------------------------------------- 1 | name: Source build Prysm 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-prysm: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Prysm/Geth 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=prysm.yml:geth.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | CL_NODE=consensus:4000 32 | var=CL_NODE 33 | set_value_in_env 34 | PRYSM_DOCKERFILE=Dockerfile.source 35 | var=PRYSM_DOCKERFILE 36 | set_value_in_env 37 | - name: Build clients 38 | run: ./ethd update --non-interactive 39 | - name: Test the stack 40 | uses: ./.github/actions/test_client_stack 41 | - name: Set Prysm/Geth w/ VC 42 | run: | 43 | source ./.github/helper.sh 44 | COMPOSE_FILE=prysm-cl-only.yml:prysm-vc-only.yml:geth.yml 45 | var=COMPOSE_FILE 46 | set_value_in_env 47 | - name: Test the stack 48 | uses: ./.github/actions/test_client_stack 49 | -------------------------------------------------------------------------------- /.github/workflows/build-reth.yml: -------------------------------------------------------------------------------- 1 | name: Source build Reth 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-reth: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Create .env file 18 | run: cp default.env .env 19 | - name: Set Lighthouse/Reth 20 | run: | 21 | source ./.github/helper.sh 22 | COMPOSE_FILE=lighthouse.yml:reth.yml 23 | var=COMPOSE_FILE 24 | set_value_in_env 25 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 26 | var=FEE_RECIPIENT 27 | set_value_in_env 28 | RETH_DOCKERFILE=Dockerfile.source 29 | var=RETH_DOCKERFILE 30 | set_value_in_env 31 | - name: Build clients 32 | run: ./ethd update --non-interactive 33 | - name: Test the stack 34 | uses: ./.github/actions/test_client_stack 35 | - name: Set Lighthouse/Reth w/ VC 36 | run: | 37 | source ./.github/helper.sh 38 | COMPOSE_FILE=lighthouse-cl-only.yml:lighthouse-vc-only.yml:reth.yml 39 | var=COMPOSE_FILE 40 | set_value_in_env 41 | - name: Test the stack 42 | uses: ./.github/actions/test_client_stack 43 | -------------------------------------------------------------------------------- /.github/workflows/build-teku.yml: -------------------------------------------------------------------------------- 1 | name: Source build Teku 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | schedule: 9 | - cron: "42 7 * * 2" # Weekly Tuesday at 7:42 AM UTC 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build-teku: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Set up Docker buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Create .env file 21 | run: cp default.env .env 22 | - name: Set Teku/Besu 23 | run: | 24 | source ./.github/helper.sh 25 | COMPOSE_FILE=teku.yml:besu.yml 26 | var=COMPOSE_FILE 27 | set_value_in_env 28 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 29 | var=FEE_RECIPIENT 30 | set_value_in_env 31 | TEKU_DOCKERFILE=Dockerfile.source 32 | var=TEKU_DOCKERFILE 33 | set_value_in_env 34 | - name: Build clients 35 | run: ./ethd update --non-interactive 36 | - name: Test the stack 37 | uses: ./.github/actions/test_client_stack 38 | - name: Set Teku/Besu w/ VC 39 | run: | 40 | source ./.github/helper.sh 41 | COMPOSE_FILE=teku-cl-only.yml:teku-vc-only.yml:besu.yml 42 | var=COMPOSE_FILE 43 | set_value_in_env 44 | - name: Test the stack 45 | uses: ./.github/actions/test_client_stack 46 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint sources 2 | run-name: Lint sources 3 | 4 | on: 5 | push: 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Lint sources 15 | run: | 16 | sudo apt-get update && sudo apt-get install -y pre-commit 17 | pre-commit run --all-files 18 | -------------------------------------------------------------------------------- /.github/workflows/test-ethd.yml: -------------------------------------------------------------------------------- 1 | name: Test ethd 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-ethd: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-ethd') || 17 | contains(github.event.pull_request.labels.*.name, 'test-all') || 18 | github.event_name == 'push' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Install Expect 23 | run: sudo apt-get install -y expect whiptail 24 | - name: Test ethd config defaults 25 | run: expect ./.github/test-ethd-config.exp all-defaults 26 | env: 27 | TERM: xterm 28 | - name: Test ethd config no checkpoint 29 | run: expect ./.github/test-ethd-config.exp no-checkpoint 30 | env: 31 | TERM: xterm 32 | - name: Test ethd config no mev 33 | run: expect ./.github/test-ethd-config.exp no-mev 34 | env: 35 | TERM: xterm 36 | - name: Test ethd config no grafana 37 | run: expect ./.github/test-ethd-config.exp no-grafana 38 | env: 39 | TERM: xterm 40 | -------------------------------------------------------------------------------- /.github/workflows/test-fluffy.yml: -------------------------------------------------------------------------------- 1 | name: Test Grandine and Nimbus EL w/ Fluffy Portal 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-grandine-nimbus-fluffy: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-fluffy') || 17 | contains(github.event.pull_request.labels.*.name, 'test-all') || 18 | github.event_name == 'push' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Create .env file 23 | run: cp default.env .env 24 | - name: Set Grandine/Nimbus EL w/ Fluffy 25 | run: | 26 | source ./.github/helper.sh 27 | COMPOSE_FILE=grandine-allin1.yml:nimbus-el.yml:fluffy.yml 28 | var=COMPOSE_FILE 29 | set_value_in_env 30 | NETWORK=mainnet 31 | var=NETWORK 32 | set_value_in_env 33 | PORTAL=true 34 | var=PORTAL 35 | set_value_in_env 36 | EL_MINIMAL_NODE=true 37 | var=EL_MINIMAL_NODE 38 | set_value_in_env 39 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 40 | var=FEE_RECIPIENT 41 | set_value_in_env 42 | - name: Start Grandine/Nimbus EL w/ Fluffy 43 | run: ./ethd up 44 | - name: Pause for 30 seconds 45 | run: sleep 30 46 | - name: Test Nimbus EL 47 | run: ./.github/check-service.sh execution 48 | - name: Test Nimbus Fluffy 49 | run: ./.github/check-service.sh portal 50 | -------------------------------------------------------------------------------- /.github/workflows/test-grafana.yml: -------------------------------------------------------------------------------- 1 | name: Test Grafana 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-grafana: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-grafana') || 17 | contains(github.event.pull_request.labels.*.name, 'test-all') || 18 | github.event_name == 'push' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | - name: Set up Docker buildx 24 | uses: docker/setup-buildx-action@v3 25 | - name: Create .env file 26 | run: cp default.env .env 27 | - name: Set Lighthouse/Geth/Grafana 28 | run: | 29 | source ./.github/helper.sh 30 | COMPOSE_FILE=lighthouse.yml:geth.yml:grafana.yml 31 | var=COMPOSE_FILE 32 | set_value_in_env 33 | - name: Start Lighthouse/Geth/Grafana 34 | run: ./ethd up 35 | - name: Pause for 30 seconds 36 | run: sleep 30 37 | - name: Test Prometheus 38 | run: ./.github/check-service.sh prometheus 39 | - name: Test metrics exporter 40 | run: ./.github/check-service.sh ethereum-metrics-exporter 41 | - name: Test node exporter 42 | run: ./.github/check-service.sh node-exporter 43 | - name: Test blackbox exporter 44 | run: ./.github/check-service.sh blackbox-exporter 45 | - name: Test json exporter 46 | run: ./.github/check-service.sh json-exporter 47 | - name: Test cadvisor 48 | run: ./.github/check-service.sh cadvisor 49 | - name: Test promtail 50 | run: ./.github/check-service.sh promtail 51 | - name: Test Loki 52 | run: ./.github/check-service.sh loki 53 | - name: Test Grafana 54 | run: ./.github/check-service.sh grafana 55 | -------------------------------------------------------------------------------- /.github/workflows/test-grandine-nimbus.yml: -------------------------------------------------------------------------------- 1 | name: Test Grandine and Nimbus EL 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-grandine-nimbus: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-grandine') || 17 | contains(github.event.pull_request.labels.*.name, 'test-nimbus-el') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v3 23 | - name: Create .env file 24 | run: cp default.env .env 25 | - name: Set Grandine/Nimbus EL 26 | run: | 27 | source ./.github/helper.sh 28 | COMPOSE_FILE=grandine-allin1.yml:nimbus-el.yml 29 | var=COMPOSE_FILE 30 | set_value_in_env 31 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 32 | var=FEE_RECIPIENT 33 | set_value_in_env 34 | - name: Start Grandine/Nimbus EL 35 | run: ./ethd up 36 | - name: Pause for 30 seconds 37 | run: sleep 30 38 | - name: Test Nimbus EL 39 | run: ./.github/check-service.sh execution 40 | - name: Test Grandine CL 41 | run: ./.github/check-service.sh consensus 42 | # - name: Test Grandine VC 43 | # run: ./.github/check-service.sh validator 44 | - name: Set Grandine/Nimbus EL w/ Lighthouse VC 45 | run: | 46 | source ./.github/helper.sh 47 | COMPOSE_FILE=grandine-cl-only.yml:lighthouse-vc-only.yml:nimbus-el.yml 48 | var=COMPOSE_FILE 49 | set_value_in_env 50 | - name: Test the stack 51 | uses: ./.github/actions/test_client_stack 52 | -------------------------------------------------------------------------------- /.github/workflows/test-lighthouse-reth.yml: -------------------------------------------------------------------------------- 1 | name: Test Lighthouse and Reth 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-lighthouse-reth: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-lighthouse') || 17 | contains(github.event.pull_request.labels.*.name, 'test-reth') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - name: Set up Docker buildx 25 | uses: docker/setup-buildx-action@v3 26 | - name: Create .env file 27 | run: cp default.env .env 28 | - name: Set Lighthouse/Reth 29 | run: | 30 | source ./.github/helper.sh 31 | COMPOSE_FILE=lighthouse.yml:reth.yml 32 | var=COMPOSE_FILE 33 | set_value_in_env 34 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 35 | var=FEE_RECIPIENT 36 | set_value_in_env 37 | - name: Test the stack 38 | uses: ./.github/actions/test_client_stack 39 | - name: Set Lighthouse/Reth w/ VC 40 | run: | 41 | source ./.github/helper.sh 42 | COMPOSE_FILE=lighthouse-cl-only.yml:lighthouse-vc-only.yml:reth.yml 43 | var=COMPOSE_FILE 44 | set_value_in_env 45 | - name: Test the stack 46 | uses: ./.github/actions/test_client_stack 47 | -------------------------------------------------------------------------------- /.github/workflows/test-lodestar-erigon.yml: -------------------------------------------------------------------------------- 1 | name: Test Lodestar and Erigon 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-lodestar-erigon: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-lodestar') || 17 | contains(github.event.pull_request.labels.*.name, 'test-erigon') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - name: Set up Docker buildx 25 | uses: docker/setup-buildx-action@v3 26 | - name: Create .env file 27 | run: cp default.env .env 28 | - name: Set Lodestar/Erigon 29 | run: | 30 | source ./.github/helper.sh 31 | COMPOSE_FILE=lodestar.yml:erigon.yml 32 | var=COMPOSE_FILE 33 | set_value_in_env 34 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 35 | var=FEE_RECIPIENT 36 | set_value_in_env 37 | - name: Test the stack 38 | uses: ./.github/actions/test_client_stack 39 | - name: Set Lodestar/Erigon w/ VC 40 | run: | 41 | source ./.github/helper.sh 42 | COMPOSE_FILE=lodestar-cl-only.yml:lodestar-vc-only.yml:erigon.yml 43 | var=COMPOSE_FILE 44 | set_value_in_env 45 | - name: Test the stack 46 | uses: ./.github/actions/test_client_stack 47 | -------------------------------------------------------------------------------- /.github/workflows/test-nimbus-nethermind.yml: -------------------------------------------------------------------------------- 1 | name: Test Nimbus and Nethermind 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-nimbus-nethermind: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-nimbus') || 17 | contains(github.event.pull_request.labels.*.name, 'test-nethermind') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - name: Set up Docker buildx 25 | uses: docker/setup-buildx-action@v3 26 | - name: Create .env file 27 | run: cp default.env .env 28 | - name: Set Nimbus/Nethermind 29 | run: | 30 | source ./.github/helper.sh 31 | COMPOSE_FILE=nimbus.yml:nethermind.yml 32 | var=COMPOSE_FILE 33 | set_value_in_env 34 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 35 | var=FEE_RECIPIENT 36 | set_value_in_env 37 | - name: Test the stack 38 | uses: ./.github/actions/test_client_stack 39 | - name: Set Nimbus/Nethermind w/ VC 40 | run: | 41 | source ./.github/helper.sh 42 | COMPOSE_FILE=nimbus-cl-only.yml:nimbus-vc-only.yml:nethermind.yml 43 | var=COMPOSE_FILE 44 | set_value_in_env 45 | - name: Test the stack 46 | uses: ./.github/actions/test_client_stack 47 | -------------------------------------------------------------------------------- /.github/workflows/test-prysm-geth.yml: -------------------------------------------------------------------------------- 1 | name: Test Prysm and Geth 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-prysm-geth: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-prysm') || 17 | contains(github.event.pull_request.labels.*.name, 'test-geth') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - name: Set up Docker buildx 25 | uses: docker/setup-buildx-action@v3 26 | - name: Create .env file 27 | run: cp default.env .env 28 | - name: Set Prysm/Geth 29 | run: | 30 | source ./.github/helper.sh 31 | COMPOSE_FILE=prysm.yml:geth.yml 32 | var=COMPOSE_FILE 33 | set_value_in_env 34 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 35 | var=FEE_RECIPIENT 36 | set_value_in_env 37 | CL_NODE=consensus:4000 38 | var=CL_NODE 39 | set_value_in_env 40 | - name: Test the stack 41 | uses: ./.github/actions/test_client_stack 42 | - name: Set Prysm/Geth w/ VC 43 | run: | 44 | source ./.github/helper.sh 45 | COMPOSE_FILE=prysm-cl-only.yml:prysm-vc-only.yml:geth.yml 46 | var=COMPOSE_FILE 47 | set_value_in_env 48 | - name: Test the stack 49 | uses: ./.github/actions/test_client_stack 50 | -------------------------------------------------------------------------------- /.github/workflows/test-teku-besu.yml: -------------------------------------------------------------------------------- 1 | name: Test Teku and Besu 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-teku-besu: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-teku') || 17 | contains(github.event.pull_request.labels.*.name, 'test-besu') || 18 | contains(github.event.pull_request.labels.*.name, 'test-all') || 19 | github.event_name == 'push' 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | - name: Set up Docker buildx 25 | uses: docker/setup-buildx-action@v3 26 | - name: Create .env file 27 | run: cp default.env .env 28 | - name: Set Teku/Besu 29 | run: | 30 | source ./.github/helper.sh 31 | COMPOSE_FILE=teku.yml:besu.yml 32 | var=COMPOSE_FILE 33 | set_value_in_env 34 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 35 | var=FEE_RECIPIENT 36 | set_value_in_env 37 | - name: Test the stack 38 | uses: ./.github/actions/test_client_stack 39 | - name: Set Teku/Besu w/ VC 40 | run: | 41 | source ./.github/helper.sh 42 | COMPOSE_FILE=teku-cl-only.yml:teku-vc-only.yml:besu.yml 43 | var=COMPOSE_FILE 44 | set_value_in_env 45 | - name: Test the stack 46 | uses: ./.github/actions/test_client_stack 47 | -------------------------------------------------------------------------------- /.github/workflows/test-update.yml: -------------------------------------------------------------------------------- 1 | name: Test ethd update 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | branches: [main] 11 | 12 | jobs: 13 | test-update: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | - name: Set up Docker buildx 20 | uses: docker/setup-buildx-action@v3 21 | - name: Create .env file 22 | run: cp default.env .env 23 | - name: Test ethd update for missed variables 24 | run: ./ethd update --debug --non-interactive 25 | -------------------------------------------------------------------------------- /.github/workflows/test-vero.yml: -------------------------------------------------------------------------------- 1 | name: Test Vero 2 | 3 | defaults: 4 | run: 5 | shell: bash 6 | 7 | on: 8 | push: 9 | pull_request: 10 | types: [opened, synchronize, labeled, unlabeled] 11 | branches: [main] 12 | 13 | jobs: 14 | test-vero: 15 | if: | 16 | contains(github.event.pull_request.labels.*.name, 'test-vero') || 17 | contains(github.event.pull_request.labels.*.name, 'test-all') || 18 | github.event_name == 'push' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | - name: Set up Docker buildx 24 | uses: docker/setup-buildx-action@v3 25 | - name: Create .env file 26 | run: cp default.env .env 27 | - name: Set Nimbus/Nethermind/Vero/Web3signer 28 | run: | 29 | source ./.github/helper.sh 30 | COMPOSE_FILE=nimbus-cl-only.yml:vero-vc-only.yml:nethermind.yml:web3signer.yml 31 | var=COMPOSE_FILE 32 | set_value_in_env 33 | FEE_RECIPIENT=0xDccf8451070a86183eE70D330C4c43b686E9CF86 34 | var=FEE_RECIPIENT 35 | set_value_in_env 36 | WEB3SIGNER=true 37 | var=WEB3SIGNER 38 | set_value_in_env 39 | - name: Start the stack 40 | run: ./ethd up 41 | - name: Wait 5m 42 | run: sleep 300 43 | - name: Test CL 44 | run: ./.github/check-service.sh consensus 45 | shell: bash 46 | - name: Test EL 47 | run: ./.github/check-service.sh execution 48 | shell: bash 49 | - name: Test VC 50 | run: ./.github/check-service.sh validator 51 | shell: bash 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env* 2 | docker-compose.yml 3 | *.original 4 | *.bak 5 | .eth/* 6 | .eth_backup* 7 | !.eth/README.md 8 | !.eth/validator_keys/.empty 9 | !.eth/exit_messages/.empty 10 | !.eth/dkg_output/.empty 11 | !.eth/charon/.empty 12 | !.eth/lido-ejector/.empty 13 | !.eth/ethdo/README.md 14 | !.eth/ethdo/create-withdrawal-change.sh 15 | *.swp 16 | custom.yml 17 | ssv-config.yaml 18 | ssv-config.yaml.bak 19 | blox-ssv-config.yaml 20 | blox-ssv-config.yaml.bak 21 | promtail/custom-lokiurl.yml 22 | ssv-config/password.pass 23 | ssv-config/password 24 | ssv-config/encrypted_private_key.json 25 | ssv-config/config.yaml 26 | ssv-config/config.yaml.original 27 | ssv-config/dkg-config.yaml 28 | ssv-config/dkg-config.yaml.original 29 | commit-boost/cb-config.toml 30 | .nada 31 | -------------------------------------------------------------------------------- /.motd: -------------------------------------------------------------------------------- 1 | 2 | This system runs an Ethereum node in the ~/eth-docker directory 3 | 4 | Get scrolling logs: 'ethd logs -f --tail 50' 5 | Update the Ethereum clients: 'ethd update', then 'ethd up' to run them 6 | See the version of Ethereum clients: 'ethd version' 7 | Get help: 'ethd' 8 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v5.0.0 4 | hooks: 5 | - id: trailing-whitespace-fixer 6 | - id: end-of-file-fixer 7 | - id: check-json 8 | - id: check-yaml 9 | - id: double-quote-string-fixer 10 | - id: check-shebang-scripts-are-executable 11 | - id: check-executables-have-shebangs 12 | - id: detect-private-key 13 | - id: detect-aws-credentials 14 | repos: 15 | - repo: https://github.com/jumanjihouse/pre-commit-hooks 16 | rev: 3.0.0 17 | hooks: 18 | - id: shellcheck 19 | - id: script-must-have-extension 20 | - id: git-dirty 21 | - id: git-check 22 | - id: forbid-binary 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are welcome. All contributed code will be covered by the Apache License v2 of this project. 4 | 5 | ## Linting 6 | 7 | eth-docker CI uses [pre-commit](https://pre-commit.com/) to lint all code within the repo. Add it to your local 8 | copy with `apt install pre-commit` and `pre-commit install`. 9 | 10 | This repo uses a squash-and-merge workflow to avoid extra merge commits. Create a branch for your feature or fix, 11 | and work on this branch, then offer a PR from there. 12 | 13 | If you end up working on `main`, you can create an `upstream` remote with 14 | `git remote add upstream https://github.com/eth-educators/eth-docker.git`, and create a git alias with 15 | `git config --global alias.push-clean '!git fetch upstream main && git rebase upstream/main && git push -f'`. You can 16 | then `git push-clean` to your fork before opening a PR. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eth Docker: Docker automation for Ethereum nodes. 2 | 3 | [![GitPOAP Badge](https://public-api.gitpoap.io/v1/repo/eth-educators/eth-docker/badge)](https://www.gitpoap.io/gh/eth-educators/eth-docker) 4 | 5 | Eth Docker, a simple yet configurable way to run [Ethereum](https://ethereum.org/roadmap/) nodes. 6 | 7 | ## Getting Started 8 | 9 | Please see the [official documentation](https://ethdocker.com). 10 | 11 | For a quick testnet start, you can install prerequisites and configure Eth Docker, as any user not named `root`: 12 | 13 | * `cd ~ && git clone https://github.com/eth-educators/eth-docker.git && cd eth-docker` 14 | * `./ethd install` 15 | * `./ethd config` 16 | 17 | ## Support 18 | 19 | The #software channel in [ethstaker Discord](https://discord.gg/ethstaker) is the place to ask questions about Eth Docker. 20 | 21 | ## Contributions 22 | 23 | Contributions are highly appreciated. We have [GitPOAPs](https://www.gitpoap.io/gh/eth-educators/eth-docker)! To make your life easier, 24 | please read the [contribution guidelines](CONTRIBUTING.md) so you can run lint checks locally on pre-commit. 25 | 26 | ## License 27 | 28 | [Apache License v2](LICENSE) 29 | 30 | ## Version 31 | 32 | Eth Docker uses a "semver-ish" scheme. 33 | - First digit, major shifts in how things work. The last one was the Ethereum merge. I do not expect another shift that 34 | large. 35 | - Second through fourth digit, [semver](https://semver.org/). 36 | 37 | This is Eth Docker v2.15.3.0 38 | -------------------------------------------------------------------------------- /allin1-keyapi-shared.yml: -------------------------------------------------------------------------------- 1 | services: 2 | consensus: 3 | ports: 4 | - ${SHARE_IP:-}:${KEY_API_PORT:-7500}:${KEY_API_PORT:-7500}/tcp 5 | -------------------------------------------------------------------------------- /bash-completion: -------------------------------------------------------------------------------- 1 | completions() { 2 | local cur prev 3 | cur=${COMP_WORDS[COMP_CWORD]} 4 | prev=${COMP_WORDS[COMP_CWORD - 1]} 5 | 6 | case ${COMP_CWORD} in 7 | 1) 8 | COMPREPLY=($(compgen -W "install config keys update up start down stop restart version logs cmd terminate prune-geth prune-nethermind resync-execution resync-consensus attach-geth" -- ${cur})) 9 | ;; 10 | 2) 11 | case ${prev} in 12 | logs|restart|down|stop) 13 | COMPREPLY=($(docker container ls --filter "name=eth-docker-*" --format "{{.Names}}" | sed 's/eth-docker-\(.*\)-[0-9]/\1/')) 14 | ;; 15 | keys) 16 | COMPREPLY=($(compgen -W "list import delete register get-recipient set-recipient delete-recipient get-gas set-gas delete-gas get-api-token create-prysm-wallet get-prysm-wallet prepare-address-change send-address-change sign-exit send-exit" -- ${cur})) 17 | ;; 18 | *) 19 | COMPREPLY=() 20 | ;; 21 | esac 22 | ;; 23 | 3) 24 | case ${prev} in 25 | sign-exit) 26 | COMPREPLY=($(compgen -W "0x from-keystore" -- ${cur}) ) 27 | ;; 28 | *) 29 | COMPREPLY=() 30 | ;; 31 | esac 32 | ;; 33 | *) 34 | COMPREPLY=() 35 | ;; 36 | esac 37 | } 38 | 39 | complete -F completions ethd 40 | -------------------------------------------------------------------------------- /besu/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=hyperledger/besu 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused but included to avoid warnings 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=besu 11 | ARG UID=10001 12 | # GID 10002 is deliberate so it can exchange secret with CL 13 | ARG GID=10002 14 | 15 | USER root 16 | 17 | RUN groupmod -g "${GID}" besu && usermod -u "${UID}" -g "${GID}" besu 18 | 19 | RUN set -eux; \ 20 | apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git git-lfs wget; \ 21 | rm -rf /var/lib/apt/lists/*; \ 22 | # verify that the binary works 23 | gosu nobody true 24 | 25 | # Create data mount point with permissions 26 | RUN mkdir -p /var/lib/besu-og && chown -R ${USER}:${USER} /var/lib/besu-og && chmod -R 700 /var/lib/besu-og 27 | RUN mkdir -p /var/lib/besu/ee-secret && chown -R ${USER}:${USER} /var/lib/besu && chmod -R 700 /var/lib/besu && chmod 777 /var/lib/besu/ee-secret 28 | 29 | # Cannot assume buildkit, hence no chmod 30 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 31 | # Belt and suspenders 32 | RUN chmod -R 755 /usr/local/bin/* 33 | 34 | USER ${USER} 35 | 36 | ENTRYPOINT ["/opt/besu/bin/besu"] 37 | -------------------------------------------------------------------------------- /besu/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Besu in a stock Ubuntu container 2 | FROM eclipse-temurin:21-jdk-noble AS builder 3 | 4 | # This is here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git libjemalloc-dev 12 | 13 | WORKDIR /usr/src 14 | RUN bash -c "git clone --recurse-submodules -j8 ${SRC_REPO} besu && cd besu && git config advice.detachedHead false && git fetch --all --tags && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:besu-pr; git checkout besu-pr; else git checkout ${BUILD_TARGET}; fi && ./gradlew installDist" 15 | 16 | # Pull all binaries into a second stage deploy Ubuntu container 17 | FROM eclipse-temurin:21-jre-noble 18 | 19 | ARG USER=besu 20 | ARG UID=10001 21 | # GID 10002 is deliberate so it can exchange secret with CL 22 | ARG GID=10002 23 | 24 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 25 | ca-certificates \ 26 | tzdata \ 27 | gosu \ 28 | libjemalloc-dev \ 29 | git \ 30 | git-lfs \ 31 | wget \ 32 | adduser \ 33 | && apt-get clean \ 34 | && rm -rf /var/lib/apt/lists/* 35 | 36 | RUN addgroup \ 37 | --gid "${GID}" \ 38 | "${USER}" 39 | 40 | # See https://stackoverflow.com/a/55757473/12429735RUN 41 | RUN adduser \ 42 | --disabled-password \ 43 | --gecos "" \ 44 | --home "/nonexistent" \ 45 | --shell "/usr/sbin/nologin" \ 46 | --no-create-home \ 47 | --uid "${UID}" \ 48 | --ingroup "${USER}" \ 49 | "${USER}" 50 | 51 | RUN mkdir -p /var/lib/besu-og && chown -R ${USER}:${USER} /var/lib/besu-og && chmod -R 700 /var/lib/besu-og 52 | RUN mkdir -p /var/lib/besu/ee-secret && chown -R besu:besu /var/lib/besu && chmod -R 700 /var/lib/besu && chmod 777 /var/lib/besu/ee-secret 53 | 54 | # Cannot assume buildkit, hence no chmod 55 | COPY --from=builder --chown=${USER}:${USER} /usr/src/besu/build/install/besu/. /opt/besu/ 56 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 57 | # Belt and suspenders 58 | RUN chmod -R 755 /usr/local/bin/* 59 | 60 | USER ${USER} 61 | 62 | ENTRYPOINT ["/opt/besu/bin/besu"] 63 | -------------------------------------------------------------------------------- /caplin-shared.yml: -------------------------------------------------------------------------------- 1 | services: 2 | execution: 3 | ports: 4 | - ${SHARE_IP:-}:${CL_REST_PORT:-5052}:${CL_REST_PORT:-5052}/tcp 5 | -------------------------------------------------------------------------------- /caplin-traefik.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with erigon.yml when it is using Caplin 2 | # For remote validator setups only. Please be very cautious when exposing your consensus API port 3 | services: 4 | execution: 5 | labels: 6 | - traefik.enable=true 7 | - traefik.http.routers.${CL_HOST:-cl}.service=${CL_HOST:-cl} 8 | - traefik.http.routers.${CL_HOST:-cl}.entrypoints=websecure 9 | - traefik.http.routers.${CL_HOST:-cl}.rule=Host(`${CL_HOST:-cl}.${DOMAIN}`) 10 | - traefik.http.routers.${CL_HOST:-cl}.tls.certresolver=letsencrypt 11 | - traefik.http.routers.${CL_HOST:-cl}lb.service=${CL_HOST:-cl} 12 | - traefik.http.routers.${CL_HOST:-cl}lb.entrypoints=websecure 13 | - traefik.http.routers.${CL_HOST:-cl}lb.rule=Host(`${CL_LB:-cl-lb}.${DOMAIN}`) 14 | - traefik.http.routers.${CL_HOST:-cl}lb.tls.certresolver=letsencrypt 15 | - traefik.http.services.${CL_HOST:-cl}.loadbalancer.server.port=${CL_REST_PORT:-5052} 16 | -------------------------------------------------------------------------------- /central-metrics.yml: -------------------------------------------------------------------------------- 1 | # For scraping with central-proxy-docker, when all you want is the metrics exporter 2 | x-logging: &logging 3 | logging: 4 | driver: json-file 5 | options: 6 | max-size: 100m 7 | max-file: "3" 8 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 9 | 10 | services: 11 | ethereum-metrics-exporter: 12 | restart: "unless-stopped" 13 | image: samcm/ethereum-metrics-exporter:debian-latest 14 | entrypoint: 15 | - /ethereum-metrics-exporter 16 | - --consensus-url=http://consensus:${CL_REST_PORT:-5052} 17 | - --execution-url=http://execution:${EL_RPC_PORT:-8545} 18 | <<: *logging 19 | labels: 20 | - metrics.scrape=true 21 | - metrics.path=/metrics 22 | - metrics.port=9090 23 | - metrics.instance=ethereum-metrics-exporter 24 | - metrics.network=${NETWORK} 25 | -------------------------------------------------------------------------------- /cl-shared.yml: -------------------------------------------------------------------------------- 1 | services: 2 | consensus: 3 | ports: 4 | - ${SHARE_IP:-}:${CL_REST_PORT:-5052}:${CL_REST_PORT:-5052}/tcp 5 | -------------------------------------------------------------------------------- /cl-traefik.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with lodestar.yml, nimbus.yml, teku.yml, lighthouse.yml or prysm.yml, ditto their 2 | # -cl-only.yml versions 3 | # For remote validator setups only. Please be very cautious when exposing your consensus API port 4 | services: 5 | consensus: 6 | labels: 7 | - traefik.enable=true 8 | - traefik.http.routers.${CL_HOST:-cl}.service=${CL_HOST:-cl} 9 | - traefik.http.routers.${CL_HOST:-cl}.entrypoints=websecure 10 | - traefik.http.routers.${CL_HOST:-cl}.rule=Host(`${CL_HOST:-cl}.${DOMAIN}`) 11 | - traefik.http.routers.${CL_HOST:-cl}.tls.certresolver=letsencrypt 12 | - traefik.http.routers.${CL_HOST:-cl}lb.service=${CL_HOST:-cl} 13 | - traefik.http.routers.${CL_HOST:-cl}lb.entrypoints=websecure 14 | - traefik.http.routers.${CL_HOST:-cl}lb.rule=Host(`${CL_LB:-cl-lb}.${DOMAIN}`) 15 | - traefik.http.routers.${CL_HOST:-cl}lb.tls.certresolver=letsencrypt 16 | - traefik.http.services.${CL_HOST:-cl}.loadbalancer.server.port=${CL_REST_PORT:-5052} 17 | -------------------------------------------------------------------------------- /commit-boost-pbs.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | cb-pbs: 11 | image: ${CB_PBS_DOCKER_REPO:-ghcr.io/commit-boost/pbs}:${CB_PBS_DOCKER_TAG:-latest} 12 | environment: 13 | CB_CONFIG: /cb-config.toml 14 | CB_METRICS_PORT: 10000 15 | volumes: 16 | - ./commit-boost/cb-config.toml:/cb-config.toml:ro 17 | networks: 18 | default: 19 | aliases: 20 | - ${MEV_ALIAS:-default-mev} # This allows multiple Eth Docker stacks all connected to the same bridge network 21 | labels: 22 | - metrics.scrape=true 23 | - metrics.path=/metrics 24 | - metrics.port=10000 25 | - metrics.instance=cb-pbs 26 | - metrics.network=${NETWORK} 27 | -------------------------------------------------------------------------------- /commit-boost/cb-config.toml.sample: -------------------------------------------------------------------------------- 1 | chain = "Hoodi" 2 | 3 | [pbs] 4 | port = 18550 5 | 6 | [[relays]] 7 | id = "aestus" 8 | url = "https://0x98f0ef62f00780cf8eb06701a7d22725b9437d4768bb19b363e882ae87129945ec206ec2dc16933f31d983f8225772b6@hoodi.aestus.live" 9 | [[relays]] 10 | id = "titan" 11 | url = "https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@hoodi.titanrelay.xyz" 12 | [[relays]] 13 | id = "flashbots" 14 | url = "https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-hoodi.flashbots.net" 15 | [[relays]] 16 | id = "ultrasound" 17 | url = "https://0xb1559beef7b5ba3127485bbbb090362d9f497ba64e177ee2c8e7db74746306efad687f2cf8574e38d70067d40ef136dc@relay-hoodi.ultrasound.money" 18 | -------------------------------------------------------------------------------- /contributoor.yml: -------------------------------------------------------------------------------- 1 | # EthPandaOps Contributoor, for use alongside a consensus layer client 2 | ## Read more: https://github.com/ethpandaops/contributoor 3 | x-logging: &logging 4 | logging: 5 | driver: json-file 6 | options: 7 | max-size: 100m 8 | max-file: "3" 9 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 10 | 11 | services: 12 | contributoor: 13 | restart: "unless-stopped" 14 | image: ${CONTRIBUTOOR_DOCKER_REPO}:${CONTRIBUTOOR_DOCKER_TAG} 15 | volumes: 16 | - /etc/localtime:/etc/localtime:ro 17 | <<: *logging 18 | command: 19 | - --network=${NETWORK} 20 | - --beacon-node-address=${CL_NODE} 21 | - --username=${CONTRIBUTOOR_USERNAME} 22 | - --password=${CONTRIBUTOOR_PASSWORD} 23 | -------------------------------------------------------------------------------- /deposit-cli.yml: -------------------------------------------------------------------------------- 1 | services: 2 | deposit-cli-new: 3 | profiles: ["tools"] 4 | restart: "no" 5 | build: 6 | context: ./ethstaker-deposit-cli 7 | dockerfile: ${DEPCLI_DOCKERFILE} 8 | args: 9 | - BUILD_TARGET=${DEPCLI_SRC_BUILD_TARGET:-'$(git describe --tags $(git rev-list --tags --max-count=1))'} 10 | - SRC_REPO=${DEPCLI_SRC_REPO:-https://github.com/eth-educators/ethstaker-deposit-cli} 11 | - DOCKER_TAG=${DEPCLI_DOCKER_TAG:-latest} 12 | - DOCKER_REPO=${DEPCLI_DOCKER_REPO:-ghcr.io/eth-educators/ethstaker-deposit-cli} 13 | image: ethstaker-deposit-cli:local 14 | pull_policy: never 15 | volumes: 16 | - ./.eth:/app/.eth/ 17 | entrypoint: 18 | - docker-entrypoint.sh 19 | - python3 20 | - -m 21 | - ethstaker_deposit 22 | - new-mnemonic 23 | - --chain 24 | - ${NETWORK} 25 | deposit-cli-existing: 26 | profiles: ["tools"] 27 | restart: "no" 28 | build: 29 | context: ./ethstaker-deposit-cli 30 | dockerfile: ${DEPCLI_DOCKERFILE} 31 | args: 32 | - BUILD_TARGET=${DEPCLI_SRC_BUILD_TARGET:-'$(git describe --tags $(git rev-list --tags --max-count=1))'} 33 | - SRC_REPO=${DEPCLI_SRC_REPO:-https://github.com/eth-educators/ethstaker-deposit-cli} 34 | - DOCKER_TAG=${DEPCLI_DOCKER_TAG:-latest} 35 | - DOCKER_REPO=${DEPCLI_DOCKER_REPO:-ghcr.io/eth-educators/ethstaker-deposit-cli} 36 | image: ethstaker-deposit-cli:local 37 | pull_policy: never 38 | volumes: 39 | - ./.eth:/app/.eth/ 40 | entrypoint: 41 | - docker-entrypoint.sh 42 | - python3 43 | - -m 44 | - ethstaker_deposit 45 | - existing-mnemonic 46 | - --chain 47 | - ${NETWORK} 48 | deposit-cli-change: 49 | profiles: ["tools"] 50 | build: 51 | context: ./ethstaker-deposit-cli 52 | dockerfile: ${DEPCLI_DOCKERFILE} 53 | args: 54 | - BUILD_TARGET=${DEPCLI_SRC_BUILD_TARGET:-'$(git describe --tags $(git rev-list --tags --max-count=1))'} 55 | - SRC_REPO=${DEPCLI_SRC_REPO:-https://github.com/eth-educators/ethstaker-deposit-cli} 56 | - DOCKER_TAG=${DEPCLI_DOCKER_TAG:-latest} 57 | - DOCKER_REPO=${DEPCLI_DOCKER_REPO:-ghcr.io/eth-educators/ethstaker-deposit-cli} 58 | restart: "no" 59 | image: ethstaker-deposit-cli:local 60 | pull_policy: never 61 | volumes: 62 | - ./.eth:/app/.eth 63 | entrypoint: 64 | - docker-entrypoint.sh 65 | - python3 66 | - -m 67 | - ethstaker_deposit 68 | - generate-bls-to-execution-change 69 | - --chain 70 | - ${NETWORK} 71 | -------------------------------------------------------------------------------- /ee-shared.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with erigon.yml, nethermind.yml, besu.yml or geth.yml 2 | # For distributed setups only. Please be very cautious when exposing your engine API 3 | services: 4 | execution: 5 | ports: 6 | - ${SHARE_IP:-}:${EE_PORT}:${EE_PORT:-8551}/tcp 7 | -------------------------------------------------------------------------------- /ee-traefik.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with erigon.yml, nethermind.yml, besu.yml, reth.yml or geth.yml 2 | # For distributed setups only. Please be very cautious when exposing your engine port 3 | services: 4 | execution: 5 | labels: 6 | - traefik.enable=true 7 | - traefik.http.routers.${EE_HOST:-ee}.service=${EE_HOST:-ee} 8 | - traefik.http.routers.${EE_HOST:-ee}.entrypoints=websecure 9 | - traefik.http.routers.${EE_HOST:-ee}.rule=Host(`${EE_HOST:-ee}.${DOMAIN}`) 10 | - traefik.http.routers.${EE_HOST:-ee}.tls.certresolver=letsencrypt 11 | - traefik.http.services.${EE_HOST:-ee}.loadbalancer.server.port=${EE_PORT:-8551} 12 | -------------------------------------------------------------------------------- /el-shared.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with erigon.yml, nethermind.yml, besu.yml or geth.yml 2 | services: 3 | execution: 4 | ports: 5 | - ${SHARE_IP:-}:${EL_RPC_PORT}:${EL_RPC_PORT:-8545}/tcp 6 | - ${SHARE_IP:-}:${EL_WS_PORT}:${EL_WS_PORT:-8546}/tcp 7 | -------------------------------------------------------------------------------- /el-traefik.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with erigon.yml, nethermind.yml, besu.yml, reth.yml or geth.yml 2 | services: 3 | execution: 4 | labels: 5 | - traefik.enable=true 6 | - traefik.http.routers.${EL_HOST:-el}.service=${EL_HOST:-el} 7 | - traefik.http.routers.${EL_HOST:-el}.entrypoints=websecure 8 | - traefik.http.routers.${EL_HOST:-el}.rule=Host(`${EL_HOST:-el}.${DOMAIN}`) 9 | - traefik.http.routers.${EL_HOST:-el}.tls.certresolver=letsencrypt 10 | - traefik.http.routers.${EL_HOST:-el}lb.service=${EL_HOST:-el} 11 | - traefik.http.routers.${EL_HOST:-el}lb.entrypoints=websecure 12 | - traefik.http.routers.${EL_HOST:-el}lb.rule=Host(`${EL_LB:-el-lb}.${DOMAIN}`) 13 | - traefik.http.routers.${EL_HOST:-el}lb.tls.certresolver=letsencrypt 14 | - traefik.http.services.${EL_HOST:-el}.loadbalancer.server.port=${EL_RPC_PORT:-8545} 15 | - traefik.http.routers.${EL_WS_HOST:-elws}.service=${EL_WS_HOST:-elws} 16 | - traefik.http.routers.${EL_WS_HOST:-elws}.entrypoints=websecure 17 | - traefik.http.routers.${EL_WS_HOST:-elws}.rule=Host(`${EL_WS_HOST:-elws}.${DOMAIN}`) 18 | - traefik.http.routers.${EL_WS_HOST:-elws}.tls.certresolver=letsencrypt 19 | - traefik.http.routers.${EL_WS_HOST:-elws}lb.service=${EL_WS_HOST:-elws} 20 | - traefik.http.routers.${EL_WS_HOST:-elws}lb.entrypoints=websecure 21 | - traefik.http.routers.${EL_WS_HOST:-elws}lb.rule=Host(`${EL_WS_LB:-elws-lb}.${DOMAIN}`) 22 | - traefik.http.routers.${EL_WS_HOST:-elws}lb.tls.certresolver=letsencrypt 23 | - traefik.http.services.${EL_WS_HOST:-elws}.loadbalancer.server.port=${EL_WS_PORT:-8546} 24 | -------------------------------------------------------------------------------- /erigon/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=erigontech/erigon 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=erigon 11 | ARG UID=10001 12 | # GID 10002 is deliberate so it can exchange secret with CL 13 | ARG GID=10002 14 | 15 | USER root 16 | 17 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 18 | ca-certificates \ 19 | tzdata \ 20 | gosu \ 21 | git \ 22 | git-lfs \ 23 | jq \ 24 | && apt-get clean \ 25 | && rm -rf /var/lib/apt/lists/* 26 | 27 | RUN groupmod -g "${GID}" ${USER} && usermod -u "${UID}" -g "${GID}" ${USER} 28 | 29 | RUN mkdir -p /var/lib/erigon/ee-secret && chown -R ${USER}:${USER} /var/lib/erigon && chmod -R 700 /var/lib/erigon && chmod 777 /var/lib/erigon/ee-secret 30 | 31 | # Cannot assume buildkit, hence no chmod 32 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 33 | # Belt and suspenders 34 | RUN chmod -R 755 /usr/local/bin/* 35 | 36 | USER ${USER} 37 | 38 | ENTRYPOINT ["erigon"] 39 | -------------------------------------------------------------------------------- /erigon/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Erigon in a stock Go build container 2 | FROM golang:1.24-bookworm AS builder 3 | 4 | # Unused, this is here to avoid build time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | WORKDIR /src 12 | RUN bash -c "git clone ${SRC_REPO} erigon && cd erigon && git config advice.detachedHead false && git fetch --all --tags && \ 13 | if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:erigon-pr; git checkout erigon-pr; else git checkout ${BUILD_TARGET}; fi && make BUILD_TAGS=nosqlite,noboltdb,nosilkworm erigon" 14 | 15 | # Pull all binaries into a second stage deploy container 16 | FROM debian:bookworm-slim 17 | 18 | ARG USER=erigon 19 | ARG UID=10001 20 | # GID 10002 is deliberate so it can exchange secret with CL 21 | ARG GID=10002 22 | 23 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 24 | ca-certificates \ 25 | tzdata \ 26 | gosu \ 27 | git \ 28 | git-lfs \ 29 | jq \ 30 | && apt-get clean \ 31 | && rm -rf /var/lib/apt/lists/* 32 | 33 | RUN addgroup \ 34 | --gid "${GID}" \ 35 | "${USER}" 36 | 37 | # See https://stackoverflow.com/a/55757473/12429735RUN 38 | RUN adduser \ 39 | --disabled-password \ 40 | --gecos "" \ 41 | --shell "/sbin/nologin" \ 42 | --uid "${UID}" \ 43 | --ingroup "${USER}" \ 44 | "${USER}" 45 | 46 | RUN mkdir -p /var/lib/erigon/ee-secret && chown -R ${USER}:${USER} /var/lib/erigon && chmod -R 700 /var/lib/erigon && chmod 777 /var/lib/erigon/ee-secret 47 | 48 | # Cannot assume buildkit, hence no chmod 49 | COPY --from=builder --chown=${USER}:${USER} /src/erigon/build/bin/erigon /usr/local/bin/ 50 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 51 | # Belt and suspenders 52 | RUN chmod -R 755 /usr/local/bin/* 53 | 54 | USER ${USER} 55 | 56 | ENTRYPOINT ["erigon"] 57 | -------------------------------------------------------------------------------- /ethdo.yml: -------------------------------------------------------------------------------- 1 | # To be used with one of the yml files that start a CL client 2 | services: 3 | ethdo: 4 | profiles: ["tools"] 5 | restart: "no" 6 | build: 7 | context: ./ethdo 8 | image: ethdo:local 9 | pull_policy: never 10 | volumes: 11 | - ./.eth:/app/.eth 12 | - ethdo-wallet:/app/wallet 13 | environment: 14 | - NETWORK=${NETWORK} 15 | - CL_NODE=${CL_NODE:-http://consensus:5052} 16 | entrypoint: 17 | - docker-entrypoint.sh 18 | - /app/ethdo 19 | - --allow-insecure-connections 20 | - --debug 21 | 22 | volumes: 23 | ethdo-wallet: 24 | -------------------------------------------------------------------------------- /ethdo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM wealdtech/ethdo:latest 2 | 3 | ARG USER=ethdo 4 | ARG UID=1000 5 | 6 | # See https://stackoverflow.com/a/55757473/12429735RUN 7 | RUN adduser \ 8 | --disabled-password \ 9 | --gecos "" \ 10 | --home "/nonexistent" \ 11 | --shell "/sbin/nologin" \ 12 | --no-create-home \ 13 | --uid "${UID}" \ 14 | "${USER}" 15 | 16 | RUN apt-get update && apt-get install -y gosu jq 17 | 18 | RUN mkdir -p /app/wallet 19 | RUN chown -R ${USER}:${USER} /app 20 | 21 | COPY ./docker-entrypoint.sh /usr/local/bin/ 22 | 23 | ENTRYPOINT [ "/app/ethdo" ] 24 | -------------------------------------------------------------------------------- /ethstaker-deposit-cli/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=ghcr.io/eth-educators/ethstaker-deposit-cli 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | ARG BUILD_TARGET 7 | ARG SRC_REPO 8 | 9 | ARG USER=depcli 10 | ARG UID=1000 11 | 12 | # See https://stackoverflow.com/a/55757473/12429735RUN 13 | RUN adduser \ 14 | --disabled-password \ 15 | --gecos "" \ 16 | --home "/nonexistent" \ 17 | --shell "/sbin/nologin" \ 18 | --no-create-home \ 19 | --uid "${UID}" \ 20 | "${USER}" 21 | 22 | RUN apt-get update && apt-get install -y gosu 23 | 24 | WORKDIR /app 25 | 26 | RUN chown -R ${USER}:${USER} /app 27 | 28 | COPY ./docker-entrypoint.sh /usr/local/bin/ 29 | 30 | ENTRYPOINT [ "python3", "-m", "ethstaker_deposit" ] 31 | -------------------------------------------------------------------------------- /ethstaker-deposit-cli/Dockerfile.source: -------------------------------------------------------------------------------- 1 | FROM python:3.13-bookworm AS builder 2 | 3 | ARG BUILD_TARGET 4 | ARG SRC_REPO 5 | 6 | ARG DOCKER_TAG 7 | ARG DOCKER_REPO 8 | 9 | RUN mkdir -p /src 10 | 11 | RUN apt-get update && apt-get install -y bash git 12 | 13 | WORKDIR /src 14 | RUN bash -c "git clone ${SRC_REPO} ethstaker-deposit-cli && cd ethstaker-deposit-cli && git config advice.detachedHead false && git fetch --all --tags \ 15 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:deposit-pr; git checkout deposit-pr; else git checkout ${BUILD_TARGET}; fi" 16 | 17 | FROM python:3.13-bookworm 18 | 19 | ARG USER=depcli 20 | ARG UID=1000 21 | 22 | # See https://stackoverflow.com/a/55757473/12429735RUN 23 | RUN adduser \ 24 | --disabled-password \ 25 | --gecos "" \ 26 | --home "/nonexistent" \ 27 | --shell "/sbin/nologin" \ 28 | --no-create-home \ 29 | --uid "${UID}" \ 30 | "${USER}" 31 | 32 | WORKDIR /app 33 | 34 | COPY --from=builder /src/ethstaker-deposit-cli/requirements.txt ./ 35 | COPY --from=builder /src/ethstaker-deposit-cli/ethstaker_deposit ./ethstaker_deposit 36 | 37 | RUN apt-get update && apt-get install -y build-essential bash gosu 38 | 39 | RUN pip3 install -r requirements.txt 40 | 41 | RUN chown -R ${USER}:${USER} /app 42 | 43 | COPY ./docker-entrypoint.sh /usr/local/bin/ 44 | 45 | ENTRYPOINT [ "python3", "-m", "ethstaker_deposit" ] 46 | -------------------------------------------------------------------------------- /ethstaker-deposit-cli/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | # This will be started as root, so the generated files can be copied when done 5 | 6 | # Find --uid if it exists, parse and discard. Used to chown after. 7 | # Ditto --folder, since this now copies we need to parse it out 8 | ARGS=() 9 | foundu=0 10 | foundf=0 11 | foundnonint=0 12 | uid=1000 13 | folder="validator_keys" 14 | for var in "$@"; do 15 | if [ "$var" = '--uid' ]; then 16 | foundu=1 17 | continue 18 | fi 19 | if [ "$var" = '--folder' ]; then 20 | foundf=1 21 | continue 22 | fi 23 | if [ "$var" = '--non_interactive' ]; then 24 | foundnonint=1 25 | continue 26 | fi 27 | if [ "$foundu" = '1' ]; then 28 | foundu=0 29 | if ! [[ $var =~ ^[0-9]+$ ]] ; then 30 | echo "error: Passed user ID is not a number, ignoring" 31 | continue 32 | fi 33 | uid="$var" 34 | continue 35 | fi 36 | if [ "$foundf" = '1' ]; then 37 | foundf=0 38 | folder="$var" 39 | continue 40 | fi 41 | ARGS+=("$var") 42 | done 43 | 44 | for i in "${!ARGS[@]}"; do 45 | if [ "${ARGS[$i]}" = '/app/staking_deposit/deposit.py' ]; then 46 | if [ "$foundnonint" = '1' ]; then 47 | # the flag should be before the command 48 | ARGS=("${ARGS[@]:0:$i+1}" "--non_interactive" "${ARGS[@]:$i+1}") 49 | fi 50 | break 51 | fi 52 | done 53 | 54 | gosu depcli "${ARGS[@]}" 55 | 56 | if [[ "$*" =~ "generate-bls-to-execution-change" ]]; then 57 | cp -rp /app/bls_to_execution_changes /app/.eth/ 58 | chown -R "$uid":"$uid" /app/.eth/bls_to_execution_changes 59 | echo "The change files have been copied to ./.eth/bls_to_execution_changes" 60 | else 61 | mkdir -p /app/.eth/"$folder" 62 | cp -p /app/validator_keys/* /app/.eth/"$folder"/ 63 | chown -R "$uid":"$uid" /app/.eth/"$folder" 64 | echo "The generated files have been copied to ./.eth/$folder/" 65 | fi 66 | -------------------------------------------------------------------------------- /ext-network.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | default: 3 | name: traefik_default 4 | external: true 5 | -------------------------------------------------------------------------------- /flashbots/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=flashbots/mev-boost 3 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 4 | 5 | # Unused, this is here to avoid build time complaints 6 | ARG BUILD_TARGET 7 | ARG SRC_REPO 8 | 9 | ARG USER=mev 10 | ARG UID=10666 11 | 12 | # See https://stackoverflow.com/a/55757473/12429735RUN 13 | RUN adduser \ 14 | --disabled-password \ 15 | --gecos "" \ 16 | --shell "/sbin/nologin" \ 17 | --uid "${UID}" \ 18 | "${USER}" 19 | 20 | USER ${USER} 21 | -------------------------------------------------------------------------------- /flashbots/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build in a stock Go build container 2 | FROM golang:1.24-alpine AS builder 3 | 4 | # Unused, this is here to avoid build time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apk update && apk add --no-cache make gcc musl-dev linux-headers git bash 12 | 13 | WORKDIR /src 14 | RUN bash -c "git clone ${SRC_REPO} mev-boost && cd mev-boost && git config advice.detachedHead false && git fetch --all --tags && \ 15 | if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:mev-pr; git checkout mev-pr; else git checkout ${BUILD_TARGET}; fi && \ 16 | make build" 17 | 18 | # Pull all binaries into a second stage deploy container 19 | FROM alpine:3 20 | 21 | ARG USER=mev 22 | ARG UID=10666 23 | 24 | # See https://stackoverflow.com/a/55757473/12429735RUN 25 | RUN adduser \ 26 | --disabled-password \ 27 | --gecos "" \ 28 | --shell "/sbin/nologin" \ 29 | --uid "${UID}" \ 30 | "${USER}" 31 | 32 | RUN mkdir -p /app && chown -R ${USER}:${USER} /app 33 | 34 | # Cannot assume buildkit, hence no chmod 35 | COPY --from=builder --chown=${USER}:${USER} /src/mev-boost/mev-boost /app/ 36 | # Belt and suspenders 37 | RUN chmod -R 755 /app/* 38 | 39 | USER ${USER} 40 | 41 | ENTRYPOINT ["/app/mev-boost"] 42 | -------------------------------------------------------------------------------- /fluffy.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | portal: 11 | restart: "unless-stopped" 12 | build: 13 | context: ./fluffy 14 | dockerfile: ${FLUFFY_DOCKERFILE} 15 | args: 16 | - BUILD_TARGET=${FLUFFY_SRC_BUILD_TARGET:-master} 17 | - SRC_REPO=${FLUFFY_SRC_REPO:-https://github.com/status-im/nimbus-eth1} 18 | - DOCKER_TAG=${FLUFFY_DOCKER_TAG:-amd64-master-latest} 19 | - DOCKER_REPO=${FLUFFY_DOCKER_REPO:-statusim/nimbus-fluffy} 20 | stop_grace_period: 5m 21 | stop_signal: SIGINT 22 | image: fluffy:local 23 | pull_policy: never 24 | user: user 25 | volumes: 26 | - nimbus-fluffy-data:/var/lib/nimbus 27 | - /etc/localtime:/etc/localtime:ro 28 | ports: 29 | - ${HOST_IP:-}:${PORTAL_P2P_PORT:-9009}:${PORTAL_P2P_PORT:-9009}/udp 30 | networks: 31 | default: 32 | aliases: 33 | - ${PORTAL_ALIAS:-default-portal} # This allows multiple Eth Docker stacks all connected to the same bridge network 34 | <<: *logging 35 | entrypoint: 36 | - fluffy 37 | - --data-dir=/var/lib/nimbus 38 | - --network=${NETWORK} 39 | - --rpc 40 | - --rpc-address=0.0.0.0 41 | - --rpc-port=${PORTAL_RPC_PORT:-8545} 42 | - --ws 43 | - --ws-address=0.0.0.0 44 | - --ws-port=${PORTAL_WS_PORT:-8546} 45 | - --udp-port=${PORTAL_P2P_PORT:-9009} 46 | - --enr-auto-update 47 | - --metrics 48 | - --metrics-port=8008 49 | - --metrics-address=0.0.0.0 50 | - --log-level=${LOG_LEVEL} 51 | labels: 52 | - metrics.scrape=true 53 | - metrics.path=/metrics 54 | - metrics.port=8008 55 | - metrics.instance=portal 56 | - metrics.network=${NETWORK} 57 | 58 | volumes: 59 | nimbus-fluffy-data: 60 | 61 | networks: 62 | default: 63 | enable_ipv6: ${IPV6:-false} 64 | -------------------------------------------------------------------------------- /fluffy/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=master 2 | ARG DOCKER_REPO=statusim/nimbus-eth1 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Included here to avoid build-time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=user 11 | ARG UID=10001 12 | 13 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 14 | ca-certificates bash tzdata librocksdb-dev adduser \ 15 | && apt-get clean \ 16 | && rm -rf /var/lib/apt/lists/* 17 | 18 | RUN set -eux; \ 19 | apt-get update; \ 20 | apt-get install -y gosu; \ 21 | rm -rf /var/lib/apt/lists/*; \ 22 | # verify that the binary works 23 | gosu nobody true 24 | 25 | # See https://stackoverflow.com/a/55757473/12429735RUN 26 | RUN adduser \ 27 | --disabled-password \ 28 | --gecos "" \ 29 | --home "/nonexistent" \ 30 | --shell "/usr/sbin/nologin" \ 31 | --no-create-home \ 32 | --uid "${UID}" \ 33 | "${USER}" 34 | 35 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus 36 | 37 | RUN cp /usr/bin/fluffy /usr/local/bin/ && chown ${USER}:${USER} /usr/local/bin/fluffy 38 | # Belt and suspenders 39 | RUN chmod -R 755 /usr/local/bin/* 40 | 41 | USER ${USER} 42 | 43 | ENTRYPOINT ["fluffy"] 44 | -------------------------------------------------------------------------------- /fluffy/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Nimbus in a stock debian container 2 | FROM debian:bookworm-slim AS builder 3 | 4 | # Included here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get install -y build-essential git ca-certificates librocksdb-dev curl 12 | 13 | WORKDIR /usr/src 14 | 15 | RUN bash -c "git clone ${SRC_REPO} nimbus-eth1 && cd nimbus-eth1 && git config advice.detachedHead false && git fetch --all --tags && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:nim-pr; git checkout nim-pr; else git checkout ${BUILD_TARGET}; fi && make -j$(nproc) update && make -j$(nproc) fluffy" 16 | 17 | # Pull all binaries into a second stage deploy debian container 18 | FROM debian:bookworm-slim 19 | 20 | ARG USER=user 21 | ARG UID=10001 22 | 23 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 24 | ca-certificates bash tzdata librocksdb-dev \ 25 | && apt-get clean \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | RUN set -eux; \ 29 | apt-get update; \ 30 | apt-get install -y gosu; \ 31 | rm -rf /var/lib/apt/lists/*; \ 32 | # verify that the binary works 33 | gosu nobody true 34 | 35 | # See https://stackoverflow.com/a/55757473/12429735RUN 36 | RUN adduser \ 37 | --disabled-password \ 38 | --gecos "" \ 39 | --home "/nonexistent" \ 40 | --shell "/usr/sbin/nologin" \ 41 | --no-create-home \ 42 | --uid "${UID}" \ 43 | "${USER}" 44 | 45 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus 46 | 47 | # Cannot assume buildkit, hence no chmod 48 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth1/build/fluffy /usr/local/bin/ 49 | # Belt and suspenders 50 | RUN chmod -R 755 /usr/local/bin/* 51 | 52 | USER ${USER} 53 | 54 | ENTRYPOINT ["fluffy"] 55 | -------------------------------------------------------------------------------- /geth.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | execution: 11 | restart: "unless-stopped" 12 | build: 13 | context: ./geth 14 | dockerfile: ${GETH_DOCKERFILE} 15 | args: 16 | - BUILD_TARGET=${GETH_SRC_BUILD_TARGET:-'$(git describe --tags $(git rev-list --tags --max-count=1))'} 17 | - SRC_REPO=${GETH_SRC_REPO:-https://github.com/ethereum/go-ethereum} 18 | - DOCKER_TAG=${GETH_DOCKER_TAG:-stable} 19 | - DOCKER_REPO=${GETH_DOCKER_REPO:-ethereum/client-go} 20 | stop_grace_period: 5m 21 | image: geth:local 22 | pull_policy: never 23 | user: geth 24 | environment: 25 | - JWT_SECRET=${JWT_SECRET:-} 26 | - LOG_LEVEL=${LOG_LEVEL:-info} 27 | - EL_EXTRAS=${EL_EXTRAS:-} 28 | - ARCHIVE_NODE=${EL_ARCHIVE_NODE:-} 29 | - MINIMAL_NODE=${EL_MINIMAL_NODE:-} 30 | - NETWORK=${NETWORK} 31 | - IPV6=${IPV6:-false} 32 | - ANCIENT_DIR=${ANCIENT_DIR:-} 33 | volumes: 34 | - geth-eth1-data:/var/lib/goethereum 35 | - geth-el-data:/var/lib/geth 36 | - ${ANCIENT_DIR:-.nada}:/var/lib/ancient 37 | - /etc/localtime:/etc/localtime:ro 38 | - jwtsecret:/var/lib/geth/ee-secret 39 | ports: 40 | - ${HOST_IP:-}:${EL_P2P_PORT:-30303}:${EL_P2P_PORT:-30303}/tcp 41 | - ${HOST_IP:-}:${EL_P2P_PORT:-30303}:${EL_P2P_PORT:-30303}/udp 42 | networks: 43 | default: 44 | aliases: 45 | - eth1 46 | - ${EL_ALIAS:-default-execution} # This allows multiple Eth Docker stacks all connected to the same bridge network 47 | <<: *logging 48 | entrypoint: 49 | - docker-entrypoint.sh 50 | - geth 51 | - --http 52 | - --http.addr 53 | - 0.0.0.0 54 | - --http.vhosts=* 55 | - --http.corsdomain=* 56 | - --port 57 | - ${EL_P2P_PORT:-30303} 58 | - --http.port 59 | - ${EL_RPC_PORT:-8545} 60 | - --ws 61 | - --ws.addr 62 | - 0.0.0.0 63 | - --ws.port 64 | - ${EL_WS_PORT:-8546} 65 | - --ws.origins=* 66 | - --metrics 67 | - --pprof 68 | - --pprof.addr 69 | - 0.0.0.0 70 | - --authrpc.jwtsecret 71 | - /var/lib/geth/ee-secret/jwtsecret 72 | - --authrpc.addr 73 | - 0.0.0.0 74 | - --authrpc.port 75 | - ${EE_PORT:-8551} 76 | - --authrpc.vhosts=* 77 | - --maxpeers 78 | - ${EL_MAX_PEER_COUNT:-50} 79 | labels: 80 | - metrics.scrape=true 81 | - metrics.path=/debug/metrics/prometheus 82 | - metrics.port=6060 83 | - metrics.instance=execution 84 | - metrics.network=${NETWORK} 85 | 86 | set-prune-marker: 87 | profiles: ["tools"] 88 | image: alpine:3 89 | user: "10001:10001" 90 | restart: "no" 91 | volumes: 92 | - geth-el-data:/var/lib/geth 93 | entrypoint: ["/bin/sh","-c"] 94 | command: /bin/sh 95 | 96 | volumes: 97 | geth-el-data: 98 | geth-eth1-data: 99 | jwtsecret: 100 | 101 | networks: 102 | default: 103 | enable_ipv6: ${IPV6:-false} 104 | -------------------------------------------------------------------------------- /geth/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=stable 2 | ARG DOCKER_REPO=ethereum/client-go 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=geth 11 | ARG UID=10001 12 | # GID 10002 is deliberate so it can exchange secret with CL 13 | ARG GID=10002 14 | 15 | RUN apk update && apk add --no-cache ca-certificates tzdata bash su-exec git git-lfs jq 16 | 17 | RUN addgroup \ 18 | --gid "${GID}" \ 19 | "${USER}" 20 | 21 | # See https://stackoverflow.com/a/55757473/12429735RUN 22 | RUN adduser \ 23 | --disabled-password \ 24 | --gecos "" \ 25 | --shell "/sbin/nologin" \ 26 | --uid "${UID}" \ 27 | --ingroup "${USER}" \ 28 | "${USER}" 29 | 30 | RUN mkdir -p /var/lib/goethereum && chown -R ${USER}:${USER} /var/lib/goethereum && chmod -R 700 /var/lib/goethereum 31 | RUN mkdir -p /var/lib/geth/ee-secret && chown -R ${USER}:${USER} /var/lib/geth && chmod -R 700 /var/lib/geth && chmod 777 /var/lib/geth/ee-secret 32 | 33 | # Cannot assume buildkit, hence no chmod 34 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 35 | # Belt and suspenders 36 | RUN chmod -R 755 /usr/local/bin/* 37 | 38 | USER ${USER} 39 | 40 | ENTRYPOINT ["geth"] 41 | -------------------------------------------------------------------------------- /geth/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Geth in a stock Go build container 2 | FROM golang:1.24-alpine AS builder 3 | 4 | # Unused, this is here to avoid build time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apk update && apk add --no-cache make gcc musl-dev linux-headers git bash 12 | 13 | WORKDIR /src 14 | RUN bash -c "git clone ${SRC_REPO} go-ethereum && cd go-ethereum && git config advice.detachedHead false && git fetch --all --tags && \ 15 | if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:geth-pr; git checkout geth-pr; else git checkout ${BUILD_TARGET}; fi && \ 16 | go run build/ci.go install -static" 17 | 18 | # Pull all binaries into a second stage deploy container 19 | FROM alpine:3 20 | 21 | ARG USER=geth 22 | ARG UID=10001 23 | # GID 10002 is deliberate so it can exchange secret with CL 24 | ARG GID=10002 25 | 26 | RUN apk add --no-cache ca-certificates tzdata bash su-exec git git-lfs jq 27 | 28 | RUN addgroup \ 29 | --gid "${GID}" \ 30 | "${USER}" 31 | 32 | # See https://stackoverflow.com/a/55757473/12429735RUN 33 | RUN adduser \ 34 | --disabled-password \ 35 | --gecos "" \ 36 | --shell "/sbin/nologin" \ 37 | --uid "${UID}" \ 38 | --ingroup "${USER}" \ 39 | "${USER}" 40 | 41 | RUN mkdir -p /var/lib/goethereum && chown -R ${USER}:${USER} /var/lib/goethereum && chmod -R 700 /var/lib/goethereum 42 | RUN mkdir -p /var/lib/geth/ee-secret && chown -R ${USER}:${USER} /var/lib/geth && chmod -R 700 /var/lib/geth && chmod 777 /var/lib/geth/ee-secret 43 | 44 | # Cannot assume buildkit, hence no chmod 45 | COPY --from=builder --chown=${USER}:${USER} /src/go-ethereum/build/bin/geth /usr/local/bin/ 46 | COPY --from=builder --chown=${USER}:${USER} /src/go-ethereum/build/bin/clef /usr/local/bin/ 47 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 48 | # Belt and suspenders 49 | RUN chmod -R 755 /usr/local/bin/* 50 | 51 | USER ${USER} 52 | 53 | ENTRYPOINT ["geth"] 54 | -------------------------------------------------------------------------------- /grafana-rootless.yml: -------------------------------------------------------------------------------- 1 | # Grafana for use with rootless docker. Omits node-exporter, cadvisor, promtail and Loki 2 | x-logging: &logging 3 | logging: 4 | driver: json-file 5 | options: 6 | max-size: 100m 7 | max-file: "3" 8 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 9 | 10 | services: 11 | prometheus: 12 | restart: "unless-stopped" 13 | build: 14 | context: ./prometheus 15 | image: prometheus:local 16 | pull_policy: never 17 | volumes: 18 | - prom-data:/prometheus 19 | - /etc/localtime:/etc/localtime:ro 20 | - ./prometheus/conf.d/:/etc/prometheus/conf.d/:ro 21 | - ./prometheus/custom-prom.yml:/etc/prometheus/custom-prom.yml:ro 22 | environment: 23 | - CLIENT=${COMPOSE_FILE} 24 | command: 25 | - --storage.tsdb.path=/prometheus 26 | - --storage.tsdb.retention.time=40d 27 | - --web.console.libraries=/usr/share/prometheus/console_libraries 28 | - --web.console.templates=/usr/share/prometheus/consoles 29 | <<: *logging 30 | depends_on: 31 | - blackbox-exporter 32 | - json-exporter 33 | - ethereum-metrics-exporter 34 | 35 | ethereum-metrics-exporter: 36 | restart: "unless-stopped" 37 | image: samcm/ethereum-metrics-exporter:debian-latest 38 | entrypoint: 39 | - /ethereum-metrics-exporter 40 | - --consensus-url=http://consensus:${CL_REST_PORT:-5052} 41 | - --execution-url=http://execution:${EL_RPC_PORT:-8545} 42 | <<: *logging 43 | 44 | blackbox-exporter: 45 | restart: "unless-stopped" 46 | image: prom/blackbox-exporter:master 47 | volumes: 48 | - ./prometheus/blackbox.yml:/config/blackbox.yml 49 | - /etc/localtime:/etc/localtime:ro 50 | <<: *logging 51 | command: 52 | - --config.file=/config/blackbox.yml 53 | 54 | json-exporter: 55 | restart: "unless-stopped" 56 | image: prometheuscommunity/json-exporter:latest 57 | volumes: 58 | - ./prometheus/json.yml:/config/json.yml 59 | - /etc/localtime:/etc/localtime:ro 60 | <<: *logging 61 | command: 62 | - --config.file 63 | - /config/json.yml 64 | 65 | grafana: 66 | restart: "unless-stopped" 67 | build: 68 | context: ./grafana 69 | image: grafana:local 70 | pull_policy: never 71 | user: grafana 72 | environment: 73 | - GF_SERVER_HTTP_PORT=${GRAFANA_PORT} 74 | - CLIENT=${COMPOSE_FILE} 75 | volumes: 76 | - grafana-data:/var/lib/grafana 77 | - grafana-config:/etc/grafana 78 | - /etc/localtime:/etc/localtime:ro 79 | depends_on: 80 | - prometheus 81 | entrypoint: ["provision.sh"] 82 | command: /run.sh 83 | <<: *logging 84 | labels: 85 | - traefik.enable=true 86 | - traefik.http.routers.grafana.entrypoints=web,websecure 87 | - traefik.http.routers.grafana.rule=Host(`${GRAFANA_HOST}.${DOMAIN}`) 88 | - traefik.http.routers.grafana.tls.certresolver=letsencrypt 89 | - traefik.http.services.grafana.loadbalancer.server.port=${GRAFANA_PORT} 90 | 91 | volumes: 92 | grafana-data: 93 | grafana-config: 94 | prom-data: 95 | -------------------------------------------------------------------------------- /grafana-shared.yml: -------------------------------------------------------------------------------- 1 | services: 2 | grafana: 3 | ports: 4 | - ${SHARE_IP:-}:${GRAFANA_PORT}:${GRAFANA_PORT}/tcp 5 | -------------------------------------------------------------------------------- /grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM grafana/grafana:latest 2 | 3 | USER root 4 | RUN apk --update add wget tree jq sed su-exec 5 | 6 | RUN mkdir -p /etc/grafana/provisioning/dashboards/ 7 | RUN mkdir -p /etc/grafana/provisioning/datasources/ 8 | RUN mkdir -p /etc/grafana/provisioning/alerting/ 9 | RUN mkdir -p /tmp/grafana/provisioning/alerting/ 10 | RUN chown -R grafana:root /etc/grafana/ 11 | RUN chown -R grafana:root /tmp/grafana/ 12 | COPY --chown=grafana:root ./dashboard.yml /etc/grafana/provisioning/dashboards/ 13 | COPY --chown=grafana:root ./datasource.yml /etc/grafana/provisioning/datasources/ 14 | COPY --chown=grafana:root ./default-alerts/*.yml /tmp/grafana/provisioning/alerting/ 15 | COPY --chown=grafana:root ./provision.sh /usr/local/bin/ 16 | # Belt and suspenders 17 | RUN chmod -R 755 /usr/local/bin/* 18 | 19 | ENTRYPOINT [ "/run.sh" ] 20 | -------------------------------------------------------------------------------- /grafana/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | # an unique provider name. Required 5 | - name: "Prometheus" 6 | # Org id. Default to 1 7 | orgId: 1 8 | # name of the dashboard folder. 9 | folder: "" 10 | # folder UID. will be automatically generated if not specified 11 | folderUid: "" 12 | # provider type. Default to 'file' 13 | type: file 14 | # disable dashboard deletion 15 | disableDeletion: false 16 | # how often Grafana will scan for changed dashboards 17 | updateIntervalSeconds: 10 18 | # allow updating provisioned dashboards from the UI 19 | allowUiUpdates: true 20 | options: 21 | # path to dashboard files on disk. Required when using the 'file' type 22 | path: /etc/grafana/provisioning/dashboards 23 | # use folder names from filesystem to create folders in Grafana 24 | foldersFromFilesStructure: true 25 | -------------------------------------------------------------------------------- /grafana/datasource.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # list of datasources that should be deleted from the database 5 | deleteDatasources: 6 | - name: Prometheus 7 | orgId: 1 8 | 9 | - name: Loki 10 | orgId: 1 11 | 12 | # list of datasources to insert/update depending 13 | # what's available in the database 14 | datasources: 15 | - name: Prometheus 16 | type: prometheus 17 | access: proxy 18 | orgId: 1 19 | uid: PBFA97CFB590B2093 20 | url: http://prometheus:9090 21 | basicAuth: false 22 | isDefault: true 23 | version: 1 24 | editable: true 25 | 26 | - name: Loki 27 | type: loki 28 | access: proxy 29 | orgId: 1 30 | uid: P8E80F9AEF21F6940 31 | url: http://loki:3100 32 | editable: true 33 | -------------------------------------------------------------------------------- /grafana/default-alerts/cpu.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | groups: 3 | - orgId: 1 4 | name: eth-docker 5 | folder: eth-docker 6 | interval: 5m 7 | rules: 8 | - uid: e253066f-d9b5-4d5c-a82b-ef833d2ebf16 9 | title: CPU high 10 | condition: C 11 | data: 12 | - refId: A 13 | relativeTimeRange: 14 | from: 600 15 | to: 0 16 | datasourceUid: PBFA97CFB590B2093 17 | model: 18 | editorMode: code 19 | expr: avg(100 - rate(node_cpu_seconds_total{mode="idle"}[2m]) * 100) 20 | instant: false 21 | intervalMs: 1000 22 | legendFormat: __auto 23 | maxDataPoints: 43200 24 | range: true 25 | refId: A 26 | - refId: B 27 | relativeTimeRange: 28 | from: 600 29 | to: 0 30 | datasourceUid: __expr__ 31 | model: 32 | conditions: 33 | - evaluator: 34 | params: [] 35 | type: gt 36 | operator: 37 | type: and 38 | query: 39 | params: 40 | - B 41 | reducer: 42 | params: [] 43 | type: last 44 | type: query 45 | datasource: 46 | type: __expr__ 47 | uid: __expr__ 48 | expression: A 49 | intervalMs: 1000 50 | maxDataPoints: 43200 51 | reducer: mean 52 | refId: B 53 | settings: 54 | mode: dropNN 55 | type: reduce 56 | - refId: C 57 | relativeTimeRange: 58 | from: 600 59 | to: 0 60 | datasourceUid: __expr__ 61 | model: 62 | conditions: 63 | - evaluator: 64 | params: 65 | - 90 66 | type: gt 67 | operator: 68 | type: and 69 | query: 70 | params: 71 | - C 72 | reducer: 73 | params: [] 74 | type: last 75 | type: query 76 | datasource: 77 | type: __expr__ 78 | uid: __expr__ 79 | expression: B 80 | intervalMs: 1000 81 | maxDataPoints: 43200 82 | refId: C 83 | type: threshold 84 | noDataState: NoData 85 | execErrState: Error 86 | for: 10m 87 | annotations: 88 | summary: CPU usage high, above 90% 89 | labels: 90 | severity: medium 91 | isPaused: false 92 | -------------------------------------------------------------------------------- /grafana/default-alerts/crit_disk_space.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | groups: 3 | - orgId: 1 4 | name: eth-docker 5 | folder: eth-docker 6 | interval: 5m 7 | rules: 8 | - uid: 5d2f7756-31fb-4fc1-84c3-c892751c07c0 9 | title: Disk Space critically low 10 | condition: C 11 | data: 12 | - refId: A 13 | relativeTimeRange: 14 | from: 600 15 | to: 0 16 | datasourceUid: PBFA97CFB590B2093 17 | model: 18 | editorMode: code 19 | expr: round((node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100) 20 | instant: true 21 | intervalMs: 1000 22 | legendFormat: __auto 23 | maxDataPoints: 43200 24 | range: false 25 | refId: A 26 | - refId: B 27 | relativeTimeRange: 28 | from: 600 29 | to: 0 30 | datasourceUid: __expr__ 31 | model: 32 | conditions: 33 | - evaluator: 34 | params: [] 35 | type: gt 36 | operator: 37 | type: and 38 | query: 39 | params: 40 | - B 41 | reducer: 42 | params: [] 43 | type: last 44 | type: query 45 | datasource: 46 | type: __expr__ 47 | uid: __expr__ 48 | expression: A 49 | intervalMs: 1000 50 | maxDataPoints: 43200 51 | reducer: last 52 | refId: B 53 | type: reduce 54 | - refId: C 55 | relativeTimeRange: 56 | from: 600 57 | to: 0 58 | datasourceUid: __expr__ 59 | model: 60 | conditions: 61 | - evaluator: 62 | params: 63 | - 2 64 | type: lt 65 | operator: 66 | type: and 67 | query: 68 | params: 69 | - C 70 | reducer: 71 | params: [] 72 | type: last 73 | type: query 74 | datasource: 75 | type: __expr__ 76 | uid: __expr__ 77 | expression: B 78 | intervalMs: 1000 79 | maxDataPoints: 43200 80 | refId: C 81 | type: threshold 82 | noDataState: NoData 83 | execErrState: Error 84 | for: 10m 85 | annotations: 86 | summary: Disk space critically low on {{ $labels.mountpoint }}, {{ $values.B }} percent free 87 | labels: 88 | severity: critical 89 | isPaused: false 90 | -------------------------------------------------------------------------------- /grafana/default-alerts/disk_space.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | groups: 3 | - orgId: 1 4 | name: eth-docker 5 | folder: eth-docker 6 | interval: 5m 7 | rules: 8 | - uid: f6e55538-a3a3-4dd3-8308-19437ee8a58d 9 | title: Disk Space low 10 | condition: C 11 | data: 12 | - refId: A 13 | relativeTimeRange: 14 | from: 600 15 | to: 0 16 | datasourceUid: PBFA97CFB590B2093 17 | model: 18 | editorMode: code 19 | expr: round((node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100) 20 | instant: true 21 | intervalMs: 1000 22 | legendFormat: __auto 23 | maxDataPoints: 43200 24 | range: false 25 | refId: A 26 | - refId: B 27 | relativeTimeRange: 28 | from: 600 29 | to: 0 30 | datasourceUid: __expr__ 31 | model: 32 | conditions: 33 | - evaluator: 34 | params: [] 35 | type: gt 36 | operator: 37 | type: and 38 | query: 39 | params: 40 | - B 41 | reducer: 42 | params: [] 43 | type: last 44 | type: query 45 | datasource: 46 | type: __expr__ 47 | uid: __expr__ 48 | expression: A 49 | intervalMs: 1000 50 | maxDataPoints: 43200 51 | reducer: last 52 | refId: B 53 | type: reduce 54 | - refId: C 55 | relativeTimeRange: 56 | from: 600 57 | to: 0 58 | datasourceUid: __expr__ 59 | model: 60 | conditions: 61 | - evaluator: 62 | params: 63 | - 11 64 | type: lt 65 | operator: 66 | type: and 67 | query: 68 | params: 69 | - C 70 | reducer: 71 | params: [] 72 | type: last 73 | type: query 74 | datasource: 75 | type: __expr__ 76 | uid: __expr__ 77 | expression: B 78 | intervalMs: 1000 79 | maxDataPoints: 43200 80 | refId: C 81 | type: threshold 82 | noDataState: NoData 83 | execErrState: Error 84 | for: 10m 85 | annotations: 86 | summary: Disk space low on {{ $labels.mountpoint }}, {{ $values.B }} percent free 87 | labels: 88 | severity: medium 89 | isPaused: false 90 | -------------------------------------------------------------------------------- /grafana/default-alerts/memory.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | groups: 3 | - orgId: 1 4 | name: eth-docker 5 | folder: eth-docker 6 | interval: 5m 7 | rules: 8 | - uid: c195f905-45da-4e49-8bd1-f5f94d1e2cf2 9 | title: Memory use high 10 | condition: C 11 | data: 12 | - refId: A 13 | relativeTimeRange: 14 | from: 600 15 | to: 0 16 | datasourceUid: PBFA97CFB590B2093 17 | model: 18 | editorMode: code 19 | exemplar: false 20 | expr: 1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) 21 | instant: false 22 | intervalMs: 1000 23 | legendFormat: __auto 24 | maxDataPoints: 43200 25 | range: true 26 | refId: A 27 | - refId: B 28 | relativeTimeRange: 29 | from: 600 30 | to: 0 31 | datasourceUid: __expr__ 32 | model: 33 | conditions: 34 | - evaluator: 35 | params: [] 36 | type: gt 37 | operator: 38 | type: and 39 | query: 40 | params: 41 | - B 42 | reducer: 43 | params: [] 44 | type: last 45 | type: query 46 | datasource: 47 | type: __expr__ 48 | uid: __expr__ 49 | expression: A 50 | intervalMs: 1000 51 | maxDataPoints: 43200 52 | reducer: mean 53 | refId: B 54 | settings: 55 | mode: dropNN 56 | type: reduce 57 | - refId: C 58 | relativeTimeRange: 59 | from: 600 60 | to: 0 61 | datasourceUid: __expr__ 62 | model: 63 | conditions: 64 | - evaluator: 65 | params: 66 | - 0.97 67 | type: gt 68 | operator: 69 | type: and 70 | query: 71 | params: 72 | - C 73 | reducer: 74 | params: [] 75 | type: last 76 | type: query 77 | datasource: 78 | type: __expr__ 79 | uid: __expr__ 80 | expression: B 81 | intervalMs: 1000 82 | maxDataPoints: 43200 83 | refId: C 84 | type: threshold 85 | noDataState: NoData 86 | execErrState: Error 87 | for: 5m 88 | annotations: 89 | summary: memory usage is dangerously high at {{ humanizePercentage $values.B.Value }}. 90 | labels: 91 | severity: critical 92 | isPaused: false 93 | -------------------------------------------------------------------------------- /grafana/default-alerts/oom.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | groups: 3 | - orgId: 1 4 | name: eth-docker 5 | folder: eth-docker 6 | interval: 5m 7 | rules: 8 | - uid: c4c5849a-640a-43e5-9908-fb7f403f9e75 9 | title: Container OOM 10 | condition: C 11 | data: 12 | - refId: A 13 | relativeTimeRange: 14 | from: 600 15 | to: 0 16 | datasourceUid: PBFA97CFB590B2093 17 | model: 18 | editorMode: code 19 | expr: increase(node_vmstat_oom_kill[2m]) 20 | instant: true 21 | intervalMs: 1000 22 | legendFormat: __auto 23 | maxDataPoints: 43200 24 | range: false 25 | refId: A 26 | - refId: B 27 | relativeTimeRange: 28 | from: 600 29 | to: 0 30 | datasourceUid: __expr__ 31 | model: 32 | conditions: 33 | - evaluator: 34 | params: [] 35 | type: gt 36 | operator: 37 | type: and 38 | query: 39 | params: 40 | - B 41 | reducer: 42 | params: [] 43 | type: last 44 | type: query 45 | datasource: 46 | type: __expr__ 47 | uid: __expr__ 48 | expression: A 49 | intervalMs: 1000 50 | maxDataPoints: 43200 51 | reducer: max 52 | refId: B 53 | settings: 54 | mode: replaceNN 55 | replaceWithValue: 0 56 | type: reduce 57 | - refId: C 58 | relativeTimeRange: 59 | from: 600 60 | to: 0 61 | datasourceUid: __expr__ 62 | model: 63 | conditions: 64 | - evaluator: 65 | params: 66 | - 0 67 | type: gt 68 | operator: 69 | type: and 70 | query: 71 | params: 72 | - C 73 | reducer: 74 | params: [] 75 | type: last 76 | type: query 77 | datasource: 78 | type: __expr__ 79 | uid: __expr__ 80 | expression: B 81 | intervalMs: 1000 82 | maxDataPoints: 43200 83 | refId: C 84 | type: threshold 85 | noDataState: OK 86 | execErrState: OK 87 | for: 0s 88 | annotations: 89 | summary: A container ran out of memory and was killed by Linux 90 | labels: 91 | severity: critical 92 | isPaused: false 93 | -------------------------------------------------------------------------------- /grandine/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=stable 2 | ARG DOCKER_REPO=sifrai/grandine 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=gdconsensus 11 | ARG UID=10002 12 | 13 | # See https://stackoverflow.com/a/55757473/12429735RUN 14 | RUN adduser \ 15 | --disabled-password \ 16 | --gecos "" \ 17 | --home "/nonexistent" \ 18 | --shell "/sbin/nologin" \ 19 | --no-create-home \ 20 | --uid "${UID}" \ 21 | "${USER}" 22 | 23 | RUN set -eux; \ 24 | apt-get update; \ 25 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates bash tzdata git git-lfs curl; \ 26 | rm -rf /var/lib/apt/lists/*; \ 27 | # verify that the binary works 28 | gosu nobody true 29 | 30 | # Create data mount point with permissions 31 | RUN mkdir -p /var/lib/grandine/ee-secret && chown -R ${USER}:${USER} /var/lib/grandine \ 32 | && chmod -R 700 /var/lib/grandine && chmod 777 /var/lib/grandine/ee-secret 33 | # Cannot assume buildkit, hence no chmod 34 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 35 | # Belt and suspenders 36 | RUN chmod -R 755 /usr/local/bin/* 37 | 38 | USER gdconsensus 39 | 40 | ENTRYPOINT ["grandine"] 41 | -------------------------------------------------------------------------------- /grandine/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Grandine in a stock Rust build container 2 | FROM rust:bookworm AS builder 3 | 4 | # Unused, this is here to avoid build time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y cmake libclang-dev protobuf-compiler libz-dev libssl-dev unzip 12 | 13 | WORKDIR /usr/src 14 | RUN bash -c "git clone ${SRC_REPO} grandine && cd grandine && git config advice.detachedHead false \ 15 | && git fetch --all --tags \ 16 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:gd-pr; git checkout gd-pr; else git checkout ${BUILD_TARGET}; fi \ 17 | && git submodule update --init dedicated_executor eth2_libp2p \ 18 | && cargo build --bin grandine --profile compact --features default-networks" 19 | 20 | # Pull all binaries into a second stage deploy debian container 21 | FROM debian:bookworm-slim 22 | 23 | RUN set -eux; \ 24 | apt-get update; \ 25 | apt-get install -y gosu; \ 26 | rm -rf /var/lib/apt/lists/*; \ 27 | # verify that the binary works 28 | gosu nobody true 29 | 30 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 31 | libssl-dev \ 32 | ca-certificates \ 33 | tzdata \ 34 | git \ 35 | git-lfs \ 36 | curl \ 37 | && apt-get clean \ 38 | && rm -rf /var/lib/apt/lists/* 39 | 40 | ARG USER=gdconsensus 41 | ARG UID=10002 42 | 43 | # See https://stackoverflow.com/a/55757473/12429735RUN 44 | RUN adduser \ 45 | --disabled-password \ 46 | --gecos "" \ 47 | --home "/nonexistent" \ 48 | --shell "/sbin/nologin" \ 49 | --no-create-home \ 50 | --uid "${UID}" \ 51 | "${USER}" 52 | 53 | # Create data mount point with permissions 54 | RUN mkdir -p /var/lib/grandine/ee-secret && chown -R ${USER}:${USER} /var/lib/grandine \ 55 | && chmod -R 700 /var/lib/grandine && chmod 777 /var/lib/grandine/ee-secret 56 | # Cannot assume buildkit, hence no chmod 57 | COPY --from=builder --chown=${USER}:${USER} /usr/src/grandine/target/compact/grandine /usr/local/bin/ 58 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 59 | # Belt and suspenders 60 | RUN chmod -R 755 /usr/local/bin/* 61 | 62 | USER gdconsensus 63 | 64 | ENTRYPOINT ["grandine"] 65 | -------------------------------------------------------------------------------- /keyapi-shared.yml: -------------------------------------------------------------------------------- 1 | services: 2 | validator: 3 | ports: 4 | - ${SHARE_IP:-}:${KEY_API_PORT:-7500}:${KEY_API_PORT:-7500}/tcp 5 | -------------------------------------------------------------------------------- /lighthouse/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=sigp/lighthouse 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=lhconsensus 11 | ARG UID=10002 12 | 13 | # See https://stackoverflow.com/a/55757473/12429735RUN 14 | RUN adduser \ 15 | --disabled-password \ 16 | --gecos "" \ 17 | --home "/nonexistent" \ 18 | --shell "/sbin/nologin" \ 19 | --no-create-home \ 20 | --uid "${UID}" \ 21 | "${USER}" 22 | 23 | # Create mount point for old volume 24 | RUN mkdir -p /var/lib/lighthouse-og && chown -R ${USER}:${USER} /var/lib/lighthouse-og 25 | # Create data mount point with permissions 26 | RUN mkdir -p /var/lib/lighthouse/beacon/ee-secret && chown -R ${USER}:${USER} /var/lib/lighthouse/beacon && chmod -R 700 /var/lib/lighthouse/beacon && chmod 777 /var/lib/lighthouse/beacon/ee-secret 27 | # Cannot assume buildkit, hence no chmod 28 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 29 | # Belt and suspenders 30 | RUN chmod -R 755 /usr/local/bin/* 31 | 32 | ARG USER=lhvalidator 33 | ARG UID=10000 34 | 35 | # See https://stackoverflow.com/a/55757473/12429735RUN 36 | RUN adduser \ 37 | --disabled-password \ 38 | --gecos "" \ 39 | --home "/nonexistent" \ 40 | --shell "/sbin/nologin" \ 41 | --no-create-home \ 42 | --uid "${UID}" \ 43 | "${USER}" 44 | 45 | # Create data mount point with permissions 46 | RUN mkdir -p /var/lib/lighthouse/validators && chown ${USER}:${USER} /var/lib/lighthouse/validators && chmod 700 /var/lib/lighthouse/validators 47 | 48 | RUN set -eux; \ 49 | apt-get update; \ 50 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git git-lfs wget curl; \ 51 | rm -rf /var/lib/apt/lists/*; \ 52 | # verify that the binary works 53 | gosu nobody true 54 | # rsync for migration 55 | RUN apt-get update && apt-get install -y --no-install-recommends rsync 56 | 57 | # Cannot assume buildkit, hence no chmod 58 | COPY --chown=${USER}:${USER} ./validator-exit.sh /usr/local/bin/ 59 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 60 | # Belt and suspenders 61 | RUN chmod -R 755 /usr/local/bin/* 62 | 63 | # For voluntary exit 64 | ENV KEYSTORE=nonesuch 65 | 66 | USER lhconsensus 67 | 68 | ENTRYPOINT ["lighthouse"] 69 | -------------------------------------------------------------------------------- /lighthouse/docker-entrypoint-vc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | if [ "$(id -u)" = '0' ]; then 5 | chown -R lhvalidator:lhvalidator /var/lib/lighthouse 6 | exec gosu lhvalidator docker-entrypoint-vc.sh "$@" 7 | fi 8 | 9 | if [[ "${NETWORK}" =~ ^https?:// ]]; then 10 | echo "Custom testnet at ${NETWORK}" 11 | repo=$(awk -F'/tree/' '{print $1}' <<< "${NETWORK}") 12 | branch=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f1) 13 | config_dir=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f2-) 14 | echo "This appears to be the ${repo} repo, branch ${branch} and config directory ${config_dir}." 15 | # For want of something more amazing, let's just fail if git fails to pull this 16 | set -e 17 | if [ ! -d "/var/lib/lighthouse/validators/testnet/${config_dir}" ]; then 18 | mkdir -p /var/lib/lighthouse/validators/testnet 19 | cd /var/lib/lighthouse/validators/testnet 20 | git init --initial-branch="${branch}" 21 | git remote add origin "${repo}" 22 | git config core.sparseCheckout true 23 | echo "${config_dir}" > .git/info/sparse-checkout 24 | git pull origin "${branch}" 25 | fi 26 | set +e 27 | __network="--testnet-dir=/var/lib/lighthouse/validators/testnet/${config_dir}" 28 | else 29 | __network="--network=${NETWORK}" 30 | fi 31 | 32 | # Check whether we should use MEV Boost 33 | if [ "${MEV_BOOST}" = "true" ]; then 34 | __mev_boost="--builder-proposals" 35 | echo "MEV Boost enabled" 36 | else 37 | __mev_boost="" 38 | fi 39 | 40 | # Check whether we should send stats to beaconcha.in 41 | if [ -n "${BEACON_STATS_API}" ]; then 42 | __beacon_stats="--monitoring-endpoint https://beaconcha.in/api/v1/client/metrics?apikey=${BEACON_STATS_API}&machine=${BEACON_STATS_MACHINE}" 43 | else 44 | __beacon_stats="" 45 | fi 46 | 47 | # Check whether we should enable doppelganger protection 48 | if [ "${DOPPELGANGER}" = "true" ]; then 49 | __doppel="--enable-doppelganger-protection" 50 | echo "Doppelganger protection enabled, VC will pause for 2 epochs" 51 | else 52 | __doppel="" 53 | fi 54 | 55 | # Distributed attestation aggregation 56 | if [ "${ENABLE_DIST_ATTESTATION_AGGR}" = "true" ]; then 57 | __att_aggr="--distributed" 58 | else 59 | __att_aggr="" 60 | fi 61 | 62 | if [ "${DEFAULT_GRAFFITI}" = "true" ]; then 63 | # Word splitting is desired for the command line parameters 64 | # shellcheck disable=SC2086 65 | exec "$@" ${__network} ${__mev_boost} ${__beacon_stats} ${__doppel} ${__att_aggr} ${VC_EXTRAS} 66 | else 67 | # Word splitting is desired for the command line parameters 68 | # shellcheck disable=SC2086 69 | exec "$@" ${__network} "--graffiti" "${GRAFFITI}" ${__mev_boost} ${__beacon_stats} ${__doppel} ${__att_aggr} ${VC_EXTRAS} 70 | fi 71 | -------------------------------------------------------------------------------- /lighthouse/validator-exit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | # Copy keys, then restart script without root 5 | if [ "$(id -u)" = '0' ]; then 6 | mkdir /keys 7 | cp -r /validator_keys/* /keys/ 8 | chown lhvalidator:lhvalidator /keys/* 9 | exec gosu lhvalidator "${BASH_SOURCE[0]}" "$@" 10 | fi 11 | 12 | exec "$@" 13 | -------------------------------------------------------------------------------- /lodestar/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=chainsafe/lodestar 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Here only to avoid build-time errors 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates tzdata bash gosu git git-lfs wget \ 11 | && apt-get clean && rm -rf /var/lib/apt/lists/* 12 | 13 | ARG USER=lsconsensus 14 | ARG UID=10002 15 | 16 | # See https://stackoverflow.com/a/55757473/12429735RUN 17 | RUN adduser \ 18 | --disabled-password \ 19 | --gecos "" \ 20 | --home "/nonexistent" \ 21 | --shell "/sbin/nologin" \ 22 | --no-create-home \ 23 | --uid "${UID}" \ 24 | "${USER}" 25 | 26 | RUN mkdir -p /var/lib/lodestar/consensus/ee-secret && chown -R ${USER}:${USER} /var/lib/lodestar/consensus \ 27 | && chmod -R 700 /var/lib/lodestar/consensus && chmod 777 /var/lib/lodestar/consensus/ee-secret 28 | 29 | # Cannot assume buildkit, hence no chmod 30 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 31 | # Belt and suspenders 32 | RUN chmod -R 755 /usr/local/bin/* 33 | 34 | ARG USER=lsvalidator 35 | ARG UID=10000 36 | 37 | # See https://stackoverflow.com/a/55757473/12429735RUN 38 | RUN adduser \ 39 | --disabled-password \ 40 | --gecos "" \ 41 | --home "/nonexistent" \ 42 | --shell "/sbin/nologin" \ 43 | --no-create-home \ 44 | --uid "${UID}" \ 45 | "${USER}" 46 | 47 | # Create data mount point with permissions 48 | RUN mkdir -p /var/lib/lodestar/validators && chown -R ${USER}:${USER} /var/lib/lodestar/validators \ 49 | && chmod 700 /var/lib/lodestar/validators 50 | 51 | # Cannot assume buildkit, hence no chmod 52 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 53 | # Belt and suspenders 54 | RUN chmod -R 755 /usr/local/bin/* 55 | 56 | ENTRYPOINT ["node", "/usr/app/node_modules/.bin/lodestar"] 57 | -------------------------------------------------------------------------------- /lodestar/Dockerfile.source: -------------------------------------------------------------------------------- 1 | FROM node:22-slim AS builder 2 | 3 | # Here only to avoid build-time errors 4 | ARG DOCKER_TAG 5 | ARG DOCKER_REPO 6 | 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git g++ make python3 python3-setuptools bash && apt-get clean && rm -rf /var/lib/apt/lists/* 11 | 12 | WORKDIR /usr/app 13 | 14 | RUN bash -c "cd .. && rm -rf app && git clone ${SRC_REPO} app && cd app && git config advice.detachedHead false \ 15 | && git fetch --all --tags \ 16 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:ls-pr; git checkout ls-pr; else git checkout ${BUILD_TARGET}; fi \ 17 | && yarn install --non-interactive --frozen-lockfile && yarn build" 18 | 19 | FROM node:22-slim 20 | 21 | RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates tzdata bash gosu git git-lfs wget \ 22 | && apt-get clean && rm -rf /var/lib/apt/lists/* 23 | 24 | ARG USER=lsconsensus 25 | ARG UID=10002 26 | 27 | # See https://stackoverflow.com/a/55757473/12429735RUN 28 | RUN adduser \ 29 | --disabled-password \ 30 | --gecos "" \ 31 | --home "/nonexistent" \ 32 | --shell "/sbin/nologin" \ 33 | --no-create-home \ 34 | --uid "${UID}" \ 35 | "${USER}" 36 | 37 | RUN mkdir -p /var/lib/lodestar/consensus/ee-secret && chown -R ${USER}:${USER} /var/lib/lodestar/consensus && chmod -R 700 /var/lib/lodestar/consensus && chmod 777 /var/lib/lodestar/consensus/ee-secret 38 | 39 | WORKDIR /usr/app 40 | COPY --from=builder --chown=${USER}:${USER} /usr/app . 41 | RUN ln -s ../../packages/cli/lib/index.js node_modules/.bin/lodestar 42 | 43 | # Cannot assume buildkit, hence no chmod 44 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 45 | # Belt and suspenders 46 | RUN chmod -R 755 /usr/local/bin/* 47 | 48 | ARG USER=lsvalidator 49 | ARG UID=10000 50 | 51 | # See https://stackoverflow.com/a/55757473/12429735RUN 52 | RUN adduser \ 53 | --disabled-password \ 54 | --gecos "" \ 55 | --home "/nonexistent" \ 56 | --shell "/sbin/nologin" \ 57 | --no-create-home \ 58 | --uid "${UID}" \ 59 | "${USER}" 60 | 61 | # Create data mount point with permissions 62 | RUN mkdir -p /var/lib/lodestar/validators && chown -R ${USER}:${USER} /var/lib/lodestar/validators && chmod 700 /var/lib/lodestar/validators 63 | 64 | # Cannot assume buildkit, hence no chmod 65 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 66 | # Belt and suspenders 67 | RUN chmod -R 755 /usr/local/bin/* 68 | 69 | USER lsconsensus 70 | 71 | ENV NODE_OPTIONS=--max-old-space-size=8192 72 | 73 | ENTRYPOINT ["node", "/usr/app/node_modules/.bin/lodestar"] 74 | -------------------------------------------------------------------------------- /lodestar/docker-entrypoint-vc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | if [ "$(id -u)" = '0' ]; then 5 | chown -R lsvalidator:lsvalidator /var/lib/lodestar 6 | exec gosu lsvalidator docker-entrypoint-vc.sh "$@" 7 | fi 8 | 9 | if [[ "${NETWORK}" =~ ^https?:// ]]; then 10 | echo "Custom testnet at ${NETWORK}" 11 | repo=$(awk -F'/tree/' '{print $1}' <<< "${NETWORK}") 12 | branch=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f1) 13 | config_dir=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f2-) 14 | echo "This appears to be the ${repo} repo, branch ${branch} and config directory ${config_dir}." 15 | # For want of something more amazing, let's just fail if git fails to pull this 16 | set -e 17 | if [ ! -d "/var/lib/lodestar/validators/testnet/${config_dir}" ]; then 18 | mkdir -p /var/lib/lodestar/validators/testnet 19 | cd /var/lib/lodestar/validators/testnet 20 | git init --initial-branch="${branch}" 21 | git remote add origin "${repo}" 22 | git config core.sparseCheckout true 23 | echo "${config_dir}" > .git/info/sparse-checkout 24 | git pull origin "${branch}" 25 | fi 26 | set +e 27 | __network="--paramsFile=/var/lib/lodestar/validators/testnet/${config_dir}/config.yaml" 28 | else 29 | __network="--network ${NETWORK}" 30 | fi 31 | 32 | # Check whether we should use MEV Boost 33 | if [ "${MEV_BOOST}" = "true" ]; then 34 | __mev_boost="--builder" 35 | echo "MEV Boost enabled" 36 | else 37 | __mev_boost="" 38 | fi 39 | 40 | # Check whether we should send stats to beaconcha.in 41 | if [ -n "${BEACON_STATS_API}" ]; then 42 | __beacon_stats="--monitoring.endpoint https://beaconcha.in/api/v1/client/metrics?apikey=${BEACON_STATS_API}&machine=${BEACON_STATS_MACHINE}" 43 | echo "Beacon stats API enabled" 44 | else 45 | __beacon_stats="" 46 | fi 47 | 48 | # Check whether we should enable doppelganger protection 49 | if [ "${DOPPELGANGER}" = "true" ]; then 50 | __doppel="--doppelgangerProtection" 51 | echo "Doppelganger protection enabled, VC will pause for 2 epochs" 52 | else 53 | __doppel="" 54 | fi 55 | 56 | # Web3signer URL 57 | if [ "${WEB3SIGNER}" = "true" ]; then 58 | __w3s_url="--externalSigner.url ${W3S_NODE} --externalSigner.fetch" 59 | else 60 | __w3s_url="" 61 | fi 62 | 63 | # Distributed attestation aggregation 64 | if [ "${ENABLE_DIST_ATTESTATION_AGGR}" = "true" ]; then 65 | __att_aggr="--distributed" 66 | else 67 | __att_aggr="" 68 | fi 69 | 70 | if [ "${DEFAULT_GRAFFITI}" = "true" ]; then 71 | # Word splitting is desired for the command line parameters 72 | # shellcheck disable=SC2086 73 | exec "$@" ${__network} ${__mev_boost} ${__beacon_stats} ${__doppel} ${__w3s_url} ${__att_aggr} ${VC_EXTRAS} 74 | else 75 | # Word splitting is desired for the command line parameters 76 | # shellcheck disable=SC2086 77 | exec "$@" ${__network} "--graffiti" "${GRAFFITI}" ${__mev_boost} ${__beacon_stats} ${__doppel} ${__w3s_url} ${__att_aggr} ${VC_EXTRAS} 78 | fi 79 | -------------------------------------------------------------------------------- /loki/loki.yml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | 3 | server: 4 | http_listen_port: 3100 5 | grpc_listen_port: 9096 6 | 7 | common: 8 | path_prefix: /tmp/loki 9 | storage: 10 | filesystem: 11 | chunks_directory: /tmp/loki/chunks 12 | rules_directory: /tmp/loki/rules 13 | replication_factor: 1 14 | ring: 15 | instance_addr: 127.0.0.1 16 | kvstore: 17 | store: inmemory 18 | 19 | compactor: 20 | working_directory: /tmp/loki/retention 21 | compaction_interval: 10m 22 | retention_enabled: true 23 | retention_delete_delay: 2h 24 | retention_delete_worker_count: 150 25 | delete_request_store: filesystem 26 | 27 | schema_config: 28 | configs: 29 | - from: 2024-05-01 30 | store: tsdb 31 | object_store: filesystem 32 | schema: v13 33 | index: 34 | prefix: tsdb_index 35 | period: 24h 36 | 37 | limits_config: 38 | retention_period: 30d 39 | ingestion_rate_mb: 128 40 | ingestion_burst_size_mb: 512 41 | -------------------------------------------------------------------------------- /mev-boost.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: "{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}" 8 | 9 | services: 10 | mev-boost: 11 | restart: "unless-stopped" 12 | build: 13 | context: ./flashbots 14 | dockerfile: ${MEV_DOCKERFILE} 15 | args: 16 | - BUILD_TARGET=${MEV_SRC_BUILD_TARGET:-develop} 17 | - SRC_REPO=${MEV_SRC_REPO:-https://github.com/flashbots/mev-boost} 18 | - DOCKER_TAG=${MEV_DOCKER_TAG:-latest} 19 | - DOCKER_REPO=${MEV_DOCKER_REPO:-flashbots/mev-boost} 20 | image: mev-boost:local 21 | pull_policy: never 22 | networks: 23 | default: 24 | aliases: 25 | - ${MEV_ALIAS:-default-mev} # This allows multiple Eth Docker stacks all connected to the same bridge network 26 | entrypoint: 27 | - /app/mev-boost 28 | - -addr 29 | - 0.0.0.0:18550 30 | - -${NETWORK} 31 | - -relay-check 32 | - -relays 33 | - ${MEV_RELAYS} 34 | - -min-bid 35 | - ${MEV_MIN_BID:-0} 36 | - -loglevel 37 | - ${LOG_LEVEL} 38 | <<: *logging 39 | -------------------------------------------------------------------------------- /nethermind/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=nethermind/nethermind 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=nethermind 11 | ARG UID=10001 12 | # GID 10002 is deliberate so it can exchange secret with CL 13 | ARG GID=10002 14 | 15 | RUN set -eux; \ 16 | apt-get update; \ 17 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y ca-certificates gosu tzdata wget git git-lfs adduser; \ 18 | rm -rf /var/lib/apt/lists/*; \ 19 | # verify that the binary works 20 | gosu nobody true 21 | 22 | RUN addgroup \ 23 | --gid "${GID}" \ 24 | "${USER}" 25 | 26 | # See https://stackoverflow.com/a/55757473/12429735RUN 27 | RUN adduser \ 28 | --disabled-password \ 29 | --gecos "" \ 30 | --home "/nonexistent" \ 31 | --shell "/sbin/nologin" \ 32 | --no-create-home \ 33 | --uid "${UID}" \ 34 | --ingroup "${USER}" \ 35 | "${USER}" 36 | 37 | # This only goes so far. keystore, logs and nethermind_db are volumes and need to be chown'd in the entrypoint 38 | RUN chown -R ${USER}:${USER} /nethermind 39 | RUN mkdir -p /var/lib/nethermind-og && chown -R ${USER}:${USER} /var/lib/nethermind-og \ 40 | && chmod -R 700 /var/lib/nethermind-og 41 | RUN mkdir -p /var/lib/nethermind/ee-secret && chown -R ${USER}:${USER} /var/lib/nethermind \ 42 | && chmod -R 700 /var/lib/nethermind && chmod 777 /var/lib/nethermind/ee-secret 43 | 44 | # Cannot assume buildkit, hence no chmod 45 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 46 | # Belt and suspenders 47 | RUN chmod -R 755 /usr/local/bin/* 48 | 49 | USER ${USER} 50 | 51 | ENTRYPOINT ["./nethermind"] 52 | -------------------------------------------------------------------------------- /nethermind/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG 2 | 3 | FROM nethermindeth/nethermind:${DOCKER_TAG} 4 | 5 | # Unused, this is here to avoid build time complaints 6 | ARG BUILD_TARGET 7 | 8 | ARG USER=nethermind 9 | ARG UID=10001 10 | # GID 10002 is deliberate so it can exchange secret with CL 11 | ARG GID=10002 12 | 13 | RUN addgroup \ 14 | --gid "${GID}" \ 15 | "${USER}" 16 | 17 | # See https://stackoverflow.com/a/55757473/12429735RUN 18 | RUN adduser \ 19 | --disabled-password \ 20 | --gecos "" \ 21 | --home "/nonexistent" \ 22 | --shell "/sbin/nologin" \ 23 | --no-create-home \ 24 | --uid "${UID}" \ 25 | --ingroup "${USER}" \ 26 | "${USER}" 27 | 28 | RUN set -eux; \ 29 | apt-get update; \ 30 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y ca-certificates gosu tzdata git; \ 31 | rm -rf /var/lib/apt/lists/*; \ 32 | # verify that the binary works 33 | gosu nobody true 34 | 35 | # This only goes so far. keystore, logs and nethermind_db are volumes and need to be chown'd in the entrypoint 36 | RUN chown -R ${USER}:${USER} /nethermind 37 | RUN mkdir -p /var/lib/nethermind/ee-secret && chown -R ${USER}:${USER} /var/lib/nethermind && chmod -R 700 /var/lib/nethermind && chmod 777 /var/lib/nethermind/ee-secret 38 | 39 | # Cannot assume buildkit, hence no chmod 40 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 41 | # Belt and suspenders 42 | RUN chmod -R 755 /usr/local/bin/* 43 | 44 | USER ${USER} 45 | 46 | ENTRYPOINT ["dotnet","/nethermind/nethermind.dll"] 47 | -------------------------------------------------------------------------------- /nethermind/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Partially from Nethermind github 2 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS builder 3 | # Unused, this is here to avoid build time complaints 4 | ARG DOCKER_TAG 5 | ARG DOCKER_REPO 6 | 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | WORKDIR / 11 | 12 | RUN apt-get update -y && apt-get install -y git 13 | RUN bash -c "\ 14 | git clone ${SRC_REPO} nethermind && \ 15 | cd nethermind && \ 16 | git config advice.detachedHead false && \ 17 | git fetch --all --tags && \ 18 | if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:nm-pr; \ 19 | git checkout nm-pr; else \ 20 | git checkout ${BUILD_TARGET}; fi && \ 21 | git submodule update --init --recursive && \ 22 | dotnet publish src/Nethermind/Nethermind.Runner -c release -o out" 23 | 24 | FROM mcr.microsoft.com/dotnet/aspnet:9.0 25 | 26 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install libsnappy-dev libc6-dev libc6 ca-certificates gosu tzdata wget git git-lfs && rm -rf /var/lib/apt/lists/* 27 | 28 | ARG USER=nethermind 29 | ARG UID=10001 30 | # GID 10002 is deliberate so it can exchange secret with CL 31 | ARG GID=10002 32 | 33 | RUN addgroup \ 34 | --gid "${GID}" \ 35 | "${USER}" 36 | 37 | RUN adduser \ 38 | --disabled-password \ 39 | --gecos "" \ 40 | --shell "/sbin/nologin" \ 41 | --no-create-home \ 42 | --uid "${UID}" \ 43 | --ingroup "${USER}" \ 44 | "${USER}" 45 | 46 | WORKDIR /nethermind 47 | 48 | # Cannot assume buildkit, hence no chmod 49 | COPY --from=builder --chown=${USER}:${USER} /nethermind/out . 50 | 51 | RUN chown -R ${USER}:${USER} /nethermind 52 | RUN mkdir -p /var/lib/nethermind-og && chown -R ${USER}:${USER} /var/lib/nethermind-og \ 53 | && chmod -R 700 /var/lib/nethermind-og 54 | RUN mkdir -p /var/lib/nethermind/ee-secret && chown -R ${USER}:${USER} /var/lib/nethermind \ 55 | && chmod -R 700 /var/lib/nethermind && chmod 777 /var/lib/nethermind/ee-secret 56 | 57 | # Cannot assume buildkit, hence no chmod 58 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 59 | # Belt and suspenders 60 | RUN chmod -R 755 /usr/local/bin/* 61 | 62 | USER ${USER} 63 | 64 | ENTRYPOINT ["./nethermind"] 65 | -------------------------------------------------------------------------------- /nimbus-el.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | execution: 11 | restart: "unless-stopped" 12 | build: 13 | context: ./nimbus-el 14 | dockerfile: ${NIMEL_DOCKERFILE} 15 | args: 16 | - BUILD_TARGET=${NIMEL_SRC_BUILD_TARGET:-master} 17 | - SRC_REPO=${NIMEL_SRC_REPO:-https://github.com/status-im/nimbus-eth1} 18 | - DOCKER_TAG=${NIMEL_DOCKER_TAG:-master} 19 | - DOCKER_REPO=${NIMEL_DOCKER_REPO:-statusim/nimbus-eth1} 20 | stop_grace_period: 5m 21 | stop_signal: SIGINT 22 | image: nimbus-el:local 23 | pull_policy: never 24 | user: user 25 | environment: 26 | - JWT_SECRET=${JWT_SECRET:-} 27 | - EL_EXTRAS=${EL_EXTRAS:-} 28 | - ARCHIVE_NODE=${EL_ARCHIVE_NODE:-false} 29 | - MINIMAL_NODE=${EL_MINIMAL_NODE:-false} 30 | - NETWORK=${NETWORK} 31 | - ERA1_URL=${ERA1_URL:-} 32 | - ERA_URL=${ERA_URL:-} 33 | - PORTAL_NODE=${PORTAL_NODE} 34 | - PORTAL=${PORTAL:-false} 35 | volumes: 36 | - nimbus-el-data:/var/lib/nimbus 37 | - /etc/localtime:/etc/localtime:ro 38 | - jwtsecret:/var/lib/nimbus/ee-secret 39 | ports: 40 | - ${HOST_IP:-}:${EL_P2P_PORT:-30303}:${EL_P2P_PORT:-30303}/tcp 41 | - ${HOST_IP:-}:${EL_P2P_PORT:-30303}:${EL_P2P_PORT:-30303}/udp 42 | networks: 43 | default: 44 | aliases: 45 | - eth1 46 | - ${EL_ALIAS:-default-execution} # This allows multiple Eth Docker stacks all connected to the same bridge network 47 | <<: *logging 48 | entrypoint: 49 | - docker-entrypoint.sh 50 | - nimbus_execution_client 51 | - --rpc 52 | - --http-address=0.0.0.0 53 | - --http-port=${EL_RPC_PORT:-8545} 54 | - --ws 55 | - --data-dir=/var/lib/nimbus 56 | - --tcp-port=${EL_P2P_PORT:-30303} 57 | - --discovery=V5 58 | - --metrics 59 | - --metrics-port=6060 60 | - --metrics-address=0.0.0.0 61 | - --jwt-secret=/var/lib/nimbus/ee-secret/jwtsecret 62 | - --engine-api 63 | - --engine-api-port=${EE_PORT:-8551} 64 | - --engine-api-address=0.0.0.0 65 | - --engine-api-ws 66 | - --max-peers=${EL_MAX_PEER_COUNT:-25} 67 | - --log-level=${LOG_LEVEL} 68 | labels: 69 | - metrics.scrape=true 70 | - metrics.path=/metrics 71 | - metrics.port=6060 72 | - metrics.instance=execution 73 | - metrics.network=${NETWORK} 74 | 75 | volumes: 76 | nimbus-el-data: 77 | jwtsecret: 78 | 79 | networks: 80 | default: 81 | enable_ipv6: ${IPV6:-false} 82 | -------------------------------------------------------------------------------- /nimbus-el/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=master 2 | ARG DOCKER_REPO=statusim/nimbus-eth1 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Included here to avoid build-time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=user 11 | ARG UID=10001 12 | 13 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 14 | ca-certificates bash tzdata librocksdb-dev adduser curl aria2 \ 15 | && apt-get clean \ 16 | && rm -rf /var/lib/apt/lists/* 17 | 18 | RUN set -eux; \ 19 | apt-get update; \ 20 | apt-get install -y gosu; \ 21 | rm -rf /var/lib/apt/lists/*; \ 22 | # verify that the binary works 23 | gosu nobody true 24 | 25 | # See https://stackoverflow.com/a/55757473/12429735RUN 26 | RUN adduser \ 27 | --disabled-password \ 28 | --gecos "" \ 29 | --home "/nonexistent" \ 30 | --shell "/usr/sbin/nologin" \ 31 | --no-create-home \ 32 | --uid "${UID}" \ 33 | "${USER}" 34 | 35 | RUN mkdir -p /var/lib/nimbus/ee-secret && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus && chmod 777 /var/lib/nimbus/ee-secret 36 | 37 | RUN cp /home/user/nimbus-eth1/build/nimbus_execution_client /usr/local/bin/ && chown ${USER}:${USER} /usr/local/bin/nimbus_execution_client 38 | # Cannot assume buildkit, hence no chmod 39 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 40 | # Belt and suspenders 41 | RUN chmod -R 755 /usr/local/bin/* 42 | 43 | USER ${USER} 44 | 45 | ENTRYPOINT ["nimbus_execution_client"] 46 | -------------------------------------------------------------------------------- /nimbus-el/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Nimbus in a stock debian container 2 | FROM debian:bookworm-slim AS builder 3 | 4 | # Included here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get install -y build-essential git ca-certificates librocksdb-dev curl 12 | 13 | WORKDIR /usr/src 14 | 15 | RUN bash -c "git clone ${SRC_REPO} nimbus-eth1 && cd nimbus-eth1 && git config advice.detachedHead false && git fetch --all --tags && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:nim-pr; git checkout nim-pr; else git checkout ${BUILD_TARGET}; fi && make -j$(nproc) update && make -j$(nproc) nimbus_execution_client" 16 | 17 | # Pull all binaries into a second stage deploy debian container 18 | FROM debian:bookworm-slim 19 | 20 | ARG USER=user 21 | ARG UID=10001 22 | 23 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 24 | ca-certificates bash tzdata librocksdb-dev curl aria2 \ 25 | && apt-get clean \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | RUN set -eux; \ 29 | apt-get update; \ 30 | apt-get install -y gosu; \ 31 | rm -rf /var/lib/apt/lists/*; \ 32 | # verify that the binary works 33 | gosu nobody true 34 | 35 | # See https://stackoverflow.com/a/55757473/12429735RUN 36 | RUN adduser \ 37 | --disabled-password \ 38 | --gecos "" \ 39 | --home "/nonexistent" \ 40 | --shell "/usr/sbin/nologin" \ 41 | --no-create-home \ 42 | --uid "${UID}" \ 43 | "${USER}" 44 | 45 | RUN mkdir -p /var/lib/nimbus/ee-secret && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus && chmod 777 /var/lib/nimbus/ee-secret 46 | 47 | # Cannot assume buildkit, hence no chmod 48 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth1/build/nimbus_execution_client /usr/local/bin/ 49 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 50 | # Belt and suspenders 51 | RUN chmod -R 755 /usr/local/bin/* 52 | 53 | USER ${USER} 54 | 55 | ENTRYPOINT ["nimbus_execution_client"] 56 | -------------------------------------------------------------------------------- /nimbus-stats.yml: -------------------------------------------------------------------------------- 1 | # Send client stats to beaconcha.in service using client-metrics-exporter 2 | services: 3 | client-stats: 4 | restart: "unless-stopped" 5 | image: gobitfly/eth2-client-metrics-exporter:latest 6 | volumes: 7 | - /etc/localtime:/etc/localtime:ro 8 | entrypoint: 9 | - /bin/eth2-client-metrics-exporter 10 | - --beaconnode.type 11 | - nimbus 12 | - --beaconnode.address 13 | - http://consensus:8008/metrics 14 | - --validator.type 15 | - nimbus 16 | - --server.address 17 | - https://beaconcha.in/api/v1/client/metrics?apikey=${BEACON_STATS_API}&machine=${BEACON_STATS_MACHINE} 18 | -------------------------------------------------------------------------------- /nimbus/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=multiarch-latest 2 | ARG DOCKER_VC_TAG=multiarch-latest 3 | ARG DOCKER_REPO=statusim/nimbus-eth2 4 | ARG DOCKER_VC_REPO=statusim/nimbus-validator-client 5 | 6 | FROM ${DOCKER_REPO}:${DOCKER_TAG} AS consensus 7 | 8 | # Included here to avoid build-time complaints 9 | ARG BUILD_TARGET 10 | ARG SRC_REPO 11 | 12 | ARG USER=user 13 | ARG UID=10002 14 | 15 | USER root 16 | 17 | RUN groupmod -g "${UID}" ${USER} && usermod -u "${UID}" -g "${UID}" ${USER} 18 | 19 | RUN set -eux; \ 20 | apt-get update; \ 21 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates bash tzdata git git-lfs curl; \ 22 | rm -rf /var/lib/apt/lists/*; \ 23 | # verify that the binary works 24 | gosu nobody true 25 | 26 | # Create data mount point with permissions 27 | RUN mkdir -p /var/lib/nimbus/ee-secret && chown -R ${USER}:${USER} /var/lib/nimbus && chmod -R 700 /var/lib/nimbus && chmod 777 /var/lib/nimbus/ee-secret 28 | 29 | RUN cp /home/user/nimbus_beacon_node /usr/local/bin/ 30 | RUN chown ${USER}:${USER} /usr/local/bin/nimbus_beacon_node 31 | # Cannot assume buildkit, hence no chmod 32 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 33 | COPY --chown=${USER}:${USER} ./validator-exit.sh /usr/local/bin/ 34 | # Belt and suspenders 35 | RUN chmod -R 755 /usr/local/bin/* 36 | 37 | USER ${USER} 38 | 39 | ENTRYPOINT ["nimbus_beacon_node"] 40 | 41 | FROM ${DOCKER_VC_REPO}:${DOCKER_VC_TAG} AS validator 42 | 43 | # Included here to avoid build-time complaints 44 | ARG BUILD_TARGET 45 | 46 | ARG USER=user 47 | ARG UID=10000 48 | 49 | USER root 50 | 51 | RUN groupmod -g "${UID}" ${USER} && usermod -u "${UID}" -g "${UID}" ${USER} 52 | 53 | RUN set -eux; \ 54 | apt-get update; \ 55 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates bash tzdata curl; \ 56 | rm -rf /var/lib/apt/lists/*; \ 57 | # verify that the binary works 58 | gosu nobody true 59 | 60 | # Create data mount point with permissions 61 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod -R 700 /var/lib/nimbus 62 | 63 | RUN cp /home/user/nimbus_validator_client /usr/local/bin/ 64 | RUN chown ${USER}:${USER} /usr/local/bin/nimbus_validator_client 65 | # Cannot assume buildkit, hence no chmod 66 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 67 | # Belt and suspenders 68 | RUN chmod -R 755 /usr/local/bin/* 69 | 70 | USER user 71 | 72 | ENTRYPOINT ["nimbus_validator_client"] 73 | -------------------------------------------------------------------------------- /nimbus/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Nimbus in a stock Debian container 2 | FROM debian:bookworm-slim AS builder 3 | 4 | # Included here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_VC_TAG 7 | ARG DOCKER_REPO 8 | ARG DOCKER_VC_REPO 9 | 10 | ARG BUILD_TARGET 11 | ARG SRC_REPO 12 | 13 | RUN apt-get update && apt-get install -y build-essential ca-certificates bash git-lfs cmake 14 | 15 | WORKDIR /usr/src 16 | RUN bash -c "git clone --recurse-submodules -j8 ${SRC_REPO} nimbus-eth2 && cd nimbus-eth2 && git config advice.detachedHead false && git fetch --all --tags && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:nim-pr; git checkout nim-pr; else git checkout ${BUILD_TARGET}; fi && make -j$(nproc) update && make -j$(nproc) nimbus_beacon_node nimbus_validator_client" 17 | 18 | # Pull all binaries into a second stage deploy debian container 19 | FROM debian:bookworm-slim AS consensus 20 | 21 | ARG USER=user 22 | ARG UID=10002 23 | 24 | RUN apt-get update && apt-get install -y \ 25 | ca-certificates bash tzdata git git-lfs curl gosu 26 | 27 | # See https://stackoverflow.com/a/55757473/12429735RUN 28 | RUN adduser \ 29 | --disabled-password \ 30 | --gecos "" \ 31 | --home "/nonexistent" \ 32 | --shell "/usr/sbin/nologin" \ 33 | --no-create-home \ 34 | --uid "${UID}" \ 35 | "${USER}" 36 | 37 | RUN mkdir -p /var/lib/nimbus/ee-secret && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus && chmod 777 /var/lib/nimbus/ee-secret 38 | 39 | # Cannot assume buildkit, hence no chmod 40 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_beacon_node /usr/local/bin/ 41 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 42 | COPY --chown=${USER}:${USER} ./validator-exit.sh /usr/local/bin/ 43 | # Belt and suspenders 44 | RUN chmod -R 755 /usr/local/bin/* 45 | 46 | USER ${USER} 47 | 48 | ENTRYPOINT ["nimbus_beacon_node"] 49 | 50 | FROM debian:bookworm-slim AS validator 51 | 52 | ARG USER=user 53 | ARG UID=10000 54 | 55 | RUN apt-get update && apt-get install -y \ 56 | ca-certificates bash tzdata curl gosu 57 | 58 | # See https://stackoverflow.com/a/55757473/12429735RUN 59 | RUN adduser \ 60 | --disabled-password \ 61 | --gecos "" \ 62 | --home "/nonexistent" \ 63 | --shell "/sbin/nologin" \ 64 | --no-create-home \ 65 | --uid "${UID}" \ 66 | "${USER}" 67 | 68 | # Create data mount point with permissions 69 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod -R 700 /var/lib/nimbus 70 | 71 | # Cannot assume buildkit, hence no chmod 72 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_validator_client /usr/local/bin/ 73 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 74 | # Belt and suspenders 75 | RUN chmod -R 755 /usr/local/bin/* 76 | 77 | USER ${USER} 78 | 79 | ENTRYPOINT ["nimbus_validator_client"] 80 | -------------------------------------------------------------------------------- /nimbus/Dockerfile.sourcegnosis: -------------------------------------------------------------------------------- 1 | # Build Nimbus in a stock debian container 2 | FROM debian:bookworm-slim AS builder 3 | 4 | # Included here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_VC_TAG 7 | ARG DOCKER_REPO 8 | ARG DOCKER_VC_REPO 9 | 10 | ARG BUILD_TARGET 11 | ARG SRC_REPO 12 | 13 | RUN apt-get update && apt-get install -y build-essential ca-certificates bash git-lfs cmake 14 | 15 | WORKDIR /usr/src 16 | RUN bash -c "git clone --recurse-submodules -j8 ${SRC_REPO} nimbus-eth2 && cd nimbus-eth2 && git config advice.detachedHead false && git fetch --all --tags && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:nim-pr; git checkout nim-pr; else git checkout ${BUILD_TARGET}; fi && make -j$(nproc) update && make -j$(nproc) gnosis-build gnosis-vc-build" 17 | 18 | # Pull all binaries into a second stage deploy debian container 19 | FROM debian:bookworm-slim AS consensus 20 | 21 | ARG USER=user 22 | ARG UID=10002 23 | 24 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 25 | ca-certificates bash tzdata git \ 26 | && apt-get clean \ 27 | && rm -rf /var/lib/apt/lists/* 28 | 29 | RUN set -eux; \ 30 | apt-get update; \ 31 | apt-get install -y gosu; \ 32 | rm -rf /var/lib/apt/lists/*; \ 33 | # verify that the binary works 34 | gosu nobody true 35 | 36 | # See https://stackoverflow.com/a/55757473/12429735RUN 37 | RUN adduser \ 38 | --disabled-password \ 39 | --gecos "" \ 40 | --home "/nonexistent" \ 41 | --shell "/usr/sbin/nologin" \ 42 | --no-create-home \ 43 | --uid "${UID}" \ 44 | "${USER}" 45 | 46 | RUN mkdir -p /var/lib/nimbus/ee-secret && chown -R ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus && chmod 777 /var/lib/nimbus/ee-secret 47 | 48 | # Cannot assume buildkit, hence no chmod 49 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_beacon_node_gnosis /usr/local/bin/nimbus_beacon_node 50 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 51 | # Belt and suspenders 52 | RUN chmod -R 755 /usr/local/bin/* 53 | 54 | USER ${USER} 55 | 56 | ENTRYPOINT ["nimbus_beacon_node"] 57 | 58 | FROM debian:bookworm-slim AS validator 59 | 60 | ARG USER=user 61 | ARG UID=10000 62 | 63 | # See https://stackoverflow.com/a/55757473/12429735RUN 64 | RUN adduser \ 65 | --disabled-password \ 66 | --gecos "" \ 67 | --home "/nonexistent" \ 68 | --shell "/sbin/nologin" \ 69 | --no-create-home \ 70 | --uid "${UID}" \ 71 | "${USER}" 72 | 73 | # Create data mount point with permissions 74 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod -R 700 /var/lib/nimbus 75 | 76 | # Cannot assume buildkit, hence no chmod 77 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_validator_client_gnosis /usr/local/bin/nimbus_validator_client 78 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 79 | # Belt and suspenders 80 | RUN chmod -R 755 /usr/local/bin/* 81 | 82 | USER ${USER} 83 | 84 | ENTRYPOINT ["nimbus_validator_client"] 85 | -------------------------------------------------------------------------------- /nimbus/Dockerfile.sourceslottime: -------------------------------------------------------------------------------- 1 | # Build Nimbus in a stock debian container 2 | FROM debian:bookworm-slim AS builder 3 | 4 | # Included here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_VC_TAG 7 | ARG DOCKER_REPO 8 | ARG DOCKER_VC_REPO 9 | 10 | ARG BUILD_TARGET 11 | ARG SRC_REPO 12 | ARG SECONDS_PER_SLOT=12 13 | 14 | RUN apt-get update && apt-get install -y build-essential ca-certificates bash git-lfs cmake 15 | 16 | WORKDIR /usr/src 17 | RUN bash -c "git clone ${SRC_REPO} nimbus-eth2 && cd nimbus-eth2 && git config advice.detachedHead false && git fetch --all --tags && git checkout ${BUILD_TARGET} && \ 18 | make -j$(nproc) update && make -j$(nproc) NIMFLAGS="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT}" nimbus_beacon_node nimbus_validator_client" 19 | 20 | # Pull all binaries into a second stage deploy debian container 21 | FROM debian:bookworm-slim as consensus 22 | 23 | ARG USER=user 24 | ARG UID=10002 25 | 26 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 27 | ca-certificates bash tzdata git \ 28 | && apt-get clean \ 29 | && rm -rf /var/lib/apt/lists/* 30 | 31 | RUN set -eux; \ 32 | apt-get update; \ 33 | apt-get install -y gosu; \ 34 | rm -rf /var/lib/apt/lists/*; \ 35 | # verify that the binary works 36 | gosu nobody true 37 | 38 | # See https://stackoverflow.com/a/55757473/12429735RUN 39 | RUN adduser \ 40 | --disabled-password \ 41 | --gecos "" \ 42 | --home "/nonexistent" \ 43 | --shell "/usr/sbin/nologin" \ 44 | --no-create-home \ 45 | --uid "${UID}" \ 46 | "${USER}" 47 | 48 | RUN mkdir -p /var/lib/nimbus && chown ${USER}:${USER} /var/lib/nimbus && chmod 700 /var/lib/nimbus 49 | 50 | # Cannot assume buildkit, hence no chmod 51 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_beacon_node /usr/local/bin/nimbus_beacon_node 52 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 53 | COPY --chown=${USER}:${USER} ./validator-exit.sh /usr/local/bin/ 54 | # Belt and suspenders 55 | RUN chmod -R 755 /usr/local/bin/* 56 | 57 | USER ${USER} 58 | 59 | ENTRYPOINT ["nimbus_beacon_node"] 60 | 61 | FROM debian:bookworm-slim AS validator 62 | 63 | ARG USER=user 64 | ARG UID=10000 65 | 66 | RUN apt-get update && apt-get install -y \ 67 | ca-certificates bash tzdata curl gosu 68 | 69 | # See https://stackoverflow.com/a/55757473/12429735RUN 70 | RUN adduser \ 71 | --disabled-password \ 72 | --gecos "" \ 73 | --home "/nonexistent" \ 74 | --shell "/sbin/nologin" \ 75 | --no-create-home \ 76 | --uid "${UID}" \ 77 | "${USER}" 78 | 79 | # Create data mount point with permissions 80 | RUN mkdir -p /var/lib/nimbus && chown -R ${USER}:${USER} /var/lib/nimbus && chmod -R 700 /var/lib/nimbus 81 | 82 | # Cannot assume buildkit, hence no chmod 83 | COPY --from=builder --chown=${USER}:${USER} /usr/src/nimbus-eth2/build/nimbus_validator_client /usr/local/bin/ 84 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 85 | # Belt and suspenders 86 | RUN chmod -R 755 /usr/local/bin/* 87 | 88 | USER ${USER} 89 | 90 | ENTRYPOINT ["nimbus_validator_client"] 91 | -------------------------------------------------------------------------------- /nimbus/docker-entrypoint-vc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$(id -u)" = '0' ]; then 4 | chown -R user:user /var/lib/nimbus 5 | exec su-exec user docker-entrypoint-vc.sh "$@" 6 | fi 7 | 8 | # Remove old low-entropy token, related to Sigma Prime security audit 9 | # This detection isn't perfect - a user could recreate the token without ./ethd update 10 | if [[ -f /var/lib/nimbus/api-token.txt && "$(date +%s -r /var/lib/nimbus/api-token.txt)" -lt "$(date +%s --date="2023-05-02 09:00:00")" ]]; then 11 | rm /var/lib/nimbus/api-token.txt 12 | fi 13 | 14 | if [ ! -f /var/lib/nimbus/api-token.txt ]; then 15 | __token=api-token-0x$(head -c 8 /dev/urandom | od -A n -t u8 | tr -d '[:space:]' | sha256sum | head -c 32)$(head -c 8 /dev/urandom | od -A n -t u8 | tr -d '[:space:]' | sha256sum | head -c 32) 16 | echo "$__token" > /var/lib/nimbus/api-token.txt 17 | fi 18 | 19 | # Check whether we should enable doppelganger protection 20 | if [ "${DOPPELGANGER}" = "true" ]; then 21 | __doppel="--doppelganger-detection=true" 22 | echo "Doppelganger protection enabled, VC will pause for 2 epochs" 23 | else 24 | __doppel="--doppelganger-detection=false" 25 | fi 26 | 27 | # Check whether we should use MEV Boost 28 | if [ "${MEV_BOOST}" = "true" ]; then 29 | __mev_boost="--payload-builder=true" 30 | echo "MEV Boost enabled" 31 | else 32 | __mev_boost="" 33 | fi 34 | 35 | # accommodate comma separated list of consensus nodes 36 | __nodes=$(echo "$CL_NODE" | tr ',' ' ') 37 | __beacon_nodes=() 38 | for __node in $__nodes; do 39 | __beacon_nodes+=("--beacon-node=$__node") 40 | done 41 | 42 | __log_level="--log-level=${LOG_LEVEL^^}" 43 | 44 | # Web3signer URL 45 | if [ "${WEB3SIGNER}" = "true" ]; then 46 | __w3s_url="--web3-signer-url=${W3S_NODE}" 47 | while true; do 48 | if curl -s -m 5 "${W3S_NODE}" &> /dev/null; then 49 | echo "Web3signer is up, starting Nimbus" 50 | break 51 | else 52 | echo "Waiting for Web3signer to be reachable..." 53 | sleep 5 54 | fi 55 | done 56 | else 57 | __w3s_url="" 58 | fi 59 | 60 | # Distributed attestation aggregation 61 | if [ "${ENABLE_DIST_ATTESTATION_AGGR}" = "true" ]; then 62 | __att_aggr="--distributed" 63 | else 64 | __att_aggr="" 65 | fi 66 | 67 | if [ "${DEFAULT_GRAFFITI}" = "true" ]; then 68 | # Word splitting is desired for the command line parameters 69 | # shellcheck disable=SC2086 70 | exec "$@" "${__beacon_nodes[@]}" ${__w3s_url} ${__log_level} ${__doppel} ${__mev_boost} ${__att_aggr} ${VC_EXTRAS} 71 | else 72 | # Word splitting is desired for the command line parameters 73 | # shellcheck disable=SC2086 74 | exec "$@" "${__beacon_nodes[@]}" ${__w3s_url} "--graffiti=${GRAFFITI}" ${__log_level} ${__doppel} ${__mev_boost} ${__att_aggr} ${VC_EXTRAS} 75 | fi 76 | -------------------------------------------------------------------------------- /nimbus/validator-exit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | # Copy keys, then restart script without root 5 | if [ "$(id -u)" = '0' ]; then 6 | mkdir /keys 7 | cp -r /validator_keys/* /keys/ 8 | chown user:user /keys/* 9 | exec gosu user "${BASH_SOURCE[0]}" "$@" 10 | fi 11 | 12 | exec "$@" 13 | -------------------------------------------------------------------------------- /portal-shared.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with fluffy.yml 2 | services: 3 | portal: 4 | ports: 5 | - ${SHARE_IP:-}:${PORTAL_RPC_PORT}:${PORTAL_RPC_PORT:-8545}/tcp 6 | - ${SHARE_IP:-}:${PORTAL_WS_PORT}:${PORTAL_WS_PORT:-8546}/tcp 7 | -------------------------------------------------------------------------------- /prometheus-shared.yml: -------------------------------------------------------------------------------- 1 | # Prometheus federation, or other reasons to have prometheus through traefik 2 | services: 3 | prometheus: 4 | ports: 5 | - ${SHARE_IP:-}:${PROMETHEUS_PORT:-9090}:9090/tcp 6 | -------------------------------------------------------------------------------- /prometheus-traefik.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with grafana.yml 2 | # Please be very cautious, prometheus is not authenticated by default 3 | services: 4 | prometheus: 5 | labels: 6 | - traefik.enable=true 7 | - traefik.http.routers.${PROM_HOST:-prom}.service=${PROM_HOST:-prom} 8 | - traefik.http.routers.${PROM_HOST:-prom}.entrypoints=web,websecure 9 | - traefik.http.routers.${PROM_HOST:-prom}.rule=Host(`${PROM_HOST:-prom}.${DOMAIN}`) 10 | - traefik.http.routers.${PROM_HOST:-prom}.tls.certresolver=letsencrypt 11 | - traefik.http.services.${PROM_HOST:-prom}.loadbalancer.server.port=9090 12 | -------------------------------------------------------------------------------- /prometheus/.gitignore: -------------------------------------------------------------------------------- 1 | # Ensure user-added configs don't get mixed up in git 2 | .conf.d/* 3 | !.conf.d/internet-scraper.yml 4 | !.conf.d/coingecko-scraper.yml 5 | custom-prom.yml -------------------------------------------------------------------------------- /prometheus/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG YQ_TAG=4 2 | ARG YQ_REPO=mikefarah/yq 3 | FROM $YQ_REPO:$YQ_TAG AS yq 4 | 5 | FROM prom/prometheus:latest 6 | 7 | ARG USER=nobody 8 | 9 | COPY --from=yq /usr/bin/yq /usr/local/bin/yq 10 | 11 | COPY base-config.yml rootless-base-config.yml /etc/prometheus/ 12 | COPY ./rootless/*.yml /etc/prometheus/rootless/ 13 | COPY ./docker-entrypoint.sh /usr/local/bin/ 14 | 15 | # Belt and suspenders 16 | USER root 17 | RUN chmod -R 755 /usr/local/bin/* 18 | RUN find /etc/prometheus -type d -exec chmod 755 {} \; 19 | RUN find /etc/prometheus -type f -exec chmod 664 {} \; 20 | RUN chown -R ${USER}:${USER} /etc/prometheus 21 | USER ${USER} 22 | 23 | ENTRYPOINT [ "docker-entrypoint.sh" ] 24 | -------------------------------------------------------------------------------- /prometheus/blackbox.yml: -------------------------------------------------------------------------------- 1 | modules: 2 | icmp: 3 | prober: icmp 4 | timeout: 10s 5 | icmp: 6 | preferred_ip_protocol: ipv4 7 | -------------------------------------------------------------------------------- /prometheus/conf.d/coingecko.yml: -------------------------------------------------------------------------------- 1 | # Scrape Coingeck price feeds 2 | 3 | scrape_configs: 4 | - job_name: 'json' 5 | metrics_path: /probe 6 | scrape_interval: 300s 7 | params: 8 | module: [default] 9 | static_configs: 10 | - targets: 11 | - https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd 12 | relabel_configs: 13 | - source_labels: [__address__] 14 | target_label: __param_target 15 | - source_labels: [__param_target] 16 | target_label: instance 17 | - target_label: __address__ 18 | replacement: json-exporter:7979 19 | -------------------------------------------------------------------------------- /prometheus/conf.d/ping.yml: -------------------------------------------------------------------------------- 1 | # Checking internet connectivity 2 | 3 | scrape_configs: 4 | - job_name: 'ping_google' 5 | metrics_path: /probe 6 | params: 7 | module: [icmp] 8 | static_configs: 9 | - targets: 10 | - 8.8.8.8 11 | relabel_configs: 12 | - source_labels: [__address__] 13 | target_label: __param_target 14 | - source_labels: [__param_target] 15 | target_label: instance 16 | - target_label: __address__ 17 | replacement: blackbox-exporter:9115 18 | - job_name: 'ping_cloudflare' 19 | metrics_path: /probe 20 | params: 21 | module: [icmp] 22 | static_configs: 23 | - targets: 24 | - 1.1.1.1 25 | relabel_configs: 26 | - source_labels: [__address__] 27 | target_label: __param_target 28 | - source_labels: [__param_target] 29 | target_label: instance 30 | - target_label: __address__ 31 | replacement: blackbox-exporter:9115 -------------------------------------------------------------------------------- /prometheus/custom-prom.yml.sample: -------------------------------------------------------------------------------- 1 | # Additional config for Prometheus. Modifications here will override the global settings, however 2 | # in the case of lists (e.g. scrape_configs) new items will be added. 3 | # This means that it's not possible to override existing scrape target configurations. 4 | 5 | global: 6 | label_limit: 2000 7 | scrape_interval: 10s 8 | scrape_timeout: 8s 9 | evaluation_interval: 10s 10 | 11 | remote_write: 12 | - url: "" 13 | basic_auth: 14 | username: "your Grafana Cloud username" 15 | password: "your Grafana Cloud API key" 16 | 17 | scrape_configs: 18 | - job_name: Another job 19 | -------------------------------------------------------------------------------- /prometheus/json.yml: -------------------------------------------------------------------------------- 1 | modules: 2 | default: 3 | metrics: 4 | - name: ethusd 5 | path: "{ .ethereum.usd }" 6 | help: Ethereum (ETH) price in USD 7 | -------------------------------------------------------------------------------- /prometheus/obol-prom.yml: -------------------------------------------------------------------------------- 1 | remote_write: 2 | - url: https://vm.monitoring.gcp.obol.tech/write 3 | authorization: 4 | credentials: OBOL_PROM_REMOTE_WRITE_TOKEN 5 | write_relabel_configs: 6 | - source_labels: [job] 7 | regex: "charon" 8 | action: keep # Keeps charon metrics and drop metrics from other containers. -------------------------------------------------------------------------------- /prometheus/rootless-base-config.yml: -------------------------------------------------------------------------------- 1 | # This file is not intended to be modified - any changes here could be overwritten next time you update. 2 | # If you just need to add some new scrape targets to Prometheus, place these in the conf.d folder. 3 | # You can use the existing files as inspiration, and the docs are here: 4 | # https://prometheus.io/docs/prometheus/latest/configuration/configuration/ 5 | # 6 | # If you need to override the settings in this file, or add other top-level configuration 7 | # (e.g.) remote_write config, please use custom-prom.yml. 8 | # The modifications in that file will supersede the settings here (or extend, in the case of lists) 9 | 10 | # This config differs from the regular one, as there is no access to the Docker socket itself 11 | # and the scrape configs get added manually 12 | 13 | global: 14 | scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. 15 | scrape_timeout: 12s # Timeout must be shorter than the interval 16 | evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. 17 | 18 | # Directories with extra scraping targets 19 | scrape_config_files: 20 | - /etc/prometheus/conf.d/*.yml # Mounted folder, place extra scraping configs in conf.d to include 21 | - /etc/prometheus/rootless.d/*.yml # Populated when container starts based on .env settings 22 | 23 | # These targets are present regardless of client choice, so they are listed here rather than 24 | # via one of the above configuration folders 25 | scrape_configs: 26 | - job_name: 'prometheus' 27 | scrape_interval: 5s 28 | static_configs: 29 | - targets: ['prometheus:9090'] 30 | - job_name: 'ethereum-metrics-exporter' 31 | static_configs: 32 | - targets: ['ethereum-metrics-exporter:9090'] 33 | - job_name: 'json-exporter' 34 | static_configs: 35 | - targets: ['json-exporter:7979'] 36 | -------------------------------------------------------------------------------- /prometheus/rootless/besu-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: besu 3 | metrics_path: /metrics 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - execution:6060 8 | -------------------------------------------------------------------------------- /prometheus/rootless/erigon-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: erigon 3 | metrics_path: /debug/metrics/prometheus 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - execution:6060 8 | -------------------------------------------------------------------------------- /prometheus/rootless/geth-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: geth 3 | metrics_path: /debug/metrics/prometheus 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - execution:6060 8 | -------------------------------------------------------------------------------- /prometheus/rootless/lh-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'nodes' 3 | static_configs: 4 | - targets: ['consensus:8008'] 5 | - job_name: 'validator' 6 | static_configs: 7 | - targets: ['validator:8009'] 8 | -------------------------------------------------------------------------------- /prometheus/rootless/lhcc-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'nodes' 3 | static_configs: 4 | - targets: ['consensus:8008'] 5 | -------------------------------------------------------------------------------- /prometheus/rootless/lido-obol-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: charon 3 | metrics_path: /metrics 4 | static_configs: 5 | - targets: 6 | - charon:3620 7 | - job_name: validator-ejector 8 | metrics_path: /metrics 9 | static_configs: 10 | - targets: 11 | - validator-ejector:8989 -------------------------------------------------------------------------------- /prometheus/rootless/ls-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'beacon' 3 | static_configs: 4 | - targets: ['consensus:8008'] 5 | - job_name: 'validator' 6 | static_configs: 7 | - targets: ['validator:8009'] 8 | -------------------------------------------------------------------------------- /prometheus/rootless/lscc-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'beacon' 3 | static_configs: 4 | - targets: ['consensus:8008'] 5 | -------------------------------------------------------------------------------- /prometheus/rootless/nethermind-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: nethermind 3 | metrics_path: /metrics 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - execution:6060 8 | -------------------------------------------------------------------------------- /prometheus/rootless/nimbus-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'nimbus' 3 | static_configs: 4 | - targets: ['consensus:8008'] 5 | -------------------------------------------------------------------------------- /prometheus/rootless/prysm-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'validator' 3 | scrape_interval: 5s 4 | static_configs: 5 | - targets: ['validator:8009'] 6 | - job_name: 'consensus node' 7 | scrape_interval: 5s 8 | static_configs: 9 | - targets: ['consensus:8008'] 10 | -------------------------------------------------------------------------------- /prometheus/rootless/prysmcc-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'consensus node' 3 | scrape_interval: 5s 4 | static_configs: 5 | - targets: ['consensus:8008'] 6 | -------------------------------------------------------------------------------- /prometheus/rootless/reth-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: reth 3 | metrics_path: /metrics 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - execution:6060 8 | -------------------------------------------------------------------------------- /prometheus/rootless/ssv-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: ssv 3 | metrics_path: /metrics 4 | static_configs: 5 | - targets: 6 | - ssv-node:15000 7 | -------------------------------------------------------------------------------- /prometheus/rootless/teku-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: "teku-dev" 3 | scrape_timeout: 10s 4 | metrics_path: /metrics 5 | scheme: http 6 | static_configs: 7 | - targets: ["consensus:8008"] 8 | -------------------------------------------------------------------------------- /prometheus/rootless/traefik-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: traefik 3 | metrics_path: /metrics 4 | scheme: http 5 | static_configs: 6 | - targets: 7 | - traefik:8080 8 | -------------------------------------------------------------------------------- /prometheus/rootless/web3signer-prom.yml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'web3signer' 3 | static_configs: 4 | - targets: ['web3signer:9001'] 5 | -------------------------------------------------------------------------------- /promtail/custom-lokiurl.yml.sample: -------------------------------------------------------------------------------- 1 | # URL 1 2 | - url: https://LOKI_DOMAIN/loki/api/v1/push 3 | 4 | # If using basic auth authentication 5 | # basic_auth: 6 | # username: primary 7 | # password: rn5egfjjzaZ8qtG2ybG94gseLxy3 8 | 9 | # If using headers authentication 10 | # headers: 11 | # "Header1": "Header value" 12 | # "Header2": "Header value" 13 | # "X-Scope-OrgID": "primary" 14 | 15 | # Any other url parameters as defined by promtail https://grafana.com/docs/loki/latest/clients/promtail/configuration/#clients 16 | 17 | # URL 2 18 | - url: https://LOKI_IP:PORT/loki/api/v1/push 19 | -------------------------------------------------------------------------------- /promtail/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Start fresh every time 4 | cp /etc/promtail/global.yml /promtail-config.yml 5 | 6 | # Add custom loki urls to config with indentation to make sure its valid yml 7 | if [ -s "/etc/promtail/custom-lokiurl.yml" ]; then 8 | echo "/etc/promtail/custom-lokiurl.yml" | xargs sed 's/^/ /' >> /promtail-config.yml 9 | else 10 | cat >> /promtail-config.yml << EOF 11 | - url: http://loki:3100/loki/api/v1/push 12 | EOF 13 | fi 14 | 15 | # Replace SERVER_LABEL_HOSTNAME in config file 16 | sed -i "s/SERVER_LABEL_HOSTNAME/$SERVER_LABEL_HOSTNAME/" "/promtail-config.yml" 17 | exec "$@" --config.file=/promtail-config.yml -------------------------------------------------------------------------------- /promtail/global.yml: -------------------------------------------------------------------------------- 1 | server: 2 | http_listen_port: 9080 3 | grpc_listen_port: 9081 4 | log_level: warn 5 | 6 | positions: 7 | filename: /tmp/positions.yaml 8 | 9 | scrape_configs: 10 | - job_name: containers 11 | static_configs: 12 | - targets: 13 | - localhost 14 | labels: 15 | job: containerlogs 16 | server: SERVER_LABEL_HOSTNAME 17 | __path__: /var/lib/docker/containers/*/*log 18 | 19 | pipeline_stages: 20 | - json: 21 | expressions: 22 | output: log 23 | stream: stream 24 | attrs: 25 | 26 | - json: 27 | expressions: 28 | tag: 29 | source: attrs 30 | 31 | - regex: 32 | expression: (?P(?:[^|]*[^|])).(?P(?:[^|]*[^|])).(?P(?:[^|]*[^|])).(?P(?:[^|]*[^|])) 33 | source: tag 34 | 35 | - timestamp: 36 | format: RFC3339Nano 37 | source: time 38 | 39 | - labels: 40 | stream: 41 | container_name: 42 | 43 | - labeldrop: 44 | - filename 45 | 46 | - output: 47 | source: output 48 | 49 | clients: 50 | -------------------------------------------------------------------------------- /prysm-stats.yml: -------------------------------------------------------------------------------- 1 | # Send client stats to beaconcha.in service using client-metrics-exporter 2 | services: 3 | client-stats: 4 | restart: "unless-stopped" 5 | image: gobitfly/eth2-client-metrics-exporter:latest 6 | volumes: 7 | - /etc/localtime:/etc/localtime:ro 8 | entrypoint: 9 | - /bin/eth2-client-metrics-exporter 10 | - --beaconnode.type 11 | - prysm 12 | - --beaconnode.address 13 | - http://consensus:8008/metrics 14 | - --validator.type 15 | - prysm 16 | - --validator.address 17 | - http://validator:8009/metrics 18 | - --server.address 19 | - https://beaconcha.in/api/v1/client/metrics?apikey=${BEACON_STATS_API}&machine=${BEACON_STATS_MACHINE} 20 | # As of Nov 2022 Prysm's own client-stats would require source build. Using beaconcha.in's instead 21 | # client-stats: 22 | # restart: "unless-stopped" 23 | # image: prysm-consensus:local 24 | # pull_policy: never 25 | # volumes: 26 | # - /etc/localtime:/etc/localtime:ro 27 | # entrypoint: 28 | # - client-stats 29 | # - --validator-metrics-url 30 | # - http://validator:8009/metrics 31 | # - --beacon-node-metrics-url 32 | # - http://consensus:8008/metrics 33 | # - --clientstats-api-url 34 | # - https://beaconcha.in/api/v1/client/metrics?apikey=${BEACON_STATS_API}&machine=${BEACON_STATS_MACHINE} 35 | -------------------------------------------------------------------------------- /prysm-web-shared.yml: -------------------------------------------------------------------------------- 1 | keyapi-shared.yml -------------------------------------------------------------------------------- /prysm/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=stable 2 | ARG DOCKER_VC_TAG=stable 3 | ARG DOCKER_REPO=gcr.io/offchainlabs/prysm/beacon-chain 4 | ARG DOCKER_VC_REPO=gcr.io/offchainlabs/prysm/validator 5 | 6 | FROM ${DOCKER_REPO}:${DOCKER_TAG} AS clsource 7 | 8 | FROM debian:bookworm-slim AS consensus 9 | 10 | #Included here to avoid build-time complaints 11 | ARG BUILD_TARGET 12 | ARG SRC_REPO 13 | 14 | ARG USER=prysmconsensus 15 | ARG UID=10002 16 | 17 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 18 | ca-certificates curl bash tzdata git git-lfs \ 19 | && apt-get clean \ 20 | && rm -rf /var/lib/apt/lists/* 21 | # rsync for migration 22 | RUN apt-get update && apt-get install -y --no-install-recommends rsync 23 | 24 | RUN set -eux; \ 25 | apt-get update; \ 26 | apt-get install -y gosu; \ 27 | rm -rf /var/lib/apt/lists/*; \ 28 | # verify that the binary works 29 | gosu nobody true 30 | 31 | # See https://stackoverflow.com/a/55757473/12429735RUN 32 | RUN adduser \ 33 | --disabled-password \ 34 | --gecos "" \ 35 | --home "/nonexistent" \ 36 | --shell "/bin/false" \ 37 | --no-create-home \ 38 | --uid "${UID}" \ 39 | "${USER}" 40 | 41 | # Create mount point for old volume 42 | RUN mkdir -p /var/lib/prysm-og && chown -R ${USER}:${USER} /var/lib/prysm-og 43 | # Create data mount point with permissions 44 | RUN mkdir -p /var/lib/prysm/ee-secret && chown -R ${USER}:${USER} /var/lib/prysm && chmod -R 700 /var/lib/prysm && chmod 777 /var/lib/prysm/ee-secret 45 | 46 | # Cannot assume buildkit, hence no chmod 47 | COPY --from=clsource --chown=${USER}:${USER} /app/cmd/beacon-chain/beacon-chain /usr/local/bin/ 48 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 49 | # Belt and suspenders 50 | RUN chmod -R 755 /usr/local/bin/* 51 | 52 | USER ${USER} 53 | 54 | ENTRYPOINT ["beacon-chain"] 55 | 56 | FROM ${DOCKER_VC_REPO}:${DOCKER_VC_TAG} AS vcsource 57 | 58 | FROM consensus AS validator 59 | 60 | ARG USER=prysmvalidator 61 | ARG UID=10000 62 | USER root 63 | 64 | # See https://stackoverflow.com/a/55757473/12429735RUN 65 | RUN adduser \ 66 | --disabled-password \ 67 | --gecos "" \ 68 | --home "/nonexistent" \ 69 | --shell "/bin/false" \ 70 | --no-create-home \ 71 | --uid "${UID}" \ 72 | "${USER}" 73 | 74 | # Create data mount point with permissions 75 | RUN mkdir -p /var/lib/prysm && chown ${USER}:${USER} /var/lib/prysm && chmod 700 /var/lib/prysm 76 | 77 | # Cannot assume buildkit, hence no chmod 78 | COPY --from=vcsource --chown=${USER}:${USER} /app/cmd/validator/validator /usr/local/bin/ 79 | COPY --chown=${USER}:${USER} ./create-wallet.sh /usr/local/bin/ 80 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 81 | # Belt and suspenders 82 | RUN chmod -R 755 /usr/local/bin/* 83 | 84 | USER ${USER} 85 | 86 | ENTRYPOINT ["validator"] 87 | -------------------------------------------------------------------------------- /prysm/create-wallet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | __password=$(head -c 8 /dev/urandom | od -A n -t u8 | tr -d '[:space:]' | sha256sum | head -c 32) 5 | 6 | echo "$__password" >/tmp/password.txt 7 | echo "Wallet password created" 8 | set +e 9 | if [ "${WEB3SIGNER}" = "true" ]; then 10 | __kind=web3signer 11 | echo "No need to create a permanent wallet when using web3signer with Prysm. Aborting." 12 | exit 0 13 | else 14 | __kind=imported 15 | fi 16 | __result=$(validator --datadir=/var/lib/prysm wallet create --"${NETWORK}" --wallet-dir=/var/lib/prysm --keymanager-kind=${__kind} --accept-terms-of-use --wallet-password-file=/tmp/password.txt 2>&1) 17 | if echo "$__result" | grep -qi error; then 18 | echo "An error occurred while attempting to create a Prysm wallet" 19 | echo "$__result" 20 | exit 1 21 | else 22 | echo "$__result" 23 | fi 24 | set -e 25 | echo "Wallet has been created" 26 | echo "$__password" >/var/lib/prysm/password.txt 27 | chmod 600 /var/lib/prysm/password.txt 28 | echo "Wallet password stored" 29 | -------------------------------------------------------------------------------- /prysm/docker-entrypoint-vc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | if [ "$(id -u)" = '0' ]; then 5 | chown -R prysmvalidator:prysmvalidator /var/lib/prysm 6 | exec gosu prysmvalidator docker-entrypoint-vc.sh "$@" 7 | fi 8 | 9 | if [[ "${NETWORK}" =~ ^https?:// ]]; then 10 | echo "Custom testnet at ${NETWORK}" 11 | repo=$(awk -F'/tree/' '{print $1}' <<< "${NETWORK}") 12 | branch=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f1) 13 | config_dir=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f2-) 14 | echo "This appears to be the ${repo} repo, branch ${branch} and config directory ${config_dir}." 15 | # For want of something more amazing, let's just fail if git fails to pull this 16 | set -e 17 | if [ ! -d "/var/lib/prysm/testnet/${config_dir}" ]; then 18 | mkdir -p /var/lib/prysm/testnet 19 | cd /var/lib/prysm/testnet 20 | git init --initial-branch="${branch}" 21 | git remote add origin "${repo}" 22 | git config core.sparseCheckout true 23 | echo "${config_dir}" > .git/info/sparse-checkout 24 | git pull origin "${branch}" 25 | fi 26 | set +e 27 | __network="--chain-config-file=/var/lib/prysm/testnet/${config_dir}/config.yaml" 28 | else 29 | __network="--${NETWORK}" 30 | fi 31 | 32 | # Check whether we should use MEV Boost 33 | if [ "${MEV_BOOST}" = "true" ]; then 34 | __mev_boost="--enable-builder" 35 | echo "MEV Boost enabled" 36 | else 37 | __mev_boost="" 38 | fi 39 | 40 | # Check whether we should enable doppelganger protection 41 | if [ "${DOPPELGANGER}" = "true" ]; then 42 | __doppel="--enable-doppelganger" 43 | echo "Doppelganger protection enabled, VC will pause for 2 epochs" 44 | else 45 | __doppel="" 46 | fi 47 | 48 | # Web3signer URL 49 | if [ "${WEB3SIGNER}" = "true" ]; then 50 | __w3s_url="--validators-external-signer-url ${W3S_NODE} \ 51 | --validators-external-signer-public-keys ${W3S_NODE}/api/v1/eth2/publicKeys \ 52 | --validators-external-signer-key-file=/var/lib/prysm/w3s-keys.txt" 53 | 54 | if [ ! -f /var/lib/prysm/w3s-keys.txt ]; then 55 | touch /var/lib/prysm/w3s-keys.txt 56 | fi 57 | else 58 | __w3s_url="--web --wallet-password-file /var/lib/prysm/password.txt" 59 | fi 60 | 61 | # Distributed attestation aggregation 62 | if [ "${ENABLE_DIST_ATTESTATION_AGGR}" = "true" ]; then 63 | __att_aggr="--distributed" 64 | else 65 | __att_aggr="" 66 | fi 67 | 68 | if [ "${DEFAULT_GRAFFITI}" = "true" ]; then 69 | # Word splitting is desired for the command line parameters 70 | # shellcheck disable=SC2086 71 | exec "$@" ${__network} ${__w3s_url} ${__mev_boost} ${__doppel} ${__att_aggr} ${VC_EXTRAS} 72 | else 73 | # Word splitting is desired for the command line parameters 74 | # shellcheck disable=SC2086 75 | exec "$@" ${__network} "--graffiti" "${GRAFFITI}" ${__w3s_url} ${__mev_boost} ${__doppel} ${__att_aggr} ${VC_EXTRAS} 76 | fi 77 | -------------------------------------------------------------------------------- /reth/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=ghcr.io/paradigmxyz/reth 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused, this is here to avoid build time complaints 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=reth 11 | ARG UID=10001 12 | 13 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 14 | ca-certificates \ 15 | tzdata \ 16 | gosu \ 17 | git \ 18 | git-lfs \ 19 | wget \ 20 | && apt-get clean \ 21 | && rm -rf /var/lib/apt/lists/* 22 | 23 | # See https://stackoverflow.com/a/55757473/12429735RUN 24 | RUN adduser \ 25 | --disabled-password \ 26 | --gecos "" \ 27 | --shell "/sbin/nologin" \ 28 | --uid "${UID}" \ 29 | "${USER}" 30 | 31 | RUN mkdir -p /var/lib/reth/ee-secret && chown -R ${USER}:${USER} /var/lib/reth && chmod -R 700 /var/lib/reth && chmod 777 /var/lib/reth/ee-secret 32 | 33 | # Cannot assume buildkit, hence no chmod 34 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 35 | # Belt and suspenders 36 | RUN chmod -R 755 /usr/local/bin/* 37 | 38 | USER ${USER} 39 | 40 | ENTRYPOINT ["reth", "node"] 41 | -------------------------------------------------------------------------------- /reth/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build reth in a stock rust container 2 | FROM rust:bookworm AS builder 3 | 4 | # Unused, this is here to avoid build time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get install -y libclang-dev 12 | 13 | WORKDIR /src 14 | RUN bash -c "git clone --recurse-submodules -j8 ${SRC_REPO} reth && cd reth \ 15 | && git config advice.detachedHead false && git fetch --all --tags \ 16 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:reth-pr; git checkout reth-pr; else git checkout ${BUILD_TARGET}; fi \ 17 | && RUSTFLAGS='-C target-cpu=native' cargo build --profile maxperf --features jemalloc" 18 | 19 | # Pull all binaries into a second stage deploy debian container 20 | FROM debian:bookworm-slim 21 | 22 | ARG USER=reth 23 | ARG UID=10001 24 | 25 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 26 | ca-certificates \ 27 | tzdata \ 28 | gosu \ 29 | git \ 30 | git-lfs \ 31 | wget \ 32 | && apt-get clean \ 33 | && rm -rf /var/lib/apt/lists/* 34 | 35 | # See https://stackoverflow.com/a/55757473/12429735RUN 36 | RUN adduser \ 37 | --disabled-password \ 38 | --gecos "" \ 39 | --shell "/sbin/nologin" \ 40 | --uid "${UID}" \ 41 | "${USER}" 42 | 43 | RUN mkdir -p /var/lib/reth/ee-secret && chown -R ${USER}:${USER} /var/lib/reth && chmod -R 700 /var/lib/reth && chmod 777 /var/lib/reth/ee-secret 44 | 45 | # Cannot assume buildkit, hence no chmod 46 | COPY --from=builder --chown=${USER}:${USER} /src/reth/target/maxperf/reth /usr/local/bin/ 47 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 48 | # Belt and suspenders 49 | RUN chmod -R 755 /usr/local/bin/* 50 | 51 | USER ${USER} 52 | 53 | ENTRYPOINT ["reth", "node"] 54 | -------------------------------------------------------------------------------- /siren-shared.yml: -------------------------------------------------------------------------------- 1 | # To be used in conjunction with siren.yml 2 | services: 3 | siren: 4 | ports: 5 | - ${SHARE_IP:-}:${SIREN_PORT}:443/tcp 6 | -------------------------------------------------------------------------------- /siren.yml: -------------------------------------------------------------------------------- 1 | # Sigma Prime Siren, for use with Lighthouse 2 | x-logging: &logging 3 | logging: 4 | driver: json-file 5 | options: 6 | max-size: 100m 7 | max-file: "3" 8 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 9 | 10 | services: 11 | siren: 12 | restart: "unless-stopped" 13 | image: ${SIREN_DOCKER_REPO}:${SIREN_DOCKER_TAG} 14 | volumes: 15 | - lhvalidator-data:/var/lib/lighthouse 16 | - ./siren/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh 17 | - /etc/localtime:/etc/localtime:ro 18 | environment: 19 | - BEACON_URL=${CL_NODE} 20 | - VALIDATOR_URL=http://vc:7500 21 | - SESSION_PASSWORD=${SIREN_PASSWORD} 22 | - SSL_ENABLED=true 23 | - DEBUG=false 24 | - SIREN_PORT=${SIREN_PORT} 25 | - NODE_OPTIONS="--dns-result-order=ipv4first" 26 | <<: *logging 27 | entrypoint: 28 | - docker-entrypoint.sh 29 | labels: 30 | - traefik.enable=true 31 | - traefik.http.routers.$(SIREN_HOST:-siren}.service=${SIREN_HOST:-siren} 32 | - traefik.http.routers.${SIREN_HOST:-siren}.entrypoints=websecure 33 | - traefik.http.routers.${SIREN_HOST:-siren}.rule=Host(`${SIREN_HOST:-siren}.${DOMAIN}`) 34 | - traefik.http.routers.${SIREN_HOST:-siren}.tls.certresolver=letsencrypt 35 | - traefik.http.services.${SIREN_HOST:-siren}.loadbalancer.server.port=80 36 | -------------------------------------------------------------------------------- /siren/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | if [ ! -f /var/lib/lighthouse/validators/api-token.txt ]; then 5 | echo "Validator client API token not found. Waiting 30s before restarting." 6 | sleep 30 7 | exit 1 8 | fi 9 | 10 | API_TOKEN=$(cat /var/lib/lighthouse/validators/api-token.txt) 11 | export API_TOKEN 12 | 13 | # In case there are multiple consensus nodes, use the first one 14 | export BEACON_URL=${BEACON_URL%%,*} 15 | 16 | echo "Log into Siren at https://my-node-ip/${SIREN_PORT} with password ${SESSION_PASSWORD}" 17 | exec /app/docker-assets/docker-entrypoint.sh 18 | -------------------------------------------------------------------------------- /ssv-config/config-sample.yaml: -------------------------------------------------------------------------------- 1 | ssv: 2 | Network: hoodi 3 | ValidatorOptions: 4 | BuilderProposals: true 5 | KeyStore: 6 | PrivateKeyFile: /config/encrypted_private_key.json 7 | PasswordFile: /config/password.pass 8 | p2p: 9 | DiscoveryType: discv5 10 | TcpPort: 13001 11 | UdpPort: 12001 12 | db: 13 | Path: /tmp/ssv/db 14 | Type: badger-db 15 | eth2: 16 | BeaconNodeAddr: http://consensus:5052 17 | eth1: 18 | ETH1Addr: ws://execution:8546 19 | MetricsAPIPort: 15000 20 | SSVAPIPort: 16000 21 | global: 22 | LogFormat: json 23 | LogLevelFormat: lowercase 24 | LogLevel: info 25 | LogFilePath: /tmp/ssv/debug.log 26 | -------------------------------------------------------------------------------- /ssv-config/dkg-config-sample.yaml: -------------------------------------------------------------------------------- 1 | privKey: ./config/encrypted_private_key.json 2 | privKeyPassword: ./config/password.pass 3 | operatorID: 4 | port: 3030 5 | logLevel: info 6 | logFormat: json 7 | logLevelFormat: capitalColor 8 | logFilePath: ./output/debug.log 9 | outputPath: ./output 10 | ethEndpointURL: http://execution:8545 11 | -------------------------------------------------------------------------------- /ssv-dkg.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | curl-jq: 11 | image: curl-jq:local 12 | pull_policy: never 13 | build: 14 | context: ./traefik 15 | dockerfile: Dockerfile.jq 16 | restart: "no" 17 | profiles: [ "tools" ] 18 | 19 | ssv-dkg: 20 | restart: "unless-stopped" 21 | image: ${SSV_DKG_REPO:-ssvlabs/ssv-dkg}:${SSV_DKG_TAG:-latest} 22 | volumes: 23 | - ./ssv-config:/ssv-dkg/config 24 | - ssv-dkg-tls:/ssv-dkg/data/ssl 25 | - .eth/dkg_output:/ssv-dkg/output 26 | - /etc/localtime:/etc/localtime:ro 27 | ports: 28 | - ${HOST_IP:-}:${SSV_DKG_PORT}:${SSV_DKG_PORT}/tcp 29 | <<: *logging 30 | command: > 31 | start-operator 32 | --configPath 33 | ./config/dkg-config.yaml 34 | --port 35 | ${SSV_DKG_PORT} 36 | 37 | volumes: 38 | ssv-dkg-tls: 39 | 40 | networks: 41 | default: 42 | enable_ipv6: ${IPV6:-false} 43 | -------------------------------------------------------------------------------- /ssv-pulse.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | ssv-pulse: 11 | image: ghcr.io/ssvlabs/ssv-pulse:latest 12 | pull_policy: always 13 | restart: no 14 | command: 15 | - 'benchmark' 16 | - '--consensus-addr=${CL_NODE}' 17 | - '--execution-addr=${EL_RPC_NODE}' 18 | - '--ssv-addr=http://ssv-node:16000' # Change to your SSV Node's address with SSVAPIPort 19 | - '--duration=60m' 20 | - '--network=${NETWORK}' 21 | # - '--platform linux/arm64' # Add this if you run on an arm64 machine 22 | 23 | networks: 24 | default: 25 | enable_ipv6: ${IPV6:-false} 26 | -------------------------------------------------------------------------------- /ssv.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | ssv-node: 11 | restart: "unless-stopped" 12 | image: ${SSV_NODE_REPO:-ssvlabs/ssv-node}:${SSV_NODE_TAG:-latest} 13 | user: 12000:12000 14 | volumes: 15 | - ./ssv-config:/config 16 | - ssv-data:/tmp 17 | - /etc/localtime:/etc/localtime:ro 18 | ports: 19 | - ${HOST_IP:-}:${SSV_P2P_PORT}:${SSV_P2P_PORT}/tcp 20 | - ${HOST_IP:-}:${SSV_P2P_PORT_UDP}:${SSV_P2P_PORT_UDP}/udp 21 | <<: *logging 22 | environment: 23 | - CONFIG_PATH=/config/config.yaml 24 | - HOME=/tmp 25 | - ENABLE_DOPPELGANGER_PROTECTION=${DOPPELGANGER:-false} 26 | command: make BUILD_PATH=/go/bin/ssvnode start-node 27 | labels: 28 | - metrics.scrape=true 29 | - metrics.path=/metrics 30 | - metrics.port=15000 31 | - metrics.instance=ssv-node 32 | - metrics.network=${NETWORK} 33 | 34 | volumes: 35 | ssv-data: 36 | 37 | networks: 38 | default: 39 | enable_ipv6: ${IPV6:-false} 40 | -------------------------------------------------------------------------------- /teku/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=consensys/teku 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | #Next two are unused but included to avoid warnings 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=teku 11 | ARG UID=10002 12 | 13 | USER root 14 | 15 | RUN groupmod -g "${UID}" ${USER} && usermod -u "${UID}" -g "${UID}" ${USER} 16 | 17 | RUN set -eux; \ 18 | apt-get update; \ 19 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git git-lfs libjemalloc-dev; \ 20 | rm -rf /var/lib/apt/lists/*; \ 21 | # verify that the binary works 22 | gosu nobody true 23 | 24 | # Create data mount point with permissions 25 | RUN mkdir -p /var/lib/teku/validator-keys && mkdir -p /var/lib/teku/validator-passwords && mkdir -p /var/lib/teku/ee-secret && chown -R ${USER}:${USER} /var/lib/teku && chmod -R 700 /var/lib/teku && chmod 777 /var/lib/teku/ee-secret 26 | # Cannot assume buildkit, hence no chmod 27 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 28 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 29 | # Belt and suspenders 30 | RUN chmod -R 755 /usr/local/bin/* 31 | 32 | USER ${USER} 33 | 34 | ENTRYPOINT ["/opt/teku/bin/teku"] 35 | -------------------------------------------------------------------------------- /teku/Dockerfile.source: -------------------------------------------------------------------------------- 1 | # Build Teku in a stock Ubuntu container 2 | FROM eclipse-temurin:21-jdk-noble AS builder 3 | 4 | # This is here to avoid build-time complaints 5 | ARG DOCKER_TAG 6 | ARG DOCKER_REPO 7 | 8 | ARG BUILD_TARGET 9 | ARG SRC_REPO 10 | 11 | RUN apt-get update && apt-get install -y ca-certificates git 12 | 13 | WORKDIR /usr/src 14 | RUN bash -c "git clone ${SRC_REPO} teku \ 15 | && cd teku \ 16 | && git config advice.detachedHead false \ 17 | && git fetch --all --tags \ 18 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:teku-pr; git checkout teku-pr; \ 19 | else git checkout ${BUILD_TARGET}; fi \ 20 | && git submodule update --init --recursive \ 21 | && ./gradlew installDist" 22 | 23 | # Pull all binaries into a second stage deploy Ubuntu container 24 | FROM eclipse-temurin:21-jre-noble 25 | 26 | ARG USER=teku 27 | ARG UID=10002 28 | 29 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y --no-install-recommends \ 30 | ca-certificates \ 31 | tzdata \ 32 | git \ 33 | git-lfs \ 34 | adduser \ 35 | libjemalloc-dev \ 36 | && apt-get clean \ 37 | && rm -rf /var/lib/apt/lists/* 38 | 39 | RUN set -eux; \ 40 | apt-get update; \ 41 | apt-get install -y gosu; \ 42 | rm -rf /var/lib/apt/lists/*; \ 43 | # verify that the binary works 44 | gosu nobody true 45 | 46 | # See https://stackoverflow.com/a/55757473/12429735RUN 47 | RUN adduser \ 48 | --disabled-password \ 49 | --gecos "" \ 50 | --home "/nonexistent" \ 51 | --shell "/usr/sbin/nologin" \ 52 | --no-create-home \ 53 | --uid "${UID}" \ 54 | "${USER}" 55 | 56 | RUN mkdir -p /var/lib/teku/validator-keys && mkdir -p /var/lib/teku/validator-passwords && mkdir -p /var/lib/teku/ee-secret && chown -R ${USER}:${USER} /var/lib/teku && chmod -R 700 /var/lib/teku && chmod 777 /var/lib/teku/ee-secret 57 | 58 | # Cannot assume buildkit, hence no chmod 59 | COPY --from=builder --chown=${USER}:${USER} /usr/src/teku/build/install/teku/. /opt/teku/ 60 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 61 | COPY --chown=${USER}:${USER} ./docker-entrypoint-vc.sh /usr/local/bin/ 62 | # Belt and suspenders 63 | RUN chmod -R 755 /usr/local/bin/* 64 | 65 | USER ${USER} 66 | 67 | ENTRYPOINT ["/opt/teku/bin/teku"] 68 | -------------------------------------------------------------------------------- /traefik-aws.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | traefik: 11 | build: 12 | context: ./traefik 13 | args: 14 | - DOCKER_TAG=${TRAEFIK_TAG} 15 | image: traefik-aws 16 | pull_policy: never 17 | restart: "unless-stopped" 18 | command: 19 | # - --accesslog=true 20 | # - --accesslog.format=json 21 | # - --accesslog.fields.defaultmode=keep 22 | # - --accesslog.fields.headers.defaultmode=keep 23 | # - --certificatesResolvers.letsencrypt.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory 24 | - --log.level=${LOG_LEVEL:-info} 25 | - --providers.docker=true 26 | - --providers.docker.exposedbydefault=false 27 | - --certificatesresolvers.letsencrypt.acme.dnschallenge=true 28 | - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=route53 29 | - --certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL} 30 | - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json 31 | - --entrypoints.web.address=:${TRAEFIK_WEB_HTTP_PORT} 32 | - --entrypoints.web.http.redirections.entrypoint.to=websecure 33 | - --entrypoints.web.http.redirections.entrypoint.scheme=https 34 | - --entrypoints.websecure.address=:${TRAEFIK_WEB_PORT} 35 | - --metrics 36 | - --metrics.prometheus 37 | - --global.sendAnonymousUsage 38 | ports: 39 | - ${HOST_IP:-}:${TRAEFIK_WEB_PORT}:${TRAEFIK_WEB_PORT}/tcp 40 | - ${HOST_IP:-}:${TRAEFIK_WEB_HTTP_PORT}:${TRAEFIK_WEB_HTTP_PORT}/tcp 41 | environment: 42 | - AWS_PROFILE=${AWS_PROFILE} 43 | - AWS_HOSTED_ZONE_ID=${AWS_HOSTED_ZONE_ID} 44 | volumes: 45 | - /var/run/docker.sock:/var/run/docker.sock:ro 46 | - certs:/letsencrypt 47 | - ~/.aws:/root/.aws:ro 48 | - /etc/localtime:/etc/localtime:ro 49 | labels: 50 | - metrics.scrape=true 51 | - metrics.path=/metrics 52 | - metrics.port=8080 53 | - metrics.instance=traefik 54 | - metrics.network=${NETWORK} 55 | <<: *logging 56 | 57 | volumes: 58 | certs: 59 | 60 | networks: 61 | default: 62 | enable_ipv6: ${IPV6:-false} 63 | -------------------------------------------------------------------------------- /traefik-cf.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | traefik: 11 | image: traefik:${TRAEFIK_TAG} 12 | restart: "unless-stopped" 13 | command: 14 | # - --accesslog=true 15 | # - --accesslog.format=json 16 | # - --accesslog.fields.defaultmode=keep 17 | # - --accesslog.fields.headers.defaultmode=keep 18 | # - --certificatesResolvers.letsencrypt.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory 19 | - --log.level=${LOG_LEVEL:-info} 20 | - --providers.docker=true 21 | - --providers.docker.exposedbydefault=false 22 | - --certificatesresolvers.letsencrypt.acme.dnschallenge=true 23 | - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare 24 | - --certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL} 25 | - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json 26 | - --entrypoints.web.address=:${TRAEFIK_WEB_HTTP_PORT} 27 | - --entrypoints.web.http.redirections.entrypoint.to=websecure 28 | - --entrypoints.web.http.redirections.entrypoint.scheme=https 29 | - --entrypoints.websecure.address=:${TRAEFIK_WEB_PORT} 30 | - --metrics 31 | - --metrics.prometheus 32 | - --global.sendAnonymousUsage 33 | ports: 34 | - ${HOST_IP:-}:${TRAEFIK_WEB_PORT}:${TRAEFIK_WEB_PORT}/tcp 35 | - ${HOST_IP:-}:${TRAEFIK_WEB_HTTP_PORT}:${TRAEFIK_WEB_HTTP_PORT}/tcp 36 | environment: 37 | - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} 38 | - CF_ZONE_API_TOKEN=${CF_ZONE_API_TOKEN:-} 39 | volumes: 40 | - /var/run/docker.sock:/var/run/docker.sock:ro 41 | - certs:/letsencrypt 42 | - /etc/localtime:/etc/localtime:ro 43 | labels: 44 | - metrics.scrape=true 45 | - metrics.path=/metrics 46 | - metrics.port=8080 47 | - metrics.instance=traefik 48 | - metrics.network=${NETWORK} 49 | <<: *logging 50 | 51 | cf-ddns: 52 | image: qmcgaw/ddns-updater:${DDNS_TAG} 53 | restart: "unless-stopped" 54 | environment: 55 | - LOG_LEVEL=${LOG_LEVEL:-info} 56 | - 'CONFIG={"settings": [{"provider": "cloudflare", "zone_identifier": "${CF_ZONE_ID}", "domain": "${DDNS_SUBDOMAIN}.${DOMAIN}", "ttl": 1, "token": "${CF_DNS_API_TOKEN}", "proxied": ${DDNS_PROXY}, "ip_version": "ipv4"},{"provider": "cloudflare", "zone_identifier": "${CF_ZONE_ID}", "domain": "${DDNS_SUBDOMAIN}.${DOMAIN}", "ttl": 1, "token": "${CF_DNS_API_TOKEN}", "proxied": ${DDNS_PROXY}, "ip_version": "ipv6"}]}' 57 | volumes: 58 | - /etc/localtime:/etc/localtime:ro 59 | <<: *logging 60 | 61 | curl-jq: 62 | image: curl-jq:local 63 | pull_policy: never 64 | build: 65 | context: ./traefik 66 | dockerfile: Dockerfile.jq 67 | restart: "no" 68 | profiles: ["tools"] 69 | 70 | volumes: 71 | certs: 72 | 73 | networks: 74 | default: 75 | enable_ipv6: ${IPV6:-false} 76 | -------------------------------------------------------------------------------- /traefik/Dockerfile: -------------------------------------------------------------------------------- 1 | # Add AWS CLI to traefik image 2 | ARG DOCKER_TAG=latest 3 | 4 | FROM traefik:${DOCKER_TAG} 5 | 6 | RUN apk add --no-cache \ 7 | python3 \ 8 | py3-pip \ 9 | && pip3 install --upgrade pip \ 10 | && pip3 install \ 11 | awscli \ 12 | tzdata \ 13 | && rm -rf /var/cache/apk/* 14 | -------------------------------------------------------------------------------- /traefik/Dockerfile.jq: -------------------------------------------------------------------------------- 1 | FROM debian:bookworm-slim 2 | 3 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl jq gosu 4 | -------------------------------------------------------------------------------- /vc-utils/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bookworm-slim 2 | 3 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl jq gosu 4 | COPY --chown=1000:1000 ./keymanager.sh /usr/local/bin/ 5 | # Belt and suspenders 6 | RUN chmod -R 755 /usr/local/bin/* 7 | -------------------------------------------------------------------------------- /vero-vc-only.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | x-build: &vero-build 10 | context: ./vero 11 | dockerfile: ${VERO_DOCKERFILE} 12 | args: 13 | - BUILD_TARGET=${VERO_SRC_BUILD_TARGET:-'$(git describe --tags $(git rev-list --tags --max-count=1))'} 14 | - SRC_REPO=${VERO_SRC_REPO:-https://github.com/serenita-org/vero} 15 | - DOCKER_TAG=${VERO_DOCKER_TAG:-latest} 16 | - DOCKER_REPO=${VERO_DOCKER_REPO:-ghcr.io/serenita-org/vero} 17 | 18 | services: 19 | validator: 20 | restart: "unless-stopped" 21 | build: 22 | <<: *vero-build 23 | image: vero:local 24 | pull_policy: never 25 | user: vero 26 | stop_grace_period: 1m 27 | environment: 28 | - MEV_BOOST=${MEV_BOOST} 29 | - VC_EXTRAS=${VC_EXTRAS:-} 30 | - GRAFFITI=${GRAFFITI:-} 31 | - DEFAULT_GRAFFITI=${DEFAULT_GRAFFITI:-false} 32 | - WEB3SIGNER=${WEB3SIGNER} 33 | - W3S_NODE=${W3S_NODE} 34 | - NETWORK=${NETWORK} 35 | - CL_NODE=${CL_NODE} 36 | - LOG_LEVEL=${LOG_LEVEL} 37 | volumes: 38 | - vero-data:/var/lib/vero 39 | - /etc/localtime:/etc/localtime:ro 40 | networks: 41 | default: 42 | aliases: 43 | - ${VC_ALIAS:-vc} 44 | <<: *logging 45 | entrypoint: 46 | - docker-entrypoint.sh 47 | - python 48 | - main.py 49 | - --beacon-node-urls 50 | - ${CL_NODE} 51 | - --data-dir 52 | - /var/lib/vero 53 | - --metrics-port 54 | - "8009" 55 | - --metrics-address 56 | - 0.0.0.0 57 | - --fee-recipient 58 | - ${FEE_RECIPIENT} 59 | - --enable-keymanager-api 60 | - --keymanager-api-address 61 | - 0.0.0.0 62 | - --keymanager-api-port 63 | - ${KEY_API_PORT:-7500} 64 | labels: 65 | - metrics.scrape=true 66 | - metrics.path=/metrics 67 | - metrics.port=8009 68 | - metrics.instance=validator 69 | - metrics.network=${NETWORK} 70 | 71 | validator-keys: 72 | profiles: ["tools"] 73 | restart: "no" 74 | build: 75 | context: ./vc-utils 76 | image: vc-utils:local 77 | pull_policy: never 78 | user: root 79 | volumes: 80 | - vero-data:/var/lib/vero 81 | - ./.eth/validator_keys:/validator_keys 82 | - ./.eth/exit_messages:/exit_messages 83 | - /etc/localtime:/etc/localtime:ro 84 | environment: 85 | - KEYSTORE_PASSWORD=${KEYSTORE_PASSWORD:-} 86 | - KEY_API_PORT=${KEY_API_PORT:-7500} 87 | - WEB3SIGNER=${WEB3SIGNER:-false} 88 | - W3S_NODE=${W3S_NODE} 89 | - CL_NODE=${CL_NODE} 90 | depends_on: 91 | - validator 92 | entrypoint: 93 | - keymanager.sh 94 | - /var/lib/vero/keymanager-api-token.txt 95 | - ${VC_ALIAS:-vc} 96 | 97 | volumes: 98 | vero-data: 99 | 100 | networks: 101 | default: 102 | enable_ipv6: ${IPV6:-false} 103 | -------------------------------------------------------------------------------- /vero/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=ghcr.io/serenita-org/vero 3 | 4 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 5 | 6 | # Unused but included to avoid warnings 7 | ARG BUILD_TARGET 8 | ARG SRC_REPO 9 | 10 | ARG USER=vero 11 | ARG UID=10000 12 | 13 | USER root 14 | 15 | RUN groupmod -g "${UID}" vero && usermod -u "${UID}" -g "${UID}" vero 16 | 17 | RUN set -eux; \ 18 | apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git wget curl; \ 19 | rm -rf /var/lib/apt/lists/*; \ 20 | # verify that the binary works 21 | gosu nobody true 22 | 23 | # Create data mount point with permissions 24 | RUN mkdir -p /var/lib/vero && chown -R ${USER}:${USER} /var/lib/vero && chmod -R 700 /var/lib/vero 25 | RUN chown -R ${USER}:${USER} /tmp/multiprocessing 26 | 27 | # Cannot assume buildkit, hence no chmod 28 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 29 | # Belt and suspenders 30 | RUN chmod -R 755 /usr/local/bin/* 31 | 32 | USER ${USER} 33 | WORKDIR /vero 34 | 35 | ENTRYPOINT ["python", "main.py"] 36 | -------------------------------------------------------------------------------- /vero/Dockerfile.real: -------------------------------------------------------------------------------- 1 | ARG VENV_LOCATION="/opt/venv" 2 | 3 | # Build image 4 | FROM python:3.13-bookworm AS builder 5 | 6 | # Unused but included to avoid warnings 7 | ARG DOCKER_TAG 8 | ARG DOCKER_REPO 9 | 10 | ARG BUILD_TARGET=master 11 | ARG SRC_REPO=https://github.com/serenita-org/vero 12 | 13 | ARG VENV_LOCATION 14 | 15 | WORKDIR /build 16 | 17 | RUN apt-get update && apt-get install --no-install-recommends -y bash git && \ 18 | apt-get clean && rm -rf /var/lib/apt/lists/* 19 | 20 | ENV PATH="$VENV_LOCATION/bin:$PATH" 21 | RUN pip install --no-cache-dir uv && uv venv ${VENV_LOCATION} 22 | RUN bash -c "git clone ${SRC_REPO} vero && cd vero && git config advice.detachedHead false && git fetch --all --tags \ 23 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:vero-pr; git checkout vero-pr; else git checkout ${BUILD_TARGET}; fi \ 24 | && uv pip sync --prefix ${VENV_LOCATION} requirements.txt" 25 | 26 | # App image 27 | FROM python:3.13-bookworm 28 | 29 | ARG VENV_LOCATION 30 | COPY --from=builder $VENV_LOCATION $VENV_LOCATION 31 | ENV PATH="$VENV_LOCATION/bin:$PATH" 32 | 33 | RUN groupadd -g 10000 vero && \ 34 | useradd --no-create-home --shell /bin/false -u 10000 -g vero vero 35 | 36 | RUN set -eux; \ 37 | apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git wget; \ 38 | rm -rf /var/lib/apt/lists/*; \ 39 | # verify that the binary works 40 | gosu nobody true 41 | 42 | RUN mkdir -p /vero && chown -R vero:vero /vero 43 | WORKDIR /vero 44 | 45 | # Create directory for prometheus in multiprocess mode 46 | RUN mkdir /tmp/multiprocessing && chown -R vero:vero /tmp/multiprocessing 47 | ENV PROMETHEUS_MULTIPROC_DIR=/tmp/multiprocessing 48 | 49 | COPY --from=builder /build/vero/src . 50 | 51 | USER vero 52 | 53 | ENTRYPOINT ["python", "main.py"] 54 | -------------------------------------------------------------------------------- /vero/Dockerfile.source: -------------------------------------------------------------------------------- 1 | ARG VENV_LOCATION="/opt/venv" 2 | 3 | # Build image 4 | FROM python:3.13-bookworm AS builder 5 | 6 | # Unused but included to avoid warnings 7 | ARG DOCKER_TAG 8 | ARG DOCKER_REPO 9 | 10 | ARG BUILD_TARGET=master 11 | ARG SRC_REPO=https://github.com/serenita-org/vero 12 | 13 | ARG VENV_LOCATION 14 | 15 | WORKDIR /build 16 | 17 | RUN apt-get update && apt-get install --no-install-recommends -y bash git && \ 18 | apt-get clean && rm -rf /var/lib/apt/lists/* 19 | 20 | ENV PATH="$VENV_LOCATION/bin:$PATH" 21 | RUN pip install --no-cache-dir uv && uv venv ${VENV_LOCATION} 22 | RUN bash -c "git clone ${SRC_REPO} vero && cd vero && git config advice.detachedHead false && git fetch --all --tags \ 23 | && if [[ ${BUILD_TARGET} =~ pr-.+ ]]; then git fetch origin pull/$(echo ${BUILD_TARGET} | cut -d '-' -f 2)/head:vero-pr; git checkout vero-pr; else git checkout ${BUILD_TARGET}; fi \ 24 | && uv pip sync --prefix ${VENV_LOCATION} requirements.txt" 25 | 26 | # App image 27 | FROM python:3.13-bookworm 28 | 29 | ARG USER=vero 30 | ARG UID=10000 31 | 32 | ARG VENV_LOCATION 33 | COPY --from=builder $VENV_LOCATION $VENV_LOCATION 34 | ENV PATH="$VENV_LOCATION/bin:$PATH" 35 | 36 | RUN groupadd -g ${UID} ${USER} && \ 37 | useradd --no-create-home --shell /bin/false -u ${UID} -g ${USER} ${USER} 38 | 39 | RUN set -eux; \ 40 | apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git wget curl; \ 41 | rm -rf /var/lib/apt/lists/*; \ 42 | # verify that the binary works 43 | gosu nobody true 44 | 45 | RUN mkdir -p /vero && chown -R ${USER}:${USER} /vero 46 | WORKDIR /vero 47 | 48 | # Create directory for prometheus in multiprocess mode 49 | RUN mkdir /tmp/multiprocessing && chown -R ${USER}:${USER} /tmp/multiprocessing 50 | ENV PROMETHEUS_MULTIPROC_DIR=/tmp/multiprocessing 51 | 52 | COPY --chown=${USER}:${USER} --from=builder /build/vero/src . 53 | 54 | # Create data mount point with permissions 55 | RUN mkdir -p /var/lib/vero && chown -R ${USER}:${USER} /var/lib/vero && chmod -R 700 /var/lib/vero 56 | 57 | # Cannot assume buildkit, hence no chmod 58 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 59 | # Belt and suspenders 60 | RUN chmod -R 755 /usr/local/bin/* 61 | 62 | USER ${USER} 63 | 64 | ENTRYPOINT ["python", "main.py"] 65 | -------------------------------------------------------------------------------- /web3signer.yml: -------------------------------------------------------------------------------- 1 | x-logging: &logging 2 | logging: 3 | driver: json-file 4 | options: 5 | max-size: 100m 6 | max-file: "3" 7 | tag: '{{.ImageName}}|{{.Name}}|{{.ImageFullID}}|{{.FullID}}' 8 | 9 | services: 10 | web3signer: 11 | restart: "unless-stopped" 12 | build: 13 | context: ./web3signer 14 | args: 15 | - DOCKER_TAG=${W3S_DOCKER_TAG:-latest} 16 | - DOCKER_REPO=${W3S_DOCKER_REPO:-consensys/web3signer} 17 | dockerfile: Dockerfile.binary 18 | image: web3signer:local 19 | pull_policy: never 20 | user: web3signer 21 | volumes: 22 | - web3signer-keys:/var/lib/web3signer 23 | - /etc/localtime:/etc/localtime:ro 24 | environment: 25 | - JAVA_OPTS=${W3S_HEAP:--Xmx6g} 26 | - NETWORK=${NETWORK} 27 | - PG_ALIAS=${PG_ALIAS:-${NETWORK}-postgres} 28 | networks: 29 | default: 30 | aliases: 31 | - ${W3S_ALIAS:-${NETWORK}-web3signer} # This allows multiple Eth Docker stacks all connected to the same bridge network 32 | depends_on: 33 | postgres: 34 | condition: service_healthy 35 | <<: *logging 36 | entrypoint: 37 | - docker-entrypoint.sh 38 | - /opt/web3signer/bin/web3signer 39 | - --key-store-path=/var/lib/web3signer/keys 40 | - --metrics-enabled 41 | - --metrics-host-allowlist=* 42 | - --http-host-allowlist=* 43 | - --logging=${LOG_LEVEL:-info} 44 | - eth2 45 | - --enable-key-manager-api=true 46 | - --slashing-protection-db-url=jdbc:postgresql://${PG_ALIAS:-${NETWORK}-postgres}/web3signer 47 | - --slashing-protection-db-username=postgres 48 | - --slashing-protection-db-password=postgres 49 | - --slashing-protection-pruning-enabled=true 50 | labels: 51 | - metrics.scrape=true 52 | - metrics.path=/metrics 53 | - metrics.port=9001 54 | - metrics.instance=web3signer 55 | - metrics.network=${NETWORK} 56 | 57 | postgres: 58 | restart: "unless-stopped" 59 | image: "postgres:${PG_DOCKER_TAG}" 60 | environment: 61 | - POSTGRES_USER=postgres 62 | - POSTGRES_PASSWORD=postgres 63 | - POSTGRES_DB=web3signer 64 | healthcheck: 65 | test: ["CMD-SHELL", "pg_isready -U postgres"] 66 | start_period: 5s 67 | interval: 10s 68 | timeout: 5s 69 | volumes: 70 | - web3signer-slashing-data:/var/lib/postgresql/data/ 71 | networks: 72 | default: 73 | aliases: 74 | - ${PG_ALIAS:-${NETWORK}-postgres} # This allows multiple Eth Docker stacks all connected to the same bridge network 75 | 76 | volumes: 77 | web3signer-keys: 78 | web3signer-slashing-data: 79 | -------------------------------------------------------------------------------- /web3signer/Dockerfile.binary: -------------------------------------------------------------------------------- 1 | ARG DOCKER_TAG=latest 2 | ARG DOCKER_REPO=consensys/web3signer 3 | 4 | FROM flyway/flyway:latest AS flyway 5 | 6 | FROM ${DOCKER_REPO}:${DOCKER_TAG} 7 | 8 | ARG USER=web3signer 9 | ARG UID=10000 10 | 11 | USER root 12 | 13 | RUN groupmod -g "${UID}" ${USER} && usermod -u "${UID}" -g "${UID}" ${USER} 14 | 15 | RUN set -eux; \ 16 | apt-get update; \ 17 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y gosu ca-certificates tzdata git git-lfs; \ 18 | rm -rf /var/lib/apt/lists/*; \ 19 | # verify that the binary works 20 | gosu nobody true 21 | 22 | # Create data mount point with permissions 23 | RUN mkdir -p /var/lib/web3signer/keys && chown -R ${USER}:${USER} /var/lib/web3signer && chmod -R 700 /var/lib/web3signer 24 | # Cannot assume buildkit, hence no chmod 25 | COPY --chown=${USER}:${USER} ./docker-entrypoint.sh /usr/local/bin/ 26 | # Belt and suspenders 27 | RUN chmod -R 755 /usr/local/bin/* 28 | 29 | # Flyway for initial migrations 30 | 31 | COPY --from=flyway --chown=${USER}:${USER} /flyway /flyway 32 | 33 | USER ${USER} 34 | 35 | ENTRYPOINT ["/opt/web3signer/bin/web3signer"] 36 | -------------------------------------------------------------------------------- /web3signer/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | if [ "$(id -u)" = '0' ]; then 5 | chown -R web3signer /var/lib/web3signer 6 | exec gosu web3signer docker-entrypoint.sh "$@" 7 | fi 8 | 9 | if [[ "${NETWORK}" =~ ^https?:// ]]; then 10 | echo "Custom testnet at ${NETWORK}" 11 | repo=$(awk -F'/tree/' '{print $1}' <<< "${NETWORK}") 12 | branch=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f1) 13 | config_dir=$(awk -F'/tree/' '{print $2}' <<< "${NETWORK}" | cut -d'/' -f2-) 14 | echo "This appears to be the ${repo} repo, branch ${branch} and config directory ${config_dir}." 15 | # For want of something more amazing, let's just fail if git fails to pull this 16 | set -e 17 | if [ ! -d "/var/lib/web3signer/testnet/${config_dir}" ]; then 18 | mkdir -p /var/lib/web3signer/testnet 19 | cd /var/lib/web3signer/testnet 20 | git init --initial-branch="${branch}" 21 | git remote add origin "${repo}" 22 | git config core.sparseCheckout true 23 | echo "${config_dir}" > .git/info/sparse-checkout 24 | git pull origin "${branch}" 25 | fi 26 | set +e 27 | __network="--network=/var/lib/web3signer/testnet/${config_dir}/config.yaml" 28 | else 29 | __network="--network=${NETWORK}" 30 | fi 31 | 32 | if [ -f /var/lib/web3signer/.migration_fatal_error ]; then 33 | echo "An error occurred during slashing protection database migration, that makes it unsafe to start Web3signer." 34 | echo "Until this is manually remedied, Web3signer will refuse to start up." 35 | echo "Aborting." 36 | exit 1 37 | fi 38 | 39 | /flyway/flyway migrate -url="jdbc:postgresql://${PG_ALIAS}/web3signer" -user=postgres -password=postgres -locations=filesystem:/opt/web3signer/migrations/postgresql 40 | 41 | # Word splitting is desired for the command line parameters 42 | # shellcheck disable=SC2086 43 | exec "$@" ${__network} 44 | --------------------------------------------------------------------------------