Deploy Flynn on Packet

    Why Use a Platform?

    Platforms do most of the work of operating your software for you so you can focus on building and improving your applications. A good platform will help you move faster, do more with a smaller team, and better utilize your servers.

    There are lots of tools that help with deploying apps, creating and managing containers, virtual machines, networking, database configurations, and scheduling jobs. What sets platforms apart is they offer a complete stack out of the box, so you don't need to learn or configure dozens of tools. You get everything you need for modern devops practices so you can spend time building your own apps rather than building or maintaining infrastructure.  

    While there are a zillion options, one of our favorites is Flynn—it's modern, opinionated, and super scalable.   Want to watch a video version of this guide? Click here.

    Key Benefit: High Availability

    When you run a cluster of three or more servers, Flynn automatically sets everything up to be highly available. This means that if a server goes down, your apps and all of Flynn's components will recover immediately and keep on working on the remaining servers.

    Getting Started

    Start installing Flynn by provisioning one or 3+ new servers on Packet to be the servers in your Flynn cluster. They should all be the same type, running Ubuntu 16.04 LTS, and in the same datacenter.

    You will also need a Internet-accessible domain name for the cluster (it can be a subdomain) and DNS hosting provider for the domain. For this text we will use an example domain:

    The Technical Tidbits

    Once the servers are up and running, SSH in and set up a firewall to block all external access to the servers with the exception of ports 80, 443, and 22.

    Here's an example of how to do that on Packet servers with iptables:

    apt-get install -y iptables-persistent
    iptables -F INPUT
    ip6tables -F INPUT
    iptables -A INPUT -s $ip -j ACCEPT // $ip is your host's public IPv4 address
    iptables -A INPUT -i bond0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    ip6tables -A INPUT -i bond0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -i bond0 -p tcp --dport 80 -j ACCEPT
    ip6tables -A INPUT -i bond0 -p tcp --dport 80 -j ACCEPT
    iptables -A INPUT -i bond0 -p tcp --dport 443 -j ACCEPT
    ip6tables -A INPUT -i bond0 -p tcp --dport 443 -j ACCEPT
    iptables -A INPUT -i bond0 -p tcp --dport 22 -j ACCEPT
    ip6tables -A INPUT -i bond0 -p tcp --dport 22 -j ACCEPT
    iptables -A INPUT -s $nodeip -j ACCEPT // $nodeip is your other node's public IPv4 address (insert another line if you have 2 or more nodes)
    iptables -A INPUT -i bond0 -p icmp --icmp-type echo-request -j ACCEPT
    ip6tables -A INPUT -i bond0 -p ipv6-icmp -j ACCEPT
    ip6tables -A INPUT -i bond0 -j DROP
    netfilter-persistent save

    Install Flynn and Flynn CLI

    Once the firewall is running and your iptable rules are in place, you may start to setup your Flynn cluster. First, install flynn on all your nodes by running this command:

    $ curl -fsSL -o /tmp/install-flynn
    $ bash /tmp/install-flynn

    Note: if you made some mistake with your installation you can always execute:

    $ bash /tmp/install-flynn --clean

    this command will clean all your installation and deploy fresh.

    After Flynn is installed you need to generate a discovery token on your primary node as identifier for the other nodes in your cluster. In our example, we have the minimum cluster size which is 3 nodes.

    $ sudo flynn-host init --init-discovery

    Once we have generated the discovery token on the first/primary node, let's apply it to the nodes we have in the cluster:

    $ sudo flynn-host init --discovery

    Note: The above example is not applicable if you are running a single node Flynn instance.

    Then you may start the Flynn daemon on all servers and ensure that all nodes are free from errors.

    $ sudo systemctl start flynn-host
    $ sudo systemctl status flynn-host

    Now that we have a Flynn host running on all these 3 servers. We need to boostrap the cluster with flynn-host bootsrap command. But first, we need to make sure that we have a resolvable domain (or subdomain) with DNS A records pointing to all 3 nodes IP address, and a wildcard domain that is CNAME to the cluster domain.

    e.g.   A   A   A
    * CNAME

    Once we have the proper DNS, we bootstrap the Flynn cluster.

    $ sudo flynn-host bootstrap --min-hosts 3 --discover

    CLUSTER_DOMAIN is your domain (or subdomain) assigned to your Flynn cluster, you can also specify the number of nodes that you have in the cluster (--min-hosts) which we have 3 and lastly, the discovery token that you have generated earlier.

    Note: You only need to run this on your primary node in the cluster. It will schedule jobs on nodes across the cluster as required.

    After Bootstrap you should see this message:

    Flynn bootstrapping complete. Install the Flynn CLI (see for instructions) and paste the line below into a terminal window:

    To install the CLI paste this command into your terminal:

    L=/usr/local/bin/flynn && curl -sSL -A "`uname -sp`" | zcat >$L $$ chmod +x $L

    Then you may add your cluster with the command printed after bootstrapping:

    flynn cluster add -p [tls pin] [cluster name] [controller domain] [controller key]

    The built-in dashboard can be accessed at

    When you access the dashboard, you will need to install the certificate in your browser before you can proceed and navigate through the other functions. You can refer to the screenshots below on how to install the SSL certificate in your browser, or just simply follow the guide shown in the Flynn dashboard.


    dashboard-2 dashboard-3

    The flynn dashboard will now prompt for your login token, which you can find with the following command:

    flynn -a dashboard env get LOGIN_TOKEN

    Note: You should safe keep the login token generated in the message given above as it will serve as your access to the Dashboard.

    Deploying Your First App

    Once you have everything setup, you should be ready to deploy your first test app! There are a lot of samples from the repo, but for this particular guide, we will use Go.

    Flynn Example Repo:

    Start by cloning the app from GitHub:

    $ git clone

    This is a Go example application that starts a HTTP server and talks to a database.

    Go to the cloned repository:

    $ cd go-flynn-example

    First, you will need to create your app. You can do this by running this command:

    $ flynn create example
    Created example
    I've set the app name as example.

    The command should also add a Flynn Git Remote, you can verify this by running:

    $ git remote -v
    flynn       (fetch)
    flynn       (push)
    origin (fetch)
    origin (push)

    The app uses Postgres as database, so we will add it:

    Note: this command must be run from ~/go-flynn-example/, or the app must be specified with flynn -a [app_name].

    $ flynn resource add postgres
    Created resource 320f38ba-36bc-40ce-97e5-dad1b5c3bd20 and release c7b793ca-b7b1-4da0-bd1d-4ed95c1b52e8.

    You should be able to see the database configuration when you run:

    $ flynn env
    DATABASE_URL=postgres://84abab8e4000453fe2e1ce3f4f04392a:[email protected]:5432/7f02ee75fe57cb70fe1e5d9afc37935c

    Push the flynn Git remote to deploy the application:

    $ git push flynn master
    Counting objects: 728, done.
    Delta compression using up to 8 threads.
    Compressing objects: 100% (451/451), done.
    Writing objects: 100% (728/728), 933.29 KiB | 0 bytes/s, done.
    Total 728 (delta 215), reused 728 (delta 215)
    -----> Building example...
    -----> Go app detected
    -----> Checking Godeps/Godeps.json file.
    -----> Installing go1.6.3... done
    -----> Running: go install -v -tags heroku .
    -----> Discovering process types
           Procfile declares types -> web
    -----> Compiled slug size is 3.6M
    -----> Creating release...
    =====> Scaling initial release to web=1
    -----> Waiting for initial web job to start...
    =====> Initial web job started
    =====> Application deployed
     * [new branch]      master -> master

    Now that the application is deployed, you can make HTTP requests to it using the default route for the application:

    $ curl
    Hello from Flynn using Packet bare-metal on port 8080 from container ddc97c7e-19a5-4033-8253-f0a337b20a0e
    Hits = 2


    You can open this to any browser using the default route for the app:


    At this point, you may now use the Dashboard to manage your app. The sample screenshot below display the application that we have deployed:


    Scaling Up

    Applications declare their process types in a Procfile in the root directory. For example, you may have a web process type that serves HTTP traffic, and a worker type that handles background jobs.

    This application declares a single web process type which executes go-flynn-example:

    $ cat Procfile
    web: go-flynn-example

    New applications with a web process type are initially scaled to run one web process, as can be seen with the ps command:

    $ flynn ps
    ID                                          TYPE  STATE  CREATED             RELEASE                               COMMAND
    flynn-db0440f7-19b4-4369-b79e-7a48dba415c2  web   up     About a minute ago  ccd1aa34-77f7-4b7c-9772-e5d39a9f2d1e  /runner/init start web

    We can increase the number of web processes using the scale command:

    $ flynn scale web=3
    scaling web: 1=>3
    09:33:51.730 ==> web 4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9 pending
    09:33:51.733 ==> web ccd3aff7-80b3-46b4-a95f-006bfceb80c6 pending
    09:33:51.743 ==> web flynn-ccd3aff7-80b3-46b4-a95f-006bfceb80c6 starting
    09:33:51.751 ==> web flynn-4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9 starting
    09:33:52.129 ==> web flynn-4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9 up
    09:33:52.171 ==> web flynn-ccd3aff7-80b3-46b4-a95f-006bfceb80c6 up
    scale completed in 464.957638ms

    ps should now show three running processes:

    $ flynn ps
    ID                                          TYPE  STATE  CREATED         RELEASE                               COMMAND
    flynn-db0440f7-19b4-4369-b79e-7a48dba415c2  web   up     2 minutes ago   ccd1aa34-77f7-4b7c-9772-e5d39a9f2d1e  /runner/init start web
    flynn-4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9  web   up     16 seconds ago  ccd1aa34-77f7-4b7c-9772-e5d39a9f2d1e  /runner/init start web
    flynn-ccd3aff7-80b3-46b4-a95f-006bfceb80c6  web   up     16 seconds ago  ccd1aa34-77f7-4b7c-9772-e5d39a9f2d1e  /runner/init start web

    Repeated HTTP requests should show that the requests are load balanced across those processes and talk to the database:

    $ curl
    Hello from Flynn on port 8080 from container db0440f7-19b4-4369-b79e-7a48dba415c2
    Hits = 2
    $ curl
    Hello from Flynn on port 8080 from container 4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9
    Hits = 3
    $ curl
    Hello from Flynn on port 8080 from container ccd3aff7-80b3-46b4-a95f-006bfceb80c6
    Hits = 4
    $ curl
    Hello from Flynn on port 8080 from container 4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9
    Hits = 5

    You can view the logs (the stdout/stderr streams) of all processes running in the app using the log command:

    $ flynn log
    2016-07-26T13:32:05.987763Z app[web.flynn-db0440f7-19b4-4369-b79e-7a48dba415c2]: hitcounter listening on port 8080
    2016-07-26T13:33:52.370073Z app[web.flynn-4ef91e4b-d0c3-4e3f-931b-6db3b551dcd9]: hitcounter listening on port 8080
    2016-07-26T13:33:52.402620Z app[web.flynn-ccd3aff7-80b3-46b4-a95f-006bfceb80c6]: hitcounter listening on port 8080

    Backup and Restore

    To take a full-cluster backup, run flynn cluster backup --file backup.tar. This will create a file named backup.tar with a complete copy of all apps and databases.

    You can restore to a new cluster using the backup file. Just follow the manual installation instructions and modify the flynn-host bootstrap command to include an extra flag: --from-backup backup.tar

    Learn more about how to use and operate Flynn at

    Was it helpful?