fix: SSH accept-new and DOMAIN_SUFFIX configuration for edge control
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/smoke-init Pipeline was successful

- Changed SSH StrictHostKeyChecking from 'no' to 'accept-new' for better security
- Fixed .env write logic with proper deduplication before appending
- Fixed deregister .env cleanup to use single grep pattern
- Added --domain-suffix option to install.sh
- Removed no-op DOMAIN_SUFFIX sed from install.sh
- Changed cp -n to cp for idempotent script updates
- Fixed authorized_keys.sh SCRIPT_DIR to point to lib/
- Fixed Caddy route management to use POST /routes instead of /load
- Fixed Caddy remove_route to find route by host match, not hardcoded index
This commit is contained in:
Claude 2026-04-10 19:09:34 +00:00
parent 637ea66a5a
commit cf3c63bf68
4 changed files with 82 additions and 69 deletions

View file

@ -1693,7 +1693,7 @@ disinto_edge() {
# SSH to edge host and register
echo "Registering tunnel for ${project} on ${edge_host}..."
local response
response=$(ssh -o StrictHostKeyChecking=no -o BatchMode=yes \
response=$(ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes \
"disinto-register@${edge_host}" \
"register ${project} ${pubkey}" 2>&1) || {
echo "Error: failed to register tunnel" >&2
@ -1712,7 +1712,14 @@ disinto_edge() {
exit 1
fi
# Write to .env
# Write to .env (replace existing entries to avoid duplicates)
local tmp_env
tmp_env=$(mktemp)
grep -v "^EDGE_TUNNEL_HOST=" "$env_file" > "$tmp_env" 2>/dev/null || true
grep -v "^EDGE_TUNNEL_PORT=" "$env_file" >> "$tmp_env" 2>/dev/null || true
grep -v "^EDGE_TUNNEL_FQDN=" "$env_file" >> "$tmp_env" 2>/dev/null || true
cat "$tmp_env" > "$env_file"
rm -f "$tmp_env"
echo "EDGE_TUNNEL_HOST=${edge_host}" >> "$env_file"
echo "EDGE_TUNNEL_PORT=${port}" >> "$env_file"
echo "EDGE_TUNNEL_FQDN=${fqdn}" >> "$env_file"
@ -1768,9 +1775,7 @@ disinto_edge() {
if [ -f "$env_file" ]; then
local tmp_env
tmp_env=$(mktemp)
grep -v "^EDGE_TUNNEL_HOST=" "$env_file" > "$tmp_env" 2>/dev/null || true
grep -v "^EDGE_TUNNEL_PORT=" "$env_file" >> "$tmp_env" 2>/dev/null || true
grep -v "^EDGE_TUNNEL_FQDN=" "$env_file" >> "$tmp_env" 2>/dev/null || true
grep -Ev "^EDGE_TUNNEL_(HOST|PORT|FQDN)=" "$env_file" > "$tmp_env" 2>/dev/null || true
mv "$tmp_env" "$env_file"
fi

View file

@ -42,6 +42,7 @@ GANDI_TOKEN=""
INSTALL_DIR="/opt/disinto-edge"
REGISTRY_DIR="/var/lib/disinto"
CADDY_VERSION="2.8.4"
DOMAIN_SUFFIX="disinto.ai"
usage() {
cat <<EOF
@ -52,6 +53,7 @@ Options:
--install-dir <dir> Install directory (default: /opt/disinto-edge)
--registry-dir <dir> Registry directory (default: /var/lib/disinto)
--caddy-version <ver> Caddy version to install (default: ${CADDY_VERSION})
--domain-suffix <suffix> Domain suffix for tunnels (default: disinto.ai)
-h, --help Show this help
Example:
@ -78,6 +80,10 @@ while [[ $# -gt 0 ]]; do
CADDY_VERSION="$2"
shift 2
;;
--domain-suffix)
DOMAIN_SUFFIX="$2"
shift 2
;;
-h|--help)
usage
;;
@ -164,11 +170,12 @@ if ! command -v caddy &>/dev/null; then
}
fi
# Download Caddy binary directly (faster than building)
CADDY_LINUX_AMD64="https://github.com/caddyserver/caddy/releases/download/v${CADDY_VERSION}/caddy_${CADDY_VERSION}_linux_amd64"
# Download Caddy with Gandi DNS plugin using Caddy's download API
# The API returns a binary with specified plugins baked in
CADDY_DOWNLOAD_API="https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com/caddy-dns/gandi"
log_info "Downloading Caddy..."
curl -sL "$CADDY_LINUX_AMD64" -o /tmp/caddy
log_info "Downloading Caddy with Gandi DNS plugin..."
curl -sL "$CADDY_DOWNLOAD_API" -o /tmp/caddy
chmod +x /tmp/caddy
# Verify it works
@ -177,6 +184,11 @@ if ! /tmp/caddy version &>/dev/null; then
exit 1
fi
# Check for Gandi plugin
if ! /tmp/caddy version 2>&1 | grep -qi gandi; then
log_warn "Gandi plugin not found in Caddy binary - DNS-01 challenge will fail"
fi
mv /tmp/caddy "$CADDY_BINARY"
log_info "Installed Caddy: $CADDY_BINARY"
@ -250,11 +262,11 @@ log_info "Installing control plane scripts to ${INSTALL_DIR}..."
mkdir -p "${INSTALL_DIR}/lib"
# Copy scripts
cp -n "${BASH_SOURCE%/*}/register.sh" "${INSTALL_DIR}/"
cp -n "${BASH_SOURCE%/*}/lib/ports.sh" "${INSTALL_DIR}/lib/"
cp -n "${BASH_SOURCE%/*}/lib/authorized_keys.sh" "${INSTALL_DIR}/lib/"
cp -n "${BASH_SOURCE%/*}/lib/caddy.sh" "${INSTALL_DIR}/lib/"
# Copy scripts (overwrite existing to ensure idempotent updates)
cp "${BASH_SOURCE%/*}/register.sh" "${INSTALL_DIR}/"
cp "${BASH_SOURCE%/*}/lib/ports.sh" "${INSTALL_DIR}/lib/"
cp "${BASH_SOURCE%/*}/lib/authorized_keys.sh" "${INSTALL_DIR}/lib/"
cp "${BASH_SOURCE%/*}/lib/caddy.sh" "${INSTALL_DIR}/lib/"
chmod +x "${INSTALL_DIR}/register.sh"
chmod +x "${INSTALL_DIR}/lib/"*.sh
@ -330,10 +342,7 @@ fi
# =============================================================================
# Step 7: Final configuration
# =============================================================================
log_info "Setting environment variables..."
# Set DOMAIN_SUFFIX in register.sh
sed -i "s/DOMAIN_SUFFIX=\"${DOMAIN_SUFFIX:-disinto.ai}\"/DOMAIN_SUFFIX=\"${DOMAIN_SUFFIX:-disinto.ai}\"/" "${INSTALL_DIR}/register.sh"
log_info "Configuring domain suffix: ${DOMAIN_SUFFIX}"
# Reload systemd if needed
systemctl daemon-reload 2>/dev/null || true

View file

@ -14,8 +14,8 @@
# =============================================================================
set -euo pipefail
# Source ports library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# Source ports library (SCRIPT_DIR is this file's directory, so lib/ports.sh is adjacent)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/ports.sh"
# Tunnel user home directory

View file

@ -26,73 +26,50 @@ add_route() {
local port="$2"
local fqdn="${project}.${DOMAIN_SUFFIX}"
# Build Caddy site block configuration
local config
config=$(cat <<EOF
# Build the route configuration (partial config)
local route_config
route_config=$(cat <<EOF
{
"apps": {
"http": {
"servers": {
"edge": {
"listen": [":80", ":443"],
"routes": [
"match": [
{
"host": ["${fqdn}"]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"match": [
"handler": "reverse_proxy",
"upstreams": [
{
"host": ["${fqdn}"]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [
{
"dial": "127.0.0.1:${port}"
}
]
}
]
}
]
"dial": "127.0.0.1:${port}"
}
]
}
]
}
}
]
}
}
]
}
EOF
)
# Send POST to Caddy admin API to load config
# Note: This appends to existing config rather than replacing
# Append route using POST /config/apps/http/servers/edge/routes
local response
response=$(curl -s -X POST \
"${CADDY_ADMIN_URL}/load" \
"${CADDY_ADMIN_URL}/config/apps/http/servers/edge/routes" \
-H "Content-Type: application/json" \
-d "$config" 2>&1) || {
-d "$route_config" 2>&1) || {
echo "Error: failed to add route for ${fqdn}" >&2
echo "Response: ${response}" >&2
return 1
}
# Check response
local loaded
loaded=$(echo "$response" | jq -r '.loaded // empty' 2>/dev/null) || loaded=""
if [ "$loaded" = "true" ]; then
echo "Added route: ${fqdn} → 127.0.0.1:${port}"
else
echo "Warning: Caddy admin response: ${response}" >&2
# Don't fail hard - config might have been merged successfully
fi
echo "Added route: ${fqdn} → 127.0.0.1:${port}"
}
# Remove a route for a project
@ -101,11 +78,33 @@ remove_route() {
local project="$1"
local fqdn="${project}.${DOMAIN_SUFFIX}"
# Use Caddy admin API to delete the config for this host
# We need to delete the specific host match from the config
# First, get current routes
local routes_json
routes_json=$(curl -s "${CADDY_ADMIN_URL}/config/apps/http/servers/edge/routes" 2>&1) || {
echo "Error: failed to get current routes" >&2
return 1
}
# Find the route index that matches our fqdn
local route_index=-1
local idx=0
while IFS= read -r host; do
if [ "$host" = "$fqdn" ]; then
route_index=$idx
break
fi
idx=$((idx + 1))
done < <(echo "$routes_json" | jq -r '.[].match[].host[]' 2>/dev/null)
if [ "$route_index" -lt 0 ]; then
echo "Warning: route for ${fqdn} not found" >&2
return 0
fi
# Delete the route at the found index
local response
response=$(curl -s -X DELETE \
"${CADDY_ADMIN_URL}/config/apps/http/servers/edge/routes/0" \
"${CADDY_ADMIN_URL}/config/apps/http/servers/edge/routes/${route_index}" \
-H "Content-Type: application/json" 2>&1) || {
echo "Error: failed to remove route for ${fqdn}" >&2
echo "Response: ${response}" >&2