Skip to content

Instantly share code, notes, and snippets.

@ozero
Last active November 22, 2021 02:56
Show Gist options
  • Save ozero/beb89fc6a462320dc60de3ff64006c9d to your computer and use it in GitHub Desktop.
Save ozero/beb89fc6a462320dc60de3ff64006c9d to your computer and use it in GitHub Desktop.
Humhub: Mounting S3 Using goofys & catfs, allows to more capacity than your VPS.

Humhub: Mounting S3 Using goofys & catfs.

Install from these repository.

Here is example of usage for Humhub,

  • Catfs caches any files you accessed through goofys, up to (Your_storage_size - 1) GB. (-free:1G option below.)
  • Assumes your php runs as uid=33 & gid=33 (-uid 33 --gid 33 option below).

Try at your shell

$ sudo goofys -o allow_other --file-mode 0666 --dir-mode 0777 --uid 33 --gid 33 --cache=-o:allow_other:--free:1G:/PATH/TO/MY/CATFS_CACHE MY_S3_BUCKET:MY_S3_DIRECTORY_FOR_UPLOAD /PATH/TO/MY/S3_BUCKET_MOUNTPOINT

Auto mount in /etc/fstab

goofys#MY_S3_BUCKET:MY_S3_DIRECTORY_FOR_UPLOAD /PATH/TO/MY/S3_BUCKET_MOUNTPOINT fuse allow_other,--file-mode=0666,--dir-mode=0777,--uid=33,--gid=33,--cache=-o:allow_other:--free:1G:/PATH/TO/MY/CATFS_CACHE 0 0

Then check /etc/fstab with sudo mount -a and mount | grep fuse.

Move upload into S3 & swap upload directory

  • Copy all /PATH/TO/MY/HUMHUB/uploads files into /PATH/TO/MY/S3_BUCKET_MOUNTPOINT
  • Rename /PATH/TO/MY/HUMHUB/uploads to /PATH/TO/MY/HUMHUB/uploads_bak
  • Make symbolic link sudo ln -s /PATH/TO/MY/S3_BUCKET_MOUNTPOINT /PATH/TO/MY/HUMHUB/uploads

Issues needs to solve

  • All media traffic still delivered from your Server, not CDN (CloudFront)
    • Need to output proper CF distribution URL.
    • Override /protected/humhub/modules/file/models/File.php 's getUrl().
  • CloudFront has "Restrict viewer access" feature, can identify access from Guest or Humhub user, with Signed cookie.
    • Limit lifetime of the signed cookie with DateLessThan policy
    • You can also limit with IpAddress policy, but site will broken with iOS 15's "Private relay" feature.
  • But CloudFront itself can't check whether the access (from the Humhub user) has proper privilege for private post or community.
    • Concept to solve: We may be able to use CloudFront functions or Lambda@Edge to validate access.
    • Add JSON Web Token on all /file/file/download URLs and CF func / Lambda@Edge validate them.
    • Users are given short-time JWT string for every valid (privileged) user access. JWT is issued from your code on Humhub, So only their access are allowed on CloudFront distribution.
    • Minor cons: If even as the post was move into private, JWT & the URL still Valid until JWT expires.

More cool concepts are welcome.

@ozero
Copy link
Author

ozero commented Nov 16, 2021

OK, I've made them somehow useful, I'll write what I did someday. Draft are below:


Part A: Get unlimited storage

Strategy: disk usage matters

  • Create S3 bucket
  • Install s3fs
  • mount manually & check sync
  • mount by fstab & check sync
  • copy content via s3fs mountpoint
  • rename /humhub/uploads & create Symlink to mountpoint

current pros & cons

Part B: Get unlimited bandwidth

Strategy: security matters

  • https don't secures domain name, but entire query string
  • Humhub secures the URL
  • CDN & Signed-URL make the URL ephemeral, secures content
  • Case: A space gone private, how its contents secured?
  • Don't expect Humhub project to support S3, use it as-is.

B-1. Create CloudFront distribution

  • Create RSA key
  • Limit viewers
  • Set up Alternate domain name (CNAME) with your DNS zone setting.

B-2. Redirect the request to upload content

  • Strategy: Nginx rewrite → Redirect & signing → CloudFront
  • Write your original redirector to CloudFront
  • Redirect requests for your redirector using Nginx rewrite rules
  • you'll found need to add a header for direct download

B-3. Pass original filename using Cloud function

  • append filenames as query string by JS in theme.
  • Redirector pass the query string to CloudFront
  • Cloud function reads the query string and add header
  • Set the function on the behavior, view-response.

@ozero
Copy link
Author

ozero commented Nov 22, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment