Euruko 2021

Lightning Talk: Shipping Ruby and Rails apps as native Linux packages

Lightning Talk: Shipping Ruby and Rails apps as native Linux packages

by Cyril Rohr

In the lightning talk titled "Shipping Ruby and Rails apps as native Linux packages," Cyril Rohr discusses the challenges of packaging Ruby on Rails applications for native Linux distributions, such as .deb and .rpm formats. The talk emphasizes the relevance of native packages despite the popularity of containerization technologies like Docker, particularly in environments with constraints, such as banks and traditional enterprises. The key areas covered in this presentation include:

  • Advantages of Native Packaging: Native packages are significantly smaller than Docker images, require fewer resources for transfer, and allow reliance on system dependencies. They integrate well with configuration management tools, making them attractive for both developers and end-users accustomed to package installations.

  • Introducing Packager: Cyril introduces the open-source tool "Packager," which automates the process of creating native packages from various programming languages, including Ruby. It detects the language of the application using Heroku buildpacks and generates either a Debian or RPM package based on the target distribution.

  • Package Creation Process: The demonstration involves building a Rails application package using Packager. Cyril details the steps involved—from building the package using the Packager Docker image, to deploying it on a server, and running installation commands. The entire process, including environment setup and configuration, can be completed rapidly, showcasing the efficiency of utilizing Packager.

  • Deployment and Configuration: Cyril demonstrates how to provision a new server, transfer the generated Debian package, and install it using system package management commands. The built-in CLI tools provided by Packager simplify tasks such as setting environment variables, scaling processes, and running database migrations or seeds, showcasing a streamlined development and deployment experience.

  • Conclusion and Takeaways: Cyril summarizes the features of Packager, highlighting its support for various Linux distributions and the potential for automation in package publishing. The ease of generating, deploying, and managing Ruby on Rails applications using native packages reinforces the tool’s practicality for developers looking for a straightforward solution without relying on Docker. For further learning, resources and documentation are available online, encouraging developers to explore Packager for their packaging needs. The talk closes with an invitation for questions and shares contact information for further engagement, promoting an ongoing dialogue with the audience.

00:00:00.399 With these words, we shall continue with our program. We are going to have the next lightning talk, which will not include questions and answers. So, let's keep all the discussions in the stream chat and on Discord.
00:00:08.160 In this presentation, you will learn how to package a Rails application for the main Linux distributions available. You'll also learn how to host the resulting packages and how to apply the same recipe to package a Ruby CLI that can be shipped to users.
00:00:19.999 I am Cyril Rohr, and I discovered Rails in 2006 and have never stopped using it since then. I love Ruby and writing tools that help developers ship code more easily. I am the founder of Packager.io and the CTO at Kellindy.com. I currently live in Brittany, France.
00:00:38.000 Hello and welcome to this talk about packaging Rails applications for Linux. This will be a short talk about how to go from bare code to a deployed application on a server using a Debian package in under five minutes.
00:00:44.560 First, the question is: why bother with packages at all when we have Docker? It's great, but in many places, Docker may not be available. So, system packages are still the way to go if you want to deploy apps, for instance, in banks or other types of enterprises that require them. One advantage is that, most of the time, the packages end up being far smaller than Docker images, resulting in less disk space consumption and fewer resources to transfer.
00:01:12.080 Because they are packaged, you can rely on system dependencies, and if there are any security updates to these system packages, the Linux distribution will handle it for you. Moreover, most end users and customers are already familiar with packages; they know how to install a package, and the ability to simply run 'apt install my application' on a server is quite attractive.
00:01:19.920 Lastly, packaging integrates well with configuration management tools like Puppet, Chef, and Ansible, which makes managing a fleet of servers easier. So, how does it work? I have published a tool called Packager, which is available on GitHub and is open-source. It takes your code, which can be written in Ruby, Node.js, Go, or Python, and detects the language using the buildpacks that Heroku uses. It then performs a compilation step, outputting either a Debian or RPM package depending on your target distribution.
00:01:49.920 You can then take this package and deploy it to any server. To quickly walk through the steps: first, you build your package. This means you take your code and run Packager, which can be executed as a Docker image for ease of use. You apply Packager to your repository folder, and after a while, it produces a Debian or RPM package based on your target distribution. In our example, we will use Ubuntu 20.04.
00:02:07.360 After building your package, you proceed to deploy it. You either provision a new server or use an existing one, connect to it, and run 'apt install' for the package you just compiled. Finally, you need to configure and run your package. Packager includes a CLI tool that is named after your application, allowing you to easily set environment variables and run arbitrary processes within the context of your application, such as a Rails console or Rails task.
00:02:29.600 This tool also allows you to scale your processes as declared in a Procfile, similar to what Heroku uses. For this demo, I have already cloned the Git repository containing the code, which is a standard Rails application. I will now apply the Packager Docker image on the current repository so it can detect the type of application it is.
00:02:49.680 It detected that this is a Ruby application and applied the relevant buildpack. The Ruby buildpack will set up all the gems required by the application, fetch the appropriate Ruby version, and precompile the assets for the application. As a result, we just generated a new Debian package for our application. The next step is to set up the server and run the application on it.
00:03:06.560 To do this, I will provision a new server using Hetzner Cloud, which is quite convenient. Within a few seconds, we will have our server provisioned, and the IP will be displayed. I can then transfer my Debian package to this server using SCP. Of course, you could choose another method to propagate your package, or even publish it to an actual apt repository, but for this demo, I will show you the fastest way to install your application.
00:03:28.240 Once connected to the server, we can run 'apt update' to refresh our package repositories. Finally, we can install our package with the 'apt install' command. Additionally, we want to install Nginx to expose our application on port 80. Now, we have a CLI available to us named 'travel map,' allowing us to run commands to control our application.
00:03:53.199 In our case, we need to configure our application. If you were using a PostgreSQL database, you could configure the database URL using this command or any other environment variable required by your application. However, for simplicity, we will use SQLite locally. We still need to run the Rails DB migrate and DB seed commands. Notice how we didn't have to select any Ruby version or access a repository; we just used the Packager CLI tools included with the package to run the appropriate commands with the correct versions of Ruby and gems.
00:04:16.720 As you can see, we created the database table, and we can scale our main web process for the Puma server using Packager. For example, we can instruct it to scale the process to one instance, if desired. This automatically generates and installs init scripts that allow the process to be restarted automatically if you reboot the server or manage it with tools like Systemd.
00:04:46.720 To check the status of the 'travel map web' process, we can see that it is active, running, and operating on port 6000. To expose the application further for convenience, we can set up Nginx using a one-liner to expose port 6000, followed by reloading Nginx. Finally, when we visit our server, we can see it up and running.
00:05:11.440 When I query for cities around Rennes, where I live, I receive the expected results. This concludes our demo. As you can see, there's not much to it, and it's very fast to build the package, deploy it on the server, and configure and run it. The great thing is it's not limited to web applications; you can also ship CLI tools using Packager, and there are many other features available.
00:05:45.440 For more information, you can refer to the documentation available at the address on the screen. As a recap, Packager supports almost all Linux distributions: Debian, Ubuntu, Red Hat, CentOS, SUSE, and Amazon Linux. This project has been active since 2014 and supports a variety of older versions for each distribution.
00:06:13.840 If you're looking for more automation or want to publish packages on proper APT or other repositories, you can check out Packager.io, which is a self-hosted version of Packager. If you have any questions, I am more than happy to answer them over Twitter or on my personal website, wescott.com, where you can find my contact details. Thank you very much, and I hope you enjoyed the conference. See you next time!