103 Commits

Author SHA1 Message Date
5d8aaa769d feat!: Expose consensus debug port, restart EN on config file change (#42)
Some checks failed
Release / Release (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Ansible lint (push) Has been cancelled
## What 

Subj

## Why 

QoL

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Documentation comments have been added / updated.
2025-04-25 16:54:26 +02:00
17d9ecd1ce feat: (fake release trigger) Bump default EN to v27.2.0 (#41)
## What 

Subj

## Why 

Due to incorrect repo merge settings it was allowed to merge without
squash so commits went to main without semver prefixes and did not
trigger release

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Documentation comments have been added / updated.
2025-04-25 12:23:39 +02:00
5071bb3423 Merge pull request #39 from matter-labs/update_27.2.0
feat: update default EN version to 27.2.0
2025-04-25 12:05:28 +02:00
fa4f00a62d Merge pull request #40 from matter-labs/consensus-debug-port
feat: Consensus debug config
2025-04-25 12:04:08 +02:00
f3ce6ce204 feat: Consensus debug config 2025-04-25 11:51:05 +02:00
cd5df40065 update EN versio to 27.2.0 2025-04-24 13:08:43 +03:00
4bd3805af1 Merge pull request #38 from matter-labs/docs
Some checks failed
Release / Release (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Ansible lint (push) Has been cancelled
chore(docs): Update link to EN mainnet DB backup
2024-12-16 17:45:26 +07:00
8006ed9328 chore(docs): Update link to EN mainnet backup 2024-12-16 17:38:02 +07:00
c497fc0982 Merge pull request #37 from matter-labs/yorik-patch-1
Some checks failed
Release / Release (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Ansible lint (push) Has been cancelled
feat: Fake PR to force release
2024-12-04 15:49:30 +01:00
57f3fb74e4 feat: Fake PR to force release 2024-12-04 15:47:39 +01:00
aa018348d8 Merge pull request #36 from matter-labs/gprusak-rate-limit
feat(consensus): bumped inbound connections limit
2024-12-04 15:04:28 +01:00
b8e3b89cf5 bumped inbound connections limit 2024-12-03 17:47:46 +01:00
d276d7b290 Merge pull request #35 from matter-labs/backup-user
Some checks failed
Release / Release (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Ansible lint (push) Has been cancelled
feat: Added user with backup permissions only
2024-11-27 15:45:36 +01:00
60333c40da feat: Added user with backup permissions only 2024-11-27 15:24:20 +01:00
2eb2b1f6d4 feat: Added user with backup permissions only 2024-11-27 15:12:12 +01:00
69777ac4e8 feat: Added user with backup permissions only 2024-11-27 15:08:46 +01:00
46e2a6e0e4 feat: Added user with backup permissions only 2024-11-27 14:51:33 +01:00
c5ab63672b Merge pull request #34 from matter-labs/add-more-replication
Some checks failed
Release / Release (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Ansible lint (push) Has been cancelled
feat: Configure replication from postgres collection
2024-11-20 18:04:24 +01:00
22a1d06ef7 fix lint 2024-11-20 17:59:52 +01:00
655b461ba5 add libpq-dev 2024-11-20 17:55:22 +01:00
45feed1069 add psycopg2 2024-11-20 17:51:20 +01:00
5298e9f87d add psycopg2 2024-11-20 17:48:55 +01:00
576f8eb252 change priv to role_attr_flags 2024-11-20 17:44:12 +01:00
b672d803f0 fixed lint 2024-11-20 17:01:52 +01:00
5e8657ac3b fixed lint 2024-11-20 17:00:14 +01:00
4f1b6a37ab fixed lint 2024-11-20 16:59:27 +01:00
9034dc5fd4 feat: Configure replication from postgres collection 2024-11-20 16:42:58 +01:00
dac0b0cc80 feat: Configure replication from postgres collection 2024-11-20 16:37:33 +01:00
10ea272736 Merge pull request #33 from matter-labs/fix-type-postgres_replication_interface
fix: Rename variable postgres_replication_bind_address
2024-11-20 10:41:23 +01:00
3fa5c8622b fix: Rename variable postgres_replication_bind_address 2024-11-20 10:40:16 +01:00
64198202a5 Merge pull request #32 from matter-labs/fix-typo
fix: Fixed typo in validation step for replication
2024-11-20 10:36:36 +01:00
0d1717f38a fix: Fixed typo in validation step for replication 2024-11-20 10:35:18 +01:00
13ef869339 Merge pull request #31 from matter-labs/add-replication-vars
Some checks are pending
Release / Release (push) Waiting to run
feat: Added optional postgres replication
2024-11-19 16:35:45 +01:00
cfbaed74f0 Added replication flags 2024-11-19 16:28:13 +01:00
6f1e025785 Added replication flags 2024-11-19 16:26:57 +01:00
f347a9173e feat: Added optional postgres replication 2024-11-19 16:12:31 +01:00
2bf98e9273 feat: Added optional postgres replication 2024-11-19 16:11:28 +01:00
dde435ca95 Merge pull request #30 from matter-labs/fix-snapshot-conf
feat: Bump default EN version, fix snapshot recovery config
2024-10-02 17:23:55 +02:00
8d085aa960 dedup 2024-10-02 17:21:47 +02:00
b85a7d5c65 feat: Bump default EN version, fix snapshot recovery config 2024-10-02 17:18:15 +02:00
6a3c8cb263 Merge pull request #28 from matter-labs/ya-zkd-1817-upgrade-external-nodes-on-hetzner5
fix: Route all consensus traffic to the docker port.
2024-08-13 13:57:35 +02:00
ed4feb99bc fix: Route all consensus traffic to the docker port. 2024-08-13 13:56:28 +02:00
605525c7ba Merge pull request #27 from matter-labs/ya-zkd-1817-upgrade-external-nodes-on-hetzner4
feat: Add traefik configuration for consensus TCP port, open it in firewall
2024-08-13 13:36:58 +02:00
5bdeb0fcfa feat: Add traefik configuration for consensus TCP port, open it in
firewall
2024-08-13 13:32:10 +02:00
bf186104d4 Merge pull request #26 from matter-labs/ya-zkd-1817-upgrade-external-nodes-on-hetzner3
fix: Correct path and file names for consensus
2024-08-12 17:33:38 +02:00
493e5ceffc fix: Correct path and file names for consensus 2024-08-12 17:31:25 +02:00
7a77daacf3 Merge pull request #25 from matter-labs/ya-zkd-1817-upgrade-external-nodes-on-hetzner2
fix: Correct task names
2024-08-12 17:10:16 +02:00
8290a1cd9b Yaml lint 2024-08-12 15:32:48 +02:00
191ebeced5 fix: Correct task names 2024-08-12 14:55:50 +02:00
0cdbf98bf1 Merge pull request #24 from matter-labs/ya-zkd-1817-upgrade-external-nodes-on-hetzner
feat: Add consensus support
2024-08-12 14:30:47 +02:00
ce94f307e7 Secure file permissions 2024-08-12 14:22:26 +02:00
9a8b0af6c3 feat: Add consensus support 2024-08-12 14:18:32 +02:00
7500e2b2da Merge pull request #23 from cooganb/fix-sepolia-pgs-url
chore: Provides updated URL for sepolia testnet dump access
2024-07-04 15:01:50 +02:00
ace0df965b Provides updated URL for sepolia testnet dump access 2024-07-03 14:01:29 -04:00
e8d79755da Merge pull request #22 from matter-labs/betterdetach
fix: Better handle detached docker command
2024-06-05 14:40:15 +02:00
160f497294 fix: Better handle detached docker command 2024-06-05 18:52:59 +07:00
cdf5deb718 Merge pull request #21 from matter-labs/upgradeto24.6.0
feat: update external node version to 24.6.0
2024-06-05 17:01:49 +07:00
cbf199a152 feat: update external node version to 24.6.0 2024-06-05 16:57:40 +07:00
c8a8c1b76c Merge pull request #19 from matter-labs/update_en_version
feat: update external node version to 24.0.0
2024-05-06 12:43:39 +02:00
7fcf8ab7b6 feat: update external node version 2024-05-06 13:41:45 +03:00
2c04aabc1a Merge pull request #18 from matter-labs/ya-fix-traefik
fix: Change traefik vmagent config to ip
2024-04-19 12:03:58 +02:00
875c50be71 fix: Move traefik to ip 2024-04-19 12:01:55 +02:00
135adfdeb6 Merge pull request #17 from matter-labs/ya-bump
feat: Bump external_node and vmagent versions
2024-04-19 10:51:51 +02:00
0ed6245a1d feat: Bump external_node and vmagent versions 2024-04-19 10:24:43 +02:00
a240fac3ec Merge pull request #16 from matter-labs/fix-testnet-snapshot-bucket
chore(docs): Fix and de-uglify links to EN snapshots
2024-04-18 20:12:47 +07:00
eed88e8b72 chore(docs): Fix and reformat links to snapshots 2024-04-18 15:10:17 +02:00
47edb8a161 Merge pull request #15 from matter-labs/snapshot-docs-fix
chore(docs): Minor fixes
2024-04-17 15:19:25 +02:00
d5c66009cb Merge branch 'main' into snapshot-docs-fix 2024-04-17 15:14:56 +02:00
437b174a25 chore(docs): Minor fixes 2024-04-17 15:11:59 +02:00
842af18f5c Merge pull request #14 from matter-labs/fix-unset-var
fix: Fixed unset variable external_node_raw_docker_tag
2024-04-02 18:23:01 +03:00
7f2102550b fix: Fixed unset variable external_node_raw_docker_tag 2024-04-02 18:21:27 +03:00
a3836b82bf Merge pull request #13 from matter-labs/additional-env-vars-en-container
feat: Ability to pass additional env vars to EN container
2024-04-02 16:15:46 +02:00
eecc3a5037 feat: Ability to pass additional env vars to EN container 2024-04-02 16:11:04 +02:00
d8efb3971e Merge pull request #12 from matter-labs/snapshots-recovery
feat: Support for snapshots recovery and a simple example how to run an EN using this repo
2024-03-25 13:19:29 +01:00
f0e128860c revert 2024-03-22 09:55:34 +01:00
5df4c691bb fix 2024-03-22 01:47:26 +01:00
69435131f7 added an example 2024-03-22 01:35:00 +01:00
281068a752 support for snapshots recovery 2024-03-22 01:10:42 +01:00
97a71926d7 feat: make RUST_LOG parametrized (#11)
## What 
Customize RUST_LOG variable

## Why 
There're lot of packages used for EN and each of them has their own
logging verbosity

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Documentation comments have been added / updated.
2024-03-20 15:51:04 +02:00
3fb4985ea4 feat: add parameter for set log verbosity and json format (#10)
## What 
Logs in json format and option for set verbosity level for rust 

## Why 
It can be useful for specify verbose level.

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Documentation comments have been added / updated.
2024-03-20 14:55:06 +02:00
94db2c0a69 feat!: remove node exporter from monitoring stack (#9)
## What 
Remove node exporter from monitoring

## Why 
Redundant for this context 

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Documentation comments have been added / updated.
2024-03-12 17:06:09 +02:00
26319af6d7 Merge pull request #8 from matter-labs/docs-envs
chore(docs): Better explain chain settings, minor tweaks
2024-03-08 09:24:14 +01:00
37bbe33ad7 minor tweaks 2024-03-08 09:18:55 +01:00
e776080ba4 typo fix 2024-03-08 09:17:00 +01:00
991e7ba587 typo fix 2024-03-08 09:16:24 +01:00
9f7f0bb6cd prettify dump links 2024-03-08 09:15:58 +01:00
ea06fe4c67 chore(docs): Better explain env settings, minor tweaks 2024-03-08 09:13:20 +01:00
254085bea2 Merge pull request #7 from matter-labs/pgtune-docs-fix
chore(docs): Fix duplicated pgtune block in README
2024-03-07 09:51:48 +01:00
b5cb15078b chore(docs): Fix duplicated pgtune block in README 2024-03-07 09:40:57 +01:00
46cd390d3d Merge pull request #6 from matter-labs/add_basic_auth
feat: add basic auth for external node
2024-03-07 09:36:13 +01:00
9fff909803 Update README.md 2024-03-07 09:35:33 +01:00
873119a54c Update README.md 2024-03-07 09:35:05 +01:00
3e46648470 Merge branch 'main' into add_basic_auth 2024-03-07 10:23:42 +02:00
86c976e375 chore(docs): README grammar fix (#5)
## What 

- Minor README grammar fix

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Documentation comments have been added / updated.
2024-03-07 10:23:12 +02:00
831de81f98 update doc 2024-03-07 10:21:24 +02:00
7cd995dfb5 update doc 2024-03-07 10:20:27 +02:00
4f54d8a139 update doc 2024-03-07 10:12:20 +02:00
586fe6d4dc Update README.md 2024-03-07 09:03:52 +01:00
bb74dfc55f Update README.md 2024-03-07 09:03:29 +01:00
1114c9a4c6 update doc 2024-03-07 09:55:10 +02:00
950cbd4f7d update doc 2024-03-07 09:53:03 +02:00
e3f7fe3c87 update doc 2024-03-07 09:50:05 +02:00
118523076b feat: add basic auth for external node 2024-03-07 09:49:38 +02:00
21 changed files with 403 additions and 71 deletions

View File

@ -2,3 +2,6 @@ skip_list:
- 'yaml'
- 'risky-shell-pipe'
- 'role-name'
exclude_paths:
- example_playbooks

View File

@ -26,10 +26,11 @@ Describe what actually happened.
#### 🖥️ Environment
Any relevant environment details like:
Any relevant environment details like:
* Ansible version
* Operating system
* External node version
* External Node version
#### 📋 Additional Context

View File

@ -5,7 +5,7 @@ sovereignty! We welcome contributions from anyone on the internet, and are grate
## Ways to contribute
There are many ways to contribute to the external node role:
There are many ways to contribute to the External Node role:
1. Open issues: if you find a bug, have something you believe needs to be fixed, or have an idea for a feature, please
open an issue.

View File

@ -1,6 +1,6 @@
# ansible-en-role
Ansible role to deploy and configure zkSync Era External Node, including DB isntance setup on the same machine, Traefik as reverse proxy, and Prometheus monitoring (PostgreSQL exporter, Node exporter, cAdvisor, Traefik, External Node native metrics, and VictoriaMetrics vmagent to scrape all of them).
Ansible role to deploy and configure zkSync Era External Node, including DB instance setup on the same machine, Traefik as reverse proxy, and Prometheus monitoring (PostgreSQL exporter, cAdvisor, Traefik, External Node native metrics, and VictoriaMetrics vmagent to scrape all of them).
Make sure to configure Prometheus remote write endpoint to send metrics to centralized metrics storage.
@ -14,7 +14,9 @@ This role has been tested on:
## Usage
This role contains variables which has to be set:
For a very simple minimal working example, see example_playbooks directory
Minimal required variables that have to be set:
```yaml
database_name: ""
@ -26,6 +28,17 @@ l1_chain_id: ""
l2_chain_id: ""
```
Additional arbitrary environment variables can be passed to External Node container:
```yaml
additional_env_vars:
- { name: "EN_ADDITIONAL_VAR1", value: "Value1" }
- { name: "EN_ADDITIONAL_VAR2", value: "Value2" }
- { name: "EN_ADDITIONAL_VAR3", value: "Value3" }
```
Please refer to [External Node docs](https://github.com/matter-labs/zksync-era/tree/main/docs/guides/external-node/prepared_configs) to find values for different zkSync Era chains.
If you want to use monitoring (which we highly recommend), you have to change these variables:
```yaml
@ -40,7 +53,7 @@ prometheus_remote_write_auth_password: "password"
prometheus_remote_write_common_label: "matterlabs"
```
This role also has option to secure your server and allow traffic only from specified IP address in case if you want
This role also has the option to secure your server and allow traffic only from specified IP address in case if you want
to use some load balancer in front of your node, while not having fancy cloud security groups at your disposal:
```yaml
@ -54,7 +67,7 @@ iptables_packages:
loadbalancer_ip: "1.2.3.4"
```
In most of cases, you'd want to change PostgreSQL parameters (we recommend to use <https://pgtune.leopard.in.ua/> with "Online transaction processing system" preset as sane defaults), so you can do it using `postgres_arguments` variable, eg:
In most cases, you'd want to change PostgreSQL parameters, so you can do it using `postgres_arguments` variable, eg:
```yaml
postgres_arguments:
@ -66,23 +79,39 @@ postgres_arguments:
- -c
```
We recommend using pgtune [online]<https://pgtune.leopard.in.ua/> or [self-hosted](https://github.com/le0pard/pgtune) version with with "Online transaction processing system" preset as a good starting point for generating optimal config for your hardware.
We recommend using pgtune [online](https://pgtune.leopard.in.ua/) or [self-hosted](https://github.com/le0pard/pgtune) version with "Online transaction processing system" preset as a good starting point for generating optimal config for your hardware.
If you want to use basic auth for inbound requests, you have to change next variables:
```yaml
enable_basic_auth: true
basic_auth_secret: "htpasswd-generated-secret"
```
Basic auth secret can be generated by `htpasswd` and `sed` for interpolation:
```echo $(htpasswd -nb <username> <password>) | sed -e s/\\$/\\$\\$/g```
## Step-by-step guide
1. Install ansible collection on your machine from where you will run ansible:
1. Install the ansible collection on your machine from where you will run ansible:
`ansible-galaxy collection install community.general`
2. Prepare latest database backup on your host. you can download it from our [public GCS bucket](https://storage.googleapis.com/zksync-era-mainnet-external-node-backups/external_node_latest.pgdump).
you should place it to `{{ storage_directory }}/pg_backups` directory. By default, `{{ storage_directory }}` is `/usr/src/en`
2. Prepare the latest database backup on your host. you can download it from our public GCS buckets:
Skip this step if you are recovering from a snapshot!
3. **OPTIONAL**: If you already have external-node, you can copy tree directory to new host. Copy external-node database tree to `{{ storage_directory }}/db`.
* [Era Mainnet latest dump](https://en-backups.matterlabs.dev/)
* [Era Sepolia Testnet latest dump](https://storage.googleapis.com/zksync-era-testnet-sepolia-external-node-backups/external_node_latest.pgdump)
**Keep in mind, tree should be older than PostgreSQL database backup.**
Downloaded dump, if needed, should be unarchived and named `external_node_latest.pgdump`. File should be placed into `{{ storage_directory }}/pg_backups` directory (`/usr/src/en/pg_backups` by default).
4. Run ansible-playbook using this role. We recommend to encrypt next variables with ansible-vault or some another way:
3. **OPTIONAL**: If you already have running node, you can copy its tree and state directory to a new host's `{{ storage_directory }}/db`. (`/usr/src/en/db` by default)
Skip this step if you are recovering from a snapshot!
```
**Keep in mind that tree and state should be older than PostgreSQL database backup.**
4. Run ansible-playbook using this role. We recommend encrypting next variables with ansible-vault or some another way:
```yaml
database_username
database_password
eth_l1_url
@ -92,6 +121,20 @@ vm_auth_password
5. Connect to your host, and see status of `postgres` container. It can take a lot of time before PostgreSQL database backup will be restored (hours to days, depending on your disk throughput and IOPS), after which PostgreSQL server will be ready for use. Once `postgres` becomes "healthy", `external_node` runs automatically.
## Snapshots Recovery
Example config enabling recovery from a snapshot:
```yaml
- enable_snapshots_recovery: true
- snapshots_bucket_base_url: "snapshots-bucket-name"
```
Snapshot buckets:
* Era Mainnet: `zksync-era-mainnet-external-node-snapshots`
* Era Sepolia Testnet: `zksync-era-boojnet-external-node-snapshots`
## Example Playbook
```yaml
@ -107,7 +150,6 @@ vm_auth_password
l2_chain_id: "324"
l1_chain_id: "1"
enable_tls: false
partner_id: matterlabs
vars_files:
- secrets/mainnet_secrets.yml
roles:

View File

@ -8,12 +8,12 @@ docker_install_compose: true
docker_version: "25.0.3"
docker_compose_version: "v2.23.0"
# Versions of external node and 3rd party components
# Versions of External Node and 3rd party components
traefik_version: 2.11
postgres_version: 14
external_node_version: 21.0.2
vmagent_version: 1.95.1
node_exporter_version: 1.7.0
external_node_version: 27.2.0
external_node_raw_docker_tag: ""
vmagent_version: 1.100.1
cadvisor_version: 0.47.2
postgres_exporter_version: 0.15.0
@ -56,16 +56,45 @@ postgres_arguments:
- max_parallel_maintenance_workers=4
- -c
- checkpoint_timeout=1800
enable_postgres_replication: false
# IP address of the interface replication
postgres_replications_arguments: []
postgres_replica_user_name: ""
postgres_replica_user_password: ""
postgres_replica_auth_method: "scram-sha-256"
postgres_replication_bind_address: ""
postgres_replica_address: ""
backup_db_user: ""
backup_db_password: ""
backup_db_name: ""
# Enable TLS for traefik
enable_tls: false
acme_email: ""
domain_name: ""
# Enable basic auth for External Node
enable_basic_auth: false
basic_auth_secret: ""
# Force restore pg database
force_pg_restore: false
# External node and database options
# Use a snapshot to recover
enable_snapshots_recovery: false
snapshots_bucket_base_url: ""
# https://github.com/matter-labs/zksync-era/blob/main/docs/guides/external-node/09_decentralization.md
enable_consensus: false
consensus_secrets_file: ""
consensus_port: 3054
consensus_outbound: []
consensus_debug_port: 5000
enable_consensus_debug_port: false
expose_consensus_debug_port: false
consensus_debug_port_path_prefix: "/consensus_debug"
# External Node and database options
database_name: ""
database_username: ""
database_password: ""
@ -77,6 +106,10 @@ rpc_http_port: 3060
rpc_ws_port: 3061
healthcheck_port: 3081
metrics_port: 3082
rust_log: zksync_external_node=info,zksync_core=info,zksync_core::sync_layer=info,zksync_server=info,zksync_prover=info,zksync_contract_verifier=info,zksync_dal=info,zksync_eth_client=info,zksync_storage=info,zksync_db_manager=info,zksync_merkle_tree=info,zksync_state=info,zksync_utils=info,zksync_types=info,loadnext=info,dev_ticker=info,vm=info,block_sizes_test=info,zksync_verification_key_generator_and_server=info,zksync_object_store=info,setup_key_generator_and_server=info,zksync_circuit_synthesizer=info,zksync_queued_job_processor=info,zksync_health_check=info
# Additional env vars passed to External Node
additional_env_vars: []
# Monitoring options section
enable_monitoring: false

View File

@ -0,0 +1,23 @@
# Mainnet Snapshots Recovery playbook
This directory is simple example how to set up EN using this role. It comes with snapshots recovery enabled by default.\
**Note that for simplicity it's using postgres database
with a very unsecure password and the EN is just started on the same machine**
To run this playbook, first install dependencies
```shell
ansible-galaxy install -r requirements.yml
```
and then you can run the playbook using
```shell
ansible-playbook playbook.yml -i hosts.ini -K
```
To see logs you can use
```shell
docker logs en-external_node-1
```

View File

@ -0,0 +1,2 @@
[local]
localhost ansible_connection=local

View File

@ -0,0 +1,16 @@
---
- hosts: all
become: true
vars:
database_name: "zksync_ext_node_mainnet"
database_username: "postgres"
database_password: "notsecurepassword"
eth_l1_url: "https://ethereum-rpc.publicnode.com"
main_node_url: "https://zksync2-mainnet.zksync.io"
l1_chain_id: "1"
l2_chain_id: "324"
enable_snapshots_recovery: true
snapshots_bucket_base_url: "zksync-era-mainnet-external-node-snapshots"
roles:
- external_node

View File

@ -0,0 +1,17 @@
---
roles:
- name: geerlingguy.docker
src: https://github.com/geerlingguy/ansible-role-docker
version: "7.1.0"
- name: external_node
src: https://github.com/matter-labs/ansible-en-role
version: "v3.3.0"
collections:
- name: community.docker
version: 4.5.2
- name: community.general
version: 8.4.0
# Collection for the replication only.
- name: community.postgresql
version: 3.7.0

8
handlers/main.yml Normal file
View File

@ -0,0 +1,8 @@
---
- name: Restart external-node service
community.docker.docker_compose_v2:
project_src: "{{ configuration_directory }}"
files: "{{ docker_compose_files }}"
state: restarted
services:
- external_node

View File

@ -2,12 +2,12 @@
dependencies:
- src: geerlingguy.docker
version: "7.1.0"
when: docker_install
when: docker_install_compose
galaxy_info:
role_name: external_node
author: matter-labs
description: External node setup
description: External Node setup
license: "license (MIT, APACHE)"
min_ansible_version: "2.13.9"
platforms:

View File

@ -49,6 +49,23 @@
source: "{{ loadbalancer_ip | mandatory }}"
jump: ACCEPT
- name: Allow consensus port traffic from any IP
when: enable_consensus
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
destination_port: "{{ consensus_port }}"
jump: ACCEPT
- name: Allow postgres replication traffic from replica only
when: enable_postgres_replication
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
destination_port: 5432
source: "{{ postgres_replica_address }}"
jump: ACCEPT
- name: Set default policy to DROP
ansible.builtin.iptables:
chain: INPUT

View File

@ -9,3 +9,7 @@
- name: Prepare configs
ansible.builtin.include_tasks: provision.yml
- name: Configure replication on main instance
ansible.builtin.include_tasks: replication.yml
when: enable_postgres_replication

View File

@ -32,13 +32,37 @@
- l2_chain_id
- l1_chain_id
- name: "Verify that required variables for replication is set"
when: enable_postgres_replication
ansible.builtin.assert:
that:
- postgress_replication_required_var != ""
fail_msg: "{{ postgress_replication_required_var }} needs to be set for the role for postgres replication to work"
success_msg: "Required variable for postgres replication {{ postgress_replication_required_var }} isn't empty"
loop_control:
loop_var: postgress_replication_required_var
with_items:
- enable_postgres_replication
- postgres_replication_bind_address
- postgres_replica_address
- postgres_replications_arguments
- postgres_replica_user_name
- postgres_replica_user_password
- name: Check required en vars empty
ansible.builtin.fail:
msg: "Variable '{{ item }}' is empty"
when: vars[item] == ""
with_items: "{{ en_required_variables }}"
- name: "Verify consensus debug port configuration"
ansible.builtin.fail:
msg: "Cannot expose consensus debug port (expose_consensus_debug_port=true) if it is not enabled (enable_consensus_debug_port=false)."
when:
- enable_consensus
- expose_consensus_debug_port
- not enable_consensus_debug_port
- name: Copy main configs
- name: Create main configs
ansible.builtin.template:
src: '{{ item.src }}'
dest: '{{ item.dest }}'
@ -50,8 +74,10 @@
dest: "{{ configuration_directory }}/external_node.env"
- src: "templates/postgres.env.j2"
dest: "{{ configuration_directory }}/postgres.env"
loop_control:
label: "{{ item.dest }}"
- name: Copy restore script
- name: Create restore script
register: restore_dump_script
ansible.builtin.template:
src: 'templates/restore_dump.sh.j2'
@ -64,7 +90,7 @@
when: enable_monitoring and ( vars[item] == "" )
with_items: "{{ monitoring_required_variables }}"
- name: Copy monitoring configs
- name: Create monitoring configs
when: enable_monitoring
ansible.builtin.template:
src: '{{ item.src }}'
@ -76,23 +102,32 @@
- src: "templates/vmagent-config.yml.j2"
dest: "{{ configuration_directory }}/vmagent-config.yml"
- name: Run docker-compose without monitoring
when: not enable_monitoring
ansible.builtin.shell:
cmd: nohup docker compose -f docker-compose.yaml up -d &
chdir: "{{ configuration_directory }}"
changed_when: false
- name: Create consensus config
when: enable_consensus
ansible.builtin.template:
src: "templates/consensus_config.yaml.j2"
dest: "{{ configuration_directory }}/consensus_config.yaml"
mode: '0644'
notify: Restart external-node service
- name: Run docker-compose with monitoring
when: enable_monitoring and (not restore_dump_script.changed)
ansible.builtin.shell:
cmd: nohup docker compose -f monitoring.yaml -f docker-compose.yaml up -d &
chdir: "{{ configuration_directory }}"
changed_when: false
- name: Decrypt consensus_secrets
when: enable_consensus
ansible.builtin.copy:
src: "{{ consensus_secrets_file }}"
dest: "{{ configuration_directory }}/consensus_secrets.yaml"
decrypt: true
mode: '0600'
notify: Restart external-node service
- name: Run docker-compose with monitoring with recreation
when: enable_monitoring and restore_dump_script.changed
ansible.builtin.shell:
cmd: nohup docker compose -f monitoring.yaml -f docker-compose.yaml up -d --force-recreate &
chdir: "{{ configuration_directory }}"
changed_when: false
- name: Set docker compose files list
ansible.builtin.set_fact:
docker_compose_files: "{{ ['docker-compose.yaml'] + (['monitoring.yaml'] if enable_monitoring else []) }}"
- name: Run docker compose services (non-blocking)
community.docker.docker_compose_v2:
project_src: "{{ configuration_directory }}"
files: "{{ docker_compose_files }}"
state: present
pull: "{{ docker_pull_policy | default('missing') }}"
recreate: "{{ 'always' if restore_dump_script.changed else 'auto' }}"
wait: false

60
tasks/replication.yml Normal file
View File

@ -0,0 +1,60 @@
---
- name: Install libpq-dev packages
ansible.builtin.apt:
update_cache: true
name: libpq-dev
- name: Install psycopg2 python package
ansible.builtin.pip:
name: psycopg2
- name: Grant user replication access for replication.
community.postgresql.postgresql_pg_hba:
dest: "{{ storage_directory }}/postgres/pg_hba.conf"
contype: host
users: "{{ postgres_replica_user_name }}"
source: "{{ postgres_replica_address }}/32"
databases: replication
method: "{{ postgres_replica_auth_method }}"
- name: Create postgres replication user
community.postgresql.postgresql_user:
login_host: "{{ postgres_replication_bind_address }}"
login_user: "{{ database_username }}"
login_password: "{{ database_password }}"
name: "{{ postgres_replica_user_name }}"
password: "{{ postgres_replica_user_password }}"
role_attr_flags: "REPLICATION"
- name: Create replication slot if doesn't exist
community.postgresql.postgresql_slot:
login_host: "{{ postgres_replication_bind_address }}"
login_user: "{{ database_username }}"
login_password: "{{ database_password }}"
slot_name: replica
- name: Reload postgres configuration
community.postgresql.postgresql_query:
login_host: "{{ postgres_replication_bind_address }}"
login_user: "{{ database_username }}"
login_password: "{{ database_password }}"
query: "SELECT pg_reload_conf()"
- name: Create postgres backup user
community.postgresql.postgresql_user:
login_host: "{{ postgres_replication_bind_address }}"
login_user: "{{ database_username }}"
login_password: "{{ database_password }}"
name: "{{ backup_db_user }}"
password: "{{ backup_db_password }}"
- name: Grant role pg_read_all_data to backup user
community.postgresql.postgresql_membership:
login_host: "{{ postgres_replication_bind_address }}"
login_user: "{{ database_username }}"
login_password: "{{ database_password }}"
group: pg_read_all_data
target_roles:
- "{{ backup_db_user }}"
state: present

View File

@ -0,0 +1,13 @@
server_addr: '0.0.0.0:3054'
public_addr: '{{ ansible_default_ipv4.address }}:{{ consensus_port }}'
max_payload_size: 5000000
gossip_dynamic_inbound_limit: 200
{% if enable_consensus_debug_port %}
debug_page_addr: "0.0.0.0:{{ consensus_debug_port }}"
{% endif %}
rpc_config:
get_block_rate:
burst: 5
refresh: # 0.2s
seconds: 0
nanos: 200000000

View File

@ -8,10 +8,13 @@ services:
- "--log.level=INFO"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.external_node_health.address=:3080"
- "--entryPoints.web.address=:80"
- "--entryPoints.external_node_health.address=:3080"
{% if enable_consensus %}
- "--entryPoints.external_node_consensus.address=:{{ consensus_port }}"
{% endif %}
{% if enable_tls %}
- "--entrypoints.websecure.address=:443"
- "--entryPoints.websecure.address=:443"
- "--certificatesresolvers.en_resolver.acme.tlschallenge=true"
- "--certificatesresolvers.en_resolver.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.myresolver.acme.email={{ acme_email }}"
@ -40,14 +43,27 @@ services:
- ./restore_dump.sh:/docker-entrypoint-initdb.d/restore_dump.sh
env_file:
- postgres.env
{% if enable_postgres_replication %}
ports:
- "{{ postgres_replication_bind_address }}:5432:5432"
{% endif %}
command:
- postgres
- -c
{% for argument in postgres_arguments %}
- {{ argument }}
{% endfor %}
{% if enable_postgres_replication %}
{% for repl_argument in postgres_replications_arguments %}
- {{ repl_argument }}
{% endfor %}
{% endif %}
external_node:
{% if not external_node_raw_docker_tag %}
image: "matterlabs/external-node:v{{ external_node_version }}"
{% else %}
image: "matterlabs/external-node:{{ external_node_raw_docker_tag }}"
{% endif %}
restart: unless-stopped
depends_on:
postgres:
@ -64,16 +80,45 @@ services:
- "traefik.http.routers.external_node_main.entrypoints=web"
{% endif %}
- "traefik.http.routers.external_node_main.service=external_node_main"
- "traefik.http.services.external_node_health.loadbalancer.server.port={{ healthcheck_port }}"
- "traefik.http.routers.external_node_health.rule=PathPrefix(`/`)"
- "traefik.http.routers.external_node_health.entrypoints=external_node_health"
- "traefik.http.routers.external_node_health.service=external_node_health"
{% if enable_basic_auth %}
- "traefik.http.routers.external_node_main.middlewares=external_node_auth"
- "traefik.http.middlewares.external_node_auth.basicauth.users={{ basic_auth_secret }}"
{% endif %}
{% if enable_consensus %}
- "traefik.tcp.services.external_node_consensus.loadbalancer.server.port={{ consensus_port }}"
- "traefik.tcp.routers.external_node_consensus.rule=HostSNI(`*`)"
- "traefik.tcp.routers.external_node_consensus.entrypoints=external_node_consensus"
- "traefik.tcp.routers.external_node_consensus.service=external_node_consensus"
{% endif %}
{% if enable_consensus and expose_consensus_debug_port %}
- "traefik.http.services.external_node_consensus_debug.loadbalancer.server.port={{ consensus_debug_port }}"
- "traefik.http.routers.external_node_consensus_debug.rule=PathPrefix(`{{ consensus_debug_port_path_prefix }}`)"
{% if enable_tls %}
- "traefik.http.routers.external_node_consensus_debug.entrypoints=websecure"
- "traefik.http.routers.external_node_consensus_debug.tls.certresolver=myresolver"
{% else %}
- "traefik.http.routers.external_node_consensus_debug.entrypoints=web"
{% endif %}
- "traefik.http.routers.external_node_consensus_debug.service=external_node_consensus_debug"
{% if enable_basic_auth %}
- "traefik.http.routers.external_node_consensus_debug.middlewares=external_node_auth"
{% endif %}
{% endif %}
expose:
- {{ rpc_http_port }}
- {{ rpc_ws_port }}
- {{ healthcheck_port }}
- {{ metrics_port }}
{% if enable_consensus %}
- {{ consensus_port }}
{% if expose_consensus_debug_port %}
- {{ consensus_debug_port }}
{% endif %}
{% endif %}
environment:
ZKSYNC_HOME: "/"
EN_STATE_CACHE_PATH: /db/state_keeper
@ -86,7 +131,12 @@ services:
CHAIN_STATE_KEEPER_VALIDATION_COMPUTATIONAL_GAS_LIMIT: 2000000
DATABASE_POOL_SIZE: 200
EN_MAX_BLOCKS_PER_TREE_BATCH: 200
RUST_LOG: zksync_core=debug,zksync_dal=info,zksync_eth_client=info,zksync_merkle_tree=info,zksync_storage=info,zksync_state=debug,zksync_types=info,vm=info,zksync_external_node=info,zksync_utils=debug
MISC_LOG_FORMAT: json
RUST_LOG: {{ rust_log }}
{% if enable_consensus %}
EN_CONSENSUS_CONFIG_PATH: /etc/consensus_config.yaml
EN_CONSENSUS_SECRETS_PATH: /run/secrets/consensus_secrets
{% endif %}
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:{{ healthcheck_port }}/health" ]
interval: 1m
@ -95,6 +145,21 @@ services:
start_period: 1m
volumes:
- "{{ storage_directory }}/db:/db"
{% if enable_consensus %}
- "{{ configuration_directory }}/consensus_config.yaml:/etc/consensus_config.yaml"
{% endif %}
env_file:
- "external_node.env"
- "postgres.env"
command:
{% if enable_consensus %}
- --enable-consensus
secrets:
- consensus_secrets
{% endif %}
{% if enable_consensus %}
secrets:
consensus_secrets:
file: consensus_secrets.yaml
{% endif %}

View File

@ -2,4 +2,16 @@ EN_ETH_CLIENT_URL="{{ eth_l1_url | mandatory }}"
EN_MAIN_NODE_URL="{{ main_node_url | mandatory }}"
EN_L2_CHAIN_ID="{{ l2_chain_id | mandatory }}"
EN_L1_CHAIN_ID="{{ l1_chain_id | mandatory }}"
{% if enable_snapshots_recovery %}
EN_SNAPSHOTS_RECOVERY_ENABLED="true"
EN_SNAPSHOTS_OBJECT_STORE_MODE="GCSAnonymousReadOnly"
EN_SNAPSHOTS_OBJECT_STORE_BUCKET_BASE_URL="{{ snapshots_bucket_base_url | mandatory }}"
{% endif %}
DATABASE_URL="postgres://{{ database_username | mandatory }}:{{ database_password | mandatory }}@postgres/{{ database_name | mandatory }}"
{% if additional_env_vars is defined and additional_env_vars|length > 0 %}
{% for env_var in additional_env_vars %}
{{ env_var.name }}="{{ env_var.value }}"
{% endfor %}
{% endif %}

View File

@ -21,18 +21,6 @@ services:
- "--remoteWrite.vmProtoCompressLevel=2"
restart: always
node-exporter:
image: "prom/node-exporter:v{{ node_exporter_version }}"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
restart: unless-stopped
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
cadvisor:
image: "gcr.io/cadvisor/cadvisor:v{{ cadvisor_version }}"
volumes:

View File

@ -3,7 +3,7 @@ set -e
{% if force_pg_restore %}
pg_restore --clean --exit-on-error -j $(nproc --all) -d postgres -U $POSTGRES_USER --no-owner --no-privileges --disable-triggers --create /pg_backups/external_node_latest.pgdump
{% else %}
{% elif not enable_snapshots_recovery %}
if psql -U $POSTGRES_USER -d postgres -lqt | cut -d \| -f 1 | grep -qw "{{ database_name }}"; then
echo "Database already exists"
else

View File

@ -14,14 +14,6 @@ scrape_configs:
- source_labels: [instance]
target_label: instance
replacement: '{{ node_name | mandatory }}'
- job_name: node-exporter
static_configs:
- targets:
- "node-exporter:9100"
relabel_configs:
- source_labels: [instance]
target_label: instance
replacement: '{{ node_name | mandatory }}'
- job_name: cadvisor
static_configs:
- targets:
@ -41,7 +33,8 @@ scrape_configs:
- job_name: traefik
static_configs:
- targets:
- "traefik:8080"
# traefik uses network host, so docker DNS wouldn't work.
- "127.0.0.1:8080"
relabel_configs:
- source_labels: [instance]
target_label: instance