Skip to content

Instantly share code, notes, and snippets.

@brentjanderson
Last active May 23, 2024 19:33
Show Gist options
  • Save brentjanderson/dcb59c46023c67c44eb12492b038ff84 to your computer and use it in GitHub Desktop.
Save brentjanderson/dcb59c46023c67c44eb12492b038ff84 to your computer and use it in GitHub Desktop.
Running RedwoodJS on Heroku

Redwood aims to be a serverless framework. But what if you really want to run it on Heroku?

This guide aims to walk you through each piece required to make it work.

Running RedwoodJS On Heroku

  1. Add app.json, Procfile, config/nginx.conf.erb, index.js
  2. yarn workspace api add @redwoodjs/api-server
  3. yarn remove -W @redwoodjs/core && yarn add -W @redwoodjs/core pm2
  4. Update your root package.json with the following scripts:
    "scripts": {
        "build": "rw build",
        "start": "node index.js"
    },
  5. Set apiProxyPath in redwood.toml to apiProxyPath = "/api"

Note that you will need to manually add the heroku/nginx buildpack manually to your app if you are setting this up on an already created Heroku stack.

{
"scripts": {
"postdeploy": "yarn rw db seed"
},
"addons": [
{
"plan": "heroku-postgresql",
"options": {
"version": "12"
}
}
],
"buildpacks": [
{
"url": "heroku/nodejs"
},
{
"url": "heroku/nginx"
}
]
}
var pm2 = require('pm2')
var fs = require('fs')
pm2.start(
{
name: 'my-cool-app-pm2', // Change this to whatever you want
node_args: '-r dotenv/config',
script: './node_modules/@redwoodjs/api-server/dist/index.js',
args: `-f api/dist/functions --socket /tmp/nginx.socket`,
env: {
NODE_ENV: 'production',
},
},
function (err) {
if (err)
return console.error(
'Error while launching applications',
err.stack || err
)
console.log('PM2 and application has been succesfully started')
if (process.env.DYNO) {
console.log(`Signaling to Nginx buildpack that we're ready to go`)
fs.openSync('/tmp/app-initialized', 'w')
}
// Display logs in standard output
pm2.launchBus(function (err, bus) {
console.log('[PM2] Log streaming started')
bus.on('log:out', function (packet) {
console.log('[App:%s] %s', packet.process.name, packet.data)
})
bus.on('log:err', function (packet) {
console.error('[App:%s][Err] %s', packet.process.name, packet.data)
})
})
}
)
# This file must be located at config/nginx.conf.erb
# From the NGINX buildpack: https://github.com/heroku/heroku-buildpack-nginx#customizable-nginx-config
daemon off;
# Heroku dynos have at least 4 cores.
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;
events {
use epoll;
accept_mutex on;
worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>;
}
http {
gzip on;
gzip_comp_level 2;
gzip_min_length 512;
server_tokens off;
log_format l2met 'measure#nginx.service=$request_time request_id=$http_x_request_id';
access_log <%= ENV['NGINX_ACCESS_LOG_PATH'] || 'logs/nginx/access.log' %> l2met;
error_log <%= ENV['NGINX_ERROR_LOG_PATH'] || 'logs/nginx/error.log' %>;
include mime.types;
default_type application/octet-stream;
sendfile on;
# Must read the body in 5 seconds.
client_body_timeout 5;
upstream app_server {
server unix:/tmp/nginx.socket fail_timeout=0;
}
server {
server_name _;
listen <%= ENV["PORT"] %>;
keepalive_timeout 5;
location / {
root /app/web/dist;
try_files $uri /index.html;
}
location /api/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server/;
}
}
}
release: yarn rw prisma migrate deploy
web: bin/start-nginx node index.js
@fernandopabst
Copy link

just a note to say this worked (fantastic!) but I had to manually add the nginx buildpack (as https://github.com/heroku/heroku-buildpack-nginx) since it wasn't being picked up through app.json

@brentjanderson
Copy link
Author

just a note to say this worked (fantastic!) but I had to manually add the nginx buildpack (as https://github.com/heroku/heroku-buildpack-nginx) since it wasn't being picked up through app.json

Glad to hear it! On the NGINX buildpack, did you already have an app that you added this to? App.json buildpacks only apply when building a newly-created app. I'll update the instructions with that. 👍 Thanks!

@fernandopabst
Copy link

Glad to hear it! On the NGINX buildpack, did you already have an app that you added this to? App.json buildpacks only apply when building a newly-created app. I'll update the instructions with that. 👍 Thanks!

it was the first deploy in a brand new app. Was quickly fixable, just happy to have my fullstack RedwoodJS running on one heroku dyno :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment