Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问许可证需确认审计通过

bknd-storage-configbknd 存储配置

Agent Skill

bknd-storage-config 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

324

周安装

13

GitHub Stars

3

下载量

105
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:bknd-storage-config(bknd 存储配置)
来源仓库:https://github.com/cameronapak/bknd-skills
仓库路径:skills/bknd-storage-config
安装命令:
npx skills add https://github.com/cameronapak/bknd-skills --skill bknd-storage-config
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/cameronapak/bknd-skills --skill bknd-storage-config

简介

用于配置 Bknd 媒体模块的存储后端,支持多种云服务。

  • 可选择 S3、R2、Cloudinary 或本地存储作为文件托管方案。
  • 所有配置均需在代码中指定适配器类型及相关凭证参数。
  • 生产环境务必使用加密凭证并限制最小权限原则。
  • bknd-storage-config 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Storage Configuration

Configure storage backends for Bknd's media module.

Prerequisites

  • bknd package installed
  • For S3: bucket created with appropriate permissions
  • For Cloudinary: account with API credentials
  • For R2: Cloudflare Workers environment with R2 binding

When to Use UI Mode

  • Admin panel doesn't support storage configuration
  • Storage must be configured in code

When to Use Code Mode

  • All storage configuration (required)
  • Setting up different adapters per environment
  • Production storage with credentials

Storage Adapter Overview

AdapterTypeUse Case
s3S3-compatibleAWS S3, Cloudflare R2 (external), DigitalOcean Spaces, MinIO
cloudinaryMedia-optimizedImage/video transformations, CDN delivery
localFilesystemDevelopment only (Node.js/Bun runtime)
r2Cloudflare R2Cloudflare Workers with R2 binding

Step-by-Step: S3 Adapter

Step 1: Create S3 Bucket

Create bucket in AWS console or via CLI:

aws s3 mb s3://my-app-uploads --region us-east-1

Step 2: Configure CORS (if browser uploads)

{
  "CORSRules": [{
    "AllowedOrigins": ["https://yourapp.com"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"]
  }]
}

Step 3: Get Access Credentials

Create IAM user with S3 access and get:

  • Access Key ID
  • Secret Access Key

Step 4: Configure Bknd

import { defineConfig } from "bknd";

export default defineConfig({
  media: {
    enabled: true,
    adapter: {
      type: "s3",
      config: {
        access_key: process.env.S3_ACCESS_KEY,
        secret_access_key: process.env.S3_SECRET_KEY,
        url: "https://my-bucket.s3.us-east-1.amazonaws.com",
      },
    },
  },
});

Step 5: Add Environment Variables

# .env
S3_ACCESS_KEY=AKIA...
S3_SECRET_KEY=wJalr...

S3 URL Formats

Different S3-compatible services use different URL formats:

// AWS S3
url: "https://{bucket}.s3.{region}.amazonaws.com"
// Example: "https://my-bucket.s3.us-east-1.amazonaws.com"

// Cloudflare R2 (external access via S3 API)
url: "https://{account_id}.r2.cloudflarestorage.com/{bucket}"
// Example: "https://abc123.r2.cloudflarestorage.com/my-bucket"

// DigitalOcean Spaces
url: "https://{bucket}.{region}.digitaloceanspaces.com"
// Example: "https://my-bucket.nyc3.digitaloceanspaces.com"

// MinIO (self-hosted)
url: "http://localhost:9000/{bucket}"

Step-by-Step: Cloudinary Adapter

Step 1: Get Cloudinary Credentials

From Cloudinary dashboard, copy:

  • Cloud name
  • API Key
  • API Secret

Step 2: Configure Bknd

import { defineConfig } from "bknd";

export default defineConfig({
  media: {
    enabled: true,
    adapter: {
      type: "cloudinary",
      config: {
        cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
        api_key: process.env.CLOUDINARY_API_KEY,
        api_secret: process.env.CLOUDINARY_API_SECRET,
      },
    },
  },
});

Step 3: Add Environment Variables

# .env
CLOUDINARY_CLOUD_NAME=my-cloud
CLOUDINARY_API_KEY=123456789
CLOUDINARY_API_SECRET=abcdef...

Optional: Upload Preset

For unsigned uploads or custom transformations:

adapter: {
  type: "cloudinary",
  config: {
    cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
    api_key: process.env.CLOUDINARY_API_KEY,
    api_secret: process.env.CLOUDINARY_API_SECRET,
    upload_preset: "my-preset",  // Optional
  },
},

Step-by-Step: Local Adapter (Development)

Step 1: Create Upload Directory

mkdir -p ./uploads

Step 2: Register and Configure

import { defineConfig } from "bknd";
import { registerLocalMediaAdapter } from "bknd/adapter/node";

// Register the local adapter
const local = registerLocalMediaAdapter();

export default defineConfig({
  media: {
    enabled: true,
    adapter: local({ path: "./uploads" }),
  },
});

Files served at /api/media/file/{filename}.

Note on Runtime

Local adapter requires Node.js or Bun runtime (filesystem access). It won't work in:

  • Cloudflare Workers
  • Vercel Edge Functions
  • Browser environments

Step-by-Step: Cloudflare R2 (Workers)

Step 1: Create R2 Bucket

wrangler r2 bucket create my-bucket

Step 2: Add R2 Binding to wrangler.toml

[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"

Step 3: Configure Bknd

import { serve, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";

const config: CloudflareBkndConfig = {
  app: (env) => ({
    connection: { url: env.DB },
    config: {
      media: {
        enabled: true,
        adapter: {
          type: "r2",
          config: {
            binding: "MY_BUCKET",
          },
        },
      },
    },
  }),
};

export default serve(config);

R2 adapter uses the Cloudflare Workers binding directly, no external credentials needed.

Media Module Options

Size Limit

export default defineConfig({
  media: {
    enabled: true,
    body_max_size: 10 * 1024 * 1024,  // 10MB max upload
    adapter: { ... },
  },
});

Default Size Behavior

If body_max_size not set, uploads have no size limit. Always set a reasonable limit in production.

Environment-Based Configuration

Different adapters for dev vs production:

import { defineConfig } from "bknd";
import { registerLocalMediaAdapter } from "bknd/adapter/node";

const local = registerLocalMediaAdapter();
const isDev = process.env.NODE_ENV !== "production";

export default defineConfig({
  media: {
    enabled: true,
    body_max_size: 25 * 1024 * 1024,  // 25MB
    adapter: isDev
      ? local({ path: "./uploads" })
      : {
          type: "s3",
          config: {
            access_key: process.env.S3_ACCESS_KEY,
            secret_access_key: process.env.S3_SECRET_KEY,
            url: process.env.S3_BUCKET_URL,
          },
        },
  },
});

Verify Storage Configuration

Check Media Module Enabled

import { Api } from "bknd";

const api = new Api({ host: "http://localhost:7654" });

// List files (empty if no uploads yet)
const { ok, data, error } = await api.media.listFiles();

if (ok) {
  console.log("Media module working, files:", data.length);
} else {
  console.error("Media error:", error);
}

Test Upload

async function testStorage() {
  const testFile = new File(["test content"], "test.txt", {
    type: "text/plain"
  });

  const { ok, data, error } = await api.media.upload(testFile);

  if (ok) {
    console.log("Upload succeeded:", data.name);

    // Clean up
    await api.media.deleteFile(data.name);
    console.log("Cleanup complete");
  } else {
    console.error("Upload failed:", error);
  }
}

Check via REST

# List files
curl http://localhost:7654/api/media/files

# Upload test file
echo "test" | curl -X POST \
  -H "Content-Type: text/plain" \
  --data-binary @- \
  http://localhost:7654/api/media/upload/test.txt

Complete Configuration Examples

AWS S3 Production

import { defineConfig } from "bknd";

export default defineConfig({
  connection: {
    url: process.env.DATABASE_URL,
  },
  config: {
    media: {
      enabled: true,
      body_max_size: 50 * 1024 * 1024,  // 50MB
      adapter: {
        type: "s3",
        config: {
          access_key: process.env.AWS_ACCESS_KEY_ID,
          secret_access_key: process.env.AWS_SECRET_ACCESS_KEY,
          url: `https://${process.env.S3_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com`,
        },
      },
    },
  },
});

Cloudflare R2 + D1

import { serve, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";

const config: CloudflareBkndConfig = {
  app: (env) => ({
    connection: { url: env.DB },  // D1 binding
    config: {
      media: {
        enabled: true,
        body_max_size: 25 * 1024 * 1024,
        adapter: {
          type: "r2",
          config: { binding: "UPLOADS" },
        },
      },
    },
  }),
};

export default serve(config);

Development with Hot Reload

import { defineConfig } from "bknd";
import { registerLocalMediaAdapter } from "bknd/adapter/node";

const local = registerLocalMediaAdapter();

export default defineConfig({
  connection: {
    url: "file:data.db",
  },
  config: {
    media: {
      enabled: true,
      adapter: local({ path: "./public/uploads" }),
    },
  },
});

Common Pitfalls

S3 403 Forbidden

Problem: Upload fails with 403 error.

Causes:

  1. Invalid credentials
  2. Bucket policy blocks access
  3. URL format incorrect

Fix:

// Check URL format - must NOT have trailing slash
url: "https://bucket.s3.region.amazonaws.com"  // CORRECT
url: "https://bucket.s3.region.amazonaws.com/" // WRONG

// Verify credentials
console.log("Key:", process.env.S3_ACCESS_KEY?.substring(0, 8) + "...");

Local Adapter 404

Problem: Files not found after upload.

Causes:

  1. Upload directory doesn't exist
  2. Wrong path (absolute vs relative)

Fix:

# Create directory first
mkdir -p ./uploads

# Use relative path from project root
adapter: local({ path: "./uploads" })  // CORRECT
adapter: local({ path: "/uploads" })   // WRONG (absolute)

R2 Binding Not Found

Problem: "No R2Bucket found with key" error.

Fix: Ensure wrangler.toml has correct binding:

[[r2_buckets]]
binding = "MY_BUCKET"      # This name goes in config
bucket_name = "actual-bucket"

Cloudinary Upload Fails Silently

Problem: putObject returns undefined.

Causes:

  1. Invalid credentials
  2. API key doesn't have upload permission

Fix:

  • Verify credentials in Cloudinary dashboard
  • Ensure API key has write access (not read-only)

Wrong Adapter for Runtime

Problem: Local adapter fails in serverless.

Fix: Use S3/R2/Cloudinary for serverless:

// Cloudflare Workers - use r2
// Vercel - use s3
// AWS Lambda - use s3
// Node.js server - local is OK for dev

Missing Environment Variables

Problem: Credentials undefined at runtime.

Fix:

// Add validation
if (!process.env.S3_ACCESS_KEY) {
  throw new Error("S3_ACCESS_KEY not set");
}

// Or provide defaults for dev
const config = {
  access_key: process.env.S3_ACCESS_KEY ?? "dev-key",
  // ...
};

CORS Not Configured

Problem: Browser uploads blocked.

Fix: Configure CORS on the bucket itself (AWS/R2 console), not in Bknd.

Security Checklist

  1. Never commit credentials - Use environment variables
  2. Restrict bucket access - Don't make bucket public unless needed
  3. Set size limits - Always configure body_max_size
  4. Use HTTPS - Especially for credential-based uploads
  5. Rotate keys - Periodically rotate access keys
  6. Principle of least privilege - IAM user needs only S3 access to one bucket

DOs and DON'Ts

DO:

  • Use environment variables for credentials
  • Set body_max_size in production
  • Use S3/R2/Cloudinary for production
  • Configure CORS for browser uploads
  • Test storage before deploying

DON'T:

  • Commit credentials to git
  • Use local adapter in production
  • Leave upload size unlimited
  • Forget to create upload directory for local
  • Use trailing slash in S3 URL

Related Skills

  • bknd-file-upload - Upload files after storage configured
  • bknd-serve-files - Serve and deliver uploaded files
  • bknd-env-config - Manage environment variables
  • bknd-deploy-hosting - Deploy with production storage
  • bknd-assign-permissions - Set media permissions

适合场景

01

研究助手

02

事实核查

03

知识库问答

04

带来源的搜索总结

能力概览

能力 1

组合搜索和大模型调用

能力 2

支持多来源检索和总结

能力 3

强调引用来源和事实核查

能力 4

适合研究型 Agent 流程

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

33.34%
按下载量换算35

Claude

33.78%
按下载量换算35

Cursor

19.94%
按下载量换算21

Gemini CLI

8.82%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills