# How to Configure AWS S3 or Cloudflare R2 with PicList: Complete Setup Guide

> Easily configure AWS S3 or Cloudflare R2 with PicList using our complete setup guide. Learn steps for access keys, endpoints, path style, and ACL for seamless integration.

- Repository: [Kuingsmile/piclist](https://github.com/kuingsmile/piclist)
- Tags: how-to-guide
- Published: 2026-03-05

---

**To configure AWS S3 or Cloudflare R2 with PicList, add an `aws-s3` bucket in Settings → Manage → Bucket, supply your Access Key ID and Secret, set the endpoint (required for R2), enable `s3ForcePathStyle` for R2 compatibility, and define the ACL as `public-read`.**

PicList supports both Amazon S3 and Cloudflare R2 through its unified `aws-s3` plugin, which leverages R2’s S3-compatible API. The configuration values entered in the graphical interface map directly to the JSON structure consumed by the core upload logic, specifically within [`scripts/upload-to-s3.js`](https://github.com/kuingsmile/piclist/blob/main/scripts/upload-to-s3.js).

## Adding an S3 or R2 Bucket in PicList

1. Open **Settings → Manage → Bucket** and click the **"+"** button to create a new bucket configuration.
2. Select **aws-s3** (or **aws-s3-plist**, which uses the identical implementation).
3. Fill in the required fields detailed in the next section.

The UI field definitions, including placeholders and validation rules, are defined in [`src/renderer/manage/utils/constants.ts`](https://github.com/kuingsmile/piclist/blob/main/src/renderer/manage/utils/constants.ts) under the `aws-s3` section.

## Required Configuration Fields

### Access Credentials

- **Access Key ID**: For AWS, use the IAM user’s `accessKeyId`; for Cloudflare R2, use the `R2_SECRET_ID` from your R2 API tokens.
- **Access Key Secret**: The corresponding secret key (`accessKeySecret` for AWS, `R2_SECRET_KEY` for R2).

### Bucket Name and Endpoint

- **Bucket Name**: The exact name of your existing bucket (e.g., `my-bucket`).
- **Endpoint**: Leave this blank for AWS S3 to use the default regional endpoint. For Cloudflare R2, this is mandatory and must follow the format `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`.

### Path Style and Access Control

- **Force Path Style** (`s3ForcePathStyle`): Set to **true** for Cloudflare R2, which requires path-style URLs (`https://<endpoint>/<bucket>/<key>`). For standard AWS S3, set this to **false**.
- **ACL**: Typically set to `public-read` to ensure uploaded objects are publicly accessible.

## How PicList Uploads Files to S3 and R2

When you initiate an upload, PicList constructs an `S3Client` instance using the AWS SDK for JavaScript v3. The client configuration is built from your bucket settings as implemented in [`scripts/upload-to-s3.js`](https://github.com/kuingsmile/piclist/blob/main/scripts/upload-to-s3.js):

```javascript
const client = new S3Client({
  region: 'auto',               // Region is ignored for R2
  credentials: {
    accessKeyId: bucketConfig.accessKeyId,
    secretAccessKey: bucketConfig.accessKeySecret,
  },
  endpoint: bucketConfig.endpoint, // Omitted for native AWS S3
  forcePathStyle: bucketConfig.s3ForcePathStyle ?? false,
});

```

The `PutObjectCommand` is then executed with your specified `Bucket`, `Key`, `Body`, and `ACL` values. The same upload script handles both AWS S3 and Cloudflare R2; when the `endpoint` is omitted, the AWS SDK automatically resolves the appropriate regional endpoint for S3.

## Resolving R2 Connectivity Issues in Restricted Networks

Cloudflare R2 endpoints can encounter SNI blocking by the Great Firewall. If uploads fail, inspect `piclist.log` to identify the resolved IP address. Add this IP to PicList’s proxy exception list under **Settings → Network → Proxy** to bypass the blockage. This troubleshooting step is documented in [`FAQ.md`](https://github.com/kuingsmile/piclist/blob/main/FAQ.md).

## Configuration File Examples

### Bucket Configuration JSON

When saved, your settings produce a JSON object structured like this (example for Cloudflare R2):

```json
{
  "type": "aws-s3",
  "name": "my-r2-bucket",
  "config": {
    "accessKeyId": "R2_SECRET_ID",
    "accessKeySecret": "R2_SECRET_KEY",
    "bucketName": "my-r2-bucket",
    "endpoint": "https://1234567890.r2.cloudflarestorage.com",
    "s3ForcePathStyle": true,
    "acl": "public-read"
  }
}

```

### Upload Script Implementation

The core logic in [`scripts/upload-to-s3.js`](https://github.com/kuingsmile/piclist/blob/main/scripts/upload-to-s3.js) demonstrates how the configuration object is consumed:

```javascript
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const fs = require('fs');
const path = require('path');

async function upload(filePath, config) {
  const client = new S3Client({
    region: 'auto',
    credentials: {
      accessKeyId: config.accessKeyId,
      secretAccessKey: config.accessKeySecret,
    },
    endpoint: config.endpoint,
    forcePathStyle: config.s3ForcePathStyle,
  });

  const command = new PutObjectCommand({
    Bucket: config.bucketName,
    Key: path.basename(filePath),
    Body: fs.createReadStream(filePath),
    ACL: config.acl,
  });

  return client.send(command);
}

```

## Summary

- PicList uses the `aws-s3` plugin for both Amazon S3 and Cloudflare R2 via S3-compatible APIs.
- Cloudflare R2 requires a custom endpoint and `s3ForcePathStyle: true`, while AWS S3 uses regional endpoints and virtual-hosted styles by default.
- Configuration fields are defined in [`src/renderer/manage/utils/constants.ts`](https://github.com/kuingsmile/piclist/blob/main/src/renderer/manage/utils/constants.ts) and processed by [`scripts/upload-to-s3.js`](https://github.com/kuingsmile/piclist/blob/main/scripts/upload-to-s3.js).
- For R2 users behind restrictive firewalls, adding the resolved IP to the proxy list resolves SNI blocking issues.

## Frequently Asked Questions

### Does PicList support Cloudflare R2 natively?

Yes. PicList supports Cloudflare R2 through the `aws-s3` plugin, utilizing R2’s S3-compatible API. You configure it by selecting the `aws-s3` bucket type and providing your R2-specific credentials and endpoint.

### What is the correct endpoint format for Cloudflare R2?

The endpoint must be `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`, replacing `<ACCOUNT_ID>` with your actual Cloudflare account ID. This value is mandatory for R2 but should be left blank for standard AWS S3 configurations.

### Why does R2 require Force Path Style while AWS S3 does not?

Cloudflare R2 requires path-style URLs (`https://endpoint/bucket/key`) rather than virtual-hosted style (`https://bucket.endpoint/key`). Setting `s3ForcePathStyle` to `true` ensures the AWS SDK constructs URLs compatible with R2’s architecture.

### How do I troubleshoot upload failures with R2 from China?

If you encounter timeouts or SSL errors, check `piclist.log` for the IP address resolved from the R2 endpoint. Add this specific IP address to the proxy list in **Settings → Network → Proxy** to circumvent SNI-based blocking, as noted in the project’s [`FAQ.md`](https://github.com/kuingsmile/piclist/blob/main/FAQ.md).