---
title: "Deploy OpenZeppelin Relayer (AWS KMS)"
description: "OpenZeppelin Relayer with Redis, signing with your own AWS KMS key"
category: "Other"
url: https://railway.com/deploy/openzeppelin-relayer-aws-kms
---

# Deploy OpenZeppelin Relayer (AWS KMS)

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

**[Deploy OpenZeppelin Relayer (AWS KMS) on Railway](https://railway.com/template/openzeppelin-relayer-aws-kms)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/openzeppelin-relayer-aws-kms/manifest.json

- **Creator:** Nonceworks
- **Category:** Other
- **Total deploys:** 1

## Template content

### Relayer

- **Image:** openzeppelin/openzeppelin-relayer:v1.9.0@sha256:3ceb3986c636cd41c8eadc685a50c8e3df643206f039485694e41c6922d47fae
- **Start command:** `/bin/sh -c 'sleep 15 && mkdir -p $CONFIG_DIR && printenv RELAYER_CONFIG_JSON > $CONFIG_DIR/config.json && exec /app/openzeppelin-relayer'`
- **Health check:** /api/v1/ready
- **Public domain:** Yes

### Redis

- **Image:** redis:8.2.10-bookworm@sha256:e5f23377739f95a2f530b9c99f93accb4f634577f09d00a7d8e0638f2fdf69e0
- **Start command:** `/bin/sh -c 'mkdir -p /data/redis && chown redis:redis /data/redis && cd /data/redis && exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --appendonly yes --save 60 1 --dir /data/redis'`

## Documentation

# 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

- OpenZeppelin Relayer documentation: https://docs.openzeppelin.com/relayer/
- OpenZeppelin Relayer source: https://github.com/OpenZeppelin/openzeppelin-relayer
- Our note on the KMS key, the IAM policy and revoking access: https://nonceworks.com/notes/relayer-aws-kms-permissions.html

### 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:

   ```json
   {
     "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):

   ```bash
   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:

   ```bash
   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


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/openzeppelin-relayer-aws-kms
