Skip to content

Commit

Permalink
Merge branch 'main' into custom-network
Browse files Browse the repository at this point in the history
  • Loading branch information
andie787 committed Aug 16, 2024
2 parents c71f94c + 938866e commit 6af8c6b
Show file tree
Hide file tree
Showing 18 changed files with 362 additions and 54 deletions.
2 changes: 1 addition & 1 deletion about/pricing.html.markerb
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Pricing for a GPU-enabled Fly Machine is the price of a standard Fly Machine (se
On-demand GPU pricing:

* A10: $1.50/hr per GPU
* L40S: $2.50/hr per GPU
* L40S: $1.25/hr per GPU
* A100 40G PCIe: $2.50/hr per GPU
* A100 80G SXM: $3.50/hr per GPU

Expand Down
11 changes: 7 additions & 4 deletions blueprints/autoscale-machines.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,32 @@ Machines during the period of low traffic.
This blueprint will guide you through the process of configuring the
[`fly-autoscaler` app](/docs/launch/autoscale-by-metric/) in conjunction with
[Fly Proxy autostop/autostart](/docs/launch/autostop-autostart/) to
always keep a fixed number of stopped Machines ready to be quickly started
always keep a fixed number of Machines ready to be quickly started
by Fly Proxy.

## Configuring automatic start and stop

First, we will configure the app to allow Fly Proxy to automatically start and
stop Machines based on traffic demand. The auto start and stop settings apply
stop or suspend Machines based on traffic demand. The auto start and stop settings apply
per service, so you set them within the `[[services]]` or `[http_service]`
sections of `fly.toml`:

```toml
...
[[services]]
...
auto_stop_machines = true
auto_stop_machines = "stop"
auto_start_machines = true
min_machines_running = 0
...
```

With these settings Fly Proxy will start an additional Machine if all the
running Machines are above their concurrency `soft_limit` and stop running
Machines when the traffic decreases. In the next section we will configure
Machines when the traffic decreases. You can set Machines to `"suspend"` rather than
`"stop"`, for even faster start-up, but with some [limitations on the type of Machine](https://community.fly.io/t/new-feature-in-preview-suspend-resume-for-machines/20672#current-limitations-and-caveats-8).

In the next section we will configure
and deploy `fly-autoscaler` to ensure that the app always has a spare stopped
Machine for Fly Proxy to start.

Expand Down
12 changes: 6 additions & 6 deletions blueprints/autostart-internal-apps.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You have a private, or internal, app that communicates only with other apps on y

To use Fly Proxy autostop/autostart you need to configure services in `fly.toml`, like you would for a public app. But instead of using a public Anycast address, you assign a Flycast address to expose those services only on your private network.

This blueprint focuses on using autostart and autostop to control Machines based on incoming requests. But when you use Flycast for private apps you also get other Fly Proxy features like geographically aware load balancing.
This blueprint focuses on using autostop/autostart to control Machines based on incoming requests. But when you use Flycast for private apps you also get other [Fly Proxy features](/docs/reference/fly-proxy/) like geographically aware load balancing.

Learn more about [Flycast](/docs/networking/flycast/).

Expand Down Expand Up @@ -49,9 +49,9 @@ v6 fdaa:2:45b:0:1::11 private global Mar 16 2024 18:20
v4 66.241.124.11 public (shared) Jan 1 0001 00:00
```

This example app has public IPv4 and IPv6 addresses. These are the addresses automatically assigned to an app on first deploy.
This example app has public IPv4 and IPv6 addresses. These public addresses are automatically assigned to an app with services on the first deploy.

Copy the public IP addresses and run the `release` command to remove them from your app:
Copy the public IP addresses and run the `fly ips release` command to remove them from your app:

```
fly ips release <ip address> <ip address> ...
Expand Down Expand Up @@ -82,7 +82,7 @@ Here's an example `fly.toml` snippet:
# must be false - Flycast is http-only
force_https = false
# Fly Proxy stops Machines based on traffic
auto_stop_machines = true
auto_stop_machines = "stop"
# Fly Proxy starts Machines based on traffic
auto_start_machines = true
# Number of Machines to keep running in primary region
Expand All @@ -94,7 +94,7 @@ Here's an example `fly.toml` snippet:
```

<div class="important icon">
**Important:** Set `force_https = false` since Flycast only works over HTTP. HTTPS isn't necessary because all your private network traffic goes through encrypted WireGuard tunnels.
**Important:** Set `force_https = false`; Flycast only works over HTTP. HTTPS isn't necessary because all your private network traffic goes through encrypted WireGuard tunnels.
</div>

Learn more about [Fly Launch configuration](/docs/reference/configuration/) and [Fly Proxy autostop/autostart](/docs/launch/autostop-autostart/).
Expand All @@ -107,7 +107,7 @@ To be reachable by Fly Proxy, an app needs to listen on `0.0.0.0` and bind to th

Run `fly deploy` for the configuration changes to take effect.

Other apps in your organization can now reach your private app using the [Flycast](/docs/networking/flycast/) IP address or `<appname>.flycast`.
Other apps in your organization can now reach your private app using the [Flycast](/docs/networking/flycast/) IP address or the `<appname>.flycast` domain.

## Read more

Expand Down
34 changes: 34 additions & 0 deletions happy-path/aim.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Aim
layout: framework_docs_overview
order: 2
---

For this demo, we will start with [MDN's Web Dictaphone](https://github.com/mdn/dom-examples/tree/main/media/web-dictaphone#web-dictaphone).
You can play with a [live demo](https://mdn.github.io/dom-examples/media/web-dictaphone/). This is about as basic of an
HTML form as you can get, and it has the added bonus of providing the ability to generate as many media files as you want using only your voice.

Your app undoubtely has many forms, and more complex forms, but once you can see the basic flow, the rest should be easy.

That demo as it currently stands is client side only, so to deploy it all you need is a web server that can deploy static assets (HTML, CSS, JS, images),
like NGINX, Apache HTTPd, or Caddy. In order to store the data in databases, we are going to need a server that can handle HTTP GET, POST, PUT, and DELETE requests.

This demo application will come in two flavors. For Node.js, we will select [Express.JS](https://expressjs.com/), and for Rails we will use [Puma](https://github.com/puma/puma).

* The names of the clips will go into a [PostgreSQL](https://www.postgresql.org/) relational database.
* The audio files themselves will be placed into a [Tigris bucket](https://www.tigrisdata.com/).
* For Node.js, the bulk of this code is in [app.js](https://github.com/fly-apps/node-dictaphone/blob/main/app.js). For Rails,
[app/controller/clipController.rb](https://github.com/fly-apps/rails-dictaphone/blob/main/app/controllers/clips_controller.rb).

To satisfy the realtime requirement, we will need [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
and [Upstash for Redis](https://fly.io/docs/reference/redis/). The Node.js implementation is in [pubsub.js](https://github.com/fly-apps/node-dictaphone/blob/main/pubsub.js).
For Rails, the heavy lifting is done by [ActionCable](https://guides.rubyonrails.org/action_cable_overview.html), so all that is needed is
one line in [app/models/clip.rb](https://github.com/fly-apps/rails-dictaphone/blob/6bdf4f639640c9fb55530546dbbed682b65a7df9/app/models/clip.rb#L2)
and one line in [app/views/layouts/application.html.erb](https://github.com/fly-apps/rails-dictaphone/blob/6bdf4f639640c9fb55530546dbbed682b65a7df9/app/views/layouts/application.html.erb#L9).

The important thing to note is that this is all very straightforward stuff using industry standard components that you can run on your laptop, a VPS, AWS EC2, Google Compute Engine, or Azure.

If you want to see this up and running on fly.io (and certainly you do or why else would you be here?), all you need
is an empty directory and either Node or Ruby installed.

Now that we know what we are intending to accomplish, let's proceed to the exciting step: [Fire!](../fire/)
23 changes: 23 additions & 0 deletions happy-path/application.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Your Application
layout: framework_docs_overview
order: 4
---

Your application is running by default on two [Machines](https://fly.io/docs/machines/).

Don't worry about cost. Both machines stop when not in use, and [autostart](https://fly.io/docs/launch/autostop-autostart/) when a new request comes in.
This is entirely configurable. You can chose to [suspend](https://community.fly.io/t/new-feature-in-preview-suspend-resume-for-machines/20672) instead of stop,
configure a [minimum number](https://fly.io/docs/reference/configuration/#the-http_service-section) of machines to leave running, or even decide never to
stop at all.

Familiarize yourself with [fly.toml](https://fly.io/docs/reference/configuration/). Make a change there -- or in fact to any part of your application -- and run `fly deploy`.

The purpose of two machines is twofold: redundancy and scalability. If the machine hosting one goes down, the other can continue on. If both are available, in times of high use both can be started to handle requests.
You can [vertically scale](https://fly.io/docs/launch/scale-machine/) the CPU and RAM on each machine.

You can also [horizontally scale](https://fly.io/docs/launch/scale-count/) to more machines. Be sure to scroll down on that page far enough to see how to scale to
multiple [regions](https://fly.io/docs/reference/regions/). If you have a co-worker on another continent, create a machine there.

And all this is made possible by [Anycast](https://fly.io/docs/networking/services/), a [load balancing proxy](https://fly.io/docs/reference/fly-proxy/), and [DNS certificates](https://fly.io/docs/networking/custom-domain/).
Be sure to read the last link if you are interested in custom domains.
32 changes: 32 additions & 0 deletions happy-path/fire.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Fire
layout: framework_docs_overview
order: 3
---

This is the point where the rubber meets the road, so this is where you would expect to see where the marketing hype promised by [Speedrun](https://fly.io/speedrun) and
the [Quick Start](../getting-started/launch/) don't quite cut it. But the fact of the matter is that fly.io is honed for an excellent developer experience (DX) for full stack applications with both realtime time and object storage requirements.

There truly are only two steps involved.

Step 1: [install flyctl](https://fly.io/docs/flyctl/install/)

Step 2: run `fly launch --from https://github.com/fly-apps/node-dictaphone` or `fly launch --from https://github.com/fly-apps/rails-dictaphone`

If you are new to fly, the second step will first take you to a place where you can register. Then it will provide a description of what you will be getting, and give you an opportunity to tweak the settings (suggestion: don't. They are fine for this demo and we will walk you through how to adjust them later). And then it will build and assemble and wire up your application.

Take your time and play with it. Open your application in multiple browser windows. Send a link to a friend on another continent and watch your browser update in realtime.

And then relax. We promised you it would be less than an hour. You are already up and running. In fact, if you are so inclined try bringing up this exact same application on another cloud provider.
We don't mind. In fact we encourage it. Just please don't count the time you spent there against the hour budget we asked you to allot to this activity.

Once you are back and/or rested up, let's explore. You've seen the code. You're up and running. Now lets take inventory.
Feel free to review the following in any order, or chose to skip ahead:
* [Your application](../application/)
* [PostgreSQL](../postgresql/)
* [Tigris](../tigris/)
* [Redis](../redis/)

Finally, as an added treat and as promised, let's add some AI functionality, in this case speech recognition using [Whisper](../whisper/).

And when you are done, join us for a [recap](../recap)
33 changes: 33 additions & 0 deletions happy-path/index.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: The Happy Path
layout: framework_docs
toc: false
---

You landed on this page because somebody recommended fly.io to you,
you are a bit curious, but you want to know more before you commit.

You are aware that there is a [Speedrun](https://fly.io/speedrun) and
a [Quick Start](../getting-started/launch/), but perhaps they feel a bit
too _Ready! Fire! Aim!_ for you. You want to not only be up and running,
you want to feel confident that you are heading in the right direction. A
direction that can both scale and support your present and future needs.

You are concerned about lock in. You want to be confident that you can
use services from other places and even eject entirely and move your entire
application elsewhere if things don't work out.

But most of all, you want to explore in a time boxed way as you are
a busy person. If you don't get a good feeling within an hour, you are out
of here. If you do have a good feeling, then perhaps you'd consider
sticking around for even deeper dives into areas that interest you.

If so, you have come to the right place. You should be up and
running within minutes, and have enough of the hour left over so
that you can spend some time understanding what you just did and
run a few commands and see what they do.

And when you are done, you can delete everything and then launch the
application that you came here for.

Let's get started... [Ready](./ready/) ... [Aim](./aim/) ... [Fire](./fire/)!
14 changes: 14 additions & 0 deletions happy-path/postgresql.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: PostgreSQL
layout: framework_docs_overview
order: 5
---

Your application comes initially configured for a single [Fly Postgres](https://fly.io/docs/postgres/) machine.
That is great for development, but for production we need redundancy and scalability. With but a [few commands](https://fly.io/docs/postgres/advanced-guides/high-availability-and-global-replication/) we can create a HA cluster in my primary region and read only replicas elsewhere.

If you are interested in a managed offering, [Supabase Postgres](https://fly.io/docs/reference/supabase/) is in public alpha.

And there is no lock in here. We have a list of [recommended external providers](https://fly.io/docs/postgres/getting-started/what-you-should-know/#recommended-external-providers), but you are free to host your database literally anywhere.

Before moving on, one last observation on the relational DB. While you want and need your application to be on the internet, you are much better off if your relational database is NOT directly exposed to the internet, but can only be accessed via your application. That’s the value of an [internal private network](https://fly.io/docs/networking/private-networking/). This too was configured automatically for you.
21 changes: 21 additions & 0 deletions happy-path/ready.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Ready
layout: framework_docs_overview
order: 1
---

You are not satisfied by a `hello world` or even a `hello world` with a database application.
You know that a real world application has at a minimum the following components:

* A HTML form and a database. This database is typically a relational database.
* The ability to handle media files or documents, generally using S3.
* A multi-user and realtime component, where changes made by one person in one location are relected instantly in the browser of another person.

While this doesn't seem like a tall ask, experience has shown that in order to get such an app running smoothly, you need a whole bunch of things; here are a few examples: anycast routing, load balancers, dns certificates, web sockets, an internal private network, a relational database, an object store, and an in-memory database. And the knowledge of how to connect them all together.

Taken all together, this typically takes a **minimum** of an afternoon's worth of work, even by experts familiar with their target platform. With emphasis on the word _minimum_ as there always is a surprise, and often several.

In the next few minutes we will have all this up and running, and can leisurely explore how the pieces fit together. We even will have enough time left over
to integrate in AI functionality making use of GPUs.

With that understanding of requirements in place, lets proceed on.... [Aim](../aim/)
29 changes: 29 additions & 0 deletions happy-path/recap.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: Recap
layout: framework_docs_overview
order: 9
---

We promised you that you could get through this in under an hour. How did we do? How much time did you have left over.

You successfully deployed a full-stack application with both object storage and realtime requirements, and then went on to add AI functionality.

Up front, we set some rather high goals:

* You want to not only be up and running,
you want to feel confident that you are heading in the right direction. A
direction that can both scale and support your present and future needs.
* You want to be confident that you can
use services from other places and even eject entirely and move your entire
application elsewhere if things don't work out.

Or to put it more succinctly.... did you find your happy path?

Did we meet these goals? You've seen the code, and you've seen it work. You examined each component, and from there
saw links to where you can find out more information.

Now a few links:
* [Support](https://fly.io/docs/about/support/)
* [Pricing](https://fly.io/docs/about/pricing/)
* [Application Monitoring by Sentry](../../reference/sentry/)
* [Application Security by Arcjet](../../reference/arcjet/)
16 changes: 16 additions & 0 deletions happy-path/redis.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Upstash Redis
layout: framework_docs_overview
order: 7
---

[Upstash Redis](https://fly.io/docs/reference/redis/) is used by this application for its [pubsub](https://redis.io/docs/latest/commands/?group=pubsub)
capabilities, but it can do [so much more](https://upstash.com/docs/redis/overall/rediscompatibility).

In particular, Redis is useful for caching:
[Node](https://redis.io/learn/develop/node/nodecrashcourse/caching),
[Rails](https://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-rediscachestore).

In this application, updates are broadcast to all machines via Redis, and then each machine informs browser clients
of the update via [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). Client the request
updated information from the application using HTTP GET.
9 changes: 9 additions & 0 deletions happy-path/tigris.html.markerb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: Tigris
layout: framework_docs_overview
order: 6
---

[Tigris](https://fly.io/docs/reference/tigris/) is truly a thing of beauty. It essentially requires no configuration, and seamlessly handles multi-regions. If you upload an audio file to a host in Virginia, you can access it from Amsterdam. Even better: subsequent accesses from regions other than the primary region are served locally. Unlike relational databases, there may be reasons why you want to make your object store available via the internet. In this demo, the object store starts out private, but you can make it [public](https://fly.io/docs/reference/tigris/#public-buckets) if you want.

And if you happen to have an existing S3 object store, check out [shadow buckets](https://fly.io/docs/reference/tigris/#migrating-to-tigris-with-shadow-buckets) which enable you to incrementally migrate your data.
Loading

0 comments on commit 6af8c6b

Please sign in to comment.