Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

98 lines · 4.2 KB · executableRaw History
1#!/bin/bash
2# Hosted Diffinery runners: starts the Docker daemon the first time anything needs
3# it (a step running `docker`, job containers, services, Docker actions), then runs
4# the real CLI. The daemon runs in its own session so step cleanup leaves it alone.
5#
6# The daemon reaches the Diffinery container registry through the runner's registry
7# relay (agent.mjs --registry-relay), which splits image layers into chunks under
8# Cloudflare's 100 MB request limit. Builders that `docker buildx create` starts
9# (docker/setup-buildx-action) are pointed at the relay too.
10real=/usr/bin/docker
11ready=/run/diffinery-dockerd.ready
12state=/run/diffinery
13relay_port=3129
14sys_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15
16# The Diffinery host this runner reports to, when it is reached over HTTPS.
17registry_host() {
18 local url=${DIFFINERY_API_URL:-}
19 [[ "$url" == https://* ]] || return 1
20 url=${url#https://}
21 echo "${url%%/*}"
22}
23
24start_relay() {
25 local host=$1
26 mkdir -p "$state" "/etc/docker/certs.d/$host" || return 1
27 # A certificate for the Diffinery host that only this daemon (and its builders) trust.
28 openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 30 -subj "/CN=$host" \
29 -addext "subjectAltName=DNS:$host" -keyout "$state/relay.key" -out "$state/relay.crt" >/dev/null 2>&1 || return 1
30 cp "$state/relay.crt" "/etc/docker/certs.d/$host/ca.crt"
31 printf '[registry."%s"]\n ca = ["%s"]\n' "$host" "$state/relay.crt" >"$state/buildkitd.toml"
32 env -i PATH="$sys_path" DIFFINERY_RELAY_HOST="$host" DIFFINERY_RELAY_UPSTREAM="https://$host" DIFFINERY_RELAY_PORT="$relay_port" \
33 DIFFINERY_RELAY_CERT="$state/relay.crt" DIFFINERY_RELAY_KEY="$state/relay.key" \
34 setsid -f node /opt/diffinery/agent.mjs --registry-relay >/var/log/diffinery-relay.log 2>&1 </dev/null
35 for _ in $(seq 1 80); do
36 if (exec 3<>"/dev/tcp/127.0.0.1/$relay_port") 2>/dev/null; then
37 echo "$host" >"$state/relay.host"
38 return 0
39 fi
40 sleep 0.25
41 done
42 return 1
43}
44
45if [ ! -e "$ready" ] && [ -z "${DOCKER_HOST:-}" ] && [ "$(id -u)" = 0 ]; then
46 exec 9>/run/diffinery-dockerd.lock
47 flock 9
48 if [ ! -e "$ready" ]; then
49 if ! "$real" version >/dev/null 2>&1; then
50 echo "Starting the Docker daemon" >&2
51 proxy=()
52 if host=$(registry_host) && start_relay "$host"; then
53 proxy=(HTTPS_PROXY="http://127.0.0.1:$relay_port")
54 elif [ -n "${host:-}" ]; then
55 echo "The registry relay did not start, so image layers over 100 MB can't be pushed to $host:" >&2
56 tail -n 5 /var/log/diffinery-relay.log >&2 2>/dev/null
57 fi
58 env -i PATH="$sys_path" "${proxy[@]}" setsid -f dockerd >/var/log/dockerd.log 2>&1 </dev/null
59 for _ in $(seq 1 240); do "$real" version >/dev/null 2>&1 && break; sleep 0.25; done
60 "$real" version >/dev/null 2>&1 || { echo "The Docker daemon did not start:" >&2; tail -n 20 /var/log/dockerd.log >&2; exit 1; }
61 fi
62 touch "$ready"
63 fi
64 exec 9>&-
65fi
66
67# docker buildx create (docker-container driver): run BuildKit on the host network with
68# the relay as its HTTPS proxy, trusting the relay for the Diffinery host.
69if [ "${1:-}" = buildx ] && [ "${2:-}" = create ] && [ -s "$state/relay.host" ]; then
70 host=$(cat "$state/relay.host")
71 args=("$@")
72 driver=docker-container
73 cfg=-1
74 for ((i = 2; i < ${#args[@]}; i++)); do
75 case "${args[i]}" in
76 --driver) driver=${args[i + 1]:-} ;;
77 --driver=*) driver=${args[i]#--driver=} ;;
78 --buildkitd-config | --config) cfg=$((i + 1)) ;;
79 --driver-opt) [[ "${args[i + 1]:-}" == network=* ]] && driver=custom-network ;;
80 --driver-opt=network=*) driver=custom-network ;;
81 esac
82 done
83 if [ "$driver" = docker-container ]; then
84 if [ "$cfg" -ge 0 ] && [ -f "${args[cfg]}" ]; then
85 if ! grep -qF "registry.\"$host\"" "${args[cfg]}"; then
86 merged=$(mktemp "$state/buildkitd-XXXXXX.toml")
87 { cat "${args[cfg]}"; echo; cat "$state/buildkitd.toml"; } >"$merged"
88 args[cfg]=$merged
89 fi
90 elif [ "$cfg" -lt 0 ]; then
91 args+=(--buildkitd-config "$state/buildkitd.toml")
92 fi
93 args+=(--driver-opt network=host --driver-opt "env.HTTPS_PROXY=http://127.0.0.1:$relay_port" --driver-opt "env.https_proxy=http://127.0.0.1:$relay_port")
94 exec "$real" "${args[@]}"
95 fi
96fi
97
98exec "$real" "$@"