This workflow corresponds to n8n.io template #secrets-provisioner-v1 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Secrets Provisioner",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "secrets-provisioner",
"options": {
"rawBody": false
},
"authentication": "headerAuth",
"responseMode": "lastNode"
},
"id": "webhook-trigger",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
200,
300
],
"typeVersion": 2
},
{
"parameters": {},
"id": "manual-trigger",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
200,
500
],
"typeVersion": 1
},
{
"parameters": {
"jsCode": "// Parse incoming missing secrets list (webhook body: { missing: [...] }).\nconst input = $input.first().json;\nconst body = input.body || input;\nconst missing = body.missing || body.all_missing || input.missing || input.all_missing || [];\n\n// Classify each secret as auto-provisionable or manual.\nconst AUTO_PROVISION = {\n // Secrets that COULD be auto-provisioned with a bootstrap token.\n // For now these are stubs \u2014 real implementation would call provider APIs.\n 'CLOUDFLARE_API_TOKEN': { provider: 'cloudflare', method: 'api_token_create', auto: false, reason: 'Requires Cloudflare dashboard or bootstrap Global API Key' },\n 'FIRECRAWL_API_KEY': { provider: 'firecrawl', method: 'manual', auto: false, reason: 'Sign up at firecrawl.dev and copy API key' }\n};\n\nconst ALWAYS_MANUAL = [\n 'N8N_API_KEY', 'N8N_ENCRYPTION_KEY', 'SUPABASE_SERVICE_ROLE_KEY',\n 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'MONDAY_API_TOKEN',\n 'COMMANDER_WEBHOOK_TOKEN', 'VAULT_MASTER_KEY', 'GRAFANA_PASSWORD'\n];\n\nconst provisioned = [];\nconst manual = [];\nconst errors = [];\n\nfor (const name of missing) {\n const info = AUTO_PROVISION[name];\n if (info && info.auto) {\n // Stub: attempt auto-provision\n try {\n // In a real implementation, call the provider API here.\n // e.g. Cloudflare: POST /client/v4/user/tokens with bootstrap token\n provisioned.push({ name, method: info.method, provider: info.provider });\n } catch (e) {\n errors.push({ name, error: e.message });\n }\n } else {\n const reason = info ? info.reason : 'Manual provisioning required \u2014 see docs/runbooks/missing-secrets.md';\n manual.push({ name, reason });\n }\n}\n\nreturn [{ json: { provisioned, manual, errors, total_missing: missing.length } }];"
},
"id": "classify-and-provision",
"name": "Classify & Provision",
"type": "n8n-nodes-base.code",
"position": [
480,
400
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Store any auto-provisioned secrets into the vault adapter.\nconst report = $input.first().json;\nconst vaultBase = process.env.VAULT_BASE_URL || 'http://localhost:4000';\n\nfor (const item of report.provisioned) {\n if (item.value) {\n try {\n await fetch(`${vaultBase}/secret/${item.name}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ value: item.value })\n });\n item.stored_in = 'vault';\n } catch (e) {\n report.errors.push({ name: item.name, error: `Vault store failed: ${e.message}` });\n }\n delete item.value; // never pass value downstream\n }\n}\n\nreturn [{ json: report }];"
},
"id": "store-provisioned",
"name": "Store Provisioned Secrets",
"type": "n8n-nodes-base.code",
"position": [
720,
400
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Build human-readable request packages for manual secrets.\nconst report = $input.first().json;\n\nconst packages = report.manual.map(item => ({\n secret_name: item.name,\n action_required: item.reason,\n runbook: 'https://github.com/<owner>/<repo>/blob/main/docs/runbooks/missing-secrets.md',\n instructions: [\n `1. Obtain the value for ${item.name} from the appropriate provider.`,\n `2. Store it: set in server ENV or run: echo <value> | vaultctl set ${item.name}`,\n `3. Re-run secrets:heal to verify.`\n ]\n}));\n\nreturn [{ json: { ...report, request_packages: packages } }];"
},
"id": "build-request-packages",
"name": "Build Request Packages",
"type": "n8n-nodes-base.code",
"position": [
960,
400
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Final provisioner report. Gate 4: actions_taken[], remaining_missing[].\nconst r = $input.first().json;\nconst actions_taken = r.provisioned.map(p => `Auto-provisioned or attempted: ${p.name}`).concat(r.manual.map(m => `Request package generated: ${m.name}`));\nconst remaining_missing = r.manual.map(m => m.name);\nreturn [{ json: {\n timestamp: new Date().toISOString(),\n actions_taken,\n remaining_missing,\n total_missing: r.total_missing,\n provisioned: r.provisioned.map(p => ({ name: p.name, method: p.method, stored_in: p.stored_in || 'n/a' })),\n manual: r.manual.map(m => ({ name: m.name, reason: m.reason })),\n errors: r.errors || [],\n request_packages: r.request_packages || []\n} }];"
},
"id": "final-report",
"name": "Final Report",
"type": "n8n-nodes-base.code",
"position": [
1200,
400
],
"typeVersion": 2
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Classify & Provision",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Classify & Provision",
"type": "main",
"index": 0
}
]
]
},
"Classify & Provision": {
"main": [
[
{
"node": "Store Provisioned Secrets",
"type": "main",
"index": 0
}
]
]
},
"Store Provisioned Secrets": {
"main": [
[
{
"node": "Build Request Packages",
"type": "main",
"index": 0
}
]
]
},
"Build Request Packages": {
"main": [
[
{
"node": "Final Report",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateId": "secrets-provisioner-v1",
"description": "Receives a list of missing secrets, attempts auto-provisioning where possible (stub), and generates human-readable request packages for manual secrets. Never outputs secret values."
},
"tags": [
"secrets",
"self-healing",
"infrastructure"
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Secrets Provisioner. Webhook trigger; 6 nodes.
Source: https://github.com/jowikroon/hans-crafted-stories/blob/main/apps/personal/n8n/workflows/secrets_provisioner.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A production-ready authentication workflow implementing secure user registration, login, token verification, and refresh token mechanisms. Perfect for adding authentication to any application without
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
This n8n template demonstrates how a simple Multi-Layer Perceptron (MLP) neural network can predict housing prices. The prediction is based on four key features, processed through a three-layer model.
github code Try yourself
This workflow receives new consult bookings via webhook (Calendly v2 or a generic scheduling tool), generates timed confirmation and reminder messages, runs each SMS through a separate compliance work