00:00:10.000
Good afternoon! Welcome to introducing Kamal Proxy. My name is Kevin, and I'm a programmer at Th7 Signals. Kamal Proxy is one of the projects I've been working on recently.
00:00:19.400
Before I get started, I wanted to mention that if you've just watched Donal's talk, which is also about Kamal, don't worry. I will be focusing more on the proxy layer rather than just Kamal itself. There might be some overlap, but I hope it won’t feel like a Groundhog Day situation for you. If you didn’t watch Donal’s talk, also don’t worry; there's not much prior knowledge of Kamal that you’ll need to understand this talk.
00:00:33.640
In fact, all the essential information about Kamal that you need to know for this talk can fit on one slide, which we'll review in a moment. Let’s quickly go over what we’ll cover in this talk: first, I'll explain what Kamal Proxy is, then discuss why we decided to build it, how it works, and what it’s designed to do. The bulk of the presentation will take you on a brief tour of the new features we've added to the proxy.
00:00:53.640
There are nine features organized into a few different categories. Some are designed to make it easier to set up your deployments so that they feel production-ready. I know that term is a bit vague, but it will become clearer as we dive into the details. Other features are aimed at improving the performance of your applications in production, and finally, we have features that assist in managing your apps once they are live.
00:01:08.240
At the end of the talk, I'll provide some insight into what features might be coming next for Kamal Proxy. As promised, here's the one slide guide to Kamal: the main thing you need to know is that it’s a tool for deploying apps. If you've built an application, probably in Rails, and want to deploy it to production so that users can access it, Kamal is there to help.
00:01:20.659
Kamal is Docker-based. It works by building a container image for your app, shipping that out to your servers, and then running the container image on those servers. Importantly, for the purposes of this talk, it supports what we call gapless deployments.
00:01:28.840
In gapless deployments, if you have a version of your app running in production and you deploy an updated version, there should be no gaps in service. You should not experience any downtime as the new version boots up or have any requests that are errored or dropped during the deployment process. It's a seamless transition from one version to the other.
00:01:46.440
As we’ll see in a minute, the proxy layer is essential for achieving this. Despite summarizing Kamal in one slide, it does many other things as well. I acknowledge that by trying to condense this down, I'm underselling the capabilities of Kamal, but those additional parts are not necessary to understand for the purpose of discussing the proxy layer.
00:02:01.280
Now, regarding the gapless deployments, when you have a version of your app running and have built the app container, we don't run it on its own on a server. Instead, we run it alongside or behind a small proxy layer. All the traffic destined for your app comes through the proxy layer before reaching the app itself. This proxy provides a stable endpoint, enabling us to change configurations behind the scenes to transition to new versions without affecting how users access your app.
00:02:30.440
During a deployment, the process involves starting a new container with the updated version of your app. We then ask the proxy to switch traffic from the old container to the new one. After that, we can remove the old version, effectively completing the deployment process. In Kamal 1, we utilized a third-party proxy called Traffic, which Kamal Proxy is now replacing. This leads to a natural question: why create a new proxy if one was already in use that worked?
00:02:44.160
There are two core reasons for this. The first is iterative improvement; we wanted to enhance how gapless deployments are managed. While they worked in Kamal 1, it was complicated to ensure they functioned seamlessly. The Kamal codebase had to deal with many intricate interactions with the proxy to ensure a smooth transition between versions without errors. Additionally, we encountered edge cases and sharp edges in the old setup.
00:03:10.000
As we worked with that setup, we realized that by building our own proxy that is purpose-designed for handling this specific traffic switch, we could simplify the process, make it more robust, and potentially enhance performance. This new proxy has a deeper understanding of request details, allowing it to speed up the overall deployment process. This was the first compelling reason for the new proxy; the second reason surfaced while we were working on a different project.
00:03:42.680
About a year ago, I was on a team at Th7 Signals focused on building a new line of products called 'Once'. The first offering in this line was Once Campfire, which you may have encountered if you've attended Rails World. The idea behind Once is that rather than relying on traditional Software as a Service (SaaS) models, we wanted to offer packaged software that users could run independently on their servers without incurring ongoing costs.
00:04:20.920
To ensure this model was viable and appealing, we needed the deployment process to be straightforward. Users should ideally be able to purchase the software, get it running on the internet easily, and have everything work right away. This required us to build features that delivered sufficient performance even on modest hardware, ensuring you don't have to spend excessively on hosting.
00:04:42.839
We needed to address common tasks that would usually need to be configured outside the application, such as setting up SSL certificates or ensuring that static files were served correctly. We managed to tackle these challenges for Once Campfire with a library called Thruster, which acts as a proxy running alongside the Rails process in the container, providing essential support for capabilities that would otherwise be missing.
00:05:06.760
The Thruster library allows a Rails application to serve content effectively from just a container setup, ensuring a production-ready experience. This encouraged us to think about how we could transpose these benefits into Kamal Proxy and offer the same conveniences to any Rails application created by developers.
00:05:24.760
The aim was to ensure that when users deploy their apps, they can receive the same seamless experience of launching their applications on the internet without the technical hassles that are often involved. In essence, we focused on not just getting applications to run, but also ensuring they perform optimally once deployed.
00:05:50.760
In Rails, the default configuration provides a setup where when you create a new app and deploy it via Kamal, the Kamal Proxy will operate on the front-end of your app, and Thruster will run as a companion within the container alongside Rails. The two will cooperate to address all the missing pieces that are critical to achieving a fully operational production environment. I realize that I may still be vague regarding what these critical pieces are; however, I will clarify shortly.
00:06:55.440
The main aim is to make the process easier, not only to get your applications running but to ensure that they run incredibly well. Currently, in Rails, if you deploy a new app, Kamal Proxy will be in place in front of your application to ensure everything flows smoothly, with Thruster ensuring that it operates beside Rails.
00:07:10.560
The first of the main objectives we had with Kamal is to streamline the deployment process. We believe it should be incredibly simple and efficient to deploy an application, which means fewer constraints and less complexity when delivering updates to users. By creating a proxy that can efficiently manage traffic and adapt to applications as they evolve, we provide a solution that enhances user experience.
00:07:29.760
As for the new features of Kamal Proxy that facilitate streamlined deployments, the first is host-based routing. Given that earlier deployments often experienced overlap on the same server ports, which created issues, we have built in host-based routing that resolves this problem. This allows you to deploy multiple apps onto one server easily by specifying the host name for each app.
00:07:44.760
Additionally, we’ve implemented automatic HTTPS through Let's Encrypt. Almost all applications require HTTPS as a basic security standard, and by selecting this setting during deployment, the process becomes automated and user-friendly. All of these changes contribute significantly to ensuring the deployment process is efficient and reliable.
00:08:09.160
Another feature we introduced is buffering of requests and responses by default to ensure that Rails processes remain insulated from potentially troublesome clients who might stall or misbehave. Clients that take a long time to send or read data can monopolize a Rails worker if unchecked. Our buffering layer handles incoming requests and responses, allowing Rails workers to focus on successfully serving other incoming requests.
00:08:30.760
The next category of enhancements focuses on performance improvements. By default, Kamal Proxy serves all traffic over HTTP/2—this is a significant upgrade compared to HTTP/1.1, which you would normally encounter when running Puma. HTTP/2 allows for faster transmission and improved efficiency, particularly for applications with numerous files needing to be downloaded, like those overflowing with assets.
00:08:54.560
Moreover, the performance enhancements we executed are designed to accelerate content delivery from applications back to clients. We recognize that efficiency is critical for optimal usability and user satisfaction. This includes HTTP caching and extended file support, which allows static files and certain unchanged pages to be cached effectively.
00:09:15.960
The HTTP caching feature is significant because most web applications contain static files that cache exceptionally well—such as stylesheets and images, and Thruster keeps a memory cache of all these cachable responses encountered in the Rails application.
00:09:29.160
By default, asset serving will be faster simply out of the box since every new version of your application will cache assets during its deployment, automatically improving performance. However, the benefits extend beyond just asset caching because caching can also be utilized for other non-dynamic responses—by simply setting appropriate cache-control headers.
00:09:58.560
I conducted some tests using Campfire to measure the impact of these caching strategies. Running on a low-end Digital Ocean droplet, I observed that dynamic pages served around 160 requests per second. However, when marking those pages as cacheable, Thruster allowed for serving those same pages at rates of approximately 800 requests per second. That’s an impressive increase in throughput, emphasizing the importance of dynamic versus static content considerations.
00:10:32.480
Another performance improvement made is related to EXE file handling conventions, which optimize content delivery. Instead of Rails having to return extensive file content, it simply responds with the path of the file location. In this case, Thruster takes over the task of serving the file, improving efficiency and decreasing load on Rails.
00:10:55.280
This method is also beneficial if you are utilizing Active Storage to host content on the file system that the app container can access. Consequently, serving these files will rely on Thruster, leading to faster delivery and freeing rails workers for other tasks.
00:11:09.760
The final category of features is focused on enabling easier management of apps post-deployment. These innovations offer significant conveniences that wouldn’t normally be available with a standard proxy solution. The first feature is an easy way to set up a maintenance page. If you need to conduct system upgrades or changes, it’s common practice to inform users that your app is temporarily unavailable.
00:11:31.760
In Kamal Proxy, you can invoke the 'cal proxy stop' command, and the proxy will immediately begin serving a temporarily unavailable page. Although it is a generic page that does not have specific information about your app or its reasoning for going down, you have the option to display a personalized message.
00:12:01.480
You can also provide custom HTML templates for the maintenance page, allowing you to brand these pages according to your app’s design. Once you are finished with your maintenance actions, a simple 'resume' command will bring your app back into service.
00:12:21.920
Another feature, related to maintenance, is the ability to pause requests temporarily. This is useful when you need to perform a quick update or reboot a database service without enduring downtime. For instance, you could pause incoming requests momentarily while making necessary changes behind the scenes, preventing end users from experiencing errors during that time.
00:12:58.560
Typically, you would first execute the 'proxy pause' command, perform your task, and then resume. This command structure allows for requests to queue up until your app is ready to process them, ensuring users remain unaware of maintenance activities. I have a small video demonstrating this feature in action.
00:13:24.760
The demonstration shows a Campfire instance running behind Kamal Proxy. Once I trigger the 'pause' command, users will see a loading bar, indicating that the request is queued without errors appearing. After resuming, the request processes seamlessly.
00:13:39.920
The last feature I’d like to highlight is the 'rollout' functionality. It allows for deploying an alternative version of your app alongside the main version, utilizing traffic splitting to direct a portion of requests to this alternate roll-out version. This feature is particularly effective for canary deployments, where you experiment with changes on a subset of users before rolling them out more broadly.
00:14:05.680
To use it, you first set a cookie that helps identify requests belonging to specific users; for instance, by using account IDs or user IDs. Then you can employ a traffic splitting strategy to determine which users are directed to the roll-out version. This allows for gradual and low-risk execution of updates, based on real user feedback.
00:14:43.200
The rollout command is straightforward: you can specify how you’d like traffic allocated, whether by percentage or specific user accounts. At the end of your testing, simply calling 'rollout stop' reverts all traffic back to your main container, undoing any rolling out changes you’ve made.
00:15:11.120
These features are already implemented at the proxy level, with many functioning autonomously, while others you can call through Kamal commands. Some, like EXE file support or request buffering, work behind the scenes without requiring user action. Others, such as settings for multiple apps per server, depend on the Kamal configuration that users can customize.
00:15:53.440
It's worth noting that while some features are fully implemented today, others exist only at the proxy level and haven’t yet been incorporated into the Kamal CLI commands. However, they will be soon, allowing for a unified command set for users.
00:16:22.760
In summary, today we covered the essential features of Kamal Proxy, focusing on how it improves deployment processes, enhances performance, and offers tools for better management in production environments.
00:16:25.920
Looking ahead, we are constantly searching for ways to enhance the Kamal Proxy experience, particularly in finding new conveniences that users have come to expect in managed environments. Our goal is to develop solutions that bridge any gaps left by self-hosting, ensuring users feel confident and empowered in their deployment decisions.
00:17:31.920
Two areas of interest are load balancing and WebSocket acceleration. Presently, Kamal can deploy applications across multiple hosts, but users have to manually manage load balancing. However, it would be effective and beneficial for our platform to offer built-in load balancing at the proxy level to streamline this process for users.
00:18:06.040
As for WebSocket acceleration, we’re exploring options for optimizing traffic flow through the proxy layer for applications that require real-time data transfer, such as those utilizing Action Cable. By intercepting and optimizing WebSocket traffic at this level, we aim to enhance the overall responsiveness of applications.
00:18:21.920
That wraps up everything I wanted to cover today. Thank you for listening! If you have any further questions or want to discuss proxies, feel free to reach out to me via email.