# Heroku

> Deploy Nitro apps to Heroku.

**Preset:** `heroku`

:read-more{title="heroku.com" to="https://heroku.com/"}

## Using the Heroku CLI

1. Create a new Heroku app.

   ```bash
   heroku create myapp
   ```

1. Configure Heroku to use the nodejs buildpack.

   ```bash
   heroku buildpacks:set heroku/nodejs
   ```

1. Configure your app.

   ```bash
   heroku config:set NITRO_PRESET=heroku
   ```

1. Ensure you have `start` and `build` commands in your `package.json` file.

   ```json5
   "scripts": {
     "build": "nitro build", // or `nuxt build` if using nuxt
     "start": "node .output/server/index.mjs"
   }
   ```

## With nginx

1. Add the [Heroku nginx buildpack](https://github.com/heroku/heroku-buildpack-nginx.git)

1. Change to the `node_middleware` preset in your Nitro config

   ```ts [nitro.config.ts]
   import { defineConfig } from "nitro";

   export default defineConfig({
     preset: "node_middleware",
   })
   ```

   Or if you are using Nuxt:

   ```ts [nuxt.config.ts]
   export default defineNuxtConfig({
     nitro: {
       preset: "node_middleware",
     },
   })
   ```

1. As described in the **Existing app** section of the buildpack docs, two key steps are required to get things running:

   - Listen on a socket at `/tmp/nginx.socket`
   - Create a file `/tmp/app-initialized` when your app is ready to accept connections

1. Create a custom app runner (e.g. `apprunner.mjs` at the root of the project). In this file, create a server using the middleware generated by the `node_middleware` preset, then listen on the socket as detailed in the buildpack docs:

   ```ts
   import { createServer } from 'node:http'
   import { middleware } from './.output/server/index.mjs'

   const server = createServer(middleware)

   server.listen('/tmp/nginx.socket') //following the buildpack doc
   ```

1. To create the `/tmp/app-initialized` file, use a Nitro plugin (e.g. `initServer.ts` at the root of the project):

   ```ts
   import fs from "node:fs"
   import { definePlugin } from "nitro"

   export default definePlugin((nitroApp) => {
      if((process.env.NODE_ENV || 'development') != 'development') {
         fs.openSync('/tmp/app-initialized', 'w')
      }
   })
   ```

1. Finally, create a `Procfile` at the root of the project. It tells Heroku to start nginx and use the custom `apprunner.mjs` to start the server:

   ```txt [Procfile]
   web: bin/start-nginx node apprunner.mjs
   ```

1. Bonus: create a `config/nginx.conf.erb` file to customize your nginx config. By default, the `node_middleware` preset does not generate static file handlers, so you can use nginx to serve static files by adding the right location rule to the server block(s). Alternatively, force the preset to generate static file handlers by setting `serveStatic` to `true`.
