DocsRuby (Sinatra and Rack)

Ruby (Sinatra and Rack)

Deploy a Sinatra or plain Rack app on Ruust: bundled, served over HTTPS, and bound to the port Ruust hands it.

Ruust detects a Ruby app from the Gemfile at the repo root and builds it with Nixpacks. It runs bundle install, then boots your app as a long-running Egg. Sinatra apps and plain Rack apps (anything with a config.ru) both work the same way. If you would rather control the build yourself, add a Dockerfile and Ruust builds that instead.

Deploy it

  1. Push your app to a Git repo with a Gemfile and a config.ru at the root.
  2. In the dashboard, choose New Egg and connect the repo.
  3. Pick a size and a region (London or Virginia), then lay the Egg.
  4. Watch it incubate (build) and hatch (go live) on its <name>.<region>.ruust.run URL.

The port

This is the one thing you must get right. Ruust sets a PORT environment variable and your app has to listen on it and bind to 0.0.0.0, not localhost. An app bound to localhost builds fine but never hatches, because nothing outside the container can reach it. Rackup and Puma both read PORT if you pass it explicitly.

bash
# Rackup
bundle exec rackup -o 0.0.0.0 -p $PORT

# Or Puma directly
bundle exec puma -b tcp://0.0.0.0:$PORT
Either server, bound to 0.0.0.0 on $PORT.

Pin the start command and Ruby version

Add a Procfile at the repo root with a web: line to say how your Egg boots. On the Nixpacks path the web: line is read by Nixpacks and baked into the image as the start command (it is ignored when you supply your own Dockerfile); Ruust itself does not parse the Procfile. Pin the interpreter with ruby "3.3.4" near the top of your Gemfile, which Nixpacks reads to pick a matching Ruby, and declare your server there too (gem "puma", or gem "rackup" for the rackup command). Your config.ru is the Rack entrypoint that boots, for example require "./app" then run Sinatra::Application.

text
web: bundle exec rackup -o 0.0.0.0 -p $PORT
Procfile at the repo root.

Environment variables