On this page 10 sections
A Rails app needs three things from a host: a place to run Puma, a Postgres database it can reach, and a way to run db:migrate before traffic hits the new code. Ownkube covers all three without a cloud account or hand-written YAML.
This walks through deploying a standard Rails app on Ownkube Compute: configuring Puma, wiring up a managed Postgres, setting RAILS_MASTER_KEY and SECRET_KEY_BASE, precompiling assets, and running migrations as a job.
TL;DR
- Push a Rails app with a
Dockerfile, and Ownkube builds and deploys it behind automatic TLS. - Add an Ownkube-managed Postgres database and set
DATABASE_URLfrom its connection string. - Set
RAILS_MASTER_KEY(orSECRET_KEY_BASE) andRAILS_ENV=productionas environment variables in the dashboard, not in the repo. - Precompile assets in the Docker build step, and run
db:migrateas a one-off job, so it runs once per release instead of on every container start. - Metered billing fits Rails well: Puma sits mostly idle between requests, so the CPU line barely moves outside real traffic.
1. Prepare the app for production
Rails is opinionated enough that most of the setup is standard Rails. Confirm the basics before you deploy:
config/database.ymlreads its production connection fromENV["DATABASE_URL"], which is the Rails default.config/environments/production.rbhasconfig.assets.compile = falseandconfig.public_file_server.enabledset to match your asset pipeline (Propshaft or Sprockets, either works).Gemfileincludespgfor the Postgres adapter andpumaas the app server.
production: <<: *default url: <%= ENV["DATABASE_URL"] %>2. Write a Dockerfile
Ownkube deploys from a Dockerfile. A multi-stage build keeps the final image small and lets you precompile assets during the build:
FROM ruby:3.3-slim AS build
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev git curl \ && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY Gemfile Gemfile.lock ./RUN bundle config set without 'development test' \ && bundle install --jobs 4 --retry 3
COPY . .
# Precompile assets. SECRET_KEY_BASE_DUMMY lets this run without real secrets at build time.RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile
FROM ruby:3.3-slim
RUN apt-get update -qq && apt-get install -y libpq-dev curl \ && rm -rf /var/lib/apt/lists/*
WORKDIR /appCOPY --from=build /usr/local/bundle /usr/local/bundleCOPY --from=build /app /app
ENV RAILS_ENV=productionENV RAILS_LOG_TO_STDOUT=trueENV RAILS_SERVE_STATIC_FILES=true
EXPOSE 3000CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]Puma’s default config/puma.rb reads the port and worker count from environment variables already, so leave it as Rails generated it:
port ENV.fetch("PORT", 3000)workers ENV.fetch("WEB_CONCURRENCY", 2)threads_count = ENV.fetch("RAILS_MAX_THREADS", 5).to_ithreads threads_count, threads_count3. Push the repo and create the app
Connect the repository from the Ownkube dashboard (app.ownkube.io) to deploy on every push, or deploy the current directory with the okctl CLI:
okctl loginokctl up --name rails-app --port 3000Ownkube builds the image from your Dockerfile, allocates a hostname on *.ownkube.app, and issues TLS automatically, so you have a working HTTPS URL the moment it deploys. Serving the app on a domain you own is available today when it runs on a Starter cluster in your own AWS account; custom domains on Ownkube Compute are on the roadmap.
4. Add a managed Postgres database
Create a database box from the dashboard: New > Database > Postgres. It provisions a private (in-region) Postgres box starting at $4 a month plus storage at $0.25 per GB, with backups and point-in-time recovery available on Personal and Team.
The database runs as a single private instance by default; opt-in public access and, on Team, high availability are per-database options when you need them.
Link the database to the Rails app. Ownkube writes its connection string into the app as a secret DATABASE_URL variable and redeploys it:
okctl deploy link rails-app <database-id>Because config/database.yml already reads from ENV["DATABASE_URL"], no further Rails configuration is needed.
5. Set your secrets
Rails needs its master key or secret key base to decrypt credentials and sign sessions. Set it as a secret environment variable in the dashboard and keep config/master.key out of the repository:
okctl vars set rails-app RAILS_MASTER_KEY="$(cat config/master.key)" --secretokctl vars set rails-app RAILS_ENV=productionIf you use SECRET_KEY_BASE directly instead of the encrypted credentials file, set that instead:
okctl vars set rails-app SECRET_KEY_BASE="$(bundle exec rails secret)" --secretEnvironment variables set through Ownkube are encrypted at rest and only injected into the running container.
6. Run migrations as a job
Run db:migrate as a one-off job instead of on every container start. Create a Job deployment from the same repository, set its command to bundle exec rails db:migrate, and leave the schedule empty. Variables are set per deployment, so give the job the same RAILS_MASTER_KEY and RAILS_ENV and link the same database to it.
Then trigger a run whenever a release includes new migrations:
okctl deploy link rails-migrate <database-id>okctl deploy job-runs trigger rails-migrateokctl deploy job-runs list rails-migrateThe run’s output is on the job’s Logs tab. The web app and the job deploy independently, so keep each migration safe for the version already running: add columns and tables in one release, and drop old ones in a later one.
7. Scale and watch it run
A fresh Rails app usually starts fine on a small metered ceiling, for example a 500m CPU limit and 1 GiB of memory, set on the sliders under Settings → Resources.
Turn on horizontal autoscaling if traffic is uneven, so Ownkube adds Puma instances under load and scales back down when it is quiet. On Ownkube Compute you turn it on through your coding agent (the update_deployment MCP tool) or the API, with a minimum and maximum replica count and a CPU target such as 70%.
Logs and metrics for the app and the database box are both in the dashboard, so a slow migration or a Puma worker that keeps restarting shows up in one place.
Moving to your own AWS later
If a customer contract requires the app to run in a named AWS account, your own or the customer’s, the same Dockerfile and Rails app move there with no rewrite. Ownkube provisions the instance, wires up the same deploy flow, and brings the logs, metrics, and health checks with it.
Railway, by contrast, only runs on Railway’s infrastructure. Our Railway alternatives guide compares Railway with the other options.
FAQ
Does Ownkube support Rails credentials and Active Storage?
Yes. Encrypted credentials work through RAILS_MASTER_KEY as shown above. Active Storage works against any S3-compatible bucket you configure; Ownkube does not provide managed object storage directly, so point it at your own bucket.
Do I need a Dockerfile, or can Ownkube detect Rails automatically?
A Dockerfile gives you full control over the Ruby version, native gems, and the asset precompile step, and is the most reliable path for Rails. Simpler apps without native dependencies can also deploy straight from source.
Can I run Sidekiq or another background worker alongside the web app?
Yes. Deploy the worker as a second Ownkube app pointed at the same Postgres connection string (and a Valkey cache box from $2 a month if you need Redis for the queue), so the web app and worker scale independently.
What happens if my wallet balance runs out mid-month?
The app pauses and its data, including the Postgres box, is kept. Adding credit or the next monthly plan load resumes it. Unused wallet credit rolls over and never expires, so credit from a quiet month carries into the next.
Can I roll back a bad deploy?
Yes. Ownkube keeps prior image versions and supports zero-downtime rollback from the dashboard or okctl, so a code issue does not require a manual recovery. A rollback restores the previous image, and a migration that already ran stays applied, so keep migrations additive.
For the always-current version of this walkthrough, see the Deploy Ruby on Rails guide in the docs.
Where Ownkube fits
Rails wants a real database, a way to run migrations, and an app server that survives restarts, and Ownkube gives you all three without provisioning a cloud account first. Push the Dockerfile, attach a managed Postgres, set your secrets, and run migrations as a job. See Ownkube pricing for the per-minute wallet model, from $5 a month. Deploy my first app.