Deploy render
One-shot deployment of any project to free cloud infrastructure — scan, auth, deploy, CI/CD, verify
npx -y skills add AayushMS/deploy-skills --skill deploy-renderAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use this skill when the user asks to "deploy to Render", "deploy my backend to Render", "host my server on Render", "deploy my API to Render", or when invoked by the deploy-project orchestrator to deploy a backend/server service. Uses the Render REST API (not CLI) with RENDER_API_KEY. Deploys a web service from a GitHub repo, polls until live, and exports RENDER_SERVICE_ID and RENDER_SERVICE_URL. Free tier: 750 hours/month, services spin down after 15 minutes of inactivity.
SKILL.md
7.3 KB, as published. Nobody here has run it
Deploy to Render
Render is used for backend services (Node.js, Python, Go servers). Uses REST API — no CLI.
Prerequisites
RENDER_API_KEYmust be set (run setup-auth if not)- Project must be pushed to GitHub first (run gh-repo-setup if not)
- Detect build/start commands from package.json scripts
Detect Build and Start Commands
From the project's package.json:
- Build command: look for
"build"in scripts, else"npm install" - Start command: look for
"start"in scripts, then"node src/index.js"as fallback - For Python: check
Procfileforweb:line, elseuvicorn main:app --host 0.0.0.0 --port 10000
Deployment Workflow
0. Ensure root Dockerfile exists
Render ignores dockerfilePath and always builds from ./Dockerfile at the repo root. If the project's Dockerfile is in a subdirectory (e.g. backend/Dockerfile), create a root-level one:
if [ ! -f "Dockerfile" ]; then
# Detect subdirectory Dockerfile
SUBDIR_DOCKERFILE=$(find . -name "Dockerfile" -not -path "./.git/*" | head -1)
if [ -n "$SUBDIR_DOCKERFILE" ]; then
SUBDIR=$(dirname "$SUBDIR_DOCKERFILE" | sed 's|^\./||')
echo "Found Dockerfile at $SUBDIR_DOCKERFILE — creating root Dockerfile that builds from $SUBDIR/"
# Read the original and adapt COPY paths to account for build context being repo root
# Simplest approach: copy content and adjust COPY directives
echo "Creating root Dockerfile..."
# Write a root Dockerfile that copies the subdirectory and runs from it
cat > Dockerfile << EOF
$(cat "$SUBDIR_DOCKERFILE" | sed "s|^COPY \.|COPY $SUBDIR|g")
EOF
echo "⚠ Review Dockerfile — COPY paths may need adjustment for root build context"
echo "✓ Dockerfile created at repo root"
fi
fi
If a Dockerfile was created, commit it before creating the Render service:
git add Dockerfile && git commit -m "chore: add root Dockerfile for Render deployment" && git push
1. Get owner ID
OWNER_ID=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" \
https://api.render.com/v1/owners \
| python3 -c "import sys,json; print(json.load(sys.stdin)[0]['owner']['id'])")
echo "Owner ID: $OWNER_ID"
2. Create web service
REPO_URL=$(gh repo view --json url -q .url)
SERVICE_NAME=$(basename $(pwd) | tr '[:upper:]' '[:lower:]' | tr '_' '-')
SERVICE_RESPONSE=$(curl -s -X POST https://api.render.com/v1/services \
-H "Authorization: Bearer $RENDER_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"type\": \"web_service\",
\"name\": \"$SERVICE_NAME\",
\"ownerId\": \"$OWNER_ID\",
\"repo\": \"$REPO_URL\",
\"branch\": \"main\",
\"buildCommand\": \"<detected build command>\",
\"startCommand\": \"<detected start command>\",
\"plan\": \"free\"
}")
# ⚠ Do NOT pass envVars in the creation payload — Render accepts them but does NOT persist them.
# Env vars must be set via a separate PUT /env-vars call after the service is created (step 3).
SERVICE_ID=$(echo $SERVICE_RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['service']['id'])")
SERVICE_URL=$(echo $SERVICE_RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['service']['serviceDetails']['url'])")
echo "Service ID: $SERVICE_ID"
echo "Service URL: $SERVICE_URL"
3. Set environment variables via dedicated API call
Always use this separate PUT call — never rely on the creation payload to persist env vars.
# Build the env vars JSON array with all required variables
curl -s -X PUT "https://api.render.com/v1/services/$SERVICE_ID/env-vars" \
-H "Authorization: Bearer $RENDER_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{"key": "DATABASE_URL", "value": "'"$DATABASE_URL"'"},
{"key": "REDIS_URL", "value": "'"$REDIS_URL"'"}
]'
# Verify env vars were actually saved
SAVED=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" \
"https://api.render.com/v1/services/$SERVICE_ID/env-vars" \
| python3 -c "import sys,json; vs=json.load(sys.stdin); print([v['key'] for v in vs])")
echo "Env vars saved: $SAVED"
If DATABASE_URL or other required vars are missing from the saved list, re-run the PUT call before triggering a deploy.
4. Poll until live (up to 10 minutes)
echo "Waiting for Render deploy to complete..."
for i in $(seq 1 60); do
STATUS=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" \
"https://api.render.com/v1/services/$SERVICE_ID/deploys?limit=1" \
| python3 -c "
import sys,json
deploys=json.load(sys.stdin)
print(deploys[0]['deploy']['status'] if deploys else 'pending')
" 2>/dev/null || echo "pending")
echo " [$i/60] Deploy status: $STATUS"
if [ "$STATUS" = "live" ]; then
echo "✓ Deploy complete!"
break
fi
if [ "$STATUS" = "failed" ]; then
echo "✗ Deploy FAILED. Check logs at: https://dashboard.render.com"
exit 1
fi
sleep 10
done
5. Verify service is accessible
echo "Verifying service is accessible..."
for i in 1 2 3; do
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "$SERVICE_URL/health" 2>/dev/null)
if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 400 ]; then
echo "✓ Service is live: $SERVICE_URL"
break
fi
echo " Attempt $i: HTTP $HTTP_STATUS — retrying in 15s (Render may be starting up)"
sleep 15
done
6. Export for orchestrator
RENDER_SERVICE_ID=$SERVICE_ID
RENDER_SERVICE_URL=$SERVICE_URL
Note these values — the deploy-project orchestrator uses them when setting up CI/CD and wiring env vars.
Free Tier Notes
⚠️ Render free services spin down after 15 minutes of inactivity. The next request after spindown takes ~30 seconds (cold start). This is normal behavior on the free tier. ⚠️ Free tier: 750 hours/month (enough for one always-on service if requests keep it warm).
On Failure
Do NOT use the Render /v1/logs API — it returns runtime logs only, not build logs, and is unreliable for diagnosis.
Instead, diagnose via deploy status + env var inspection:
# Check deploy status
DEPLOY_STATUS=$(curl -s -H "Authorization: Bearer $RENDER_API_KEY" \
"https://api.render.com/v1/services/$SERVICE_ID/deploys?limit=1" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['deploy']['status'] if d else 'unknown')")
echo "Status: $DEPLOY_STATUS"
# Check saved env vars
curl -s -H "Authorization: Bearer $RENDER_API_KEY" \
"https://api.render.com/v1/services/$SERVICE_ID/env-vars" \
| python3 -c "import sys,json; print([v['key'] for v in json.load(sys.stdin)])"
build_failed→ build command or Dockerfile issue → check dashboard build logs manuallyupdate_failed→ service crashed at startup → almost always a missing env var or wrong start command- Env var missing from the list → re-run the
PUT /env-varscall and trigger a new deploy
For build logs: https://dashboard.render.com/web/$SERVICE_ID/deploys