Creating and deploying a Vapor (Swift) web app into Heroku cloud platform — Part (1/2)

Ricardo Santos
7 min readJan 4, 2021


2020 @


This is the first of a serie of 2 articles:

The first article approaches how to Deploy on Heroku cloud platform a web app built using Vapor.

The second article is the natural evolution of this one, and we will improve our web app to deal with more complex HTTP methods (GETs, dynamic routing, POSTs…), and also integrating a PostgreSQL database.

Before we start, and if you’re not familiar with Heroku and Vapor,

Heroku is a cloud platform as a service (PaaS) supporting several programming languages, and Vapor is an open source web framework written in Swift that can be used to create RESTful APIs, web apps, and real-time applications using WebSockets.

I — Creating a web app using Vapor.

Installing Vapor on macOS.

Vapor can be installed using brew package manager, just by executing on macOS Terminal:

$ brew tap vapor/tap
$ brew install vapor/tap/vapor

More details or options about how to install Vapor on macOS can be found here.

Creating a Vapor web app.

Now that Vapor is installed we will create our first project. Lets say you want your project to be named MyFirstWebApp , execute on macOS Terminal:

$ vapor new MyFirstWebApp

Note: During the install, you will be asked if you want to include in your project the Leaf framework (for easy-to-use dynamic HTML) or the Fluent framework (ORM for easy-to-use databases). You can include Fluent since we will be using it next tutorial. About Leaf, you can skip it.

Image 1 : Vapor template app install

The vapor new MyFirstWebApp command created a folder with a brand new template project. Let see how it looks:

$ cd MyFirstWebApp
$ open Package.swift

After opening the project, and once the Swift Package Manager dependencies have finished downloading, click the play button to build and run your project.

Open your web browser, and visit localhost:8080 or

Image 2 : Vapor template app, first run

More information about how to create your first web app can be found here.

II — Creating an Heroku web app dyno/container

Creating an Heroku app dyno/container

Go to Heroku dashboard at (you must be registered) and create a new app.

Image 3 : Creating our dyno/app container on Heroku platform.

(Friendly note: you can have 5 apps for free)

Adding buildpack

Buildpacks are scripts that run when your app is deployed. They are used to install dependencies and configure your environment.

Saying so, on you app settings, we will need to add the Vapor buildpack. Just add the following url :

(Friendly note: you can also add Vapor build pack via Heroku CLI)

More info about buildpacks can be found here and here

III — Deploy your web app into Heroku

Installing Heroku CLI

There are several ways to deploy your code into Heroku. Connecting to your GitHub is provably the simplest way, but using Heroku CLI is provably the most useful on a long run because makes it easy to create and manage your Heroku apps directly from the terminal,

Image 5 : Heroku deployment methods

To install Heroku CLI execute on macOS Terminal:

$ brew tap heroku/brew && brew install heroku

After you install the CLI, run the heroku login command. You’ll be prompted to enter any key to go to your web browser to complete login. The CLI will then log you in automatically.

Image 6 : Heroku CLI login

More info about Heroku CLI can be found here.

Deploying app using Heroku Git

After Heroku CLI is installed and you login, we need to link your app source code with the your app Heroku git repository (and push the changes). To do so, inside your project folder, execute on macOS Terminal:

$ heroku git:remote -a my-first-vapor-web-app
$ git add .
$ git commit —m ‘first commit!’
$ vapor heroku push

Note that my-first-vapor-web-app was the name we gave our app on the beginning of this chapter.

Deploying app using Heroku Git : trouble shooting

As reported here you will face the following error:

remote: error: missing LinuxMain.swift file in the Tests directory 

You can either (for now) just comment the test target on your Package.swift file as showed bellow…

Image 7 — Dealing with error “missing LinuxMain.swift file in the Tests directory"

or passing the --enable-test-discovery build flag via Heroku configuration and attempting to deploy again.

$ heroku config:set SWIFT_BUILD_FLAGS="--enable-test-discovery"
$ git commit -m "Enable test discovery on Heroku" --allow-empty
$ vapor heroku push


Everything looks good, we have deployed our code with success, but when we try to test…

Image 8

Happens that Heroku apps must include a Procfile.

A Procfile is a file that specifies the commands that are executed by the app on startup. Is always a simple text file that is named Procfile without a file extension.

We can create our Procfile by executing on macOS Terminal:

$ echo "web: Run serve —-env production --hostname —-port $PORT" > Procfile

About our Procfile:

  • web states that our dyno is a web app,
  • Run serve will start our web app in production environment mode (--env production ),
  • —- hostname states that your app host ip will be assigned by DHCP. More info (here)
  • Our web app listening port (--port $PORT) is a config var. You can find config vars section on your app settings (See Image 9). If you don’t implicitly assign a port of your preference, Heroku will choose one; still is recommended to set the port on your Procfile.
Image 9 : Heroku environment vars

More information about your Procfile can be found here (highly recommended reading).

One last push (after adding Procfile)…

$ git add .
$ git commit -m "Added Procfile"
$ vapor heroku push

And our first Vapor web app was successfully deployed on Heroku and is ready to serve.

IV — Extra notes

Scale up

Once you’ve built successfully, you need to add at least one server, one web is free and you can get it with the following:

$ heroku ps:scale web=1


A quick way to troubleshoot problems is checking your app logs using heroku logs --tail or and then look for the error meaning here.



All the materials used can be found at here.

V — Next?

On the next article of this series (available at 8 Jan 2021), we will improve our web app with some utilities, and learn to deal with more complex HTTP methods (GETs with dynamic paths, POSTs) and how to integrate a PostgreSQL database.

VI — Article review by

VII — Related