https://github.com/tryethernal/ethernal
Ethernal is a block explorer for EVM-based chains. In a few seconds, spin up a fully-featured explorer for your L1/L2 rollup/testnet. Compatible with Optimism, ZK, Anvil, Hardhat, Geth...
https://github.com/tryethernal/ethernal
anvil block-explorer blockchain evm geth hardhat rollup zk
Last synced: 27 days ago
JSON representation
Ethernal is a block explorer for EVM-based chains. In a few seconds, spin up a fully-featured explorer for your L1/L2 rollup/testnet. Compatible with Optimism, ZK, Anvil, Hardhat, Geth...
- Host: GitHub
- URL: https://github.com/tryethernal/ethernal
- Owner: tryethernal
- License: mit
- Created: 2021-01-23T16:25:22.000Z (over 5 years ago)
- Default Branch: develop
- Last Pushed: 2026-02-27T23:19:20.000Z (4 months ago)
- Last Synced: 2026-02-28T03:30:46.270Z (4 months ago)
- Topics: anvil, block-explorer, blockchain, evm, geth, hardhat, rollup, zk
- Language: JavaScript
- Homepage: https://www.tryethernal.com
- Size: 17.6 MB
- Stars: 261
- Watchers: 1
- Forks: 68
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: FUNDING.json
- License: LICENSE
Awesome Lists containing this project
README
# Ethernal
**Ethernal** is a powerful, open-source block explorer for EVM-based chains. Effortlessly explore, search, and analyze blockchain dataβwhether you use our hosted service or run your own private instance.
[](LICENSE)
---
## π Quick Start
### Hosted Version
- **Try Ethernal instantly:** [app.tryethernal.com](https://app.tryethernal.com)
- **Create a demo explorer:** [app.tryethernal.com/demo](https://app.tryethernal.com/demo)
---
## π Self-Hosting Ethernal
> β οΈ **Beta Notice:**
>
> The self-hosted version of Ethernal is currently in **beta**. Some features may not work as expected or may be incomplete. If you encounter any issues, please consider [opening an issue](https://github.com/tryethernal/ethernal/issues) to help us improve the project. Your feedback is greatly appreciated!
Run your own Ethernal instance on your infrastructure, with full control over your data and configuration.
### Prerequisites
- [Docker](https://www.docker.com/) & [Docker Compose](https://docs.docker.com/compose/)
- [OpenSSL](https://www.openssl.org/) (for environment file generation)
- A domain name or server IP
> **Database:** Ethernal uses PostgreSQL (TimescaleDB) as its database backend. This is automatically provided through Docker containersβno manual installation required.
### 1. Clone the Repository
```bash
git clone https://github.com/tryethernal/ethernal.git
cd ethernal
git checkout $(git describe --tags --abbrev=0) # Makes sure that you are using the latest stable version
```
### 2. Start Ethernal (Automatic Setup)
Just run:
```bash
make start
```
- On first run, this will prompt you for your domain/IP and port, then generate all secrets and config files using `generate-env-files.sh`.
- On subsequent runs, it will skip generation and simply start the services.
- If you ever want to regenerate your environment/config files, you can run `bash ./generate-env-files.sh` manually.
> **Tip:** All generated secrets and config files are automatically added to `.gitignore` for your safety.
### 3. Access Your Instance
After setup, you'll see a summary like:
```
==================== Ethernal Installation Complete! ====================
π DNS Setup Reminder:
Make sure to add an A record in your DNS provider:
your-domain.com ->
π Start here to setup your instance:
http://your-domain-or-ip/setup
π PostgreSQL Connection String:
postgresql://:@:/
π Bullboard Access (background jobs):
http://your-domain-or-ip/bull
Username: ethernal
Password:
=======================================================================
```
**π Next step:**
- Open the setup link shown above in your browser.
- This guided setup will help you **create your admin user account** and **set up your first explorer** quickly and easily.
- Once complete, you'll be ready to start using Ethernal!
> **π DNS Setup Reminder:**
>
> If you are using a custom domain (not an IP address), make sure to add an **A record** in your DNS provider:
>
> your-domain.com ->
>
> Replace `` with the actual public IP of your server. This is required for your domain to resolve correctly to your Ethernal instance.
---
## π Documentation
Full documentation is available at [doc.tryethernal.com](https://doc.tryethernal.com).
---
## π‘ API
Ethernal exposes a powerful API for programmatic access to your blockchain data and explorer features.
- **API Documentation:**
- Full list of endpoints and usage examples: [Ethernal API Reference](https://documenter.getpostman.com/view/12141908/2s83zfQ5Tf)
- **Note:** Replace all instances of `api.tryethernal.com` in the documentation with your own server's domain or IP address.
You can use this API to:
- Query blocks, transactions, contracts, logs, and more
- Integrate Ethernal data into your own dashboards or tools
- Automate explorer management (add/delete explorer, customise them, etc...)
If you need additional endpoints or have suggestions for improvements, **pull requests and issues are welcome!**
---
## π οΈ Useful Makefile Commands
- `make start` β Start or restart Ethernal (with env/config generation)
- `make stop` β Stop and clean up all containers and networks
- `make update` β Pull latest images and apply migrations/seeds
- `make nuke` β Remove all containers, volumes, and generated config files (all data will be lost)
- `make info` β Display connection details and setup URLs
---
## βοΈ Configuration
**All configuration files and environment variables are generated automatically during setup. For a default installation, you should not need to change any of these values.**
If you want to customize advanced settings, you can edit the relevant files after the initial setup.
Below are the main configuration files and the variables they contain:
---
### Backend Environment Variables (`run/.env.prod`)
| Variable | Description | Default |
|--------------------|------------------------------------|-------------|
| ENCRYPTION_KEY | Key used for data encryption | - |
| ENCRYPTION_JWT_SECRET | Secret for JWT token encryption | - |
| SECRET | Application secret key | - |
| CORS_DOMAIN | CORS allowed domains | * |
| NODE_ENV | Node environment | production |
| REDIS_URL | Redis connection string | redis://redis:6379 |
| DB_USER | PostgreSQL username | postgres |
| DB_PASSWORD | PostgreSQL password | (random) |
| DB_NAME | PostgreSQL database name | ethernal |
| DB_HOST | PostgreSQL host (via pgbouncer) | pgbouncer |
| DB_PORT | PostgreSQL port (via pgbouncer) | 5433 |
| SOKETI_DEFAULT_APP_ID | Soketi app id | default-app |
| SOKETI_DEFAULT_APP_KEY| Soketi app key | app-key |
| SOKETI_DEFAULT_APP_SECRET| Soketi app secret | (random) |
| SOKETI_HOST | Soketi host | soketi |
| SOKETI_PORT | Soketi port | 6001 |
| PM2_HOST | PM2 dashboard host | pm2:9090 |
| PM2_SECRET | PM2 dashboard secret | (random) |
| BULLBOARD_USERNAME | Username for Bull dashboard | ethernal |
| BULLBOARD_PASSWORD | Password for Bull dashboard | (random) |
| APP_DOMAIN | Your domain or IP | (set at setup)|
| FIREBASE_SIGNER_KEY| Firebase signer key | (random) |
| FIREBASE_SALT_SEPARATOR| Firebase salt separator | (random) |
| FIREBASE_ROUNDS | Firebase rounds | 8 |
| FIREBASE_MEM_COST | Firebase memory cost | 14 |
| APP_URL | Application URL | (set at setup)|
| SELF_HOSTED | Self-hosted flag | true |
| PORT | Application port | 8888 |
| DEFAULT_PLAN_SLUG | Default plan slug | self-hosted |
---
### PM2 Environment Variables (`pm2-server/.env.prod`)
| Variable | Description | Default |
|--------------------|------------------------------------|-------------|
| SECRET | PM2 dashboard secret | (random) |
| ETHERNAL_SECRET | Backend secret | (random) |
| PORT | PM2 dashboard port | 9090 |
| ETHERNAL_REDIS_URL | Redis connection string | redis://redis:6379/0 |
| ETHERNAL_HOST | Backend host URL | http://backend:8888 |
---
### PostgreSQL Environment Variables (`.env.postgres.prod`)
| Variable | Description | Default |
|--------------------|------------------------------------|-------------|
| POSTGRES_HOST | PostgreSQL host | postgres |
| POSTGRES_USER | PostgreSQL username | postgres |
| POSTGRES_PASSWORD | PostgreSQL password | (random) |
| POSTGRES_DB | PostgreSQL database name | ethernal |
| POSTGRES_PORT | PostgreSQL port | 5432 |
---
### Soketi Environment Variables (`.env.soketi.prod`)
| Variable | Description | Default |
|----------------------------|------------------------------------|-------------|
| SOKETI_DEFAULT_APP_ID | Soketi app id | default-app |
| SOKETI_DEFAULT_APP_KEY | Soketi app key | app-key |
| SOKETI_DEFAULT_APP_SECRET | Soketi app secret | (random) |
| SOKETI_HOST | Soketi host | 0.0.0.0 |
| SOKETI_PORT | Soketi port | 6001 |
---
### Docker Compose Environment Variables (`.env.docker-compose.prod`)
| Variable | Description | Default |
|--------------------|------------------------------------|-------------|
| EXPOSED_PORT | Public HTTP port | 80 (or as set at setup) |
| EXPOSED_SSL_PORT | Public HTTPS port | 443 (or as set at setup) |
---
**Note:**
- All secrets and passwords are generated randomly for each installation.
- For most users, there is no need to change these values after setup.
- The production Docker Compose file is `docker-compose.prod.yml`. You should run it with the environment file like this:
```bash
docker compose -f docker-compose.prod.yml --env-file .env.docker-compose.prod up -d
```
---
## π Blog Pipeline
Ethernal's blog ([tryethernal.com/blog](https://tryethernal.com/blog)) is powered by an automated trend-scanning pipeline that discovers what's happening in the Ethereum ecosystem and produces draft articles.
### How it works
```
Sources (EIPs, ERCs, ethresear.ch, Magicians, arxiv)
β weekly scan
Classify into 12 topic clusters
β
Score by weighted signals (ERC count, research posts, arxiv papers, Google Trends)
β
Create draft cards on GitHub Project board
β every 2 days
Round-robin picker selects highest-scoring topic (skips clusters with active work)
β
Claude CLI researches sources and drafts the article
β
Article committed to develop with status: draft (invisible on site, deployed for preview)
β card link added to project board
Move card to "Published" in GitHub Project
β triggers workflow
Frontmatter updated to status: published β article goes live on next deploy
```
**Board columns:** Detected β Researched β Drafting β Published
### Running the pipeline
```bash
cd blog/pipeline
npm ci
# Scan sources and create/update project cards
node index.js
# Preview without creating cards
node index.js --dry-run
# Pick next topic for drafting
node index.js --pick --dry-run
```
### Automation
| Trigger | What | Where |
|---------|------|-------|
| Weekly (Mon 6am UTC) | Scan sources, update scores | `.github/workflows/blog-trend-scan.yml` |
| Every 2 days (8am UTC) | Pick topic, research, draft to develop | `.github/workflows/blog-draft.yml` |
| Card β Published | Update frontmatter `status: published` | `.github/workflows/blog-publish.yml` |
| Systemd timer (Hetzner) | Same as draft workflow via Claude CLI | `blog/pipeline/draft.sh` |
---
## π Bug Reports
Found a bug? Please [open an issue](https://github.com/tryethernal/ethernal/issues) in this repo.
---
## π Support Us
Support Ethernal's development by subscribing to [a paid plan](https://www.tryethernal.com/pricing).
**Note:** The self-hosted version will display ads by default. Running these ads helps support ongoing development of Ethernal. Thank you for contributing to the project by keeping them enabled!
---
## π¬ Contact Us
We'd love to hear from you!
- **Twitter:** [@tryethernal](https://twitter.com/tryethernal)
- **Discord:** [Join our community](https://discord.gg/jYCER6Mh)
- **Email:** contact@tryethernal.com
---
**Happy exploring! π**