DEV Community

Cover image for Using Tailscale on Lambda for a Live Development Proxy
Ken Collins for AWS Heroes

Posted on • Originally published at

Using Tailscale on Lambda for a Live Development Proxy

⚠️ DISCLAIMER: In no way am I advocating for the use of live proxies as a normal way to develop against cloud resources. However in some edge cases, such as developing a new system, live dev proxies or the general use of Tailscale in Lambda could be useful.

🐋 Tailscale on Lambda

Tailscale makes networking easy. Like really easy. It shines in situations where private networks do not allow inbound connections. Tailscale can connect your devices and development environments for easy access to remote resources, or allow those remote systems to access your home or office network devices.

A few years ago Corey Quinn wrote a Tailscale Lambda Extension. It is great and helped a lot of folks. Today, I'd like to share a new project based on Corey's work that makes it even easier to use Tailscale in Lambda Container. Check it out here.

🔗 Tailscale Lambda Extension for Containers on GitHub 🐙

This new version tries to improve upon Corey's work. Initialization is now stable, there are more configuration options, and we even have multi-platform Docker container packages for both x86_64 and arm64. We even have Amazon Linux 2 and Debian/Ubuntu variants. Installation is really easy, simply add one line to your Dockerfile. For example:

RUN yum install -y curl
COPY /opt /opt
Enter fullscreen mode Exit fullscreen mode

Once your container starts, taking to any device within your tailnet can be done by using the local SOCKS5 proxy. In the example below, we are using Ruby's socksify gem.

require 'socksify/http'
Net::HTTP.socks_proxy('localhost', 1055).start(...) do |http|
  # your http code here...
Enter fullscreen mode Exit fullscreen mode

🔌 ActionCable on Lambda

How did I use Tailscale for the Rails on Lambda work? A few months ago, I started work on the last critical part of the Rails ecosystem which did not work on Lambda... ActionCable & WebSockets. Specifically, I wanted Hotwire to work.

So far, everything is working great with our new LambdaCable gem. Eventually it will be a drop-in adapter for ActionCable and join the ranks of other popular alternatives like AnyCable. To bring the project to completion faster, I needed feedback loops that were much faster than deploying code to the cloud. I needed a development proxy! One where my Rails application would receive events from both Lambda's Function URLs and the WebSocket events from API Gateway. Illustrated below with a demo video.

Architecture diagram of the use of a Lambda development proxy for WebSockets with API Gateway.

If you are curious to learn more about how Rails & Lambda work together, check out our Lamby project. The architecture of Lambda Containers works so well with Rails since our framework distills everything from HTTP, Jobs, Events, & WebSocket connections down to Docker's CMD interface. The architecture above at the proxy layer was easy to build and connect up to our single delegate function, Lamby.cmd. Shown below:

Architecture diagram of the use of a Lambda development proxy for WebSockets with API Gateway.

For our Rails application on Lambda, here are the changes we made to leverage this. All outlined in our WebSockets Demo Pull Request.

  • Created a .localdev folder. Added a copy of our SAM template.yaml for all AWS Resources.
  • Made a simple .localdev/Dockerfile that included the Tailscale Extension along with basic proxy code.
  • Leveraged Lamby's Local Development Proxy Sever.
  • Ensured our Devcontainers exposed port 3000 to all local network devices so Tailscale could detect the service.

I hope you find reasons to learn more about Tailscale and how using a SOCKS5 proxy from Lambda could help your development or production needs. More so, I hope you like the new Lambda Extension project of ours making it easy for containerized applications to use. Drop us a comment if you do.

🔗 Tailscale Lambda Extension for Containers on GitHub 🐙

Top comments (0)