Skip to content

Commit c7bad63

Browse files
nsheapsclaude
andauthored
Add Docker Compose configuration for OpenClaw gateway (#13)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent a726c3e commit c7bad63

3 files changed

Lines changed: 148 additions & 3 deletions

File tree

.github/workflows/arcane-deploy.yaml

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55
branches: [main]
66
paths:
7-
- 'hosts/heapsnas/**'
7+
- 'arcane/**'
88
- '.github/workflows/arcane-deploy.yaml'
99

1010
concurrency:
@@ -20,6 +20,35 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v4
2222

23+
- name: Set Arcane global variables
24+
env:
25+
ARCANE_URL: ${{ secrets.ARCANE_URL }}
26+
ARCANE_API_KEY: ${{ secrets.ARCANE_API_KEY }}
27+
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_TOKEN }}
28+
run: |
29+
set -euo pipefail
30+
31+
# Fetch existing global variables
32+
existing=$(curl -sf --max-time 30 \
33+
-H "X-Api-Key: ${ARCANE_API_KEY}" \
34+
"${ARCANE_URL}/api/templates/variables")
35+
36+
# Merge OP_SERVICE_ACCOUNT_TOKEN into existing variables (upsert)
37+
updated=$(echo "${existing}" | jq \
38+
--arg key "OP_SERVICE_ACCOUNT_TOKEN" \
39+
--arg val "${OP_SERVICE_ACCOUNT_TOKEN}" \
40+
'.data | map(select(.key != $key)) + [{"key": $key, "value": $val}] | {"variables": .}')
41+
42+
# Update global variables
43+
curl -sf --max-time 30 \
44+
-X PUT \
45+
-H "X-Api-Key: ${ARCANE_API_KEY}" \
46+
-H "Content-Type: application/json" \
47+
-d "${updated}" \
48+
"${ARCANE_URL}/api/templates/variables" > /dev/null
49+
50+
echo "Global variables updated"
51+
2352
- name: Deploy heapsnas stacks
2453
# TODO: Pin to commit SHA once nsheaps/github-actions has releases.
2554
# See: https://github.com/nsheaps/iac/issues/3
@@ -28,7 +57,7 @@ jobs:
2857
arcane-url: ${{ secrets.ARCANE_URL }}
2958
arcane-api-key: ${{ secrets.ARCANE_API_KEY }}
3059
environment-id: ${{ secrets.ARCANE_ENVIRONMENT_ID }}
31-
compose-dir: hosts/heapsnas
60+
compose-dir: arcane/hosts/heapsnas
3261
sync-name-prefix: heapsnas
3362
auth-type: http
3463
git-token: ${{ secrets.GIT_TOKEN }}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json
2+
name: 'openclaw'
3+
4+
# OP_SERVICE_ACCOUNT_TOKEN is set as an Arcane global variable by the
5+
# arcane-deploy workflow. It's available to all compose projects via
6+
# Arcane's .env.global mechanism.
7+
8+
services:
9+
init-secrets:
10+
image: 1password/op:2
11+
user: '0:0' # Run as root for putting in the secrets dir
12+
environment:
13+
- OP_SERVICE_ACCOUNT_TOKEN=${OP_SERVICE_ACCOUNT_TOKEN}
14+
volumes:
15+
- openclaw-secrets:/run/secrets:rw
16+
command:
17+
- /bin/bash
18+
- -c
19+
- |
20+
set -euo pipefail
21+
{
22+
function fetch() {
23+
local ref="$$1"
24+
local dest="$$2"
25+
op read --no-newline "$$ref" > "$$dest"
26+
echo " got '$$ref' => '$$dest'"
27+
}
28+
echo "Fetching all secrets in parallel..."
29+
30+
fetch "op://heapsinfra/arcane--heapsnas--openclaw/gateway_token" "/run/secrets/openclaw_gateway_token" &
31+
32+
wait
33+
chmod 444 /run/secrets/*
34+
} || {
35+
echo "Failed to fetch secrets, waiting 5 minutes before exiting"
36+
sleep 300
37+
exit 1
38+
}
39+
40+
openclaw-gateway:
41+
image: ghcr.io/openclaw/openclaw:latest
42+
restart: unless-stopped
43+
init: true
44+
environment:
45+
- HOME=/home/node
46+
- TERM=xterm-256color
47+
volumes:
48+
- openclaw-config:/home/node/.openclaw
49+
- openclaw-workspace:/home/node/.openclaw/workspace
50+
- openclaw-secrets:/run/secrets:ro
51+
ports:
52+
- '${OPENCLAW_GATEWAY_PORT:-18789}:18789'
53+
command:
54+
- node
55+
- dist/index.js
56+
- gateway
57+
- --bind
58+
- lan
59+
- --port
60+
- '18789'
61+
- --token-file
62+
- /run/secrets/openclaw_gateway_token
63+
healthcheck:
64+
test:
65+
- CMD
66+
- node
67+
- -e
68+
- "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
69+
interval: 30s
70+
timeout: 5s
71+
retries: 5
72+
start_period: 20s
73+
networks:
74+
- cloudflared
75+
depends_on:
76+
init-secrets:
77+
condition: service_completed_successfully
78+
79+
openclaw-cli:
80+
image: ghcr.io/openclaw/openclaw:latest
81+
restart: unless-stopped
82+
init: true
83+
network_mode: 'service:openclaw-gateway'
84+
cap_drop:
85+
- NET_RAW
86+
- NET_ADMIN
87+
security_opt:
88+
- no-new-privileges:true
89+
environment:
90+
- HOME=/home/node
91+
- TERM=xterm-256color
92+
- BROWSER=echo
93+
volumes:
94+
- openclaw-config:/home/node/.openclaw
95+
- openclaw-workspace:/home/node/.openclaw/workspace
96+
- openclaw-secrets:/run/secrets:ro
97+
stdin_open: true
98+
tty: true
99+
entrypoint: ['node', 'dist/index.js']
100+
depends_on:
101+
openclaw-gateway:
102+
condition: service_healthy
103+
104+
# https://docs.docker.com/engine/storage/drivers/
105+
volumes:
106+
openclaw-secrets:
107+
driver: local
108+
openclaw-config:
109+
driver: local
110+
openclaw-workspace:
111+
driver: local
112+
113+
# https://docs.docker.com/engine/network/drivers/
114+
networks:
115+
cloudflared:
116+
external: true

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"check:fix": "nx run-many --target check:prettier:fix --target check:docker",
1010
"check:prettier": "nx exec -- prettier --check '**/*.{yaml,yml,md,json,json5}'",
1111
"check:prettier:fix": "nx exec -- prettier --write '**/*.{yaml,yml,md,json,json5}'",
12-
"check:docker": "nx exec -- bin/check-docker-compose.sh hosts/*/*-compose.{yaml,yml}"
12+
"check:docker": "nx exec -- bin/check-docker-compose.sh hosts/*/*-compose.{yaml,yml} arcane/hosts/*/*/compose.{yaml,yml}"
1313
},
1414
"author": "Nathan Heaps",
1515
"license": "MIT",

0 commit comments

Comments
 (0)