Hugo 接入 Decap CMS:Netlify 方案

Hugo 博客可以继续把文章放在 Git 仓库里,同时增加一个网页后台,用来写文章、修改标签和上传图片。Decap CMS 做的就是这件事:浏览器里编辑,保存成 Markdown,再提交到 Git。 如果已经有 Netlify,认证服务可以直接交给它。想用 GitHub 账号登录,可以使用 Netlify 托管的 OAuth;想用邮箱和密码登录,可以使用 Netlify Identity 配合 Git Gateway。这两种方式都不需要自己部署 Cloudflare Worker。 前台也不必迁移。一个实用的安排是:读者访问 Cloudflare 上的博客,编辑者打开 Netlify 上的管理后台,两个平台连接同一个内容仓库。 本文使用假想的 paper-notes 项目。your-github-name/paper-notes 是仓库占位符,notes.example.com 是示例域名,paper-notes.netlify.app 也需要换成自己实际分配到的项目地址。下文配置依据截至 2026 年 9 月 11 日的官方文档整理,不表示这个假想项目已经上线。 先选登录方式 Decap 自己不保存用户密码,也不会因为多了一个 /admin/ 页面就自动拥有账号系统。登录方式取决于配置的后端。 方案 编辑者如何登录 编辑者需要 GitHub 账号吗 需要自建认证服务吗 GitHub 后端 + Netlify OAuth GitHub 授权登录 需要,并且具有仓库写权限 不需要 Git Gateway + Netlify Identity 邮箱和密码,也可另配外部登录 不需要 不需要 GitHub 后端 + 自建 OAuth 代理 GitHub 授权登录 需要,并且具有仓库写权限 需要 自己维护技术博客,用 GitHub 登录比较直接。要让不使用 GitHub 的人参与编辑,邮箱和密码更方便。这里的密码属于 Netlify Identity 用户,不是 Netlify 控制台账号,也不是 GitHub 密码。 ...

2026-09-11 · 9 分钟 · czyt

使用aws go-sdk访问cloudflare R2文件

准备 需要准备Cloudflare的accountId,相应的R2 ak sk 和bucketName等信息. var ( accountId = "xxxxx" accessKeyId = "cbdade718b2ca877882csssssfcf" accessKeySecret = "04917c7d745422022e266f6b06" bucketName = "gopher" ) 完整代码 package main import ( "context" "fmt" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" "log" ) func main() { var ( accountId = "xxxxx" accessKeyId = "cbdade718b2ca877882csssssfcf" accessKeySecret = "04917c7d745422022e266f6b06" bucketName = "gopher" ) var r2Resolver = aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { return aws.Endpoint{ URL: fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountId), }, nil }) cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(r2Resolver), config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyId, accessKeySecret, "")), ) if err != nil { log.Fatal(err) } client := s3.NewFromConfig(cfg) listObjectsOutput, err := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{ Bucket: &bucketName, }) if err != nil { log.Fatal(err) } presignClient := s3.NewPresignClient(client) for _, object := range listObjectsOutput.Contents { // 创建文件访问链接 presignResult, err := presignClient.PresignGetObject(context.TODO(), &s3.GetObjectInput{ Bucket: aws.String(bucketName), Key: aws.String(*object.Key), }) if err != nil { panic("Couldn't get presigned URL for PutObject") } fmt.Printf("get URL For object: %s\n", presignResult.URL) } }

2023-05-21 · 1 分钟 · czyt