Fast search closes deals; slow search closes tabs. At Bonsai.io, we're opinionated about search. Even our free (forever) sandbox clusters get distributed to 3 nodes and managed by the same team of search engineers that manage our enterprise customers' deployments. We've been keeping our customers' tabs open from search to purchase since 2008.
Seeing is believing.
Tired of managing your own search containers? Launch a free Sandbox search cluster with your Fly.io deployment, in minutes!
Deploying fantastic search experiences on Fly.io with Bonsai.io's managed search is as easy as dropping an environment variable into your application's secrets.
In this post, we'll take that basic deployment a step further by deploying what we like to call an interleaving proxy. It's a pass-through, or reverse, proxy which will sit in-front of our search cluster, forwarding requests from our application hosted on Fly.io to our search cluster hosted, and fully managed, on Bonsai.io.
To follow along by deploying to your Fly.io account, get your own Bonsai managed cluster by signing up at Bonsai.io - we've got detailed instructions on getting started with the Sandbox cluster at this page.
For this post, we put together a little sample API web service to demonstrate interacting with Elasticsearch and
OpenSearch. It puts some static book data into an Elasticsearch index and responds to requests at /api/books
with
results fetched from our search cluster.
Clone or fork it at GitHub.
Info
OpenSearch and Elasticsearch can do a whole heckuva lot more than handle your website's search these days.
The things that make it a world-class search database also make it a fantastic vector/embedding database for AI-powered apps. We've written more about that at our blog!
Since our Books API server is configured to deploy on Elasticsearch, it expects an environment variable,
ELASTICSEARCH_NODE
,
to be populated with a connection URL, with optional embedded credentials. Deploying the server with that env variable
set to the full-access URL from our cluster's management page would work just fine.
But we aspire to more. Pointing our application to a proxy server has some security and quality-of-life benefits that are, well, pretty nice.
For starters, when credentials are set and managed in our proxy application, our API server doesn't need to blink when it comes time to rotate them out, because with a Bluegreen Fly deployment, the proxy will update, and the application can automatically retry any failed queries - transparent to the user.
We can also configure our proxy to maintain connections across requests, potentially reducing the frequency (and overhead) of opening/closing new connections from your application onto the search cluster. If we really want to dive-in, the proxy can also help isolate audit logs and control, making rate limiting, logging, and query shaping much easier to do.
Since we're deploying with a managed database, however, we're mainly focused on credential isolation (out of our web-app) and rotation. Connection pooling can probably be configured in our code (via the Elasticsearch/OpenSearch clients). And for the rest, well, we'll leave that to Bonsai.
Let's get deploying.
Install flyctl
First, you'll need flyctl, Fly.io's command-line application that allows you to deploy and manage applications, secrets, and more.
Log-in with flyctl
Once flyctl is installed, log-in by running
fly auth login
and following the prompts!
Really, clone the sample code to follow along!
If you haven't yet, make sure you clone or fork the post's example code!
Deploying an interleaving (reverse) proxy on Fly.io
We've put together a couple of examples of reverse-proxies, based on Nginx and Node.js, available in the GitHub repo. Most languages/run-times have standard libraries or community packages that make writing your own TCP proxy pretty easy. Since our Bonsai.io server will deploy with SSL support, we want to deploy a TLS termination proxy, meaning that while our application will communicate with our proxy over an unencrypted or encrypted protocol (HTTP or HTTPS), communication between the proxy and our Elasticsearch cluster will always be encrypted using Bonsai.io's SSL certificates, and our application won't need to know about those keys or certificates at all.
Info
Our application will only be using one proxy type at a time. Deploying both at the same time will allow you to switch
between them
by updating a fly secret
associated with the API server!
Deploying an Nginx proxy on Fly.io
Head into the nginx-proxy directory.
Configure the proxy's Fly app by running
fly launch --no-deploy --flycast
and following along with the prompts.
Info
The --flycast
flag lets flyctl know that we're deploying a private application
that should only be accessible via
the Flycast private proxy
Next, set the Fly app's secrets by replacing the values in the command below with the credentials from your Bonsai.io cluster's credentials page (details on how to find them here).
fly secrets set \
BONSAI_HOST="REPLACE-ME-1234567890.us-east-1.bonsaisearch.net:443" \
BONSAI_USERNAME="<from your bonsai cluster's credentials page>" \
BONSAI_PASSWORD="<from your bonsai cluster's credentials page>"
Finally, deploy the proxy to Fly.io with
fly deploy --flycast
Once deployed, the Nginx proxy will be deployed into your Fly organization's internal network, available via
the Flycast private proxy at <nginx-proxy-app-name>.flycast:9200
.
Deploying a Node.js proxy on Fly.io
Head into the node-proxy directory.
Configure the proxy's Fly app by running
fly launch --no-deploy --flycast
and following along with the prompts.
Info
The --flycast
flag lets flyctl know that we're deploying a private application
that should only be accessible via
the Flycast private proxy
Next, set the Fly app's secrets by replacing the ELASTICSEARCH_NODE
value in the command below with the full (credentials-embedded) URL from your Bonsai.io
cluster's credentials page (details on how to find them here).
fly secrets set \
ELASTICSEARCH_NODE="https://<user>:<password>@<your-cluster-name>.bonsaisearch.net"
Finally, deploy the proxy to Fly.io with
fly deploy --flycast
Once deployed, the Node.js proxy will be deployed into your Fly organization's internal network, available via
the Flycast private proxy at <node-proxy-app-name>.flycast:9200
.
Deploy our Books API service
Now that our proxy is up and ready, we can deploy our application configured to use the live proxy!
Note
Since our API service will be publicly accessible, we've dropped the --flycast
flags from our flyctl
commands.
First, configure the app with fly launch
:
fly launch --no-deploy
Then, grab the application name of our proxy with fly apps list
. Here's what mine looked like:
# NAME OWNER STATUS LATEST DEPLOY
# nginx-proxy-polished-dawn-4849 personal deployed 2m2s ago
With the app name, we can set our ELASTICSEARCH_NODE
URL to point to the internal, flycast
proxy, URL on Fly.io.
Tip
Don't forget to replace my app's name with yours in the next command!
fly secrets set ELASTICSEARCH_NODE="http://nginx-proxy-polished-dawn-4849.flycast:9200"
Deploy:
fly deploy
And finally, test our Proxy! My app deployed with the name bonsai-book-server
, yours will probably be different. Replace the next command with your app's public URL:
curl https://bonsai-book-server.fly.dev/api/books
You should see JSON data similar to
[{"id":1,"title":"The Hobbit","author":"J.R.R. Tolkien","year":1937},{"id":2,"title":"The Lord of the Rings",...}]
Next steps
You're probably planning on using search with a bit more functionality than returning a small, static, set of books over an API.
We'd love to help. Send Joel (a real, non-LLM, person) a note at [email protected].
Ready to take a closer look at Bonsai?
Find out if Bonsai is a good fit for you in just 15 minutes.
Learn how a managed service works and why it’s valuable to dev teams
You won’t be pressured or used in any manipulative sales tactics
We’ll get a deep understanding of your current tech stack and needs
Get all the information you need to decide to continue exploring Bonsai services