Guides

We have written quick and helpful guides to help you get the most out of Fly.

If you're looking for our freshest, most up-to-date, and deepest content, checkout the Fly Blog.

How to Setup a Slack Auto-Invite Using Fly

Slack is a great way to connect with users in your community, but it can be a little daunting going through the invite process. Manually accepting email invites can take a lot of time, and even worse, you might miss some users. How can we make it easier to get users to join your Slack group? We can set up an auto-invite system and host Slack in your browser in just a few steps using Fly.

Step 1. Initialize Repo

Create a new directory and initialize the git repository:

$ mkdir slack-invites && cd slack-invites
$ git init

We will be using the slackin npm package to run our server, so make sure you install it as a dependency:

$ npm init
$ npm install --save slackin

We will need to pass a few parameters into slackin. These will come into play when we deploy using Heroku. Create a Procfile with the contents:

web: ./node_modules/.bin/slackin $SLACK_SUBDOMAIN $SLACK_API_TOKEN -P "$FLY_REL_PATH"

The FLY_REL_PATH will be the path our auto-invite system is hosted on. For example, we use https://fly.io/slack/ and our relative path is /slack/.

If you would like to get a list of all the options available, just run slackin --help.

Commit your changes and push them to git.

Step 2. Create Slack Team

Create your Slack team here.

Now you'll need a Slack token! This project relies on generating a legacy token, which you can do here.

Step 3. Deploy using Heroku

Sign up/login in to Heroku.

Create a Heroku project and link it to your GitHub repo.

In the Settings tab, set the following environment variables:

SLACK_API_TOKEN
SLACK_SUBDOMAIN
FLY_REL_PATH

Step 4. Configure Fly Load Balancer

Sign up/login in to Fly. If you haven't already, you should start by setting up your app.

If you're using a custom domain, you'll also need to configure DNS and confirm your domain is verified.

Hostnames

Once you've done so, in the "Dashboard" click on the app you just created. Then go to the "Routing" tab.

Go to "Backends" and add your Heroku app as a new backend. It should look something like this:

Backends

Next, in "Rules", add a routing rule. Make sure the "Path to match" is the same as the FLY_REL_PATH you set as an environment variable in your Heroku project. "Rewrite Path" should be /.

Add routing rule

Rules

That's it! You should be able to go to https://yourdomain.com/slack/ and start inviting people to your Slack team!

Success!

How to Use the Google Authentication Middleware

The Google Auth Middleware allows you to define restrictive authentication rules for your site.

Getting a client id and secret from Google

  • Setup an app in your Google API Console.
    • Select OAuth client ID from the Create credentials drop down.
    • Choose Web application as the Application Type.
    • Define a descriptive name.
    • No need to fill in Authorized JavaScript origins.
    • Fill in Authorized redirect URIs with: https://<your site hostname>/__fly/auth/google/callback.
  • Next, we need to securely store your client ID and secret within Fly.

Configure

  • To add the client ID and secret within Fly, add the Google Auth Middleware from your site's Middleware page.

Enable Google Auth

  • Configure a client id, client secret and google apps domain.

Configure Google Auth

Setup Your Application

Before each request, you'll want to verify a user has properly gone through the Google OpenID Connect process.

  • Fly will send back a Fly-Google-Auth-User-JWT header to your app.
    • It represents the authenticated user's ID token, encoded and signed as a JSON Web Token.
    • You can decode and verify this token with your site's Fly public key according to the JWT standard.
    • The JWT's payload contains these fields:
      • exp - Expiration time.
      • iat - “Issued at” time.
      • aud - “Audience” is the base URL from the request.
      • iss - Issuer.
      • sub - Unique id for the authenticated user.
      • email - Email of the authenticated user.

FAQ

  • … but JWT isn't secure!
    • It isn't for encrypting data, but it is a good way to encode and sign data to be decoded and verified by another party. We encode and sign the token with RS256 (RSA + HMAC 256) which means we do not have access to the verifying key, we can only encrypt the token for you and you're the only one who can make sure it is legitimate.
  • How do I destroy that session?
    • Visit: https://<your site hostname>/__fly/auth/google/logout

Example implementation

Rails
  • Install the jwt gem: gem 'jwt', '~> 1.5.6'.

  • Add to your ApplicationController or to a “base” controller other controllers inherit from.

class ApplicationController < ActionController::Base
      before_action :require_admin!

      # ... your code

      private

      def require_admin!
        render :text => "Unauthorized.", :status => :unauthorized unless current_admin.present?
      end

      def current_admin
        @current_admin ||= begin
          jwt_token = request.get_header("HTTP_FLY_GOOGLE_AUTH_USER_JWT") # Rack exposes headers in this manner
          id_token, _ = JWT.decode(jwt_token, public_key, true) # "true" is to verify in addition to decoding the token
          return nil unless id_token['email'].end_with?('@mydomain.com') # not required, but just to be sure.
          OpenStruct.new(id_token.symbolize_keys) # or some other object
        end
      rescue JWT::InvalidIssuerError, JWT::VerificationError
        nil
      end

      def public_key
        @public_key ||= OpenSSL::PKey::RSA.new(Rails.application.secrets.fly_public_key)
      end
    end

Using this example implementation, you can put whichever parts of your application behind a Google Authentication-verified admin login.

How to Deliver Rails Apps on a Custom, Relative Path: example.com/sample/

When you add a backend to Fly, you can choose how to serve the backend relative to your hostname. If you're building a Rails application, for example, you could serve it from the root domain, like example.com/. Or, you have the option of serving it as a subfolder, like example.com/coolstore.

This guide will help you set-up the latter configuration: adding a Rails application as a subfolder on your hostname.

Add the Backend

There are several ways you can add a Rails application as a backend. You can host it in a container using Docker or Kubernetes or you can use a service like Heroku. Whichever you choose, to get the most of out of Fly you will need to configure the Fly agent.

For our example case, we'll create a Heroku application and put it on example.com/sample/. Once fully setup, it will look similar to the following:

Configured Heroku App

If we simpy wanted to mount our Rails application on example.com/ our work would be done. But, we want it on /sample/ as indicated by the Path begins column.

Venturing to example.com/sample/ will generate our Rails application… Sort of. We'll see that our static assets are missing - yuck! No stylesheets, no images, no JavaScript… our site isn't too much without those.

Luckily, Rails has an easy way to remedy the static asset issue. Within Heroku, or wherever your application is hosted, you will need to add an additional environment variable: RAILS_RELATIVE_URL_ROOT. The value of the environment variable should be the same as what we have for our Path begins.

RAILS_RELATIVE_URL_ROOT="/sample/"

Now when we head to example.com/sample/ we'll see that our application will load, along with our static assets. But, when we try to navigate anywhere we'll see that our application still wants to go to example.com/path instead of: example.com/sample/path.

To fix this, we need to make an adjustment to our config.ru. We will use map to namespace our routes over-top our application:

# config.ru
require_relative 'config/environment'
  run Rails.application

…Becomes…

# config.ru
require_relative 'config/environment'
map ENV['RAILS_RELATIVE_URL_ROOT'] || "/" do
  run Rails.application
end

Great. Once your application is rebuilt and your hosted deployment is up to date, we should be able to visit example.com/sample/ and see that our static assets and our relative path are working how we'd expect. You now have a fully functional Rails application running on example.com/sample/.

How to host a free HTTPS Ghost Blog on a custom domain using Heroku and Fly

Blogs are invaluable for helping you express yourself and grow the identity of your brand and product. No wonder you would want one!

Most companies will setup a blog on their own subdomain and present it like blog.groovyapp.com. Using blog as a subdomain comes with a significant caveat: it performs worse within Search Engine Optimization.

This guide will show you how to setup a self-hosted Ghost blogging platform on Heroku. Using Fly, we will be able to easily secure the blog with End-to-End SSL/TLS and, as a cherry on top, easily mount it to your domain at groovyapp.com/blog.

Why?

  • Using a subfolder, groovyapp.com/blog instead of a subdomain blog.groovyapp.com is the wiser choice for SEO.
  • End-to-End SSL keeps the entire route secure from the visitor to the application.
  • You retain full control by self-hosting.
  • Ghost is an excellent blogging platform.

Prerequisites

  • A custom hostname setup within Fly. No Fly? Check out the Quick Start.
  • A Heroku Free account.
  • The Ghost Blog source code. You can download it here.
  • Access to a macOS or Linux command line.

Steps

First, connect your hostname to Fly.io; here is a link to the quick start documentation.

Our first step is to Add a Backend.

Within the Routing page for your hostname, click Add a Backend. Provide it with a descriptive name, like Ghost Blog or Blog, whatever feels good to you.

Once it is created, we will begin the journey. We will need to configure Ghost as a Heroku application, add a database to it, add Fly, then create simple route within Fly.

Let us begin; we will need to slink over to our command line to login to Heroku.

heroku login

Next, head to wherever you downloaded the Ghost Blog to. Replace /path/to/ghost-blog with the actual path; perhaps it lives within ~/downloads/, for you.

cd /path/to/ghost-blog

First, a quick optimization. We want to add the large node_modules folder to your .gitignore. This will speed up our work.

echo node_modules > .gitignore

Excellent. Next step, initialize the repository.

git init
git add --all
git commit -m "Adds Ghost Blog"

With the commit ready, we will whip up an application within Heroku!

heroku create ghost-blog

We will want a database, too, so we will add PostgreSQL…

heroku addons:create heroku-postgresql:hobby-dev

When you enter the command, part of the output will include a string with a colour suffix, like HEROKU_POSTGRESQL_RED. You may have a different colour, like HEROKU_POSTGRESQL_BLUE or HEROKU_POSTGRESQL_TEAL. We need this value to promote and pair the database.

heroku pg:promote HEROKU_POSTGRESQL_[YOURCOLOUR]

Great! Now we have paired the database through an environment variable to our application. We will need to add some more via the command line.

To do that, you will need to visit the database's settings within the Heroku dashboard and retrieve them. Access your datastores. Under Administration, click View Credentials.

Now, pair the credentials below and enter them within the command line. Replace [YOUR_…] with the actual value.

heroku config:set POSTGRES_DATABASE=[YOUR_DATABASE]
heroku config:set POSTGRES_HOST=[YOUR_HOST]
heroku config:set POSTGRES_PASSWORD=[YOUR_PASSWORD]
heroku config:set POSTGRES_USER=[YOUR_USER]
heroku config:set MY_URL=[YOUR_https://herokudomain.herokuapp.com]
heroku config:set NODE_ENV=production

Now that the database is connected, we can add Fly. You have the option of adding Fly alongside your application, which we will demonstrate. Or, you can add it as a supervisor.

heroku buildpacks:add https://github.com/superfly/fly-heroku-buildpack

Cool. When you created your backend within Fly, you received a Token. Now is when we add this Token to our application.

heroku config:set FLY_TOKEN=[YOUR_TOKEN]

We are close, now. Ghost requires some configuration adjustments, so that we can get it running in a way that is fit for production.

Next up, create a Procfile so that Heroku knows how to run Ghost.

echo "web: NODE_ENV=production node index.js" > Procfile

We need to legitimize our config file.

mv config.example.js config.js

… And make some edits within the production block…

  • Add your Heroku URL to the url: field.
  • Add fileStorage:false underneath the url: line.
  • Change the database: field to postgres instead of sqlite3.
  • Under server:, change host: from 127.0.0.1 to 0.0.0.0 and port: from 2368 to process.env.PORT.

Once you have made the changes, it will look like so:

production: {
    url: 'https://ghost-blog.herokuapp.com',
    fileStorage: false,
    mail: {},
    database: {
        client: 'postgres',
        connection: {
          host: process.env.POSTGRES_HOST,
          user: process.env.POSTGRES_USER,
          password: process.env.POSTGRES_PASSWORD,
          database: process.env.POSTGRES_DATABASE,
          port: '5432'
        },
        debug: false
    },

    server: {
        host: '0.0.0.0',
        port: process.env.PORT
    }
},

Righteous. Time to make our last commit and push everything up to Heroku.

git add --all
git commit -m "Adds a database and Fly"
git push heroku master

Within this push to Heroku, we have included the Fly agent. Within the backends page, you will see them appear as connected. Our last step is to add a rule so that your new blog will be served from /blog/.

Within the Routing page, click on Add routing rule.

From there, we want to…

  • Set our Path to match as /blog/.
  • Establish the priority, likely 2.
  • Toggle to (match all hostnames).

We are done! To enable SSL and others goodies, venture to the Middleware tab. Finally, visit groovyapp.com/blog to see what we have accomplished.

You now have an End-to-End HTTPS secured self-hosted Ghost Blog running as a subfolder on your custom hostname… Nice.

How to run multiple Heroku apps on the same domain

This page will show you how to use Fly to run multiple Heroku applications from a single domain.

Let us say you have an application running within Heroku. To go along with your application, you have decided to host a Ghost blog.

Ideally, you want to have:

  • application served via gnarlyapp.com
  • ghost-blog served via gnarlyapp.com/blog

Heroku does not allow you to do this and will not help you with the fancy routing you would require. For good reason! It can get complicated. You may only have one domain associated with each application. Luckily, using Fly, we can set this up with haste.

Why?

  • Keep multiple apps within a single, secure domain.
  • Neat and clean.
  • No messing around with routing.

Prerequisites

  • Your hostname configured within Fly.io.
  • Two or more applications running within Heroku.
  • Time to cruise through the walkthrough.

Steps

First, setup your application within Fly. We have a document for that. After you have done this, you will have Fly running on your domain and the Fly agent connected to your application.

Each time we would like to add a separate application, we simply need to configure it as a new backend. You can follow the configuration document for Heroku to spin up and connect as many as you need.

Head to the routing page. You should have two Backends listed: one for your main application and one for your Ghost blog. A green check mark will indicate whether the agents are successfully connected or not.

The next step is to setup a Rule within Routing.

Setting up a rule requires filling in the following parameters:

  • Hostname: Which hostname this rule will apply to.
  • Path begins: The URL you will use to access differing backends.
  • Priority: Routing priority; 0 is greatest priority.
  • Backend: Which backend will follow the rule.

For our https://gnarlyapp.com example, we would want our Path Begins set to /blog/ with a priority of 2. We want to select ghost-blog as the Backend.

Once the rule has been created, that is all! We can now access our Ghost blog at /blog/ and have two Heroku applications connected to a single domain name. Add as many as you would like.

How to serve GitHub Pages with SSL on a custom domain

GitHub Pages are useful and simple to get going. To make them even more handy, you can point them to a custom domain name. Better yet, you can encrypt that domain name via HTTPS.

SSL via HTTPS keeps your pages secure. Not only that, but Google has started boosting the rankings of HTTPS sites compared to their insecure HTTP counter-parts. With Fly, you can enable SSL on your custom domain GitHub Pages with minimal effort.

Why?

  • Customized domain!
  • SSL provides an SEO ranking boost and encrypts your pages.
  • You can easily add GitHub pages to your application's hostname at groovyname.com/docs/.

Prerequisites

  • A custom domain to use as a hostname.
  • Your hostname configured on Fly.io.
  • A repository available through Github Pages.

Steps

Connect your hostname to Fly.io; here is a link to the quick start documentation.

After that, our first step is to Add a Backend.

Within the Routing page for your hostname, click Add a Backend. Provide it with a descriptive name, like GitHub Pages or Docs, whatever feels good to you.

Next, click the GitHub pages icon. Provide the repository name. It can be public or private. For example, GroovyUser/groovyuser.github.io.

The final step is to add a routing rule. We want to route GitHub pages to /docs; enter /docs/ under Path Begins.

Finally, head to the Middleware page for your hostname. Enable the HTTPS Upgrader. Voila; SSL secured GitHub pages on a custom domain name.

Mounting a GitHub Pages Backend

Fly allows you to use GitHub Pages as an SSL/TLS secure back-end associated with your hostname. A excellent example case for this is attaching a GitHub Pages repository to your domain at /docs/ to host your documentation. For example, our documentation is hosted on GitHub pages and is being served through Fly via HTTPS to this URL - neat, eh?

First, you will need to have a verified hostname. If you see green checkmarks under Verified and DNS Configured, then we are good to go. Access the hostname you would like to attach GitHub Pages to then visit the Routing page. Within the Routing page, click Add Backend.

You will then have three fields to enter:

  • Name: A descriptive name for the backend. Documentation, GitHub Pages - something like that.

  • Repository: The name of your repository. It can be public or private. If you are using GitHub Pages it will look like this GroovyUser/groovyuser.github.io.

  • Path prefix for mounting: Here you can specify the URL that will serve your GitHub Pages backend. A key note is that we do not do any content rewriting. If we choose /docs/ as the prefix for mounting, then pages will be served from /docs/ as the absolute path.

Once the backend has been created, it will have a routing rule specifying the path you have selected.

You will now be able to access your GitHub pages from that path!

This is a quick, no-cost way of hosting your own documentation, easily securing it via SSL/TLS and attaching it to your own domain name.

Note: You should be aware of the usage limits before rolling this out to thousands of users.

Mounting a Heroku Backend

Once you have verified your hostname, the next step is to add a backend. If you host your application on Heroku, you can take advantage of the Heroku Backend.

Access the hostname that you would like to associate with your Heroku application. Click within the Routing tab, then under Backends select Add a Backend.

You will now be able to select Heroku. Provide a name for the application, like Application, Store, or whatever feels good for you. Next, you need to provide the Heroku repository name - then, create it. For example, if you access your Heroku application by visiting: https://infinite-beach-71880.herokuapp.com/, you would enter infinite-beach-71880.

The next step is to attach the Fly agent to your application. We can do this by adding the Fly buildpack; after adding the backend, you receive a backend token and a Heroku command to add the buildpack.

heroku buildpacks:add https://github.com/superfly/fly-heroku-buildpack
heroku config:set FLY_TOKEN=2c2d3b67b92bee86d919ffbf8f429eac83d86fc06721cde9421de73db5cd666a

Within your Heroku initialized repository, enter the commands above. Finally, push to the changes up to master.

git push heroku master

Fly will detect the agent immediately. The final step is to click Add a routing rule; here, you can specify how this application will be accessed relative to your hostname. If you would like to set your new Heroku application on the root of the domain, /, simply add / as the Path to match.

Once the rule has been added, you are done! Your Heroku application is now attached to the Fly Global Load Balancer.

Mounting an AWS Lambda Backend

AWS Lambda can invoke user-defined functions in either “Event” or “RequestResponse” mode. The former is a fire-and-forget type of thing which responds immediately. The latter allows us to wait for a response to our request and therefore “proxy” an HTTP request to it.

It's possible to run a full node.js app on AWS Lambda. Therefore, it is possible to handle a function invocation like a normal HTTP Request.

You can view an example function here. The examples code can be found on GitHub.

First, create an AWS Lambda function on AWS. It needs to be configured as per the following documentation:

  • It needs to handle the event object. Read more.

  • It should provide the appropriate response. Read more.

Once the function is ready to go, create a user in AWS IAM with the permissions to invoke the function. Note the access ID and the security access key.

Now, the rest happens in Fly. Create a new site with an AWS Lambda backend or add an AWS Lambda backend to an existing site. Supply the AWS Lambda backend form with the AWS region, access key id, secret access key and function name. All credentials are stored encrypted.

You're good to go! You can now start serverless-ing all of your meat-y functions! You can deploy your app at the edge, proxied through Fly.io, without running your own servers.