Deploy OpenZeppelin Relayer (AWS KMS)

OpenZeppelin Relayer with Redis, signing with your own AWS KMS key

Deploy OpenZeppelin Relayer (AWS KMS)

OpenZeppelin Relayer (AWS KMS)

Just deployed

/data

Deploy and Host OpenZeppelin Relayer with AWS KMS on Railway

OpenZeppelin Relayer is open-source software (AGPL-3.0) that sends blockchain transactions for your backend: it assigns nonces, prices gas, resubmits stuck transactions and tracks confirmations. This template runs it with Redis and signs with your own AWS KMS key, so the private key stays in AWS and never reaches the server.

This is not an official OpenZeppelin template. Nonceworks publishes and maintains it, and Nonceworks is not affiliated with OpenZeppelin.

About Hosting OpenZeppelin Relayer

The template deploys two services. Relayer runs the official openzeppelin/openzeppelin-relayer image, version 1.9.0, pinned by digest. Redis 8.2 (official image, pinned by digest) stores the relayer's signers, transactions and nonce counters on a volume, so they are kept across restarts and redeploys; the signer, notification and API key records in it are encrypted with a key generated at deploy. The two talk over Railway's private network. The relayer's config.json is built from template variables and written to a file when the container starts, so no custom image is needed. The API gets a public HTTPS domain and requires a generated API key on every call except the health and readiness checks.

Common Use Cases

  • Send transactions from a backend or bot without keeping a private key in an environment variable
  • Move a relayer that signed with a local keystore onto an AWS KMS key
  • Self-host the relayer after OpenZeppelin Defender's shutdown
  • Run keeper or scheduled transactions through one queue that manages nonces and gas

Dependencies for OpenZeppelin Relayer Hosting

  • An AWS KMS key: asymmetric, key usage Sign and verify, key spec ECC_SECG_P256K1
  • An IAM identity with an access key, allowed only kms:GetPublicKey and kms:Sign on that key
  • An RPC endpoint for your chain (the default is Base Sepolia's public endpoint)
  • Native gas funds on the relayer's address, which the relayer derives from the key

Deployment Dependencies

Implementation Details

Bring your own AWS KMS key

  1. In AWS KMS, create an asymmetric key with key usage Sign and verify and key spec ECC_SECG_P256K1. Note its ARN and region.

  2. Create an IAM user (or role with an access key) with only this policy, using your key's ARN:

    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["kms:GetPublicKey", "kms:Sign"],
        "Resource": "arn:aws:kms:us-east-1:123456789012:key/11111111-2222-3333-4444-555555555555"
      }]
    }
    
  3. Deploy the template and fill in AWS_REGION, AWS_KMS_KEY_ID (key id, ARN or alias), AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. For another chain, also set CHAIN_ID, RPC_URL, NETWORK_NAME, NATIVE_SYMBOL, IS_TESTNET and AVERAGE_BLOCKTIME_MS. After the first deploy, seal AWS_SECRET_ACCESS_KEY on the Relayer service's Variables tab (the variable's 3-dot menu, Seal): Railway keeps passing it to the relayer but never shows it again in the dashboard or the API. A sealed variable cannot be unsealed, only replaced. Railway then lists the seal as a pending change; press Deploy to apply it. The relayer keeps reading its key from KMS through that and every later deploy.

  4. Read the relayer's address (copy API_KEY from the Relayer service's variables):

    curl -H "Authorization: Bearer $API_KEY" https:///api/v1/relayers/kms-relayer
    
  5. Send gas funds to that address. Until it holds a balance the relayer marks itself disabled; it rechecks on its own and enables itself once the funds arrive (about 20 seconds in our tests).

  6. Send a transaction:

    curl -X POST -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
      -d '{"to":"0x...","value":1,"data":"0x","gas_limit":21000,"speed":"fast"}' \
      https:///api/v1/relayers/kms-relayer/transactions
    

To stop all signing at once, disable the key in AWS KMS or detach the IAM policy. The note linked above has the timings we measured for each.

Changing the configuration later. Every setting lives in RELAYER_CONFIG_JSON, which is built from the other variables. With Redis storage the relayer reads that config only into empty storage. To load a change, redeploy once with RESET_STORAGE_ON_START=true, then set it back to false. That start drops stored transactions and nonce counters, so do it only when nothing is in flight. Never change STORAGE_ENCRYPTION_KEY after the first start.

If the deploy fails its health check. Open the Relayer logs. The relayer's first call to KMS is GetPublicKey. If the credentials cannot use the key (a wrong key id, the wrong region or a missing permission), that call fails, the log shows AWS KMS get_public_key failed and the relayer exits; we tested the wrong-key-id case. An empty number field, such as CHAIN_ID, leaves the config invalid, and the log shows Failed to load config file with a JSON error.

Things to know.

  • The API is public so callers outside Railway can reach it. If every caller runs in the same Railway project, remove the Relayer's public domain and call http://relayer.railway.internal:8080 instead.
  • Redis has no public domain in this template and is reachable only from services in the same project environment.
  • The image is pinned to Relayer 1.9.0 by digest; newer releases are not picked up automatically.

What it costs on Railway. Railway bills usage at its published rates: $10 per GB of RAM a month, $20 per vCPU a month, $0.15 per GB of volume a month and $0.05 per GB of egress. The Hobby plan is $5 a month and includes $5 of usage. In our local tests of Relayer 1.9.0, idle on a chain with one-second blocks, the relayer used 32 to 47 MB of RAM and 3 to 17 percent of one CPU, and Redis 6 to 8 MB and under 4 percent, which at those rates comes to roughly $1 to $5 a month. A relayer sending many transactions uses more.

Why Deploy OpenZeppelin Relayer on Railway?

Railway runs both services from one click, keeps Redis on a private network with a persistent volume, gives the API an HTTPS domain, and restarts the relayer if it fails. You keep the signing key in your own AWS account the whole time.

Hosted help

If you would rather not run the relayer yourself, Nonceworks can host OpenZeppelin Monitor and Relayer for your team, signing with your own key, and offers fixed-price moves off Defender or off a raw server key: https://nonceworks.com


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
50
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
51