Skip to content

Instantly share code, notes, and snippets.

@supersonictw
Last active November 20, 2025 06:41
Show Gist options
  • Select an option

  • Save supersonictw/f3c23fdf5c421d7dbd73c2187064b545 to your computer and use it in GitHub Desktop.

Select an option

Save supersonictw/f3c23fdf5c421d7dbd73c2187064b545 to your computer and use it in GitHub Desktop.
Quickly add a reverse proxy via the Caddy Admin API
#!/bin/bash
# rproxy.sh - Quickly add a reverse proxy via the Caddy Admin API
# Usage: rproxy <UPSTREAM_ADDR> <LISTEN_ADDR>
# Example: rproxy localhost:3000 :8080
# SPDX-License-Identifier: MIT (https://ncurl.xyz/s/Kkn2DQsNR)
# 0. Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: This script requires 'jq'. Please install jq first." >&2
exit 1
fi
# 1. Check arguments
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <UPSTREAM_ADDR> <LISTEN_ADDR>" >&2
echo "Example: $0 localhost:3000 :8080" >&2
exit 1
fi
# Caddy Admin API address
CADDY_API="${CADDY_API:-localhost:2019}"
# Input arguments
UPSTREAM_ADDR="$1"
LISTEN_ADDR="$2"
# 2. Prepare variables
SERVER_ID="rproxy_${LISTEN_ADDR}" # Unique server ID (for idempotency)
# 3. Generate JSON Payload using jq
JSON_PAYLOAD=$(jq -n \
--arg listen_addr "$LISTEN_ADDR" \
--arg upstream_addr "$UPSTREAM_ADDR" \
'{
listen: [$listen_addr],
routes: [
{
handle: [
{
handler: "reverse_proxy",
upstreams: [ { dial: $upstream_addr } ]
}
]
}
]
}'
)
# 4. Send request to Caddy Admin API
# -s: silent, -f: fail-fast (exit on HTTP error)
OUTPUT=$(curl -vf -X POST \
"http://${CADDY_API}/config/apps/http/servers/${SERVER_ID}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" 2>&1)
CURL_EXIT_CODE=$?
# 5. Check curl's exit status
if [ $CURL_EXIT_CODE -eq 0 ]; then
echo "Caddy proxy created: ${LISTEN_ADDR} -> ${UPSTREAM_ADDR} (ID: ${SERVER_ID})"
elif [ $CURL_EXIT_CODE -eq 22 ]; then
# Exit code 22 means HTTP error (e.g., 400, 404, 500)
echo "Failure! Caddy API rejected the request (HTTP 4xx/5xx)." >&2
echo "Run with 'curl -v' manually to see Caddy's error message." >&2
echo "Error: $OUTPUT" >&2
exit $CURL_EXIT_CODE
else
# Other curl error (e.g., 7 - couldn't connect)
echo "Failure! curl error $CURL_EXIT_CODE." >&2
echo "Error: $OUTPUT" >&2
exit $CURL_EXIT_CODE
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment