Add comments about AWS S3

This commit is contained in:
binwiederhier
2026-03-22 20:52:25 -04:00
parent 4d07897d2d
commit 69cc80ec1e
4 changed files with 63 additions and 4 deletions
+3 -2
View File
@@ -157,7 +157,7 @@ func (c *Store) sync() error {
// than the grace period to account for races, and skipping objects with invalid IDs. // than the grace period to account for races, and skipping objects with invalid IDs.
cutoff := time.Now().Add(-orphanGracePeriod) cutoff := time.Now().Add(-orphanGracePeriod)
var orphanIDs []string var orphanIDs []string
var size int64 var count, size int64
sizes := make(map[string]int64, len(remoteObjects)) sizes := make(map[string]int64, len(remoteObjects))
for _, obj := range remoteObjects { for _, obj := range remoteObjects {
if !fileIDRegex.MatchString(obj.ID) { if !fileIDRegex.MatchString(obj.ID) {
@@ -166,11 +166,12 @@ func (c *Store) sync() error {
if _, ok := localIDMap[obj.ID]; !ok && obj.LastModified.Before(cutoff) { if _, ok := localIDMap[obj.ID]; !ok && obj.LastModified.Before(cutoff) {
orphanIDs = append(orphanIDs, obj.ID) orphanIDs = append(orphanIDs, obj.ID)
} else { } else {
count++
size += obj.Size size += obj.Size
sizes[obj.ID] = obj.Size sizes[obj.ID] = obj.Size
} }
} }
log.Tag(tagStore).Debug("Attachment store updated: %d attachment(s), %s", len(localIDs), util.FormatSizeHuman(size)) log.Tag(tagStore).Debug("Attachment store updated: %d attachment(s), %s", count, util.FormatSizeHuman(size))
c.mu.Lock() c.mu.Lock()
c.size = size c.size = size
c.sizes = sizes c.sizes = sizes
+28
View File
@@ -565,6 +565,34 @@ When `endpoint` is specified, path-style addressing is enabled automatically (us
Note that the access key and secret key may have to be URL encoded. For instance, a secret key `YmxhY+mxhYmxhC` (note the `+`) should Note that the access key and secret key may have to be URL encoded. For instance, a secret key `YmxhY+mxhYmxhC` (note the `+`) should
be encoded as `YmxhY%2BmxhYmxhC` (note the `%2B`), so the URL would be `s3://ACCESS_KEY:YmxhY%2BmxhYmxhC@my-bucket/attachments...`. be encoded as `YmxhY%2BmxhYmxhC` (note the `%2B`), so the URL would be `s3://ACCESS_KEY:YmxhY%2BmxhYmxhC@my-bucket/attachments...`.
For **AWS S3**, the IAM user needs the following permissions on the bucket:
``` json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketMultipartUploads"
],
"Resource": "arn:aws:s3:::BUCKET_NAME"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload"
],
"Resource": "arn:aws:s3:::BUCKET_NAME/*"
}
]
}
```
## Access control ## Access control
By default, the ntfy server is open for everyone, meaning **everyone can read and write to any topic** (this is how By default, the ntfy server is open for everyone, meaning **everyone can read and write to any topic** (this is how
ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization. ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization.
+1 -1
View File
@@ -1802,7 +1802,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
**Features:** **Features:**
* Add S3-compatible object storage as an alternative [attachment](config.md#attachments) backend via `attachment-cache-dir` config option * Add S3-compatible object storage as an alternative [attachment store](config.md#attachments) via `attachment-cache-dir` config option
**Bug fixes + maintenance:** **Bug fixes + maintenance:**
+31 -1
View File
@@ -25,6 +25,32 @@ const (
// and ListObjectsV2 operations using AWS Signature V4 signing. The bucket and optional key prefix // and ListObjectsV2 operations using AWS Signature V4 signing. The bucket and optional key prefix
// are fixed at construction time. All operations target the same bucket and prefix. // are fixed at construction time. All operations target the same bucket and prefix.
// //
// The following IAM policy is required for AWS S3:
//
// {
// "Version": "2012-10-17",
// "Statement": [
// {
// "Effect": "Allow",
// "Action": [
// "s3:ListBucket",
// "s3:ListBucketMultipartUploads"
// ],
// "Resource": "arn:aws:s3:::BUCKET_NAME"
// },
// {
// "Effect": "Allow",
// "Action": [
// "s3:GetObject",
// "s3:PutObject",
// "s3:DeleteObject",
// "s3:AbortMultipartUpload"
// ],
// "Resource": "arn:aws:s3:::BUCKET_NAME/*"
// }
// ]
// }
//
// Fields must not be modified after the Client is passed to any method or goroutine. // Fields must not be modified after the Client is passed to any method or goroutine.
type Client struct { type Client struct {
config *Config config *Config
@@ -149,7 +175,11 @@ func (c *Client) ListObjectsV2(ctx context.Context) ([]*Object, error) {
// listObjectsV2 performs a single ListObjectsV2 request using the client's configured prefix. // listObjectsV2 performs a single ListObjectsV2 request using the client's configured prefix.
func (c *Client) listObjectsV2(ctx context.Context, continuationToken string) (*listObjectsV2Result, error) { func (c *Client) listObjectsV2(ctx context.Context, continuationToken string) (*listObjectsV2Result, error) {
log.Tag(tagS3Client).Debug("Listing remote objects with continuation token '%s'", continuationToken) if continuationToken == "" {
log.Tag(tagS3Client).Debug("Listing remote objects")
} else {
log.Tag(tagS3Client).Debug("Listing remote objects, continuing with token '%s'", continuationToken)
}
query := url.Values{"list-type": {"2"}} query := url.Values{"list-type": {"2"}}
if prefix := c.config.ListPrefix(); prefix != "" { if prefix := c.config.ListPrefix(); prefix != "" {
query.Set("prefix", prefix) query.Set("prefix", prefix)