GitHub Actions Integration
Reoclo provides three GitHub Actions for integrating your CI/CD workflows with your servers:
reoclo/run- Execute commands on your serversreoclo/checkout- Clone or update repositories on your serversreoclo/docker-auth- Log in to a private container registry on your server using a vaulted Reoclo credential
There’s also reoclo/deploy-sync for syncing proxy routes after an external deploy.
Your GitHub Actions workflow orchestrates the steps, Reoclo dispatches commands to your servers, and every operation is fully audited.
How It Works
Section titled “How It Works”- GitHub Actions runs your workflow on a GitHub-hosted runner
- The
reoclo/runaction sends commands to the Reoclo API - Reoclo dispatches the command to the runner agent on your server via WebSocket
- The runner executes the command and returns the result
- Every operation is logged in Reoclo’s audit trail
This means you don’t need to run self-hosted GitHub runners on your servers. Your servers only need the Reoclo runner agent installed.
1. Create an Automation API Key
Section titled “1. Create an Automation API Key”In the Reoclo dashboard:
- Navigate to the API Keys page, then select the Automation Keys tab
- Click Create Key
- Give it a descriptive name (e.g.,
github-prod-deploy) - Configure the scope:
- Servers: select which servers this key can target, or leave empty for all servers
- Operations: select which operations are allowed (
exec,deploy,restart,reboot)
- Optionally configure:
- IP allowlist: restrict to GitHub-hosted runner IP ranges for extra security
- Rate limit: requests per minute (default: 100)
- Expiration: set an expiry date
- Click Create
- Copy the key immediately. It’s shown only once.
2. Add Secrets to Your Repository
Section titled “2. Add Secrets to Your Repository”In your GitHub repository:
- Go to Settings > Secrets and variables > Actions
- Add two secrets:
REOCLO_API_KEY: the automation API key you just createdREOCLO_SERVER_ID: the ID of the target server (found in Servers page in the dashboard)
3. Add the Action to Your Workflow
Section titled “3. Add the Action to Your Workflow”name: Deployon: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy to production uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} command: | cd /srv/reoclo/myapp && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d timeout: 300Action Reference: reoclo/run
Section titled “Action Reference: reoclo/run”Execute shell commands on your servers.
Inputs
Section titled “Inputs”| Input | Required | Default | Description |
|---|---|---|---|
api_key | Yes | - | Reoclo automation API key |
server_id | Yes | - | Target server ID |
command | Yes | - | Shell command to execute on the server |
working_directory | No | - | Working directory on the server |
env | No | - | Environment variables (KEY=VALUE, one per line) |
timeout | No | 60 | Timeout in seconds (max 900) |
api_url | No | https://api.reoclo.com | Reoclo API URL (for self-hosted instances) |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
exit_code | Command exit code |
stdout | Command stdout (truncated to 64KB) |
stderr | Command stderr (truncated to 64KB) |
operation_id | Reoclo operation ID for audit trail |
duration_ms | Execution duration in milliseconds |
Action Reference: reoclo/docker-auth
Section titled “Action Reference: reoclo/docker-auth”Log in to a container registry on your server using a registry credential stored in your Reoclo tenant. The login runs on the target server, not on the GitHub runner, so subsequent reoclo/run steps can pull or push from the registry without any extra setup. When the job ends, an automatic cleanup step runs docker logout on the server.
Unlike docker/login-action@v3, this action sources the password from your Reoclo tenant instead of GitHub Secrets. You get one place to rotate credentials, per-key scoping, and a full audit trail.
Inputs
Section titled “Inputs”| Input | Required | Default | Description |
|---|---|---|---|
api_key | Yes | - | Reoclo automation API key |
server_id | Yes | - | Target server ID (must be runner-connected) |
credential_id | Conditional | - | Reoclo registry credential UUID, from the Registry Credentials page (vault mode). Required unless you use passthrough mode. |
username | Conditional | - | Registry username (passthrough mode). Provide together with access_token and registry_url. |
access_token | Conditional | - | Registry access token or password (passthrough mode). Masked in logs immediately on read. |
registry_url | Conditional | - | Registry URL for passthrough mode, e.g. ghcr.io or an ECR host. |
cleanup | No | true | Run docker logout on the server at job end |
api_url | No | https://api.reoclo.com | Reoclo API URL (for self-hosted instances) |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
operation_id | Reoclo operation ID for the login (cross-reference with the audit log) |
registry_url | Resolved registry URL (for example, ghcr.io, docker.io, or your ECR host) |
registry_type | Registry provider (docker_hub, ghcr, aws_ecr, google_artifact_registry, azure_acr, harbor, generic) |
Vault mode vs passthrough mode
Section titled “Vault mode vs passthrough mode”The action supports two ways to supply the registry credential:
- Vault mode (
credential_id) — reference a credential stored in your Reoclo tenant. The password never leaves Reoclo; rotate it once in the dashboard and every workflow picks up the new value. Best for stable, long-lived credentials. The automation key must list the credential in its allowed credentials. - Passthrough mode (
username+access_token+registry_url) — supply a username and token directly, for ephemeral tokens that can’t be vaulted ahead of time (e.g.${{ secrets.GITHUB_TOKEN }}for GHCR, or a short-livedaws ecr get-login-passwordtoken). The token is masked in workflow logs immediately on read and carried to the server as ciphertext. The automation key must haveallow_registry_passthroughenabled (dashboard, orPATCH /api-keys/{id}).
credential_id and the passthrough trio are mutually exclusive — provide one or the other, and supply all three passthrough fields together.
- name: Log in to GHCR with an ephemeral token uses: reoclo/docker-auth@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} username: ${{ github.actor }} access_token: ${{ secrets.GITHUB_TOKEN }} registry_url: ghcr.io- Create a Registry Credential in the dashboard. Pick a provider, enter the username and password or token, then save.
- Create an Automation API Key (or edit an existing one). Add
registry_login(andregistry_logoutfor the cleanup step) to Allowed Operations, and include the credential’s UUID in Allowed Credentials. - On the Registry Credentials page, click Use in CI on the credential row. The drawer generates a pre-filled workflow snippet you can copy straight into your repository.
Example: build and push a private image
Section titled “Example: build and push a private image”name: Build and pushon: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - name: Log in to GHCR on the server uses: reoclo/docker-auth@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} credential_id: ${{ secrets.REOCLO_GHCR_CREDENTIAL_ID }}
- name: Checkout code on server uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} path: /srv/reoclo/myapp token: ${{ github.token }}
- name: Build and push uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} working_directory: /srv/reoclo/myapp command: | docker build -t ghcr.io/myorg/myapp:${{ github.sha }} . docker push ghcr.io/myorg/myapp:${{ github.sha }} timeout: 600Example: log in to multiple registries
Section titled “Example: log in to multiple registries”Use one step per credential. Each step creates its own login and logout in the audit log, so partial failures stay scoped to a single credential.
- uses: reoclo/docker-auth@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} credential_id: ${{ secrets.REOCLO_GHCR_CREDENTIAL_ID }}
- uses: reoclo/docker-auth@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} credential_id: ${{ secrets.REOCLO_ECR_CREDENTIAL_ID }}Security notes
Section titled “Security notes”- The registry password is never returned to the GitHub Actions runner. Only the resolved registry URL, the registry provider type, and a Reoclo operation ID are set as outputs.
- Every login and logout is recorded in your Reoclo audit log with the originating repository, workflow, actor, and commit.
- Automation API keys must explicitly allow each credential they are permitted to use. Keys cannot reference credentials outside your tenant.
- When cleanup is enabled (the default),
docker logoutruns automatically on the server at job end so the credential does not stay resident on the server filesystem.
Action Reference: reoclo/checkout
Section titled “Action Reference: reoclo/checkout”Clone or update a repository on your server. Works like actions/checkout, but the code ends up on your remote server instead of the GitHub runner.
Inputs
Section titled “Inputs”| Input | Required | Default | Description |
|---|---|---|---|
api_key | Yes | - | Reoclo automation API key |
server_id | Yes | - | Target server ID |
repository | No | Current repo | Repository to checkout (owner/repo) |
ref | No | Current SHA | Branch, tag, or SHA to checkout |
path | No | /opt/deploy/workspace | Directory on the server to checkout into. For deploys, set this to your app’s /srv/reoclo/<app-name> path so checkout and Compose share one location. |
token | No | github.token | Token for repository access |
clean | No | true | rm -rf the target path (including .git) before fetching. Set to false for incremental git fetch updates against an existing clone. |
depth | No | 1 | Fetch depth for the requested ref. 0 means full history. The action fetches the ref directly, so any SHA on any branch resolves even at depth: 1. |
fetch_tags | No | false | Also fetch tags, even when depth > 0. |
filter | No | empty | Partial-clone filter applied to fetch (e.g. blob:none, tree:0). Pairs well with sparse_checkout. |
sparse_checkout | No | empty | Sparse checkout patterns, one per line. Empty = full working tree. |
sparse_checkout_cone_mode | No | true | Use cone mode for sparse checkout. |
submodules | No | false | Checkout submodules (true, false, or recursive) |
lfs | No | false | Download Git LFS objects after checkout. |
persist_credentials | No | true | Keep the token in .git/config after checkout. Set false to scrub it. |
github_server_url | No | $GITHUB_SERVER_URL or https://github.com | Base URL for GitHub. Use your GHES URL for GitHub Enterprise Server. |
api_url | No | https://api.reoclo.com | Reoclo API URL (for self-hosted instances) |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
commit_sha | The checked-out commit SHA on the server (40 chars) |
commit | Alias for commit_sha, matching actions/checkout naming |
short_sha | First 7 chars of the commit SHA — useful for Docker tags (myapp:${{ steps.checkout.outputs.short_sha }}) |
ref | The ref that was checked out |
path | The path on the server where the repo was checked out |
Examples
Section titled “Examples”Pass Secrets from External Providers
Section titled “Pass Secrets from External Providers”Use Bitwarden, 1Password, or any secrets manager in GitHub Actions. Secrets are fetched in the workflow and passed to Reoclo as environment variables. They never touch Reoclo’s database.
jobs: deploy: runs-on: ubuntu-latest steps: - name: Fetch secrets from Bitwarden uses: bitwarden/sm-action@v2 with: access_token: ${{ secrets.BW_ACCESS_TOKEN }} secrets: | abc123 > DB_URL
- name: Deploy with secrets uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} command: docker compose -f docker-compose.prod.yml up -d working_directory: /srv/reoclo/myapp env: | DB_URL=${{ env.DB_URL }} timeout: 300Checkout and Build on the Server
Section titled “Checkout and Build on the Server”Use reoclo/checkout to clone your code onto the server, then reoclo/run to build and deploy:
steps: - name: Checkout code on server uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} path: /srv/reoclo/myapp token: ${{ github.token }}
- name: Build and deploy uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} working_directory: /srv/reoclo/myapp command: | docker build -t myapp:latest . docker compose -f docker-compose.prod.yml up -d timeout: 600Checkout a Specific Branch
Section titled “Checkout a Specific Branch”- name: Checkout staging branch uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} ref: develop path: /srv/reoclo/myapp-staging token: ${{ github.token }}Deploy from a Non-Default Branch
Section titled “Deploy from a Non-Default Branch”When a workflow runs from a non-default branch (for example, push to staging), github.sha points at a commit on that branch — not on the default branch. From reoclo/[email protected] onwards, the action fetches the requested ref directly, so this works out of the box at depth: 1:
on: push: branches: [main, staging]
jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout the pushed commit on the server uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} # ref defaults to github.sha — explicit here for clarity ref: ${{ github.sha }} token: ${{ github.token }}If you are pinned to reoclo/[email protected] or earlier, pass ref: ${{ github.ref_name }} and depth: 0 as a workaround, or upgrade to @v1.0.2+.
Deploy to Multiple Environments
Section titled “Deploy to Multiple Environments”Route pushes on main to production and pushes on staging to your staging server. Each environment uses its own server ID, deploy path, and API key scope:
name: Deployon: push: branches: [main, staging]
jobs: deploy: runs-on: ubuntu-latest env: ENVIRONMENT: ${{ github.ref_name == 'main' && 'production' || 'staging' }} SERVER_ID: ${{ github.ref_name == 'main' && secrets.REOCLO_PROD_SERVER_ID || secrets.REOCLO_STAGING_SERVER_ID }} SERVER_PATH: /srv/reoclo/myapp-${{ github.ref_name == 'main' && 'production' || 'staging' }} steps: - name: Sync repo onto the server uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ env.SERVER_ID }} path: ${{ env.SERVER_PATH }} ref: ${{ github.sha }} token: ${{ github.token }}
- name: Pull and roll containers uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ env.SERVER_ID }} working_directory: ${{ env.SERVER_PATH }} command: | docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d timeout: 600Checkout a Different Repository
Section titled “Checkout a Different Repository”Use a Personal Access Token with cross-repo access:
- name: Checkout shared config uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} repository: myorg/shared-config path: /srv/reoclo/shared-config token: ${{ secrets.CROSS_REPO_TOKEN }}Deploy a Specific Service
Section titled “Deploy a Specific Service”on: workflow_dispatch: inputs: service: description: Service to deploy type: choice options: [api, web, worker]
jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy service uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} command: | cd /srv/reoclo/myapp docker compose -f docker-compose.prod.yml pull ${{ inputs.service }} docker compose -f docker-compose.prod.yml up -d ${{ inputs.service }} timeout: 300Multi-Step Workflows
Section titled “Multi-Step Workflows”Combine reoclo/checkout and multiple reoclo/run steps for multi-stage deployments:
steps: - name: Checkout latest code uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} path: /srv/reoclo/myapp token: ${{ github.token }}
- name: Run migrations uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} working_directory: /srv/reoclo/myapp command: docker compose -f docker-compose.prod.yml exec -T api python manage.py migrate timeout: 120
- name: Build and restart services uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} working_directory: /srv/reoclo/myapp command: | docker compose -f docker-compose.prod.yml build docker compose -f docker-compose.prod.yml up -d timeout: 600Incremental Updates (Skip Clean)
Section titled “Incremental Updates (Skip Clean)”For faster deploys, skip the full clone and fetch updates instead:
- name: Update code on server uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} clean: false token: ${{ github.token }}If the repository already exists at the target path, the action runs git fetch and checks out the ref instead of re-cloning. This is faster for large repositories.
Sparse Checkout for a Monorepo
Section titled “Sparse Checkout for a Monorepo”For a monorepo where each service has its own deploy workflow, fetch only the subtrees that service needs. Combine with filter: blob:none for a partial clone that downloads file contents on demand:
- name: Checkout just the API service uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} sparse_checkout: | services/api packages/shared docker-compose.prod.yml filter: blob:noneOn a 5 GB monorepo this typically shrinks the on-server checkout to tens of megabytes.
Git LFS
Section titled “Git LFS”Download Git LFS objects (large binaries tracked by git-lfs) after the checkout completes:
- uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} lfs: 'true'The Reoclo runner agent must have git-lfs installed on the target server. Install with apt-get install git-lfs (Debian/Ubuntu) or dnf install git-lfs (RHEL/Fedora).
GitHub Enterprise Server
Section titled “GitHub Enterprise Server”Set github_server_url to your GHES base URL. The action derives the clone URL from it. $GITHUB_SERVER_URL is auto-populated on GHES runners, so this is only needed when overriding:
- uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} github_server_url: https://github.acme-corp.com token: ${{ secrets.GHES_PAT }}Scrub Credentials After Checkout
Section titled “Scrub Credentials After Checkout”By default the action embeds the token in the on-server .git/config so subsequent git fetch calls authenticate without re-supplying it. If you don’t want the token resident on the server (e.g. for long-lived deploy paths shared across workflows), opt out with persist_credentials: false — the action will rewrite origin to the bare URL after checkout:
- uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} persist_credentials: 'false'Tag a Docker Image with the Short SHA
Section titled “Tag a Docker Image with the Short SHA”- name: Checkout on server id: checkout uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} path: /srv/reoclo/myapp
- name: Build and tag image uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} working_directory: /srv/reoclo/myapp command: | docker build -t myapp:${{ steps.checkout.outputs.short_sha }} . docker tag myapp:${{ steps.checkout.outputs.short_sha }} myapp:latest timeout: 600Full Clone with Submodules
Section titled “Full Clone with Submodules”- name: Checkout with submodules uses: reoclo/checkout@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} depth: 0 submodules: recursive token: ${{ github.token }}Audit Trail
Section titled “Audit Trail”Every command executed via the GitHub Action is logged in Reoclo’s audit trail. Each operation records:
- The command that was executed
- Which server it ran on
- The exit code, stdout, and stderr
- Which API key was used
- The GitHub Actions run context (repository, workflow, actor, commit SHA)
View automation operations in the dashboard by clicking the operation count on any key row to view history in Logs.
Operations from the same GitHub Actions run are grouped by run_id, so you can see all commands from a single workflow execution together.
Security
Section titled “Security”Key Scoping
Section titled “Key Scoping”Always scope your automation API keys to the minimum required permissions:
- Restrict to specific servers rather than all servers
- Limit operations to what the workflow needs (e.g.,
execonly) - Set an IP allowlist to GitHub’s runner IP ranges
- Use separate keys for different environments (staging vs production)
Environment Variables
Section titled “Environment Variables”Environment variables passed via the env input are:
- Sent to the server for command execution
- Never stored in Reoclo’s database. Only the key names appear in audit logs.
- Transmitted over HTTPS to the Reoclo API, then over the encrypted WebSocket to the runner
Rate Limiting
Section titled “Rate Limiting”Each API key has a configurable rate limit (default: 100 requests/minute). If exceeded, the action will receive a 429 Too Many Requests response.
Troubleshooting
Section titled “Troubleshooting”Unable to resolve action <owner>/<action>@<tag>, unable to find version <tag>
Section titled “Unable to resolve action <owner>/<action>@<tag>, unable to find version <tag>”The pinned action version tag does not exist. Either pin to an exact released version (e.g. reoclo/[email protected]) or use the floating major-version tag (@v2). Check the latest releases on GitHub to find the current tag.
Reoclo API returned 404: null
Section titled “Reoclo API returned 404: null”The action is pointed at a URL that does not serve the automation API. The default api_url in the action targets https://api.reoclo.com. If you overrode api_url in your workflow, make sure it points at the Reoclo API host for your tenant.
500 Internal Server Error
Section titled “500 Internal Server Error”A server-side error reached the action. Check the run’s operation_id output, then look up the operation in the Reoclo dashboard under Activity to see the full stack trace. If the error is not specific to your server, it may be a platform incident.
Checkout failed: ... fatal: unable to read tree (<sha>)
Section titled “Checkout failed: ... fatal: unable to read tree (<sha>)”The on-server git checkout could not find the tree for the requested SHA. This was the default failure mode on reoclo/[email protected] and earlier when deploying from a non-default branch: the action did git clone --depth 1 of the default branch and then tried to check out a SHA that was not in that shallow clone.
Fixes, in order of preference:
- Upgrade.
reoclo/[email protected]+fetches the requested ref directly, so any SHA on any branch resolves atdepth: 1. Bump youruses:line and rerun. - Workaround on older versions. Pin
ref: ${{ github.ref_name }}anddepth: 0to force a full-history clone of the branch the workflow was triggered on:- uses: reoclo/checkout@v2with:ref: ${{ github.ref_name }}depth: 0# ... - Confirm the token has access. A
403-style fetch failure can sometimes surface as a tree-read error on the next step. Make suretokenresolves to a token with read access to the repository.
command not found: docker inside the action
Section titled “command not found: docker inside the action”The runner is executing as a user that does not have Docker on its PATH. Install Docker on the server (or use rootless Docker) and verify with:
- name: Check Docker uses: reoclo/run@v2 with: api_key: ${{ secrets.REOCLO_API_KEY }} server_id: ${{ secrets.REOCLO_SERVER_ID }} command: which docker && docker versionThe deploy succeeds but https://myapp.example.com returns 404 or the default Caddy page
Section titled “The deploy succeeds but https://myapp.example.com returns 404 or the default Caddy page”Your container is running, but managed Caddy is not yet routing the domain to it. Open the server’s Proxy tab in the dashboard, find your container under Route candidates, click Route this, enter the FQDN, and confirm. See the Wire a route section below.
The workflow hangs on Executing command on server...
Section titled “The workflow hangs on Executing command on server...”The action waits synchronously for command completion. If your command takes longer than the configured timeout, the action fails with a timeout error. Increase the timeout input on the step (maximum 900 seconds).
Wire a Route to a Deployed Container
Section titled “Wire a Route to a Deployed Container”After a workflow deploys a container, it is reachable on the server but not yet attached to a domain. To expose it at https://myapp.example.com, wire a managed Caddy route:
- Open the server in the Reoclo dashboard and go to the Proxy tab.
- Find the container under Route candidates.
- Click Route this and enter the FQDN.
- Within ~30 seconds, the route appears under Active Routes and managed Caddy starts serving the container.
This is a one-time step per container + domain pair. Future deploys that replace the container leave the route intact as long as the container keeps the same name.
End-to-End Example Repository
Section titled “End-to-End Example Repository”reoclo/gh-action-tests is a live reference that exercises every action and pattern documented here across seven workflows:
test1: simplest possible deploy (nginx:alpine, no build).test2:reoclo/checkout+ nginx with a volume-mounted static site.test3: build-on-server withdocker compose.test4: private GHCR image viareoclo/docker-auth.test5: multi-container compose with env secrets.test6: large build stressing the build timeout and buildkit cache.test7: health-gated blue/green rollout with rollback.
Clone the repo to model your own workflows, or fork it to run the same tests against your own server.