For Ethereum smart contract application developers, securely exposing a node to the internet is a common challenge. This guide explains how to protect your Ethereum JSON-RPC API endpoint using Nginx and HTTP Basic Authentication, ensuring that only authorized users can access it.
Why Secure Your Ethereum Node?
Go Ethereum (geth) is one of the most widely used Ethereum node implementations. Others include Parity and cpp-ethereum. Decentralized applications (DApps) are client-side web applications that interact with these nodes via the JSON-RPC API, which operates over HTTP.
By default, node software like geth does not include built-in security features for public network exposure. Leaving your JSON-RPC API openly accessible can make it vulnerable to denial-of-service attacks and unauthorized access. Since DApps run entirely in the client—without server-side processing—it’s the developer’s responsibility to ensure that the connection between the DApp and the node is secure.
Using Nginx as a Reverse Proxy with HTTP Basic Auth
There are multiple ways to restrict access to an HTTP API. Common methods include API tokens in headers, cookie-based authentication, or HTTP Basic Authentication.
HTTP Basic Authentication is a simple, standards-based method that triggers a native browser login prompt. While not the most advanced security mechanism, it is effective for limiting access to a known group of users—ideal for private demos, permissioned blockchains, or software-as-a-service applications built on Ethereum.
Nginx, a high-performance open-source web server, can act as a reverse proxy to add this layer of security.
Step-by-Step Setup Guide
Installing Nginx
On Ubuntu 14.04 or later, you can install Nginx and the required utilities with:
sudo apt install nginx apache2-utilsThis installs both Nginx and apache2-utils, which includes the htpasswd tool for creating password files.
Configuring Nginx as a Reverse Proxy
Edit the default Nginx configuration file at /etc/nginx/sites-enabled/default. Below is a sample configuration that proxies requests to a geth instance running on localhost:8545 and serves static DApp files, all protected with HTTP Basic Authentication.
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name demo.example.com;
# Proxy configuration for JSON-RPC
location /eth {
auth_basic "Restricted access to this site";
auth_basic_user_file /etc/nginx/protected.htpasswd;
proxy_pass http://localhost:8545;
}
# Serve static DApp files
location / {
root /usr/share/nginx/html;
index index.html;
auth_basic "Restricted access to this site";
auth_basic_user_file /etc/nginx/protected.htpasswd;
}
}Creating User Credentials
Use the htpasswd tool to create a username and hashed password:
sudo htpasswd -c /etc/nginx/protected.htpasswd demoYou will be prompted to enter and confirm a password for the user “demo”. The -c flag creates a new file. Omit it when adding more users later.
Configuring Geth
Start your geth node in a detached screen session to keep it running in the background:
screen -S geth-node
geth # include your preferred command-line flags hereDetach from the screen session with Ctrl+A, D. This ensures geth continues to run after you disconnect.
For help setting up a private testnet, 👉 explore more strategies available in community forums.
Updating Your DApp Configuration
In your DApp’s JavaScript code (using web3.js), conditionally set the provider URL based on the deployment environment:
function getRPCURL() {
if (window.location.href.includes("demo.example.com")) {
return "http://demo.example.com/eth";
} else {
return "http://localhost:8545";
}
}
web3.setProvider(new web3.providers.HttpProvider(getRPCURL()));This ensures that the DApp uses the password-protected endpoint in production and localhost during development.
Deploying the DApp
Copy your DApp’s static files (HTML, JS, CSS) to the Nginx web directory:
sudo cp -r dist/* /usr/share/nginx/html/Ensure that the files are readable by the www-data user. Here’s an example deployment script using rsync:
#!/bin/bash
REMOTE="your-server"
npm run build
rsync -a -e "ssh" --rsync-path="sudo rsync" dist/* --chown www-data:www-data $REMOTE:/usr/share/nginx/html/Restarting Nginx
Apply the configuration changes with:
sudo service nginx restartTesting and Troubleshooting
Visit your DApp’s URL. You should see a login prompt. After entering the credentials, the DApp should load and interact with geth via the proxied endpoint.
Check Nginx error logs for debugging:
tail -f /var/log/nginx/error.logIf you encounter a “502 Bad Gateway” error, confirm that geth is running correctly on the specified local port.
Frequently Asked Questions
Why use HTTP Basic Authentication instead of other methods?
It is simple to implement and supported by all major browsers. For internal or demo applications, it provides a good balance of security and convenience.
Is HTTP Basic Authentication secure over HTTP?
No. Passwords are base64-encoded but not encrypted. Always use HTTPS in production. You can obtain a free TLS certificate from Let’s Encrypt and configure Nginx to use it.
Can I use this method with other Ethereum clients like Parity?
Yes. The same Nginx configuration can proxy to any HTTP-based JSON-RPC service, regardless of the client software.
What if I need to support many users?
For larger-scale applications, consider using token-based authentication or integrating with a single sign-on (SSO) provider. HTTP Basic Auth is best for small teams or limited audiences.
How do I add more users to the password file?
Run sudo htpasswd /etc/nginx/protected.htpasswd newuser to add additional users without overwriting the existing file.
Can I restrict access to specific API methods?
Yes. Nginx can be configured to filter or route requests based on the URL path or other criteria, allowing fine-grained control over which endpoints are exposed.