Giter Club home page Giter Club logo

synapse-s3-storage-provider's Introduction

Synapse S3 Storage Provider

This module can be used by synapse as a storage provider, allowing it to fetch and store media in Amazon S3.

Usage

The s3_storage_provider.py should be on the PYTHONPATH when starting synapse.

Example of entry in synapse config:

media_storage_providers:
- module: s3_storage_provider.S3StorageProviderBackend
  store_local: True
  store_remote: True
  store_synchronous: True
  config:
    bucket: <S3_BUCKET_NAME>
    # All of the below options are optional, for use with non-AWS S3-like
    # services, or to specify access tokens here instead of some external method.
    region_name: <S3_REGION_NAME>
    endpoint_url: <S3_LIKE_SERVICE_ENDPOINT_URL>
    access_key_id: <S3_ACCESS_KEY_ID>
    secret_access_key: <S3_SECRET_ACCESS_KEY>

    # Server Side Encryption for Customer-provided keys
    #sse_customer_key: <S3_SSEC_KEY>
    # Your SSE-C algorithm is very likely AES256
    # Default is AES256.
    #sse_customer_algo: <S3_SSEC_ALGO>

    # The object storage class used when uploading files to the bucket.
    # Default is STANDARD.
    #storage_class: "STANDARD_IA"

    # Prefix for all media in bucket, can't be changed once media has been uploaded
    # Useful if sharing the bucket between Synapses
    # Blank if not provided
    #prefix: "prefix/to/files/in/bucket"

    # The maximum number of concurrent threads which will be used to connect
    # to S3. Each thread manages a single connection. Default is 40.
    #
    #threadpool_size: 20

This module uses boto3, and so the credentials should be specified as described here.

Regular cleanup job

There is additionally a script at scripts/s3_media_upload which can be used in a regular job to upload content to s3, then delete that from local disk. This script can be used in combination with configuration for the storage provider to pull media from s3, but upload it asynchronously.

Once the package is installed, the script should be run somewhat like the following. We suggest using tmux or screen as these can take a long time on larger servers.

database.yaml should contain the keys that would be passed to psycopg2 to connect to your database. They can be found in the contents of the database.args parameter in your homeserver.yaml.

More options are available in the command help.

> cd s3_media_upload
# cache.db will be created if absent. database.yaml is required to
# contain PG credentials
> ls
cache.db database.yaml
# Update cache from /path/to/media/store looking for files not used
# within 2 months
> s3_media_upload update /path/to/media/store 2m
Syncing files that haven't been accessed since: 2018-10-18 11:06:21.520602
Synced 0 new rows
100%|█████████████████████████████████████████████████████████████| 1074/1074 [00:33<00:00, 25.97files/s]
Updated 0 as deleted

> s3_media_upload upload /path/to/media/store matrix_s3_bucket_name --storage-class STANDARD_IA --delete
# prepare to wait a long time

Packaging and release

For maintainers:

  1. Update the __version__ in setup.py. Commit. Push.
  2. Create a release on GitHub for this version.
  3. When published, a GitHub action workflow will build the package and upload to PyPI.

synapse-s3-storage-provider's People

Contributors

alexis211 avatar anoadragon453 avatar babolivier avatar benbz avatar clokep avatar djmaze avatar erikjohnston avatar fabianunterstell avatar hawkowl avatar keur avatar kittykat avatar michaelkaye avatar ratsclub avatar reivilibre avatar richvdh avatar rkfg avatar shadowjonathan avatar sharparam avatar squahtx avatar srhoulam avatar xangelix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

synapse-s3-storage-provider's Issues

s3_media_upload non-AWS

The s3_media_upload script suffers from a handful shortcomings that stem from - in contrast to the s3_storage_provider.py module - not inheriting the homeserver config.

Especially the trouble is that the default boto3 client instantiation somehow gets the region (from .aws/config default s3 maybe?) but not the complete URL/domain part - i.e. if you use something other that AWS, synapse will respect that but the upload script won't.

My suggestion is to instead of creating a custom database.yaml config file, to just read the homeserver.yaml instead (or worse, copy all relevant fields into it's own config).
Then parse everything relevant, e.g. endpoint_url to this:

s3 = boto3.client("s3")

S3 storage provider stopped working

Describe the bug
Yesterday it was running fine, but I upgraded synapse and now I'm getting errors.

To Reproduce

  1. upgrade to synapse 1.34.0
  2. try to get/upload any file from/to the media repo

Expected behavior
It should return or upload the image.

Log
This is a sample error:

synapse_1             | 2021-05-20 10:24:17,574 - synapse.http.server - 93 - ERROR - GET-4249 - Failed handle request via 'ThumbnailResource': <XForwardedForRequest at 0x7fa50af7f400 method='GET' uri='/_matrix/media/r0/thumbnail/matrix.org/xxxxx?width=800&height=600&method=scale' clientproto='HTTP/1.1' site='8008'>
synapse_1             | Traceback (most recent call last):
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/http/server.py", line 258, in _async_render_wrapper
synapse_1             |     callback_return = await self._async_render(request)
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/http/server.py", line 286, in _async_render
synapse_1             |     callback_return = await raw_callback_return
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 83, in _async_render_GET
synapse_1             |     await self._respond_remote_thumbnail(
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 260, in _respond_remote_thumbnail
synapse_1             |     media_info = await self.media_repo.get_remote_media_info(server_name, media_id)
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 281, in get_remote_media_info
synapse_1             |     responder, media_info = await self._get_remote_media_impl(
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 339, in _get_remote_media_impl
synapse_1             |     raise e
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 328, in _get_remote_media_impl
synapse_1             |     media_info = await self._download_remote_file(
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 431, in _download_remote_file
synapse_1             |     await finish()
synapse_1             |   File "/usr/local/lib/py-thon3.8/site-packages/synapse/rest/media/v1/media_storage.py", line 145, in finish
synapse_1             |     await provider.store_file(path, file_info)
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/synapse/rest/media/v1/storage_provider.py", line 99, in store_file
synapse_1             |     await maybe_awaitable(self.backend.store_file(path, file_info))  # type: ignore
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/twisted/python/threadpool.py", line 238, in inContext
synapse_1             |     result = inContext.theWork()  # type: ignore[attr-defined]
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/twisted/python/threadpool.py", line 254, in <lambda>
synapse_1             |     inContext.theWork = lambda: context.call(  # type: ignore[attr-defined]
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/twisted/python/context.py", line 118, in callWithContext
synapse_1             |     return self.currentContext().callWithContext(ctx, func, *args, **kw)
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/twisted/python/context.py", line 83, in callWithContext
synapse_1             |     return func(*args, **kw)
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/s3_storage_provider.py", line 121, in _store_file
synapse_1             |     self._get_s3_client().upload_file(
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/boto3/s3/inject.py", line 129, in upload_file
synapse_1             |     return transfer.upload_file(
synapse_1             |   File "/usr/local/lib/python3.8/site-packages/boto3/s3/transfer.py", line 285, in upload_file
synapse_1             |     raise S3UploadFailedError(
synapse_1             | boto3.exceptions.S3UploadFailedError: Failed to upload /data/media_store/remote_content/matrix.org/xx/xx/xxxxxx to media.matrix.systemtest.tk/remote_content/matrix.org/xx/xx/xxxxxx: An error occurred (RequestTimeout) when calling the PutObject operation (reached max retries: 4): Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed.

I get the same kind of errors when downloading files. On upload it fails as well.

When downloading:

 botocore.exceptions.ConnectionClosedError: Connection was closed before we received a valid response from endpoint URL: "https://s3.eu-west-1.amazonaws.com/media.matrix.systemtest.tk/remote_content/matrix.org/xx/xx/xxxxxx"

Versions

  • Running in docker
  • Synapse 1.34.0

Additional Context

  • Bucket name is media.matrix.systemtest.tk

Storage Provider incompatible with Synapse 1.32.x

Describe the bug
This Storage Provider seems to be incompatible with the newest releases of synapse, so that viewing any media in a client does not work.

To Reproduce
Steps to reproduce the behavior:

  1. Install/Update synapse version 1.32.x
  2. Install the storage provider
  3. Try to open any media in any client
  4. See error
2021-04-21 15:58:44,039 - twisted - 260 - CRITICAL - sentinel - Unhandled Error
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/_threads/_threadworker.py", line 46, in work
    task()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/_threads/_team.py", line 190, in doWork
    task()
--- <exception caught here> ---
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/threadpool.py", line 250, in inContext
    result = inContext.theWork()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
    inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/s3_storage_provider.py", line 166, in s3_download_task
    with LoggingContext(parent_context=parent_logcontext):
builtins.TypeError: __init__() missing 1 required positional argument: 'name'

Expected behavior
Vieweing media should wor

Steps to install

Sorry if this is a stupid question!

I'm on Debian 9 and did
pip install git+https://github.com/matrix-org/synapse-s3-storage-provider.git

I add the following configuration to /etc/matrix-synapse/homeserver.yaml

media_storage_providers:
- module: s3_storage_provider.S3StorageProviderBackend
  store_local: True
  store_remote: True
  store_synchronous: True
  config:
   bucket: matrix

Then I did a
systemctl restart matrix-synapse

In syslog I see

matrix python[6899]: ImportError: No module named s3_storage_provider

Tow questions:

  1. How do I have to install synapse-s3-storage-provider so Matrix can find/use it?

  2. How/Where do I configure my S3 credentials?

s3_media_upload lacks ability to set region or endpoint_url

At present, the synapse-s3-storage-provider toolkit has an uneven implementation of configuration options. s3_storage_provider.py permits the configuration of a custom endpoint URL and setting the region for sessions, but s3_media_upload does not support setting these as options.

Please push latest changes for synapse v.1.45.0 to PyPi

Describe the bug

The version 1.0 in PyPi does not contain the latest update required to be compatible with synapse v1.45.0.
This commit has the necessary changes.

When starting the synapse v1.45.0 server with a working config and the version 1.0 from PyPi, installed via pip, the following error crashes the media worker.

AttributeError: 'HomeServerConfig' object has no attribute 'media_store_path'

To Reproduce
Steps to reproduce the behavior:

  1. Install this storage provider from pip
    pip3 install synapse-s3-storage-provider
  2. Run synapse with a homeserver config using this module.

Expected behavior
Start up with existing correct config with no error.

Desktop (please complete the following information):
NA

Smartphone (please complete the following information):
NA

Additional context
NA

Remove strict check over Storage Tiers

There's a strict check over which storage tiers entries are allowed.
This can be problematic when providers have their own storage tiers (as an example, Scaleway provides the "ONEZONE_IA" storage tier for single-AZ data)

Here's the related code :

_VALID_STORAGE_CLASSES = (

assert storage_class in _VALID_STORAGE_CLASSES

Add support for redirecting media downloads (MSC3860)

It would be a massive efficiency to deploy MSC3860 to this storage provider to allow storage to be served directly from S3 servers.

I would see it sending a s3 get_presigned_url() of a media file to the client to keep S3 server closed from public.

`True` vs `true` in the usage example, possible doc 🐛

In the usage example here it shows the following:

  store_local: True
  store_remote: True
  store_synchronous: True

Should all of those True be true (lower case t) since yaml is weird like that? 🤷 Happy to submit a quick PR for that if needed. :)

Also thanks for working on this! I haven't gotten it working yet, but I am very excited to eventually get it working.

Final question while I'm at it: If I set store_local to false will it only store stuff in the s3 and skip the local volume all together? 🤔

Proper way to clean media_store_path?

I have the following setup:

    ## Media Store ##
    #enable_media_repo: false
    media_store_path: "/data/media_store"
    media_storage_providers:
    - module: s3_storage_provider.S3StorageProviderBackend
      store_local: True
      store_remote: True
      store_synchronous: True
      config:
        bucket: synapsebucket
        endpoint_url: http://synapse-minio-hl-svc:9000
        access_key_id: accesskey
        secret_access_key: secretkey
    uploads_path: "/data/uploads"

With this setup, files are kept both in /data/media_store and in synapsebucket bucket now.

As far as I understand, synapse upload files into /data/media_store and synapse-s3-storage-provider copies these files to synapsebucket bucket.
However, files in /data/media_store are not required, after being copied to bucket, but are still in there.

How should /data/media_store be cleaned properly?
Should I setup a cronjob and just rm old files in /data/media_store?
Or may be there are more proper ways to do this?

I have some vague idea that s3_media_upload is somehow related to this, but do not grasp the whole picture. I do not use s3_media_upload at the moment and files are successfully copied into bucket by synapse-s3-storage-provider already.

The main (and only problem at the moment) is unused files kept in /data/media_store.

Please, advise! Thanks in advance!

Handle cases where `last_access_ts` is null in s3_media_upload

Some local media files may not have been accessed at all since uploading. This may sound counterintuitive, but some bridges, for example the mautrix_telegram bridge, can generate such media files when users are not online to check the messages.

Currently, the s3_media_upload script does not handle these files at all. On my instance this has resulted in more than 20 gigabytes of media files that simply haven't been accessed at all (because they are all from the Telegram bridge) and are not removed from the local storage or uploaded to S3.

Unable to run with Synapse 1.96.1

Error at startup:

Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/app/homeserver.py", line 399, in <module>
    main()
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/app/homeserver.py", line 389, in main
    hs = setup(sys.argv[1:])
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/app/homeserver.py", line 298, in setup
    config = HomeServerConfig.load_or_generate_config(
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/config/_base.py", line 802, in load_or_generate_config
    obj.parse_config_dict(
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/config/_base.py", line 823, in parse_config_dict
    self.invoke_all(
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/config/_base.py", line 422, in invoke_all
    res[config_class.section] = getattr(config, func_name)(*args, **kwargs)
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/config/repository.py", line 193, in read_config
    provider_class, parsed_config = load_module(
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/synapse/util/module_loader.py", line 47, in load_module
    module = importlib.import_module(module_name)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/s3_storage_provider.py", line 23, in <module>
    import boto3
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/boto3/__init__.py", line 17, in <module>
    from boto3.session import Session
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/boto3/session.py", line 17, in <module>
    import botocore.session
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/session.py", line 26, in <module>
    import botocore.client
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/client.py", line 15, in <module>
    from botocore import waiter, xform_name
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/waiter.py", line 18, in <module>
    from botocore.docs.docstring import WaiterDocstring
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/docs/__init__.py", line 15, in <module>
    from botocore.docs.service import ServiceDocumenter
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/docs/service.py", line 14, in <module>
    from botocore.docs.client import ClientDocumenter, ClientExceptionsDocumenter
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/docs/client.py", line 14, in <module>
    from botocore.docs.example import ResponseExampleDocumenter
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/docs/example.py", line 13, in <module>
    from botocore.docs.shape import ShapeDocumenter
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/docs/shape.py", line 19, in <module>
    from botocore.utils import is_json_value_header
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/utils.py", line 37, in <module>
    import botocore.httpsession
  File "/opt/venvs/matrix-synapse/lib/python3.10/site-packages/botocore/httpsession.py", line 22, in <module>
    from urllib3.util.ssl_ import (
ImportError: cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_' (/opt/venvs/matrix-synapse/lib/python3.10/site-packages/urllib3/util/ssl_.py)

This synapse version uses urllib3 version 2.0.7, and as of this version, DEFAULT_CIPHERS has been deprecated.

User and room avatars missing after s3 migration

I switched my media store to use the s3 media provider using the tools and instructions here and that seems to go fairly smoothly. My media seems to have made it to s3 with no major issues despite a surprisingly large number of images being reported to be deleted.

The exception is user and room avatars. These are missing entirely and I can't find them either in my old media store or s3. There also seems to be no way to force the server to re-download those avatars.

There is an extra bit of data which may be the real problem so I wanted to mention it here before anyone spent too long trying to tie this to the s3 migration: on the same day I attempted to use the ansible playbooks to upgrade my postgres database and it failed due to the server disk filling up entirely. I had to restore to the backup of the postgres database.

I am simply assuming that this is an issue with the s3 storage provider since it's related to media, so apologies if it turns out this is obviously related to the failed postgres upgrade.

I am a novice matrix server admin so it is entirely possible (probably likely) that I just screwed something up here, but I'd appreciate any advice.

`s3_media_upload` should report number of files skipped due to already being on S3

This makes for alarming reading:

Aug 25 00:51:50 hippogriff.matrix.org synapse_media_upload[7417]: Uploading/deleting media for media_store
Aug 25 02:04:06 hippogriff.matrix.org synapse_media_upload[7417]: Uploading  92323  files
Aug 25 02:04:06 hippogriff.matrix.org synapse_media_upload[7417]: Uploaded 0 media out of 92323
Aug 25 02:04:06 hippogriff.matrix.org synapse_media_upload[7417]: Uploaded 0 files
Aug 25 02:04:06 hippogriff.matrix.org synapse_media_upload[7417]: Uploaded 0B
Aug 25 02:04:06 hippogriff.matrix.org synapse_media_upload[7417]: Deleted 92323 media

you deleted 92323 media without uploading any of them??

Presumably, these files already existed on S3. Generally the logging here could do with clarifying (what's the difference between a media and a file, and why are their counts logged separately?), but in particular it would be good to keep a count of "already existing" media (or files?) so that we can check that the numbers add up.

Installation Procedures?

I'm sorry for posting such a basic question but I really don't know what to do since I have done little with Python.
I'm currently using the prebuilt package of Synapse on my Ubuntu machine, and I am just wondering how I can satisfy the requirement that "the s3_storage_provider.py should be on the PYTHONPATH". Thank you!

Not working

I have istalled boto3 and make configure in .aws folder at the root of the directory.But when I share any image still it store locally.

Be able to utilize homeserver.yaml for any and all s3_media_upload configuration settings

Is your feature request related to a problem? Please describe.
Currently the s3_media_upload tool requires:

  1. database.yaml with an abridged snippet of database configuration.
  2. Extra configuration parameters when uploading files
  3. ~/aws/config for implicitly supplying all other parameters.

Describe the solution you'd like
Be able to extract the required information from a homeserver.yaml reference, pointing the tool to find and utilize those parameters to do an completely automated and smooth transfer.

Make async/await

There aren't inlineCallbacks here but it is using callbacks altogether; there may be interest in turning this into readable coroutine code.

Have the option to upload "all" media

This is for migration purposes, to simply place "all" in spots where duration is expected, the update subcommand will simply include all rows of media (even if they've never been accessed (#45)), and make them eligible for upload.

Uploads result in CANCELED

I've been working to determine why large file uploads fail in Element. I'm not going to re-post everything, but here's the Synapse debugging. matrix-org/synapse#15841

I am attempting to upload two video files (each about 30 MB) to a room at the same time. This always fails with a generic error message popup (The file '[filename]' failed to upload.). There is no error in the console and the network of the debug window shows the fetch request as (canceled). Synapse logs don't show any errors and neither does Openresty. Uploading the files one at a time works, but uploading them together always fails.

  • My upload limit in Synapse and Openresty (reverse proxy) is 40M. This has been an issue for a while and I have not discovered the root cause yet.
  • My client is desktop and web Element on Ubuntu.
  • I have a media worker with an S3 storage provider setup (see config below).
media_store_path:                                 "/mnt/matrix-storage/media"

media_storage_providers:
- module:                                         s3_storage_provider.S3StorageProviderBackend
  store_local:                                    True
  store_remote:                                   True
  store_synchronous:                              True
  config:
      bucket:                                     matrix-synapse
      endpoint_url:                               'https://xxx.r2.cloudflarestorage.com/matrix-synapse'
      access_key_id:                              'xxx'
      secret_access_key:                          'xxx'

When I comment out the media_storage_providers block, uploads are able to complete. I tried setting store_synchronous to False. I'm also using a media worker and disabling that didn't change anything.

The Synapse server's network doesn't have the fastest uplink and I'm suspicious that the upload to the S3 bucket is taking too long and the client gives up. Is there a way to have Synapse do the upload to S3 in the background?

Improve documentation

This provider seems to lack some important documentation.
After installing the provider and providing the correct config in the homeserver yaml, is there a need to build additional Infrastructure such as a systemd timer that calls the regular clean up job for new media files? Or is the provider doing this automatically for new media?
There seems to be no good information at this time to be found and this would be a good place to add such documentation.

Edit: This ties a bit into matrix-org/synapse#7140 which could either be linked or some basic directions given on what the provided example configuration here does.

Error: LoggingContext must be given either a name or a parent context

Describe the bug
When using this storage provider with Synapse 1.34.0 it sometimes throws the following error:
builtins.ValueError: LoggingContext must be given either a name or a parent context

To Reproduce
Steps to reproduce the behavior:

  1. Update/Install synapse 1.34.0
  2. Install & configure this storage-provider
  3. Take a look onto your logs...
  4. See error

Additional context
The following is the experpt with the error from synapse's log:

2021-05-19 20:24:54,886 - twisted - 258 - CRITICAL - sentinel - Unhandled Error                                            
Traceback (most recent call last):
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/synapse/app/_base.py", line 123, in run
    run_command()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/base.py", line 1283, in run
    self.mainLoop()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/base.py", line 1295, in mainLoop
    self.doIteration(t)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/epollreactor.py", line 235, in doPoll
    log.callWithLogger(selectable, _drdw, selectable, fd, event)
--- <exception caught here> ---
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/log.py", line 103, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/log.py", line 86, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/context.py", line 122, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/python/context.py", line 85, in callWithContext
    return func(*args,**kw)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/posixbase.py", line 627, in _doReadOrWrite
    self._disconnectSelectable(selectable, why, inRead)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/posixbase.py", line 252, in _disconnectSelectable
    selectable.readConnectionLost(f)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/tcp.py", line 307, in readConnectionLost
    self.connectionLost(reason)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/tcp.py", line 321, in connectionLost
    abstract.FileDescriptor.connectionLost(self, reason)
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/internet/abstract.py", line 205, in connectionLost
    self.producer.stopProducing()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/twisted/web/http.py", line 2610, in stopProducing
    self._requestProducer.stopProducing()
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/s3_storage_provider.py", line 296, in stopProducing
    with LoggingContext():
  File "/opt/venvs/matrix-synapse/lib/python3.6/site-packages/synapse/logging/context.py", line 322, in __init__
    "LoggingContext must be given either a name or a parent context"
builtins.ValueError: LoggingContext must be given either a name or a parent context

URL cache

Not sure where to post this but I guess the URL cache and thumbnails should not go to S3. They live only about an hour and cleaned up after 3 days so it's more rational to store them locally only. Also, cleanup doesn't affect S3 so those images are stored effectively forever. I don't see an option to exclude those file from S3. I'd only like to put local media to S3 and everything else to be stored on HDD so I could clean it up from time to time.

I think it's an issue because after I analyzed my storage the breakdown was like this (including thumbnails):

  • 70 Mb of local media
  • 160 Mb of remote media
  • 680 Mb (!!!) of url cache

And that's after just 3 days.

Package contains invalid dependency specifications

When attempting to add synapse-s3-storage-provider to a Synapse checkout via poetry I get the following:

$ poetry add git+https://github.com/matrix-org/synapse-s3-storage-provider.git#main
Invalid constraint (boto3>=1.9.23<2.0) found in synapse-s3-storage-provider-1.1 dependencies, skipping
Invalid constraint (botocore>=1.12.23<2.0) found in synapse-s3-storage-provider-1.1 dependencies, skipping
Invalid constraint (humanize>=0.5.1<0.6) found in synapse-s3-storage-provider-1.1 dependencies, skipping
Invalid constraint (psycopg2>=2.7.5<3.0) found in synapse-s3-storage-provider-1.1 dependencies, skipping
Invalid constraint (PyYAML>=3.13<4.0) found in synapse-s3-storage-provider-1.1 dependencies, skipping
Invalid constraint (tqdm>=4.26.0<5.0) found in synapse-s3-storage-provider-1.1 dependencies, skipping

Updating dependencies
Resolving dependencies... (1.2s)

Writing lock file

Package operations: 1 install, 0 updates, 0 removals

  • Installing synapse-s3-storage-provider (1.1 5d734de)

The above is with poetry 1.2.2 (poetry-core 1.3.2), however this issue is also present with poetry 1.2.0 (poetry-core 1.1.0) and poetry 1.2.1 (poetry-core 1.2.0) however -vvv needs to be provided to see these messages.

The important changes poetry add makes to my poetry.lock are:

diff --git a/poetry.lock b/poetry.lock
index 291f3c51e..6db58736e 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1174,6 +1174,24 @@ category = "main"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "synapse-s3-storage-provider"
+version = "1.1"
+description = ""
+category = "main"
+optional = false
+python-versions = "*"
+develop = false
+
+[package.dependencies]
+Twisted = "*"
+
+[package.source]
+type = "git"
+url = "https://github.com/matrix-org/synapse-s3-storage-provider.git"
+reference = "main"
+resolved_reference = "5d734dee80c9eabcb7a7a712efcf38dbb5933a55"
+
 [[package]]
 name = "systemd-python"
 version = "234"

KeyError: 'SSECustomerKey'

There is a bug introduced in #84

Specifically this line:
https://github.com/matrix-org/synapse-s3-storage-provider/pull/84/files#diff-65309baef1ac00a6facf27b1c1cb2ea43191a7c7000d4062340e5340ffc9d554R174

This line is producing an error when no SSECustomerKey is provided.

Should this be instead:

if "SSECustomerKey" in extra_args and "SSECustomerAlgorithm" in extra_args:

Error:

root@synapse:/synapse-s3-storage-provider/scripts# s3_media_upload upload /data/media_storage mybucket
  0%|                                                                                                                         | 0/113 [00:00<?, ?files/s]
Traceback (most recent call last):
  File "/usr/local/bin/s3_media_upload", line 579, in <module>
    main()
  File "/usr/local/bin/s3_media_upload", line 565, in main
    run_upload(
  File "/usr/local/bin/s3_media_upload", line 338, in run_upload
    if not check_file_in_s3(s3, bucket, rel_file_path, extra_args):
  File "/usr/local/bin/s3_media_upload", line 174, in check_file_in_s3
    if extra_args["SSECustomerKey"] and extra_args["SSECustomerAlgorithm"]:
KeyError: 'SSECustomerKey'

Cut a new release

As requested here, to include #84 and #87.

(I'm back on the 9th Jan and can do this then, if someone else hasn't gotten to it.)

PyPI/PyPA package?

It would be great to have this application available directly on PyPI servers. Any reason it hasn't been done yet?

Benefits over s3fs?

I was wondering what the benefits of using this would be over something like s3fs. ie. Couldn't you mount an s3 bucket as a file system with s3fs, matrix could access it with the file_system module and you would get the same effect?

Downloads failing most of the time

This extension is not working very well for me.

In order to fix threading problems (as mentioned in #11) with uploads, I applied this patch.

Downloads though are only partly working still.

  1. When downloading thumbnails, I see the following errors in the log for every image:
2018-09-16 16:01:37,778 - synapse.http.site - 185 - WARNING - GET-28- Error processing request <SynapseRequest at 0x7f645c7d4d40 method='GET' uri='/_matrix/media/v1/thumbnail/test.myserver.com/YnTHJxUHFwEcafAEPSFFBrAE?width=800&height=600' clientproto='HTTP/1.1' site=8008>: <class 'twisted.internet.error.Connecti
onDone'> Connection was closed cleanly.                                                                                                                                                                                                                                                                                       
2018-09-16 16:01:37,879 - synapse.http.site - 185 - WARNING - GET-29- Error processing request <SynapseRequest at 0x7f645c7dd128 method='GET' uri='/_matrix/media/v1/thumbnail/test.myserver.com/LiIsaSFVEgPPlDjonEWqsQrM?width=800&height=600' clientproto='HTTP/1.1' site=8008>: <class 'twisted.internet.error.Connecti
onDone'> Connection was closed cleanly.                                                                                                                                                                                                                                                                                       
2018-09-16 16:01:38,048 - synapse.http.server - 101 - ERROR - GET-28- Failed handle request via <function _async_render_GET at 0x7f645de935f0>: <SynapseRequest at 0x7f645c7d4d40 method='GET' uri='/_matrix/media/v1/thumbnail/test.myserver.com/YnTHJxUHFwEcafAEPSFFBrAE?width=800&height=600' clientproto='HTTP/1.1' si
te=8008>: Traceback (most recent call last):                                                                                                                                                                                                                                                                                  
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks                                                                                                                                                                                                                     
    result = g.send(result)                                                                                                                                                                                                                                                                                                   
  File "/usr/local/lib/python2.7/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 121, in _respond_local_thumbnail                                                                                                                                                                                            
    yield respond_with_responder(request, responder, t_type, t_length)                                                                                                                                                                                                                                                        
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1613, in unwindGenerator                                                                                                                                                                                                                      
    return _cancellableInlineCallbacks(gen)                                                                                                                                                                                                                                                                                   
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1529, in _cancellableInlineCallbacks                                                                                                                                                                                                          
    _inlineCallbacks(None, g, status)                                                                                                                                                                                                                                                                                         
--- <exception caught here> ---                                                                                                                                                                                                                                                                                               
  File "/usr/local/lib/python2.7/site-packages/synapse/http/server.py", line 81, in wrapped_request_handler                                                                                                                                                                                                                   
    yield h(self, request)                                                                                                                                                                                                                                                                                                    
  File "/usr/local/lib/python2.7/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 71, in _async_render_GET                                                                                                                                                                                                    
    request, media_id, width, height, method, m_type                                                                                                                                                                                                                                                                          
  File "/usr/local/lib/python2.7/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 121, in _respond_local_thumbnail                                                                                                                                                                                            
    yield respond_with_responder(request, responder, t_type, t_length)                                                                                                                                                                                                                                                        
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks                                                                                                                                                                                                                     
    result = g.send(result)                                                                                                                                                                                                                                                                                                   
  File "/usr/local/lib/python2.7/site-packages/synapse/rest/media/v1/_base.py", line 146, in respond_with_responder                                                                                                                                                                                                           
    yield responder.write_to_consumer(request)                                                                                                                                                                                                                                                                                
  File "/synapse-s3-storage-provider/s3_storage_provider.py", line 206, in write_to_consumer                                                                                                                                                                                                                                  
    consumer.registerProducer(self, False)                                                                                                                                                                                                                                                                                    
  File "/usr/local/lib/python2.7/site-packages/twisted/web/http.py", line 958, in registerProducer                                                                                                                                                                                                                            
    self.channel.registerProducer(producer, streaming)                                                                                                                                                                                                                                                                        
exceptions.AttributeError: 'NoneType' object has no attribute 'registerProducer'                                                                                                                                                                                                                                              
2018-09-16 16:01:38,049 - synapse.http.server - 394 - WARNING - GET-28- Not sending response to request <SynapseRequest at 0x7f645c7d4d40 method='GET' uri='/_matrix/media/v1/thumbnail/test.myserver.com/YnTHJxUHFwEcafAEPSFFBrAE?width=800&height=600' clientproto='HTTP/1.1' site=8008>, already disconnected.        
2018-09-16 16:01:38,115 - twisted - 131 - CRITICAL - - Unhandled Error                                                                                                                                                                                                                                                        
Traceback (most recent call last):                                                                                                                                                                                                                                                                                            
  File "/usr/local/lib/python2.7/site-packages/synapse/app/_base.py", line 104, in run                                                                                                                                                                                                                                        
    reactor.run()                                                                                                                                                                                                                                                                                                             
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1261, in run                                                                                                                                                                                                                                   
    self.mainLoop()                                                                                                                                                                                                                                                                                                           
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1270, in mainLoop                                                                                                                                                                                                                              
    self.runUntilCurrent()                                                                                                                                                                                                                                                                                                    
  File "/usr/local/lib/python2.7/site-packages/synapse/metrics/__init__.py", line 243, in f                                                                                                                                                                                                                                   
    ret = func(*args, **kwargs)                                                                                                                                                                                                                                                                                               
--- <exception caught here> ---                                                                                                                                                                                                                                                                                               
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/base.py", line 869, in runUntilCurrent                                                                                                                                                                                                                        
    f(*a, **kw)                                                                                                                                                                                                                                                                                                               
  File "/synapse-s3-storage-provider/s3_storage_provider.py", line 248, in _finish                                                                                                                                                                                                                                            
    self.consumer.unregisterProducer()                                                                                                                                                                                                                                                                                        
  File "/usr/local/lib/python2.7/site-packages/twisted/web/http.py", line 964, in unregisterProducer                                                                                                                                                                                                                          
    self.channel.unregisterProducer()                                                                                                                                                                                                                                                                                         
exceptions.AttributeError: 'NoneType' object has no attribute 'unregisterProducer'
  1. Downloads of the full image versions often stall about at 1/5 of the image. I can see that requests are stalled and the S3 connection seems to stay open for several hours.

It seems there are still some serious threading-related problems in here. I have no clue about the event-based threading model with twisted which is in use here, so would need some advice on how to debug this. Is anyone else having these problems, too?

I should mention I am using a local minio server instead of Amazon S3 (using this change).

s3_media_upload does not find media that has never been accessed

If the last_access_ts column in the postgres database is NULL, s3_media_upload update does not pick up on it, and ignores it. Is this by design? (as it could probably indeed cause a race condition between the update mechanism and the person who'd upload it)

boto3 usage may not be threadsafe

When enabling this for the first time, it appears to automatically upload everything to s3 (OK!)
However, there seems to be a threading issue and this causes this error:

 2018-08-23 17:58:36,257 - twisted - 131 - CRITICAL - - Unhandled Error
 Traceback (most recent call last):
   File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
     self.run() 
   File "/usr/lib/python2.7/threading.py", line 754, in run 
     self.__target(*self.__args, **self.__kwargs)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/_threads/_threadworker.py", line 46, in work
     task()
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/_threads/_team.py", line 190, in doWork
     task()
 --- <exception caught here> ---
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/python/threadpool.py", line 250, in inContext
     result = inContext.theWork()
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
     inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/python/context.py", line 122, in callWithContext
     return self.currentContext().callWithContext(ctx, func, *args, **kw)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/twisted/python/context.py", line 85, in callWithContext
     return func(*args,**kw)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/s3_storage_provider.py", line 57, in _store_file
     boto3.resource('s3').Bucket(self.bucket).upload_file(
   File "/opt/synapse/env/local/lib/python2.7/site-packages/boto3/__init__.py", line 100, in resource
     return _get_default_session().resource(*args, **kwargs)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/boto3/session.py", line 389, in resource
     aws_session_token=aws_session_token, config=config) 
   File "/opt/synapse/env/local/lib/python2.7/site-packages/boto3/session.py", line 263, in client
     aws_session_token=aws_session_token, config=config) 
   File "/opt/synapse/env/local/lib/python2.7/site-packages/botocore/session.py", line 875, in create_client
     endpoint_resolver = self._get_internal_component('endpoint_resolver') 
   File "/opt/synapse/env/local/lib/python2.7/site-packages/botocore/session.py", line 744, in _get_internal_component
     return self._internal_components.get_component(name)
   File "/opt/synapse/env/local/lib/python2.7/site-packages/botocore/session.py", line 950, in get_component
     del self._deferred[name] 
 exceptions.KeyError: 'endpoint_resolver'

Apparently boto3's default client is not threadsafe, based on a brief googling around the internet.

s3_storage_provider losts connect to bucket

Hello!
We have a repeatable but unregular bug with connection to s3.
Sometimes media stopped to upload to matrix, clients got timeouts by reserse-proxy. Restart of main synapse process helps for some time.
We can't cath this and can't reproduce. Logs spammed by few messages.

Spams everytime, regardless of the problem:
urllib3.connectionpool - 305 - WARNING - GET-61775200 - Connection pool is full, discarding connection: [s3 address]. Connection pool size: 10

Cathed sometimes, spammed when there is a problem:

twisted - 274 - CRITICAL - sentinel - Unhandled Error
Traceback (most recent call last):
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/synapse/app/_base.py", line 148, in <lambda>
    run_command: Callable[[], None] = lambda: reactor.run(),
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/base.py", line 1315, in run
    self.mainLoop()
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/base.py", line 1328, in mainLoop
    reactorBaseSelf.doIteration(t)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/epollreactor.py", line 244, in doPoll
    log.callWithLogger(selectable, _drdw, selectable, fd, event)
--- <exception caught here> ---
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/python/log.py", line 96, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/python/log.py", line 80, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/python/context.py", line 117, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/python/context.py", line 82, in callWithContext
    return func(*args, **kw)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/posixbase.py", line 696, in _doReadOrWrite
    self._disconnectSelectable(selectable, why, inRead)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/posixbase.py", line 297, in _disconnectSelectable
    selectable.readConnectionLost(f)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/tcp.py", line 309, in readConnectionLost
    self.connectionLost(reason)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/tcp.py", line 320, in connectionLost
    abstract.FileDescriptor.connectionLost(self, reason)
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/internet/abstract.py", line 206, in connectionLost
    self.producer.stopProducing()
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/twisted/web/http.py", line 2754, in stopProducing
    self._requestProducer.stopProducing()
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/synapse_s3_storage_provider-1.1-py3.8.egg/s3_storage_provider.py", line 314, in stopProducing
    with LoggingContext():
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/synapse/logging/context.py", line 329, in __init__
    raise ValueError(
builtins.ValueError: LoggingContext must be given either a name or a parent context

Cathed only when problem exists:

 twisted - 274 - CRITICAL - sentinel - Unhandled error in Deferred:
 twisted - 274 - CRITICAL - sentinel -
Traceback (most recent call last):
  File "/opt/venvs/matrix-synapse/lib/python3.8/site-packages/synapse_s3_storage_provider-1.1-py3.8.egg/s3_storage_provider.py", line 243, in _stream_to_producer
    raise Exception("Timed out waiting to resume")
Exception: Timed out waiting to resume

Synapse installation:

  • Ubuntu 20.04
  • Synapse 1.65 (main process and 3 generic workers)
  • S3 cleanup job via cron every night
  • Media config:
media_store_path: /var/lib/matrix-synapse/media
media_storage_providers:
- module: s3_storage_provider.S3StorageProviderBackend
  store_local: True
  store_remote: True
  store_synchronous: True
  config:
    bucket: synapse
    region_name: ***
    endpoint_url: https://***/
    access_key_id: ***
    secret_access_key: ***

purge_media_cache seems not to affect bucket

Hi there, i am using OVH and the latest synapse.
I have just realized that despite synapse reporting the deletion of >70k objects, my bucket did not reduce in size... .

Update: while the curl response is positive and only returns the number of deleted objects, the synapse log gets flooded with synapse.rest.media.v1.media_repository ... Failed to remove file: filepath - i assume this is because i delete local media from time to time, but this time i would like to cleanup the bucket.

It saves the media in both local and the S3 bucket

I had successfully setup the module and the homeserver config file, as it uploads the media to the bucket successfully ; however, after inspecting the local media directory it seems to store the media in there as well, which is very counter productive concerning using an S3 bucket in the first place.

So my question is, should I modify the homeserver.yaml file to remove or modify the media_store_path and uploads_path ?

Since I would like it to only upload and serve media from the S3 bucket.

Or should I be constantly running the clean up script mentioned in the readme on a schedule ?

Or is this a bug?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.