# How to Deploy Ruby on Rails to Render.com

*Published on April 13, 2021*

Hey everyone! Today I want to show you how to deploy a Ruby on Rails application to [render.com](https://render.com)  
  
So a few things off the top:

- I&#39;ll be using an application I&#39;ve already made, in fact it&#39;s from my second course, [Learn Hotwire by Building a Forum](https://store.afomera.dev/learn-hotwire). One Important Bit: It&#39;s already configured to use Postgres for the database in all environments. It also requires Redis to work properly (because it uses Turbo!).&amp;nbsp;
- We&#39;ll need PostgreSQL and Redis as additional services.
- _But we won&#39;t be covering background jobs / email sending / or image uploads._ Those are going to require more work depending on your application.
  - I am very interested in trying out their persistent disk storage, but that comes with limitations depending on how you want to use it. (i.e no zero downtime deploys and you&#39;re limited to one instance for now).

# Render Introduction

Render is a Platform as a Service(PasS) provider, similar to Heroku. Most Rails developers have heard of Heroku, as its super simple to get going with them. One advantage of Render is they bill themselves as a significantly cheaper Heroku. I mean, just look at [their comparison page.](https://render.com/render-vs-heroku-comparison)That seems too good to be true... or does it?  
  
I&#39;m the type of person who wants to explore on my own without resorting to digging through documentation. In Heroku, I know I can just _Heroku create_ my app, deploy it, then go add my resources for redis afterwards and it does all the ENV configuration for me. That&#39;s pretty slick and hard to beat, even though you do pay for it in cost.  
  
Part of that setup ease is habit too, I&#39;ve used Heroku off and on for the better part of like 8 years, so let&#39;s try not to let habit taint the views of this new offering.  
  
With Render, you get only the Bells and none of the whistles Heroku has. There&#39;s only managed Postgres Databases for now, and with Render, it feels like you get more controls. It&#39;s super easy to spin into a shell, and it even seemed like when you opened a shell, you&#39;re on the actual instance running the app! (I ran &#39;ps aux&#39; and it showed me my Puma process! 😱)  
  

# Setting up our app

Okay, we&#39;ll need to make a few changes. Some of these follow[Render&#39;s own deploying Rails guides.](https://render.com/docs/deploy-rails) I ignore some of what they do, because I don&#39;t have a need for multiple workers for my Puma process.  
  
**Update database.yml for production**  
  
Heroku will overwrite the database.yml to support the environment they manage for you. You&#39;ll need to do this yourself. It&#39;s common for Rails apps to use a DATABASE\_URL environment variable for storing the credentials for your database. Heroku adds this for you automatically when you provision your application (or a new database) but for Render you&#39;ll have to do this yourself.

```
production:
  &lt;&lt;: *default
  url: &lt;%= ENV[&#39;DATABASE_URL&#39;] %&gt;
```

Okay cool, that&#39;s good to go.  
  
Let&#39;s add a &#39;bin/render-build.sh&#39; script (again, taken from their guide, but it will allow us to customize it down the road if we need to!)

```
_#!/usr/bin/env bash__# exit on error_set -o errexit

bundle install
bundle exec rake assets:precompile
bundle exec rake assets:clean
bundle exec rake db:migrate
```

We&#39;ll need to ensure we give this script the ability to execute before we commit it!

```
chmod a+x bin/render-build.sh
```

Then, lastly, and this part may need to change, but I had to permit my Render subdomain and custom domain I was adding as an allowed origin for ActionCable. Inside of config/environments/production.rb, add:

```
config.action_cable.allowed_request_origins = [/https:\/\/*/]
```

In this case I&#39;m doing a bad thing, where I permit all https origins to connect to my Cable server. You&#39;d likely want to list your specific domains, but in some cases if you know what you&#39;re doing this is okay.  
  
For me to realize I had to allow it, I saw &quot;request origin not allowed: https://appname.onrender.com&quot; in my logs after I deployed the first time while setting up my app. I&#39;m putting this here, now, so you can maybe avoid the pain.  
  
**TBH** : I have no idea why I didn&#39;t need to make this change on Heroku but did on Render. I imagine it&#39;s some kind of behind the scenes magic with Heroku&#39;s router or something, but nonetheless, I&#39;ll try not to let that bother me. I don&#39;t like asking questions I won&#39;t like the answer for.

  
Okay, so that was all the changes I needed to make. I git committed those, and then pushed it up to GitHub.  
  

# Render setup

Render unfortunately doesn&#39;t let you easily group all of your services into an Application or Project. It would be nice if they did... but alas, let&#39;s create services we need for our application first, before we go to do our first deploy.  
  
In my case, I need Redis and a PostgreSQL database.  
  
Once you have a Render account and have added a Credit Card...  
  
Let&#39;s setup Redis.

1. Fork [this redis repo](https://github.com/render-examples/redis). We need to fork it, so our account doing deployments can access it when we go to deploy a Private service for redis for it.
2. Create a new Private Service
3. Select your redis repo you just forked.
4. For &quot;name&quot;, enter in something you&#39;d like to identify easily. In my case I went with appname-redis, since there&#39;s no grouping, we can at least prefix services with appname- for now.
5. Ensure Docker is the selected Environment&amp;nbsp;
6. Pick a basic plan (I went with Starter for testing!)
7. Click Advanced
  1. Add a new disk. Give it a name and set the mount path to **/var/lib/redis**. Pick a size for the disk in my case I did: **1 GB** should be enough for small projects.

8. Click Create Private Service

When it&#39;s done creating, you&#39;ll see on the page when viewing it: &quot;Service Address&quot; It may look something like &quot;appname-redis:10000&quot; You&#39;ll need this later, for example, this is what we&#39;ll use inside of a REDIS\_URL env for our App web worker.  
  
Let&#39;s setup PostgreSQL:

1. Click New, then click Database in their dropdown.
2. Give it a name, again I chose to use appname-database as my name for it. I left the database and username field blank. I also picked the same region I plan to put everything else in. (Oregon in my case)
3. Click Create

Once it&#39;s done creating, you&#39;ll view it and see &quot;Internal Connection String&quot;. Copy that value, we&#39;ll use that to set it as DATABASE\_URL shortly.   
  
&amp;nbsp; **Let&#39;s create our App service now**

1. Click New -\&gt; Web service
2. Select your source code repository, don&#39;t make a mistake here, you can&#39;t change it later :(
3. Give it a name, in my case &quot;appname-web&quot;. Ensure it&#39;s in the same region as your Database.
4. Update build command to be &quot;./bin/render-build.sh&quot; (no quotes!)
5. Update Start command to be &quot;bundle exec puma -C config/puma.rb&quot; (no quotes!)
6. Click Advanced
  1. NOTE: You may want to use an Environment Group instead if you also need to create a Background worker (like Sidekiq!) That will let you share these variables between the Web + Background Services (handy!)
  2. Under environment variables:
    1. Add DATABASE\_URL to the value of the Internal Connection String from your Database service
    2. Add REDIS\_URL as... &quot;redis://serviceaddress:10000&quot;, aka, take the service address from your private service, and prefix it with redis:// and you&#39;ll be good to go
    3. Add a RAILS\_MASTER\_KEY to the value from your config/master.key or config/environmentname/master.key file (if using environment specific keys)
    4. Or if not using RAILS\_MASTER\_KEY, add SECRET\_KEY\_BASE key and set the value to whatever &quot;rails secret&quot; outputs in your terminal.

7. Click Create Web Service.&amp;nbsp;
8. Let the deploy finish, if it works successfully go try out the app, otherwise read the logs and try and do some troubleshooting. Hopefully it works though! 🎉
9. Assuming it worked, go configure your Custom Domain in Settings on your Web service! Then your app can respond to both the onrender.com domain + your custom domains!&amp;nbsp;

# Overall thoughts

Render wasn&#39;t as quick for me to setup, but it still was faster than doing all of the setup myself. I do wish they had a managed Redis instance, as I have no idea how I&#39;d do a Redis update for my service I just deployed, or if doing so would make me loose data.   
  
**Note:** This is highly opinionated, and I realize Render is a small team, and it will take time for them to come up to the same level as Heroku (which I&#39;ve used for years and years). Take this with a grain of salt, what is a Pro or Con for me, may actually be the opposite for you! Try it out!  
  
Pro: Shell access from the browser, the terminal in the browser feels snappy. A+ job there. Felt like I really had an SSH session open, and wasn&#39;t limited with what I could do. I even &#39;vim&#39;d a file, even though I don&#39;t think it did anything since there&#39;s not a restart option.  
  
Pro: Pull Request Review feature looks neat, but I haven&#39;t tried it out.   
  
Pro: it supports HTTP/2 out of the box, which is nice if you&#39;re using Turbo Frames.  
  
Con: Access controls, for inviting teammates give full access (even for deleting) which feels like a non-starter for considering it for anything for Work. Maybe Teams let you have different controls.   
  
Con: The community/support being on Discourse is fine for some, but for those of us who are worried about harassment, posting in a public forum is not always something we want to do~~. I wish there was different support channel (maybe there is, I just couldn&#39;t find one). This is especially relevant if say you used it for work and needed custom support.~~ **NOTE** : The CEO replied to me on twitter and mentioned there&#39;s always support [at] render [.] com to email for support, so that helps solve that problem!

  
Con: Add-ons are clearly new, there was only one &quot;LogDNA&quot; at the time of writing this (April 14th, 2021). Perhaps more will come in the future.&amp;nbsp;  
  
My Verdict: I&#39;m going to consider using it in the future for projects I have upcoming. I may even move services over to cut costs, if I can figure out a smooth way of moving them off Heroku without a lot of pain.  
  

# Render: Please change these if you&#39;re listening

I have a few things right off the bat I wish were changed... Hopefully these can end up on a Roadmap somewhere and then make their way to Render&#39;s users.

- Application Groups for services (i.e let me put my Web + Database + Redis private service into one Group. If I had a background worker, it&#39;d be worse. Let me manage my access controls for a group from that one place too. Thinking about how I&#39;d handle teammate access and whatnot without going full team support, I didn&#39;t see a way to limit folks from deleting services either when inviting them...).
- Managed Redis please.
- Allow me to change Source Control repositories after creating a service. I&#39;ve had to rename repositories for work before and after I setup a service to test with I had no way to switch out my repo used for deployments so... I would have had to go make a completely new service for a production app if we were using Render at the time. Scary and frustrating!
- CLI / + REST API - It&#39;d be so nice to be able to get into a shell from a CLI (ala &#39;heroku run rails console&#39;) or view logs (for small apps that aren&#39;t a log streaming disaster). For the REST API... I want to be able to manage my ENV configs + Manage custom domains for my services.&amp;nbsp;

  
I&#39;d love to know your thoughts. [Tweet me!](https://twitter.com/afomera)  
  
- Andrea

---

By [Andrea Fomera](https://afomera.dev) | [View original post](https://afomera.dev/posts/2021-04-14-deploy-ruby-on-rails-to-render)
