Skip to main content
Rails 8.0 Release Candidate just dropped, and it’s packed with exciting features focused on deployment simplicity. While Rails 8 introduces tools like Kamal for “PaaS-free” deployment, there’s still immense value in using a modern cloud platform like Upsun - especially when you want to focus on building features rather than managing infrastructure. Let’s build a simple blog application and deploy it to production in under 10 minutes! Final Blog Application

Prerequisites

  • Basic Ruby knowledge
  • macOS (though Windows/Linux instructions available)
  • Upsun CLI installed
  • Ruby 3.3+ installed

Part 1: Local Development

Setting Up Your Environment

First, let’s install Ruby and Rails on your Mac:
If you want to use PostgreSQL locally via the pg gem, you need to install postgresql@15 on your machine to compile the extension:
If you only want to use sqlite locally and pg on your production install, you will need to add bundle config set frozen false to the Upsun build phase so that bundle can still install the gem on Upsun.

Bootstraping your Rails 8 blog

Let’s create a new Rails application:
Pro tip: Rails 8 uses SQLite by default, which works great for local development but also with Upsun’s persistent storage!

Building the Blog Features

We’ll follow the standard Rails blog tutorial but with some modern twists. Here are the key models we’ll create:
Add the following to app/models/article.rb to map the relationship between Articles and Comments:
Head over to routes.rb and define the following:
We are using a resources here to make thing simple but we could also specify only the index and show routes. And add the reverse one:

To the controllers

Let’s create the two controllers we need there to handle our Articles and Comments. The articles_controller.rb just specifies two actions, index and show:
The comments_controller.rb only handles the Comment creation process as the display is handled by the ArticlesController directly:

Let’s create the Views

With the magic of Claude.ai, we can generate some boilerplate TailwindCSS templates for our pages. If you are curious, here is the prompt that was used. Don’t forget to upload your .erb template in the UI first.
Prompt: Refactor the following Ruby on Rails template. Using TailwindCSS, create a simple and modern design to list the articles from the blog. Include the main blog name. Each article will be show with its title, publication date and a read more button.
Let’s start with our index page app/views/articles/index.html.erb:
And now the single article template app/views/articles/show.html.erb:

Add the TailwindCSS gem

If you refresh your project, you will notice that the styles are not yet applied. We need to add TailwindCSS to our project:
The install command will generate the tailwind.config.js file. No need to change anything there. You can now either build once or watch automatically for any change:
Refresh and your styles should now be properly generated and injected into application.html.erb:
Article Great! Our app is now complete!

Part 2: Preparing for Upsun deployment

Creating Your Upsun Project

Our Upsun git remote is now setup on the repository:

Configuring for Deployment

The magic happens in .upsun/config.yaml. Let’s break down each section of a production-ready Rails configuration:

1. Application Definition

This defines your application’s runtime environment:
  • rails-blog is your application name
  • type: "ruby:3.3" specifies the base image we want to use and the Ruby version

2. Database Relationship

This creates a connection between your application and services:
  • Links your app to a PostgreSQL 15 database
  • Makes the database credentials available via environment variables DATABASE_.
  • Creates a secure internal network between your app and database

3. Web Server Configuration

This configures how your application handles web requests:
  • start command launches Puma using a Unix socket
  • socket_family: unix optimizes for performance by using Unix sockets instead of TCP
  • locations configures the web server:
    • root: "public" serves static files from the public directory
    • passthru: true forwards requests to Rails when no static file is found
    • expires: 1h sets cache headers for better performance

4. Build and Deploy Hooks

These hooks run at specific points in the deployment process:
  • build runs during the build phase when you are not connected to any other services:
    • Installs Ruby dependencies
    • Compiles assets
  • deploy runs when deploying the new container on the host:
    • Runs database migrations
    • You could other actions like cache clearing and the likes

5. Persistent Storage

Configures persistent storage for your application:
  • /log for application logs
  • /storage for uploaded files and Active Storage
  • /tmp for temporary files
  • Each mount persists data across deployments and can be shared between containers

6. Environment Variables

Sets environment variables for your application:
  • PIDFILE specifies where Puma should store its process ID
  • RAILS_ENV ensures Rails runs in production mode

7. Services Definition

Defines the services your application needs:
  • Creates a PostgreSQL 15 database instance
  • Automatically manages backups and updates
  • Provides high-availability configuration

8. Routing Configuration

Configures how requests reach your application:
  • Sets up HTTPS automatically
  • Routes requests to your Rails application
  • Redirects www to non-www (or vice versa)
  • {default} is replaced with your environment URL
The last step is to make sure we properly generate the DATABASE_URL environment variable. Upsun automatically detects any .environment file at the root of the repository.
And that’s all you need!

Database Configuration

Update config/database.yml:

Asset Serving

Rails 8 uses Propshaft for asset compilation, which works seamlessly with Upsun’s static file serving:

Deploying Your Application

Once the build and deploy processes are complete, your new environment will be ready to serve traffic.
💡 Remember you can always use upsun ssh to connect to the container and upsun sql to connect to your database.
If you have setup some seeds in seeds.rb, ssh to the container and run:

Monitoring and Scaling

Upsun provides built-in monitoring and scaling capabilities:

Complete Source Code

Find the complete source code for this tutorial on GitHub: upsun-rails-8-tutorial

Conclusion

While Rails 8 makes self-hosting easier, using a Platform-as-a-Service like Upsun lets you focus on what matters most - building great applications. The time saved on infrastructure management, security updates, and scaling concerns easily justifies the platform cost for most teams. Happy Ruby coding! 🚀
Last modified on April 27, 2026