Deployment
Automated Deployments with GitHub Actions

Automate your code deployments with Carpathian Cloud. Easily push code to your development and production spark servers.

7 min read
284 views
Automated Deployments with GitHub Actions

Deploy code to your Carpathian server automatically when you push to GitHub. Uses GitHub Actions to trigger deployments via the Carpathian API.

What You Need

  • A running Carpathian Spark Server
  • A GitHub repository with your code
  • An API key with Deployment scope

How It Works

When you push to a configured branch, GitHub Actions sends a request to the Carpathian API. Carpathian then SSHs into your server and runs your configured commands in order:

  1. Before Deploy hook (optional) — e.g. enable maintenance mode
  2. Git pull — fetches and checks out the latest code
  3. Command groups — each group runs its build and restart commands in order
  4. After Deploy hook (optional) — e.g. disable maintenance mode

Step 1: Configure Deployment

  1. Go to Cloud Servers in the dashboard
  2. Click Actions on your server card
  3. Select Configure Deployment
  4. Fill in the settings:

Repository Settings

  • Repository URL (optional) — your GitHub repo URL. If blank, uses the URL from the GitHub webhook.
  • Branch (required) — the branch to deploy from (e.g. main)

Lifecycle Hooks

These run once per deployment, wrapping all command groups.

  • Before Deploy — runs first, before git pull. Use for things like enabling maintenance mode (php artisan down) or stopping workers (systemctl stop worker).
  • After Deploy — runs last, after all command groups finish. Use for disabling maintenance mode (php artisan up) or restarting workers.

Command Groups

Command groups are the core of the deployment. Each group represents one application stack (backend or frontend) with its own directory, build, and restart commands.

Click Add Backend or Add Frontend to create a group. Each group has:

  • Type — Backend or Frontend. This filters the framework templates shown.
  • Framework — pre-configured templates (Django, Flask, Next.js, React, etc.) that auto-fill build and restart commands. Select "Custom" for manual configuration.
  • Label (optional) — a display name for the group (e.g. "API Server", "Admin Panel")
  • Deploy Directory — absolute path where the code lives on your server (e.g. /var/www/app)
  • Build Command — install dependencies and build (e.g. npm install && npm run build)
  • Restart Command — restart the application process (e.g. pm2 restart app)

Groups execute top-to-bottom. For a typical dual-stack setup:

1. Before Deploy     →  php artisan down
2. Git pull          →  git fetch && checkout && pull
3. Backend group     →  cd /var/www/api && pip install && systemctl restart gunicorn
4. Frontend group    →  cd /var/www/frontend && npm install && npm run build && pm2 restart frontend
5. After Deploy      →  php artisan up

Running frontend and backend on the same server is less secure than separating them. A compromise in one layer could affect the other. For production workloads, deploy frontend and backend on separate servers.

  1. Toggle Enable Deployment to ON
  2. Click Save Configuration

Step 2: Generate an API Key

  1. On the Cloud Servers page, click Actions on your server card
  2. Select Manage API Keys
  3. Click Generate New API Key
  4. Set the permission scope to Deployment
  5. Copy the key immediately — it is only shown once

The key format is cpk_.... You can also manage keys from API Keys in the dashboard sidebar.

Step 3: Add the Key to GitHub Secrets

  1. Go to your GitHub repository
  2. Click Settings > Secrets and variables > Actions
  3. Click New repository secret
  4. Name: CARPATHIAN_API_KEY
  5. Value: your cpk_... key
  6. Click Add secret

Step 4: Create the Workflow

Create .github/workflows/deploy.yml in your repository:

name: Deploy to Carpathian

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Trigger Carpathian Deployment
        env:
          CARPATHIAN_API_KEY: ${{ secrets.CARPATHIAN_API_KEY }}
        run: |
          curl -X POST https://api.carpathian.ai/api/v1/deployment/trigger \
            -H "Authorization: Bearer $CARPATHIAN_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "repository": "${{ github.repository }}",
              "commit": "${{ github.sha }}",
              "branch": "${{ github.ref_name }}",
              "commit_message": "${{ github.event.head_commit.message }}",
              "author_name": "${{ github.event.head_commit.author.name }}",
              "author_email": "${{ github.event.head_commit.author.email }}",
              "webhook_url": "${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}"
            }'

Step 5: Test

git add .github/workflows/deploy.yml
git commit -m "Add Carpathian deployment workflow"
git push origin main

Check the Deployments page in your dashboard to see the deployment status and logs.

Framework Examples

Backend

Django

Build:    pip install -r requirements.txt && python manage.py migrate && python manage.py collectstatic --noinput
Restart:  systemctl restart gunicorn

Flask

Build:    pip install -r requirements.txt
Restart:  systemctl restart gunicorn

Node.js / Express

Build:    npm install
Restart:  pm2 restart node-app || pm2 start server.js --name node-app

Laravel

Build:    composer install --no-dev && php artisan migrate --force && php artisan config:cache && php artisan route:cache && php artisan view:cache
Restart:  php artisan queue:restart && systemctl restart php-fpm

Frontend

Next.js

Build:    npm install && npm run build
Restart:  pm2 restart nextjs-app || pm2 start npm --name nextjs-app -- start

React (Vite/CRA)

Build:    npm install && npm run build
Restart:  pm2 restart react-app || pm2 start serve --name react-app -- -s build -l 3000

Vue.js

Build:    npm install && npm run build
Restart:  pm2 restart vue-app || pm2 start serve --name vue-app -- -s dist -l 3000

Workflow Customization

Deploy on multiple branches:

on:
  push:
    branches: [main, staging, production]

Deploy on pull request merge:

on:
  pull_request:
    types: [closed]
    branches: [main]

Manual trigger:

on:
  workflow_dispatch:

Multiple environments with separate API keys:

jobs:
  deploy-staging:
    if: github.ref == 'refs/heads/staging'
    steps:
      - name: Deploy to Staging
        env:
          CARPATHIAN_API_KEY: ${{ secrets.CARPATHIAN_STAGING_KEY }}
        run: curl -X POST https://api.carpathian.ai/api/v1/deployment/trigger ...

  deploy-production:
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Deploy to Production
        env:
          CARPATHIAN_API_KEY: ${{ secrets.CARPATHIAN_PRODUCTION_KEY }}
        run: curl -X POST https://api.carpathian.ai/api/v1/deployment/trigger ...

Checking Deployment Status

The easiest way to check deployment status is the Deployments page in your dashboard. The Deployment Logs tab shows all deployments with their status, commit info, and full output logs.

If you need to check status programmatically (e.g. in a CI pipeline), the trigger endpoint returns a deployment_id in its response. You can use that ID with the status and logs endpoints. These endpoints require the same API key used to trigger the deployment — you can only query deployments that belong to your server.

#Check status (deployment_id is returned by the trigger response)
curl -H "Authorization: Bearer $CARPATHIAN_API_KEY" \
  https://api.carpathian.ai/api/v1/deployment/status/DEPLOYMENT_ID

#Get full logs
curl -H "Authorization: Bearer $CARPATHIAN_API_KEY" \
  https://api.carpathian.ai/api/v1/deployment/logs/DEPLOYMENT_ID

Troubleshooting

"Deployment Not Configured"

You haven't set up deployment on this server yet. Go to Cloud Servers > Actions > Configure Deployment.

Deployment not triggering

  • Check that the API key status is Active (not Locked or Revoked)
  • Verify the key has Deployment scope
  • Confirm CARPATHIAN_API_KEY exists in GitHub Secrets with the full cpk_... value
  • Check the GitHub Actions tab for workflow errors
  • Verify you're using the url: https://carpathian.ai for all API calls

"Invalid API Key"

The key may be revoked, deleted, or locked. Check status in API Keys. Generate a new key if needed.

API Key Locked

Keys auto-lock after 3 failed IP allowlist checks within 5 minutes. Go to the key details, review Security Events, then click Unlock.

Deployment triggered but nothing changed

  • Check the Deployments page for logs and error messages
  • Verify your deploy directory path is correct
  • Confirm build and restart commands work when run manually via SSH

Security

  • Use Deployment scope — avoid Full Access for CI/CD
  • Never commit API keys to git — always use GitHub Secrets
  • Use IP allowlists to restrict key usage to GitHub Actions IPs (185.199.108.0/22, 140.82.112.0/20, 143.55.64.0/20)
  • Revoke keys that haven't been used in 90+ days
  • Monitor key usage and security events in the dashboard

This documentation is open to the public to make the platform API available for customers. However, since Carpathian Cloud is still in beta and being actively developed, this document might be outdated or incorrect. If you find anything confusing or misleading, please send an email to info@carpathian.ai.