viabl
Theme
Guides

GitHub Actions

Automate your Viabl docs deployment with a GitHub Actions workflow.

GitHub Actions lets you automatically build and deploy your docs every time you push changes to your repository. No manual builds, no manual deploys.

How it works

git push → GitHub Actions triggers → viabl build → deploy to your server

The workflow installs the Viabl CLI, runs viabl build, then copies the .viabl/ folder to your server and restarts the running process.

Prerequisites

Your docs project is in a GitHub repository A server with Node.js 20+ and SSH access

SSH key pair — private key stored as a GitHub secret, public key on your server

viabl installed on the server or installed as part of the workflow

Setting up secrets

Go to your GitHub repository → SettingsSecrets and variablesActions and add the following secrets:

SSH_HOSTsecret

The IP address or hostname of your server.

SSH_USERsecret

The SSH username to connect with. Example: ubuntu, root, deploy.

SSH_PRIVATE_KEYsecret

The private SSH key used to connect to your server. Paste the full contents of your .pem or private key file.

SSH_PORTsecret

The SSH port on your server. Usually 22.

Basic workflow

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

yaml
name: Deploy Docs
 
on:
  push:
    branches:
      - main
 
jobs:
  deploy:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout
        uses: actions/checkout@v4
 
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
 
      - name: Install Viabl CLI
        run: npm install -g @viablkit/cli
 
      - name: Build docs
        run: viabl build
 
      - name: Copy build to server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SSH_PORT }}
          source: ".viabl/"
          target: "/srv/my-docs"
          rm: true
 
      - name: Restart docs server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SSH_PORT }}
          script: |
            cd /srv/my-docs
            pm2 restart my-docs || pm2 start .viabl/start.js --name my-docs

This workflow uses appleboy/scp-action to copy files and appleboy/ssh-action to run commands on your server. Both are well-maintained open source GitHub Actions.

With Docker

If you are deploying with Docker, replace the copy and restart steps with a Docker build and run:

yaml
name: Deploy Docs
 
on:
  push:
    branches:
      - main
 
jobs:
  deploy:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout
        uses: actions/checkout@v4
 
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
 
      - name: Install Viabl CLI
        run: npm install -g @viablkit/cli
      - name: Build docs
        run: viabl build
 
      - name: Copy build to server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          source: ".viabl/,Dockerfile"
          target: "/srv/my-docs"
          rm: true
 
      - name: Build and restart Docker container
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /srv/my-docs
            docker build --no-cache -t my-docs.
            docker rm -f my-docs|| true
            docker run -d \
            --name my-docs\
            --restart unless-stopped \
            -p 7777:7777 \
            -e PORT=7777 \
            viabl-docs
            docker image prune -f

With Railway

If you are deploying to Railway, use the Railway CLI in your workflow instead:

yaml
- name: Install Railway CLI
  run: npm install -g @railway/cli
 
- name: Deploy to Railway
  run: railway up --service my-docs
  env:
    RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}

Add RAILWAY_TOKEN as a GitHub secret — get it from your Railway account settings.

Caching the Viabl CLI

On every run the workflow installs the CLI from scratch. Speed this up by caching the global npm prefix:

yaml
- name: Cache Viabl CLI
  uses: actions/cache@v4
  with:
    path: ~/.npm-global
    key: viabl-cli-${{ runner.os }}
 
- name: Install Viabl CLI
  run: |
    npm config set prefix ~/.npm-global
    npm install -g @viablkit/cli
    echo "$HOME/.npm-global/bin" >> $GITHUB_PATH

Only deploy on changes to docs

If your docs repo also contains other code, trigger the workflow only when docs files change:

yaml
on:
  push:
    branches:
      - main
    paths:
      - "**.mdx"
      - "**.md"
      - "docs.json"
      - "public/**"
      - "openapi.yaml"

Full workflow with caching and path filtering

yaml
name: Deploy Docs
 
on:
  push:
    branches:
      - main
    paths:
      - "**.mdx"
      - "**.md"
      - "docs.json"
      - "public/**"
      - "openapi.yaml"
 
jobs:
  deploy:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout
        uses: actions/checkout@v4
 
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
 
      - name: Cache Viabl CLI
        uses: actions/cache@v4
        with:
          path: ~/.npm-global
          key: viabl-cli-${{ runner.os }}
 
      - name: Install Viabl CLI
        run: |
          npm config set prefix ~/.npm-global
          npm install -g @viablkit/cli
          echo "$HOME/.npm-global/bin" >> $GITHUB_PATH
 
      - name: Build docs
        run: viabl build
 
      - name: Copy build to server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SSH_PORT }}
          source: ".viabl/"
          target: "/srv/my-docs"
          rm: true
 
      - name: Restart docs server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SSH_PORT }}
          script: |
            cd /srv/my-docs
            pm2 restart my-docs || pm2 start .viabl/start.js --name my-docs
Was this page helpful?