Skip to main content

Kalheon API Deployment

Production deploys are driven by GitHub Actions in .github/workflows/deploy.yml.

Flow

  1. A commit is pushed to main.
  2. GitHub Actions opens an SSH session to claude@157.180.103.168.
  3. The remote repository at /home/claude/projects/kalheon_agents is fast-forwarded from origin/main.
  4. scripts/deploy-production.sh runs on the server:
    • pulls main;
    • runs npm ci;
    • runs npx prisma generate;
    • runs npm run db:migrate:deploy;
    • runs npm run build;
    • restarts pm2 app kalheon-api;
    • smoke-tests https://api.kalheon.cloud/health;
    • smoke-tests https://api.kalheon.cloud/docs/json.
  5. GitHub Actions sends a Telegram success or failure notification when Telegram secrets are configured.

The deploy script uses /tmp/kalheon-api-deploy.lock so two deploys cannot run at the same time.

GitHub Secrets

Required:

  • DEPLOY_SSH_KEY: private key allowed to deploy on AX43.

Recommended:

  • DEPLOY_KNOWN_HOSTS: pinned SSH host key entry for 157.180.103.168.

Optional overrides:

  • DEPLOY_HOST: defaults to 157.180.103.168.
  • DEPLOY_PORT: defaults to 22.
  • DEPLOY_USER: defaults to claude.
  • DEPLOY_REPO_DIR: defaults to /home/claude/projects/kalheon_agents.
  • PM2_APP: defaults to kalheon-api.
  • SMOKE_HEALTH_URL: defaults to https://api.kalheon.cloud/health.
  • SMOKE_DOCS_URL: defaults to https://api.kalheon.cloud/docs/json.

Telegram notifications:

  • TG_BOT_TOKEN: Telegram bot token.
  • TG_CHAT_ID: chat or channel id for deploy notifications.

If the Telegram secrets are missing, deploy still runs and logs that notification was skipped.

Server Bootstrap

Run this once on AX43 before enabling the restricted deploy key:

ssh claude@157.180.103.168
cd /home/claude/projects/kalheon_agents
git fetch origin main
git checkout main
git pull --ff-only origin main
chmod +x scripts/deploy-production.sh
scripts/deploy-production.sh

After the first successful bootstrap, add the deploy public key to /home/claude/.ssh/authorized_keys.

Safer restricted form:

command="/home/claude/projects/kalheon_agents/scripts/deploy-production.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAA... kalheon-deploy

With the forced command enabled, GitHub Actions can only trigger the deploy script for this key.

Manual Deploy

ssh claude@157.180.103.168
cd /home/claude/projects/kalheon_agents
DEPLOY_BRANCH=main PM2_APP=kalheon-api scripts/deploy-production.sh

Manual Rollback

Preferred rollback is a revert commit pushed to main; that keeps production and git history aligned and triggers the same pipeline:

git revert <bad_commit_sha>
git push origin main

Emergency server-side rollback when a revert cannot be pushed quickly:

ssh claude@157.180.103.168
cd /home/claude/projects/kalheon_agents
git fetch origin main
git checkout <last_good_sha>
npm ci
npx prisma generate
npm run db:migrate:deploy
npm run build
pm2 restart kalheon-api --update-env
curl -fsS https://api.kalheon.cloud/health > /dev/null
curl -fsS https://api.kalheon.cloud/docs/json > /dev/null

Database migrations are forward-only by default. If the bad deploy included a schema migration, rollback may also need an explicit corrective migration.

Smoke Endpoints

The public smoke endpoints are:

  • https://api.kalheon.cloud/health
  • https://api.kalheon.cloud/docs/json

The versioned health route remains available at https://api.kalheon.cloud/api/v1/health.