Skip to main content
A Ruby web application runs on Sevalla as an application: Sevalla builds an image from your Git repository, then runs it as processes. The web process serves HTTP with Puma, background workers run job queues such as Solid Queue, and jobs run database migrations before each deployment.

Framework guides

Rails

Deploy Rails with PostgreSQL, then add background jobs, object storage and caching.

Sinatra

Deploy a Sinatra application with Puma and config.ru.
Moving from Heroku? See Migrate from Heroku.

How Ruby applications run on Sevalla

Every process (web, worker, cron job and job) runs from the same image, each with its own start command. See Processes for every process type and its settings. Ingot stops the build with a message in the build log when Bundler can’t install the gems as committed:

Pin the Ruby version

Ingot builds on Ruby 4.0, its default line, unless the project sets a version. Pin the line you develop with in the Gemfile, under the source line, so the build doesn’t change when a new Ingot release moves its default line:
Gemfile
Then run bundle install to record it in Gemfile.lock. ~> 4.0.0 allows any 4.0 release: Ingot builds on the 4.0 line’s image, which moves to each new patch release, and Bundler refuses to run the application on another line. Ingot takes the version from the first of these that’s set:
  1. The INGOT_RUBY_VERSION environment variable, or versions.ruby in ingot.json.
  2. The ruby line of the Gemfile, or the file it names with ruby file: ".ruby-version".
  3. RUBY VERSION in Gemfile.lock, which records the version when the ruby line computes it, as ruby File.read(".ruby-version") does.
  4. .ruby-version, then .tool-versions or mise’s configuration.
The build plan’s Ruby row shows the version and where it came from. An exact release, such as the ruby-4.0.9 that rails new writes to .ruby-version, builds on that release only, without later security fixes; with the ruby line in the Gemfile, Ingot doesn’t read .ruby-version. Ingot builds with the standard Ruby interpreter: a Gemfile that names another engine, such as JRuby, fails the build. See Set the language version.

Build with a Dockerfile

Ingot needs no Dockerfile. When you want full control of the image, a Dockerfile for a Ruby application builds the gems in one stage, from Gemfile.lock with BUNDLE_DEPLOYMENT set, and copies them with the code into a final stage on ruby:4.0-slim-trixie, the Ruby line the Gemfile pins. The final stage keeps the code owned by root, runs as a non-root user with UID 1000, and starts Puma in exec form so it receives SIGTERM and finishes its requests, listening on PORT (8080 by default). Rails generates a Dockerfile with rails new: see Deploy a Rails application for what to change for Sevalla, and Deploy a Sinatra application for a Rack application.