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 accessSSH 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 → Settings → Secrets and variables → Actions and add the following secrets:
SSH_HOSTsecretThe IP address or hostname of your server.
SSH_USERsecretThe SSH username to connect with. Example: ubuntu, root, deploy.
SSH_PRIVATE_KEYsecretThe private SSH key used to connect to your server. Paste the full contents of
your .pem or private key file.
SSH_PORTsecretThe SSH port on your server. Usually 22.
Basic workflow
Create .github/workflows/deploy.yml in your docs repository:
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-docsThis 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:
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 -fWith Railway
If you are deploying to Railway, use the Railway CLI in your workflow instead:
- 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:
- 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_PATHOnly deploy on changes to docs
If your docs repo also contains other code, trigger the workflow only when docs files change:
on:
push:
branches:
- main
paths:
- "**.mdx"
- "**.md"
- "docs.json"
- "public/**"
- "openapi.yaml"Full workflow with caching and path filtering
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