Skip to content

Recipe: Set up External Deployment from scratch

Use this recipe when:

  • The repository has no reoclo/run, reoclo/checkout, or reoclo/deploy-sync steps in any workflow.
  • The user wants to add Reoclo route sync to a workflow that deploys via docker compose up or docker run.
  • The user already has a Reoclo account (tenant exists).

If the repo already has Reoclo workflow steps, use Enhance an existing GitHub workflow instead.

Step 1 — Confirm no existing Reoclo integration:

Terminal window
grep -rl "reoclo/" .github/workflows/ 2>/dev/null || echo "no reoclo steps found"

If any file contains a reoclo/ action reference, switch to the enhance recipe.

Step 2 — Confirm a Docker deploy step exists:

Terminal window
grep -rl "docker" .github/workflows/ 2>/dev/null

If no Docker commands are found in any workflow, ask the user to confirm how containers are deployed before proceeding.

Step 3 — Confirm Reoclo account exists:

The agent cannot verify account existence programmatically without a key. Ask the user:

“Do you have a Reoclo account at app.reoclo.com and at least one Application configured with a Linked Container Name?”

If the user says no, stop. External Deployments require an existing Reoclo tenant and Application.

Step A — User must do: generate an API key

Section titled “Step A — User must do: generate an API key”

The agent cannot create API keys on the user’s behalf. Instruct the user to complete this step manually in the dashboard.

Tell the user:

  1. Go to https://app.reoclo.com and navigate to API Keys > Automation Keys.
  2. Click Create Automation Key.
  3. Name it something like github-deploy-sync-prod.
  4. Under Allowed Operations, enable external_deploy.
  5. Optionally restrict to a specific server and set an IP allowlist.
  6. Click Create and copy the key — it starts with rca_ and is shown only once.

Wait for the user to confirm they have the key before proceeding to Step B.

Tell the user:

  1. In the GitHub repository, go to Settings > Secrets and variables > Actions.
  2. Click New repository secret.
  3. Name: REOCLO_API_KEY
  4. Value: the rca_ key from Step A.
  5. Click Add secret.

Step C — Add the sync step to the workflow

Section titled “Step C — Add the sync step to the workflow”

Find the workflow file that contains the docker compose up or docker run command. Add reoclo/deploy-sync@v2 as the next step after the deploy command.

If the workflow uses Docker Compose:

- name: Sync Reoclo proxy routes
uses: reoclo/deploy-sync@v2
with:
api_key: ${{ secrets.REOCLO_API_KEY }}
compose_file: ./docker-compose.prod.yml

Replace ./docker-compose.prod.yml with the actual path to the Compose file used in the deploy step.

If the workflow uses bare docker run:

- name: Sync Reoclo proxy routes
uses: reoclo/deploy-sync@v2
with:
api_key: ${{ secrets.REOCLO_API_KEY }}
services: "container-name:3000"

Replace container-name with the value passed to --name in the docker run command, and 3000 with the container port the app listens on.

Step D — Ensure the service is on the reoclo-proxy network

Section titled “Step D — Ensure the service is on the reoclo-proxy network”

Check the Compose file (or docker run command) for network configuration. For Compose:

services:
myapp-web:
# ... existing config ...
networks:
- reoclo-proxy # add this
networks:
reoclo-proxy:
external: true # add this block if absent

For docker run, add --network reoclo-proxy to the run command.

If the service is not on the reoclo-proxy network, Caddy cannot route to it and the site will return 502 after sync.

Check 1 — YAML is valid:

Terminal window
python3 -c "import yaml, sys; yaml.safe_load(open(sys.argv[1]))" .github/workflows/deploy.yml
echo "YAML OK"

Check 2 — API key has correct scope:

There is no public key-introspection endpoint. Probe the session endpoint and read the HTTP status — 201 means the key has external_deploy, 403 means it does not:

Terminal window
curl -s -o /dev/null -w "%{http_code}\n" -X POST https://api.reoclo.com/external-deploy/session \
-H "Authorization: Bearer $REOCLO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"container_names": ["YOUR_CONTAINER_NAME"]}'

A 403 means external_deploy is missing from the key’s allowed operations — add it in the dashboard under API Keys > Automation Keys.

Check 3 — Container name resolves to an Application:

Terminal window
curl -s -X POST https://api.reoclo.com/external-deploy/session \
-H "Authorization: Bearer $REOCLO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"container_names": ["YOUR_CONTAINER_NAME"]}' \
| jq '{applications: [.applications[].linked_container_name], unmatched}'

Expected: applications contains your container name, unmatched is empty.

If unmatched contains the container name, the Application’s linked_container_name field does not match. Ask the user to correct it in the dashboard under the Application’s settings.

Clean up the test session:

Terminal window
SESSION_ID=$(curl -s -X POST https://api.reoclo.com/external-deploy/session \
-H "Authorization: Bearer $REOCLO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"container_names": ["YOUR_CONTAINER_NAME"]}' \
| jq -r '.session_id')
curl -s -X DELETE "https://api.reoclo.com/external-deploy/session/$SESSION_ID" \
-H "Authorization: Bearer $REOCLO_API_KEY" \
-o /dev/null -w "%{http_code}"

Expected: 204

  • Agent cannot create API keys or GitHub secrets. These are manual steps that require browser access. Always wait for user confirmation before proceeding to the workflow edit.
  • linked_container_name must match exactly. The service name in the Compose file is the container name Docker assigns by default (prefixed with the project name in some configurations). If the Application was linked with a full container name like myapp-web-1, the Compose service name web will not match. Ask the user to verify the exact value in the dashboard.
  • Do not add server_id to the action inputs. It is not a valid input for reoclo/deploy-sync@v2.
  • Pin to @v2 for moving tags or to an exact tag (e.g. @v2.0.0) for reproducible builds. The action is published on the GitHub Marketplace.