DEV Community

Cover image for Deploying to Cloudways From GitHub Actions Using an Access Token
Md. Asaduzzaman
Md. Asaduzzaman

Posted on

Deploying to Cloudways From GitHub Actions Using an Access Token

Cloudways supports triggering a Git deployment directly from the API. Combined with GitHub Actions, this lets you deploy a Laravel (or any Git-based) application to Cloudways automatically on every push — authenticated with an Access Token rather than the legacy API Key.

This post walks through the CI/CD deployment step itself: the workflow, the API call, the parameters, and how to troubleshoot it.


How It Works

GitHub
   │
   │ push to develop
   ▼
GitHub Actions
   │
   │ Access Token (Bearer)
   ▼
Cloudways API
   │
   │ POST /git/pull
   ▼
Cloudways Application
   │
   │ SSH (optional, for post-deploy commands)
   ▼
Laravel deployment commands
Enter fullscreen mode Exit fullscreen mode

The deployment step calls Cloudways' Git deployment endpoint directly with curl, authenticating with a Bearer token:

POST /api/v1/git/pull
Authorization: Bearer YOUR_ACCESS_TOKEN
Enter fullscreen mode Exit fullscreen mode

Step 1 — Create an Access Token

In the Cloudways Platform, go to:

Profile → API Integration → Access Token

Create a token dedicated to this deployment, for example:

Name:
My App - GitHub Actions Deploy
Enter fullscreen mode Exit fullscreen mode

When choosing permissions, prefer Limited Access scoped to the Git deployment operation rather than Full Access — this limits the blast radius if the token is ever leaked.


Step 2 — Store the Token as a GitHub Secret

Never hard-code the token in your workflow file. Add it as a repository secret instead:

CW_ACCESS_TOKEN
Enter fullscreen mode Exit fullscreen mode

Along with the other values the deployment needs:

CW_ACCESS_TOKEN
CW_SERVER_ID
CW_APP_ID
Enter fullscreen mode Exit fullscreen mode

Step 3 — The Deployment Step

This is the core of the CI/CD job — a single curl call that tells Cloudways to pull the latest code for a given app:

- name: Cloudways Deployment
  run: |
    curl --fail-with-body --request POST \
      --url https://api.cloudways.com/api/v1/git/pull \
      --header "Authorization: Bearer ${{ secrets.CW_ACCESS_TOKEN }}" \
      --header "Content-Type: application/x-www-form-urlencoded" \
      --data-urlencode "server_id=${{ secrets.CW_SERVER_ID }}" \
      --data-urlencode "app_id=${{ secrets.CW_APP_ID }}" \
      --data-urlencode "branch_name=develop" \
      --data-urlencode "deploy_path="
Enter fullscreen mode Exit fullscreen mode

Parameter Reference

Parameter Purpose
Authorization: Bearer ... The Access Token, used as a Bearer token instead of the old email + API key pair
server_id Identifies the Cloudways server
app_id Identifies the application to deploy
branch_name The Git branch to pull (e.g. develop, main)
deploy_path Optional; leave empty if the app is already configured with its deploy directory

If your Cloudways app isn't already linked to a Git repository, you may also need to pass git_url:

--data-urlencode "git_url=${{ secrets.CW_GIT_URL }}"
Enter fullscreen mode Exit fullscreen mode

Step 4 — Full Workflow Example

A minimal GitHub Actions workflow that deploys on push to develop:

name: Deploy to Cloudways

on:
  push:
    branches: ["develop"]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Cloudways Deployment
        run: |
          curl --fail-with-body --request POST \
            --url https://api.cloudways.com/api/v1/git/pull \
            --header "Authorization: Bearer ${{ secrets.CW_ACCESS_TOKEN }}" \
            --header "Content-Type: application/x-www-form-urlencoded" \
            --data-urlencode "server_id=${{ secrets.CW_SERVER_ID }}" \
            --data-urlencode "app_id=${{ secrets.CW_APP_ID }}" \
            --data-urlencode "branch_name=develop" \
            --data-urlencode "deploy_path="
Enter fullscreen mode Exit fullscreen mode

If your app needs post-deploy commands (migrations, cache clearing, etc.), add an SSH step after this one — that part is unaffected by the Access Token change, since it uses separate SSH credentials.


Why Call the API Directly Instead of Using a Third-Party Action?

Several popular Cloudways GitHub Actions still expect the legacy email + api-key inputs. Rather than waiting for those actions to add Access Token support, calling curl directly against the Cloudways API gives you:

  • Immediate compatibility with Access Tokens
  • Full control over every request parameter
  • No dependency on a third-party action's release schedule

GitHub-hosted Ubuntu runners already include curl, so no extra setup is needed.


Troubleshooting

401 Unauthorized
Check the Access Token value, the GitHub Secret name, whether the token has expired, and that the header is written exactly as Authorization: Bearer <token>.

403 Forbidden
Usually a permissions issue. Confirm the Access Token's Limited Access configuration includes the Git deployment operation.

400 Bad Request
Double-check server_id, app_id, branch_name, and deploy_path. If Cloudways requires a repository URL for your app, add git_url.

Cloudways also provides an API Playground where you can authorize with an Access Token and test the /git/pull request independently of GitHub Actions, which is often faster for isolating the problem.


Summary

A Cloudways CI/CD deployment with an Access Token comes down to one API call:

POST /api/v1/git/pull
Authorization: Bearer <Access Token>
Params: server_id, app_id, branch_name, deploy_path
Enter fullscreen mode Exit fullscreen mode

Wrap that in a curl step in your GitHub Actions workflow, store the token as a secret, and scope it to Limited Access — and your deployment pipeline is fully migrated off the legacy API Key model.

Official Cloudways documentation:

Top comments (0)