Below are three options for storing client keys on our Managed V3 API:
1) Use an external Hardware Security Module. There is an entire industry of products designed for offloading security-sensitive operations to external devices. This doesn't solve the problem so much as relocate it, but it relocates it to device that is far more secure, so altogether it's a security win. If you're doing anything high-stakes, then this is almost certainly going to factor into your solution.
2) Type in the encryption key when you start up, store it in memory. This protects against offline attacks (unless they capture the key out of RAM, which is tougher to do). Similar to the option above, but also different. However, the server boots into an unusuable state, requiring you to manually supply the key before work can be done.
3) Store the keys on a different server.
Use 3 separate servers: Web Server, Database Server & Key Manager.
Your web server should have all ports closed, except for the ones you really need to be public (ALLOW all DENY few). Ex: your 443 port, which is the https port; in some cases port 80, which is http port).
Your DB server should deny all connections except the trusted connections that you think are okay (DENY ~all ALLOW few).
Your key manager server should also deny all connections except the few that you require (DENY ~all ALLOW few). We suggest Redis for this.
Whenever you need to do anything, just retrieve your client keys from your key manager server.