mirror of
https://github.com/coollabsio/coolify.git
synced 2026-08-24 10:05:47 -05:00
960 lines
23 KiB
Bash
Executable File
960 lines
23 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$ROOT"
|
|
|
|
read_coolify_env() {
|
|
key="$1"
|
|
default_value="$2"
|
|
current_value="${!key:-}"
|
|
|
|
if [ -n "$current_value" ]; then
|
|
printf '%s\n' "$current_value"
|
|
return
|
|
fi
|
|
|
|
if [ -f .env ]; then
|
|
env_value="$(grep -E "^${key}=" .env 2>/dev/null | tail -n1 | cut -d= -f2- | sed "s/^['\"]//; s/['\"]$//")"
|
|
if [ -n "$env_value" ]; then
|
|
printf '%s\n' "$env_value"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
printf '%s\n' "$default_value"
|
|
}
|
|
|
|
coold_vm_count() {
|
|
local count
|
|
count="$(read_coolify_env COOLIFY_COOLD_VM_COUNT 2)"
|
|
|
|
if [ "$count" != "1" ] && [ "$count" != "2" ]; then
|
|
echo "ERROR: COOLIFY_COOLD_VM_COUNT supports 1 or 2 for now." >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s\n' "$count"
|
|
}
|
|
|
|
coold_vm_instance() {
|
|
local index="$1"
|
|
local base
|
|
base="$(read_coolify_env COOLIFY_COOLD_LIMA_INSTANCE coold-dev)"
|
|
|
|
if [ "$index" = "1" ]; then
|
|
printf '%s\n' "$base"
|
|
return
|
|
fi
|
|
|
|
read_coolify_env "COOLIFY_COOLD_LIMA_INSTANCE_${index}" "${base}-${index}"
|
|
}
|
|
|
|
coold_vm_wg_ip() {
|
|
local index="$1"
|
|
read_coolify_env "COOLIFY_COOLD_VM_WG_IP_${index}" "100.64.0.${index}"
|
|
}
|
|
|
|
coold_vm_wg_port() {
|
|
local index="$1"
|
|
read_coolify_env "COOLIFY_COOLD_VM_WG_PORT_${index}" "$((51820 + index))"
|
|
}
|
|
|
|
coold_vm_container_subnet() {
|
|
local index="$1"
|
|
read_coolify_env "COOLIFY_COOLD_VM_CONTAINER_SUBNET_${index}" "10.210.$((index - 1)).0/24"
|
|
}
|
|
|
|
coold_vm_container_gateway() {
|
|
local index="$1"
|
|
read_coolify_env "COOLIFY_COOLD_VM_CONTAINER_GATEWAY_${index}" "10.210.$((index - 1)).1"
|
|
}
|
|
|
|
host_arch() {
|
|
case "$(uname -m)" in
|
|
x86_64|amd64)
|
|
printf '%s\n' amd64
|
|
;;
|
|
arm64|aarch64)
|
|
printf '%s\n' arm64
|
|
;;
|
|
*)
|
|
echo "ERROR: unsupported host architecture: $(uname -m)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
host_os() {
|
|
case "$(uname -s)" in
|
|
Darwin)
|
|
printf '%s\n' darwin
|
|
;;
|
|
Linux)
|
|
printf '%s\n' linux
|
|
;;
|
|
*)
|
|
echo "ERROR: unsupported host OS: $(uname -s)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
cooldctl_bin() {
|
|
printf '%s\n' "$ROOT/.dev/bin/cooldctl"
|
|
}
|
|
|
|
build_local_cooldctl() {
|
|
local bin
|
|
local coold_repo
|
|
|
|
bin="$(cooldctl_bin)"
|
|
coold_repo="$(read_coolify_env COOLIFY_COOLD_REPO /Users/heyandras/devel/coold)"
|
|
|
|
if [ ! -d "$coold_repo/cooldctl" ]; then
|
|
echo "ERROR: macOS cooldctl release artifact is not available yet and local coold repo was not found at ${coold_repo}." >&2
|
|
echo "Set COOLIFY_COOLD_REPO=/path/to/coold or build/copy cooldctl to ${bin}." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> Building local macOS cooldctl from ${coold_repo}"
|
|
(cd "$coold_repo" && cargo build -p cooldctl)
|
|
mkdir -p "$(dirname "$bin")"
|
|
install -m 0755 "$coold_repo/target/debug/cooldctl" "$bin"
|
|
}
|
|
|
|
ensure_cooldctl() {
|
|
local bin
|
|
local version
|
|
local arch
|
|
local os
|
|
local url
|
|
local tmpdir
|
|
|
|
bin="$(cooldctl_bin)"
|
|
version="$(read_coolify_env COOLIFY_COOLDCTL_VERSION "$(read_coolify_env COOLIFY_COOLD_VERSION nightly)")"
|
|
arch="$(host_arch)"
|
|
os="$(host_os)"
|
|
|
|
if [ "$os" = "darwin" ]; then
|
|
build_local_cooldctl
|
|
return
|
|
fi
|
|
|
|
if [ -x "$bin" ] && "$bin" --version >/dev/null 2>&1 && [ "${COOLIFY_COOLDCTL_FORCE_DOWNLOAD:-false}" != "true" ]; then
|
|
return
|
|
fi
|
|
|
|
url="https://github.com/coollabsio/coold/releases/download/${version}/cooldctl-${os}-${arch}.tar.gz"
|
|
echo "==> Installing cooldctl from ${url}"
|
|
|
|
mkdir -p "$(dirname "$bin")"
|
|
tmpdir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmpdir"' RETURN
|
|
curl -fsSL --retry 3 --max-time 120 -o "$tmpdir/cooldctl.tar.gz" "$url"
|
|
tar -xzf "$tmpdir/cooldctl.tar.gz" -C "$tmpdir"
|
|
install -m 0755 "$tmpdir/cooldctl" "$bin"
|
|
}
|
|
|
|
lima_ssh_target() {
|
|
local index="$1"
|
|
local instance
|
|
local ssh
|
|
|
|
instance="$(coold_vm_instance "$index")"
|
|
ssh="$(limactl list 2>/dev/null | awk -v name="$instance" 'NR > 1 && $1 == name {print $3}')"
|
|
|
|
if [ -z "$ssh" ] || [ "$ssh" = "-" ]; then
|
|
echo "ERROR: could not determine SSH target for Lima VM ${instance}. Start it first with scripts/dev.sh up." >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s\n' "$ssh"
|
|
}
|
|
|
|
cooldctl_nodes_arg() {
|
|
local count
|
|
local nodes=""
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
if [ -n "$nodes" ]; then
|
|
nodes="${nodes},"
|
|
fi
|
|
nodes="${nodes}$(lima_ssh_target "$index")"
|
|
done
|
|
|
|
printf '%s\n' "$nodes"
|
|
}
|
|
|
|
cooldctl_wg_listen_overrides_arg() {
|
|
local count
|
|
local overrides=""
|
|
local node
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
node="$(lima_ssh_target "$index")"
|
|
if [ -n "$overrides" ]; then
|
|
overrides="${overrides},"
|
|
fi
|
|
overrides="${overrides}${node}=$(coold_vm_wg_port "$index")"
|
|
done
|
|
|
|
printf '%s\n' "$overrides"
|
|
}
|
|
|
|
cooldctl_wg_endpoint_overrides_arg() {
|
|
local count
|
|
local overrides=""
|
|
local node
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
node="$(lima_ssh_target "$index")"
|
|
if [ -n "$overrides" ]; then
|
|
overrides="${overrides},"
|
|
fi
|
|
overrides="${overrides}${node}=host.lima.internal:$(coold_vm_wg_port "$index")"
|
|
done
|
|
|
|
printf '%s\n' "$overrides"
|
|
}
|
|
|
|
cooldctl_ssh_key() {
|
|
read_coolify_env COOLIFY_COOLDCTL_SSH_KEY "$HOME/.lima/_config/user"
|
|
}
|
|
|
|
cooldctl_ssh_user() {
|
|
read_coolify_env COOLIFY_COOLDCTL_SSH_USER "$USER"
|
|
}
|
|
|
|
cooldctl_bootstrap_command() {
|
|
ensure_cooldctl
|
|
|
|
cat <<CMD
|
|
$(cooldctl_bin) init bootstrap \\
|
|
--nodes "$(cooldctl_nodes_arg)" \\
|
|
--ssh-key "$(cooldctl_ssh_key)" \\
|
|
--ssh-user "$(cooldctl_ssh_user)" \\
|
|
--wg-listen-port-overrides "$(cooldctl_wg_listen_overrides_arg)" \\
|
|
--wg-endpoint-overrides "$(cooldctl_wg_endpoint_overrides_arg)" \\
|
|
--coold-version "$(read_coolify_env COOLIFY_COOLD_VERSION nightly)" \\
|
|
--corrosion-version "$(read_coolify_env COOLIFY_CORROSION_VERSION v1.0.0)" \\
|
|
--yes
|
|
CMD
|
|
}
|
|
|
|
cooldctl_bootstrap() {
|
|
ensure_cooldctl
|
|
|
|
"$(cooldctl_bin)" init bootstrap \
|
|
--nodes "$(cooldctl_nodes_arg)" \
|
|
--ssh-key "$(cooldctl_ssh_key)" \
|
|
--ssh-user "$(cooldctl_ssh_user)" \
|
|
--wg-listen-port-overrides "$(cooldctl_wg_listen_overrides_arg)" \
|
|
--wg-endpoint-overrides "$(cooldctl_wg_endpoint_overrides_arg)" \
|
|
--coold-version "$(read_coolify_env COOLIFY_COOLD_VERSION nightly)" \
|
|
--corrosion-version "$(read_coolify_env COOLIFY_CORROSION_VERSION v1.0.0)" \
|
|
--yes
|
|
}
|
|
|
|
cooldctl_dev() {
|
|
local command="${1:-help}"
|
|
if [ $# -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
case "$command" in
|
|
install)
|
|
ensure_cooldctl
|
|
"$(cooldctl_bin)" --version
|
|
;;
|
|
path)
|
|
ensure_cooldctl
|
|
cooldctl_bin
|
|
;;
|
|
bootstrap-command)
|
|
cooldctl_bootstrap_command
|
|
;;
|
|
run)
|
|
ensure_cooldctl
|
|
exec "$(cooldctl_bin)" "$@"
|
|
;;
|
|
-h|--help|help)
|
|
cat <<'USAGE'
|
|
Usage: scripts/dev.sh cooldctl <command>
|
|
|
|
Commands:
|
|
install Download/install the nightly cooldctl dev binary
|
|
path Print the local cooldctl path
|
|
bootstrap-command Print the dev Lima bootstrap command without running it
|
|
run <args> Run cooldctl with arbitrary args
|
|
|
|
Example:
|
|
scripts/dev.sh cooldctl bootstrap-command
|
|
USAGE
|
|
;;
|
|
*)
|
|
echo "unknown cooldctl command: $command" >&2
|
|
echo "Run: scripts/dev.sh cooldctl help" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
coold_vm() {
|
|
local index="$1"
|
|
shift
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$(coold_vm_instance "$index")" \
|
|
COOLIFY_COOLD_VM_WG_IP="$(coold_vm_wg_ip "$index")" \
|
|
COOLIFY_COOLD_VM_CONTAINER_SUBNET="$(coold_vm_container_subnet "$index")" \
|
|
COOLIFY_COOLD_VM_CONTAINER_GATEWAY="$(coold_vm_container_gateway "$index")" \
|
|
scripts/coold-vm.sh "$@"
|
|
}
|
|
|
|
mint_host_jwt_for_host() {
|
|
local host_id="$1"
|
|
local attempts=60
|
|
local output
|
|
local caps
|
|
local builder_capacity
|
|
|
|
builder_capacity="$(read_coolify_env COOLIFY_COOLD_VM_BUILDER_CAPACITY 2)"
|
|
caps="coold"
|
|
if [ "$builder_capacity" != "0" ]; then
|
|
caps="coold,builder"
|
|
fi
|
|
|
|
for attempt in $(seq 1 "$attempts"); do
|
|
if output="$(spin exec -T coolify php artisan flux:dev "$host_id" --caps="$caps" 2>&1)"; then
|
|
printf '%s\n' "$output" | tail -n 1
|
|
return 0
|
|
fi
|
|
|
|
echo "==> Waiting for Flux dev JWT key for ${host_id} (${attempt}/${attempts})..." >&2
|
|
printf '%s\n' "$output" | tail -n 3 | sed 's/^/[coolify] /' >&2
|
|
sleep 2
|
|
done
|
|
|
|
echo "ERROR: Could not mint Flux dev host JWT for ${host_id}." >&2
|
|
return 1
|
|
}
|
|
|
|
follow_logs() {
|
|
local coold_vm_enabled="$1"
|
|
local count
|
|
local vm_logs_pids=""
|
|
count="$(coold_vm_count)"
|
|
|
|
echo "==> Following dev logs. Press Ctrl-C to stop the dev environment."
|
|
|
|
cleanup_logs() {
|
|
for pid in $vm_logs_pids; do
|
|
kill "$pid" >/dev/null 2>&1 || true
|
|
done
|
|
}
|
|
|
|
stop_from_signal() {
|
|
trap - INT TERM EXIT
|
|
cleanup_logs
|
|
echo
|
|
echo "==> Ctrl-C received; stopping dev environment..."
|
|
down
|
|
exit 130
|
|
}
|
|
|
|
trap cleanup_logs EXIT
|
|
trap stop_from_signal INT TERM
|
|
|
|
if [ "$coold_vm_enabled" != "false" ]; then
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
coold_vm "$index" logs-agent | sed "s/^/[${instance}] /" &
|
|
vm_logs_pids="$vm_logs_pids $!"
|
|
done
|
|
fi
|
|
|
|
spin logs -f
|
|
}
|
|
|
|
configure_flux_dev_for_vm() {
|
|
local index="$1"
|
|
local host_id
|
|
local host_jwt
|
|
local flux_url
|
|
|
|
host_id="$(coold_vm_wg_ip "$index")"
|
|
flux_url="$(read_coolify_env COOLIFY_COOLD_VM_FLUX_URL http://host.lima.internal:6443)"
|
|
|
|
echo "==> Minting Flux dev host JWT for ${host_id}..."
|
|
host_jwt="$(mint_host_jwt_for_host "$host_id")"
|
|
echo "==> Installing Flux dev env/JWT into $(coold_vm_instance "$index")..."
|
|
coold_vm "$index" install-host-jwt "$host_jwt"
|
|
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$(coold_vm_instance "$index")" scripts/coold-vm.sh shell <<SH
|
|
set -e
|
|
sudo install -d -m 0755 /etc/systemd/system/coold.service.d
|
|
sudo tee /etc/systemd/system/coold.service.d/10-flux-dev.conf >/dev/null <<UNIT
|
|
[Service]
|
|
Environment=COOLIFY_COOLD_FLUX_URL=${flux_url}
|
|
Environment=COOLIFY_COOLD_HOST_JWT_PATH=/etc/coolify/host-jwt
|
|
UNIT
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart coold.service
|
|
SH
|
|
}
|
|
|
|
up() {
|
|
local coold_vm_enabled
|
|
local follow_dev_logs
|
|
local count
|
|
coold_vm_enabled="$(read_coolify_env COOLIFY_COOLD_VM_ENABLED true)"
|
|
follow_dev_logs="$(read_coolify_env COOLIFY_DEV_FOLLOW_LOGS true)"
|
|
count="$(coold_vm_count)"
|
|
|
|
if [ "$coold_vm_enabled" != "false" ]; then
|
|
echo "==> Starting ${count} Coolify coold VM(s) before Spin..."
|
|
vm_pids=""
|
|
for index in $(seq 1 "$count"); do
|
|
(
|
|
coold_vm "$index" up
|
|
) &
|
|
vm_pids="${vm_pids} $!"
|
|
done
|
|
for pid in $vm_pids; do
|
|
wait "$pid"
|
|
done
|
|
else
|
|
echo "==> COOLIFY_COOLD_VM_ENABLED=false; skipping coold VM."
|
|
fi
|
|
|
|
echo "==> Starting Coolify Docker stack with Spin..."
|
|
spin up -d "$@"
|
|
|
|
if [ "$coold_vm_enabled" != "false" ]; then
|
|
echo "==> Bootstrapping coold VM mesh with cooldctl..."
|
|
cooldctl_bootstrap
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
configure_flux_dev_for_vm "$index"
|
|
done
|
|
fi
|
|
|
|
if [ "$follow_dev_logs" = "false" ]; then
|
|
echo "==> Dev environment is ready. Use 'spin logs -f' or 'scripts/coold-vm.sh logs-agent' to follow logs."
|
|
return
|
|
fi
|
|
|
|
follow_logs "$coold_vm_enabled"
|
|
}
|
|
|
|
down() {
|
|
local coold_vm_enabled
|
|
local stop_coold_vm
|
|
coold_vm_enabled="$(read_coolify_env COOLIFY_COOLD_VM_ENABLED true)"
|
|
stop_coold_vm="$(read_coolify_env COOLIFY_COOLD_VM_STOP_ON_DOWN false)"
|
|
|
|
if [ "$coold_vm_enabled" != "false" ]; then
|
|
for index in $(seq 1 "$(coold_vm_count)"); do
|
|
echo "==> Stopping coold VM agent service on $(coold_vm_instance "$index")..."
|
|
coold_vm "$index" stop-agent || true
|
|
done
|
|
fi
|
|
|
|
echo "==> Stopping Coolify Docker stack with Spin..."
|
|
spin down "$@"
|
|
|
|
if [ "$stop_coold_vm" = "true" ]; then
|
|
echo "==> Stopping Coolify coold VM..."
|
|
for index in $(seq 1 "$(coold_vm_count)"); do
|
|
coold_vm "$index" stop
|
|
done
|
|
fi
|
|
}
|
|
|
|
clean_vms() {
|
|
local count
|
|
count="$(coold_vm_count)"
|
|
|
|
echo "==> Deleting ${count} coold Lima VM(s). This removes VM-local state."
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
echo "==> Deleting ${instance}..."
|
|
limactl stop --force --tty=false "$instance" >/dev/null 2>&1 || true
|
|
if ! run_with_timeout 60 limactl delete --force --tty=false "$instance"; then
|
|
echo "WARN: limactl delete timed out for ${instance}; killing matching limactl clients." >&2
|
|
pkill -f "limactl.*${instance}" >/dev/null 2>&1 || true
|
|
rm -rf "$HOME/.lima/${instance}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
run_with_timeout() {
|
|
local timeout_seconds="$1"
|
|
shift
|
|
local pid
|
|
local elapsed=0
|
|
|
|
"$@" &
|
|
pid="$!"
|
|
|
|
while kill -0 "$pid" >/dev/null 2>&1; do
|
|
if [ "$elapsed" -ge "$timeout_seconds" ]; then
|
|
kill "$pid" >/dev/null 2>&1 || true
|
|
sleep 2
|
|
kill -9 "$pid" >/dev/null 2>&1 || true
|
|
wait "$pid" >/dev/null 2>&1 || true
|
|
return 124
|
|
fi
|
|
|
|
sleep 1
|
|
elapsed=$((elapsed + 1))
|
|
done
|
|
|
|
wait "$pid"
|
|
}
|
|
|
|
corrosion_for_each_vm() {
|
|
local label="$1"
|
|
shift
|
|
local count
|
|
local script
|
|
count="$(coold_vm_count)"
|
|
script="$(cat)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
echo "--- ${instance}: ${label} ---"
|
|
printf '%s\n' "$script" | COOLIFY_COOLD_LIMA_INSTANCE="$instance" scripts/coold-vm.sh shell "$@"
|
|
done
|
|
}
|
|
|
|
corrosion_check() {
|
|
local count
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
peer_index=1
|
|
if [ "$index" = "1" ]; then
|
|
peer_index=2
|
|
fi
|
|
peer_ip="$(coold_vm_wg_ip "$peer_index")"
|
|
|
|
echo "--- ${instance}: check ---"
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$instance" scripts/coold-vm.sh shell <<SH
|
|
set -e
|
|
printf 'services: '
|
|
systemctl is-active corrosion.service || true
|
|
printf 'coold: '
|
|
systemctl is-active coold.service || true
|
|
printf 'wireguard: '
|
|
sudo wg show wg0 >/dev/null 2>&1 && echo active || echo unavailable
|
|
printf 'peer ping (${peer_ip}): '
|
|
ping -c 1 -W 2 ${peer_ip} >/dev/null 2>&1 && echo ok || echo failed
|
|
printf 'gossip: '
|
|
awk '/^\[gossip\]/{section=1; next} /^\[/{section=0} section && /^addr =|^bootstrap =/ {printf "%s ", \$0} END {print ""}' /etc/corrosion/config.toml
|
|
printf 'registered containers: '
|
|
sudo sqlite3 /var/lib/corrosion/corrosion.db 'select count(*) from service_endpoints;' 2>/dev/null || echo unavailable
|
|
SH
|
|
done
|
|
}
|
|
|
|
corrosion_containers() {
|
|
corrosion_for_each_vm containers <<'SH'
|
|
echo '[corrosion service_endpoints]'
|
|
sudo sqlite3 -header -column /var/lib/corrosion/corrosion.db \
|
|
'select container_id, container_name, namespace, host_mgmt_ip, container_ip, state, health, updated_at from service_endpoints order by updated_at desc;' 2>/dev/null \
|
|
|| echo 'service_endpoints table unavailable'
|
|
|
|
echo
|
|
echo '[rootful podman]'
|
|
sudo podman ps --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}' 2>/dev/null \
|
|
|| echo 'rootful podman unavailable'
|
|
|
|
echo
|
|
echo '[rootless podman]'
|
|
podman ps --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}' 2>/dev/null \
|
|
|| echo 'rootless podman unavailable'
|
|
SH
|
|
}
|
|
|
|
corrosion_config() {
|
|
corrosion_for_each_vm config <<'SH'
|
|
sudo cat /etc/corrosion/config.toml
|
|
SH
|
|
}
|
|
|
|
corrosion_logs() {
|
|
local index="${1:-1}"
|
|
coold_vm "$index" logs-agent
|
|
}
|
|
|
|
corrosion_sql() {
|
|
local query="$*"
|
|
|
|
if [ -z "$query" ]; then
|
|
echo "Usage: scripts/dev.sh corrosion sql <query>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
corrosion_for_each_vm sql <<SH
|
|
sudo sqlite3 -header -column /var/lib/corrosion/corrosion.db $(printf '%q' "$query")
|
|
SH
|
|
}
|
|
|
|
corrosion() {
|
|
local command="${1:-help}"
|
|
if [ $# -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
case "$command" in
|
|
check)
|
|
corrosion_check
|
|
;;
|
|
containers|registered-containers)
|
|
corrosion_containers
|
|
;;
|
|
config)
|
|
corrosion_config
|
|
;;
|
|
logs)
|
|
corrosion_logs "${1:-1}"
|
|
;;
|
|
sql)
|
|
corrosion_sql "$@"
|
|
;;
|
|
-h|--help|help)
|
|
cat <<'USAGE'
|
|
Usage: scripts/dev.sh corrosion <command>
|
|
|
|
Commands:
|
|
check Show Corrosion service, WireGuard, gossip, and row-count state
|
|
containers List registered service_endpoints rows on each VM
|
|
config Print /etc/corrosion/config.toml from each VM
|
|
logs [n] Follow coold/corrosion logs for VM n (default: 1)
|
|
sql <query> Run a read-only sqlite query against each Corrosion DB
|
|
USAGE
|
|
;;
|
|
*)
|
|
echo "unknown corrosion command: $command" >&2
|
|
echo "Run: scripts/dev.sh corrosion help" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
example_nginx_name() {
|
|
local index="$1"
|
|
|
|
if [ "$index" = "1" ]; then
|
|
printf '%s\n' coolify-example-nginx
|
|
return
|
|
fi
|
|
|
|
printf 'coolify-example-nginx-%s\n' "$index"
|
|
}
|
|
|
|
example_nginx_up() {
|
|
local count
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
name="$(example_nginx_name "$index")"
|
|
gateway="$(coold_vm_container_gateway "$index")"
|
|
|
|
echo "--- ${instance}: starting ${name} with coold DNS (${gateway}) ---"
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$instance" scripts/coold-vm.sh shell <<SH
|
|
set -e
|
|
sudo podman rm -f ${name} >/dev/null 2>&1 || true
|
|
sudo podman run -d \\
|
|
--name ${name} \\
|
|
--network coolify-default-mesh \\
|
|
--dns ${gateway} \\
|
|
--dns-search default.coolify.internal \\
|
|
docker.io/library/nginx:alpine
|
|
SH
|
|
done
|
|
}
|
|
|
|
example_nginx_down() {
|
|
local count
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
name="$(example_nginx_name "$index")"
|
|
|
|
echo "--- ${instance}: removing ${name} ---"
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$instance" scripts/coold-vm.sh shell <<SH
|
|
sudo podman rm -f ${name} >/dev/null 2>&1 || true
|
|
SH
|
|
done
|
|
}
|
|
|
|
example_nginx_check_dns() {
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$(coold_vm_instance 1)" scripts/coold-vm.sh shell <<'SH'
|
|
set -e
|
|
echo '--- resolv.conf ---'
|
|
sudo podman exec coolify-example-nginx cat /etc/resolv.conf
|
|
echo
|
|
echo '--- coold DNS lookup through search domain ---'
|
|
sudo podman exec coolify-example-nginx nslookup coolify-example-nginx-2
|
|
echo
|
|
echo '--- coold DNS lookup by full name ---'
|
|
sudo podman exec coolify-example-nginx nslookup coolify-example-nginx-2.default.coolify.internal
|
|
SH
|
|
}
|
|
|
|
example_nginx_help() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/dev.sh example-nginx <command>
|
|
|
|
Commands:
|
|
up Start one nginx container on each coold VM with coold DNS configured
|
|
down Remove the example nginx containers
|
|
check-dns Verify host 1 nginx can resolve host 2 nginx through coold DNS
|
|
USAGE
|
|
}
|
|
|
|
example_nginx() {
|
|
local command="${1:-help}"
|
|
if [ $# -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
case "$command" in
|
|
up)
|
|
example_nginx_up
|
|
;;
|
|
down)
|
|
example_nginx_down
|
|
;;
|
|
check-dns)
|
|
example_nginx_check_dns
|
|
;;
|
|
-h|--help|help)
|
|
example_nginx_help
|
|
;;
|
|
*)
|
|
echo "unknown example-nginx command: $command" >&2
|
|
echo "Run: scripts/dev.sh example-nginx help" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
firewall_help() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/dev.sh firewall <command>
|
|
|
|
Commands:
|
|
allow <src> <dst> [proto] [port] Allow traffic on every coold VM (proto/port optional)
|
|
revoke [id|src] [dst] [proto] [port]
|
|
Remove an allow rule from every coold VM
|
|
list List allow rules on every coold VM
|
|
reconcile Re-apply firewall snapshot on every coold VM
|
|
|
|
Examples:
|
|
scripts/dev.sh firewall allow 10.210.0.2 10.210.1.2 tcp 80
|
|
scripts/dev.sh firewall revoke
|
|
scripts/dev.sh firewall revoke 10.210.0.2 10.210.1.2 tcp 80
|
|
scripts/dev.sh firewall revoke 3ba6e0c235a6
|
|
scripts/dev.sh firewall list
|
|
USAGE
|
|
}
|
|
|
|
firewall_api_for_each_vm() {
|
|
local label="$1"
|
|
local method="$2"
|
|
local path="$3"
|
|
local body="${4:-}"
|
|
local count
|
|
count="$(coold_vm_count)"
|
|
|
|
for index in $(seq 1 "$count"); do
|
|
instance="$(coold_vm_instance "$index")"
|
|
api_ip="$(coold_vm_wg_ip "$index")"
|
|
echo "--- ${instance}: ${label} ---"
|
|
COOLIFY_COOLD_LIMA_INSTANCE="$instance" scripts/coold-vm.sh shell <<SH
|
|
set -e
|
|
token="\$(sudo cat /etc/coolify/api-token)"
|
|
curl_args=(-fsS --max-time 10 -X "${method}" "http://${api_ip}:8443${path}" -H "Authorization: Bearer \${token}")
|
|
if [ -n '${body}' ]; then
|
|
curl_args+=(-H 'Content-Type: application/json' -d '${body}')
|
|
fi
|
|
curl "\${curl_args[@]}"
|
|
echo
|
|
SH
|
|
done
|
|
}
|
|
|
|
firewall_allow() {
|
|
local src="${1:-}"
|
|
local dst="${2:-}"
|
|
local proto="${3:-}"
|
|
local port="${4:-}"
|
|
local body
|
|
|
|
if [ -z "$src" ] || [ -z "$dst" ]; then
|
|
firewall_help >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$port" ] && [ -z "$proto" ]; then
|
|
echo "ERROR: port requires proto (tcp or udp)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
body="$(printf '{"namespace":"default","src":"%s","dst":"%s"' "$src" "$dst")"
|
|
if [ -n "$proto" ]; then
|
|
body="${body}$(printf ',"proto":"%s"' "$proto")"
|
|
fi
|
|
if [ -n "$port" ]; then
|
|
body="${body}$(printf ',"port":%s' "$port")"
|
|
fi
|
|
body="${body}}"
|
|
|
|
firewall_api_for_each_vm "allow ${src} -> ${dst}" POST /api/v1/firewall/allow "$body"
|
|
}
|
|
|
|
firewall_rule_id() {
|
|
local src="$1"
|
|
local dst="$2"
|
|
local proto="${3:-}"
|
|
local port="${4:-0}"
|
|
|
|
if [ -z "$proto" ]; then
|
|
port=0
|
|
fi
|
|
|
|
printf 'default|%s|%s|%s|%s' "$src" "$dst" "$proto" "$port" \
|
|
| shasum -a 256 \
|
|
| awk '{print substr($1, 1, 12)}'
|
|
}
|
|
|
|
firewall_revoke() {
|
|
local id_or_src="${1:-}"
|
|
local dst="${2:-}"
|
|
local proto="${3:-}"
|
|
local port="${4:-}"
|
|
local id
|
|
|
|
if [ -z "$id_or_src" ]; then
|
|
echo "Current firewall allow rule IDs:"
|
|
firewall_list
|
|
echo
|
|
echo "Revoke one with: scripts/dev.sh firewall revoke <id>"
|
|
return
|
|
fi
|
|
|
|
if [ -z "$dst" ]; then
|
|
id="$id_or_src"
|
|
else
|
|
id="$(firewall_rule_id "$id_or_src" "$dst" "$proto" "$port")"
|
|
fi
|
|
|
|
firewall_api_for_each_vm "revoke ${id}" DELETE "/api/v1/firewall/allow/${id}"
|
|
}
|
|
|
|
firewall_list() {
|
|
firewall_api_for_each_vm list GET '/api/v1/firewall/allow?namespace=default'
|
|
}
|
|
|
|
firewall_reconcile() {
|
|
firewall_api_for_each_vm reconcile POST /api/v1/firewall/reconcile
|
|
}
|
|
|
|
firewall() {
|
|
local command="${1:-help}"
|
|
if [ $# -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
case "$command" in
|
|
allow)
|
|
firewall_allow "$@"
|
|
;;
|
|
revoke|remove|delete|deny)
|
|
firewall_revoke "$@"
|
|
;;
|
|
list)
|
|
firewall_list
|
|
;;
|
|
reconcile)
|
|
firewall_reconcile
|
|
;;
|
|
-h|--help|help)
|
|
firewall_help
|
|
;;
|
|
*)
|
|
echo "unknown firewall command: $command" >&2
|
|
echo "Run: scripts/dev.sh firewall help" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/dev.sh <command> [spin args]
|
|
|
|
Commands:
|
|
up Start the coold VM, Spin stack, and dev coold agent
|
|
down Stop the dev coold agent and Spin stack
|
|
shell [n] Open a shell inside coold VM n (default: 1)
|
|
list Show Lima instances
|
|
clean-vms Delete the coold Lima VMs and all VM-local runtime state
|
|
corrosion <command> Inspect Corrosion state, config, logs, and registered containers
|
|
firewall <command> Manage dev coold firewall allow rules
|
|
example-nginx <command> Start/check example nginx containers with coold DNS
|
|
cooldctl <command> Install/run the released cooldctl dev helper
|
|
USAGE
|
|
}
|
|
|
|
cmd="${1:-}"
|
|
if [ $# -gt 0 ]; then
|
|
shift
|
|
fi
|
|
|
|
case "$cmd" in
|
|
up)
|
|
up "$@"
|
|
;;
|
|
down)
|
|
down "$@"
|
|
;;
|
|
shell)
|
|
coold_vm "${1:-1}" shell
|
|
;;
|
|
list)
|
|
limactl list
|
|
;;
|
|
clean-vms|clean-vm|reset-vms)
|
|
clean_vms
|
|
;;
|
|
corrosion)
|
|
corrosion "$@"
|
|
;;
|
|
firewall)
|
|
firewall "$@"
|
|
;;
|
|
example-nginx)
|
|
example_nginx "$@"
|
|
;;
|
|
cooldctl)
|
|
cooldctl_dev "$@"
|
|
;;
|
|
-h|--help|help|"")
|
|
usage
|
|
;;
|
|
*)
|
|
echo "unknown command: $cmd" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|