Skip to main content

Deploy from CI with GitHub Actions

Use the official serverpod/serverpod_cloud_deploy action to deploy your Serverpod Cloud project on every push to your main branch. Setup takes about ten minutes once you have a personal access token.

Before you start

  • A personal access token. See Create a token on the Personal access tokens page.
  • The project's scloud.yaml committed to the repository. It's created by scloud launch or scloud link.
  • Either: generated Serverpod files committed to the repository, or a CI step that runs serverpod generate (covered as a variant below).
  • One Serverpod project per repository, located no more than two subdirectory levels below the repository root.

Add the token as a repository secret

In your GitHub repository, go to Settings → Secrets and variables → Actions → New repository secret. Name the secret SERVERPOD_CLOUD_TOKEN (or anything else, as long as it matches the workflow below) and paste the token value.

Add the workflow file

Create .github/workflows/deploy.yml with the following workflow:

.github/workflows/deploy.yml
name: Deploy to Serverpod Cloud

on:
push:
branches: [main]

permissions:
contents: read

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Flutter SDK
uses: subosito/flutter-action@v2

- name: Activate serverpod command
run: dart pub global activate serverpod_cli

- uses: serverpod/serverpod_cloud_deploy@v1
with:
token: ${{ secrets.SERVERPOD_CLOUD_TOKEN }}

What each step does:

  • The actions/checkout@v4 step clones the repository into the runner.
  • The subosito/flutter-action@v2 step installs the Flutter SDK, which also provides Dart. The deploy action needs Dart to install scloud.
  • The dart pub global activate serverpod_cli step puts the framework CLI on the runner so any pre-deploy hooks (for example, serverpod generate) can run.
  • The serverpod/serverpod_cloud_deploy@v1 step installs scloud, reads your scloud.yaml, and runs scloud deploy against your project using the token.

Push to trigger the workflow

Commit the workflow file and push to main. Open the Actions tab in your repository to watch the run. When it succeeds, confirm the deploy went live:

scloud deployment show

You should see a recent deployment moving through Upload → Cloud build → Infra deploy → Service rollout, finishing with the rocket on Service rollout.

Run serverpod generate in CI (variant)

If you don't want to commit generated Serverpod files, run serverpod generate as a workflow step instead. The Flutter SDK in the workflow below provides the Dart toolchain serverpod generate needs and is also handy if the project's pre-deploy hook builds a Flutter web client.

.github/workflows/deploy.yml
name: Deploy to Serverpod Cloud

on:
push:
branches: [main]

permissions:
contents: read

env:
# Replace with your Cloud project ID and the path to your server package.
PROJECT_ID: your-project-id
SERVER_DIR: ./path/to/server

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Flutter SDK
uses: subosito/flutter-action@v2

- name: Generate Serverpod code
working-directory: ${{ env.SERVER_DIR }}
run: |
dart pub get
dart pub global activate serverpod_cli
serverpod generate

- uses: serverpod/serverpod_cloud_deploy@v1
with:
token: ${{ secrets.SERVERPOD_CLOUD_TOKEN }}
project_id: ${{ env.PROJECT_ID }}
project_dir: ${{ env.SERVER_DIR }}

The flutter-action@v2 step is required if the generate step pulls Flutter packages. Pass project_id and project_dir to the action so it knows which project to deploy and where the server code lives.

Action inputs

InputRequiredWhat it does
tokenyesYour personal access token, passed from the repository secret.
working_directorynoThe directory the action runs in. Defaults to the repository root.
project_idnoThe Cloud project to deploy to. Inferred from scloud.yaml when present.
project_dirnoPath to the server package. Useful for monorepos where the server isn't at the repository root.
project_config_filenoPath to scloud.yaml if it's not in the default location.

Troubleshooting

scloud auth login is required in the run output. The token input is empty or the secret name in the workflow doesn't match what's in your repository's secrets. Confirm the secret name in your repository matches the name your workflow references in ${{ secrets.<name> }}.

Project not found. Either scloud.yaml isn't committed and the action can't resolve the project, or project_id was passed but doesn't match a project on your Cloud account. Commit scloud.yaml, or pass the correct project_id as an action input.

Generated files missing. The primary workflow assumes generated Serverpod files are committed. Either commit them, or switch to the variant workflow that runs serverpod generate in CI.