How to Deploy Flutter on Upsun
Tags: flutter, devops, upsun, nix
Published: 2024-06-10 19:19:09

Recently, a ticket came through regarding a user who wanted to deploy a Node.js frontend, but alongside a Flutter backend, and it that was something that was possible on Platform.sh/Upsun.

Youbetcha!

## Deploying

To get started locally (I was on a Mac), I ran:

```bash
brew install --cask flutter
```

I found a (now archived, but still useful) example repository at https://github.com/flutter/gallery, which showcases a number of example views and components. 

```bash
git clone git@github.com:flutter/gallery.git && cd gallery
mkdir .upsun
touch .upsun/config.yaml
```

Create a new project (`upsun project:create`) and connect to the remote when prompted. Then edit the `.upsun/config.yaml` file to contain the following:

```yaml
applications:    
    gallery:
        variables:
            env:
                FLUTTER_VERSION_DL: "3.22.2"
        source:
            root: "gallery"
        type: "nodejs:20"
        hooks:
            build: |
                set -eux
                
                curl -s \
                    https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION_DL-stable.tar.xz \
                    -o flutter.tar.xz
                tar -xf $PLATFORM_APP_DIR/flutter.tar.xz -C .
                export PATH="$PLATFORM_APP_DIR/flutter/bin:$PATH"

                flutter build web

        web:
            locations:
                /:
                    root: build/web
                    index:
                        - index.html
                    expires: 2m
                    scripts: false
                    allow: true
                    rules:
                        static\/*:
                            expires: 365d

routes:
    "https://{default}/":
        id: gallery
        type: upstream
        primary: true
        upstream: "gallery:http"

    "https://www.{default}":
        id: gallery-redirect
        type: redirect
        to: "https://{default}/"
```


Flutter is downloaded during the build hook, so the choice of `type` is largely arbitrary at this point. In this example, the most recent version (3.22.2) is used and set to the environment variable `FLUTTER_VERSION_DL` so that it can be downloaded. Finally, the command `flutter build web` actually downloads dependencies and builds the application 

With this configuration file now in hand, we can commit and push to Upsun:

```bash
git add . && git commit -m "Upsunify the example."
upsun push
```

And that's it! The configuration shown here works for many Flutter apps, including all of the examples in https://github.com/gskinnerTeam/flutter_vignettes.


## Next steps

1. **Caching the install.** Upsun provides a super flexible build process that's both completely configuration _and_ smart enough to understand when a commit has been pushed that actually requires to rebuild an application. That assumption won't hold true for our downloads of Flutter though -- that is, we will redownload Flutter every time a commit requires a new build image, even if we want to continue to use the same version of Flutter. This build hook could be improved by utilizing Upsun's build cache to double check if the version has been edited by us, or otherwise reuse a cached download, which will save us some time.
2. **Nix.** A great thing that's come out recently on Upsun is support for Nix via our composable image syntax. In the example so far, we used the legacy `type: "node:20"` syntax, which pulls one of our maintained image versions. Instead, we could configure the project like this:

```yaml
applications:    
    gallery:
        source:
            root: "gallery"
        stack:
            - "flutter"
```

Where the `stack` entry `"flutter"` pulls [the most recent version from Nix Packages](https://search.nixos.org/packages?channel=24.05&show=flutter&from=0&size=50&sort=relevance&type=packages&query=flutter).

Seeing as Upsun Nix support doesn't yet allow for the kind of version pinning we might want in Beta, we'll just have to hold off on that experiment until next time!

Until then, happy deploying!

Chad C.