SSL/TLS for buckets

Public buckets with a custom domain and SSL #

Using our object storage for internals, is one thing — but using it for assets is another. Usually, you would want to access your files using a custom domain — e.g. https://test-storage.staging.planetary-quantum.com with TLS enabled. The following guide walks you through the setup of a bucket on our object storage with files that are accessible (readable) to the public.

In order to use this, your objects have to be created using acl: public-read or (our recommendation) you use a add a bucket policy. Adding the public-read ACL or a policy implies that the objects are accessible to anyone. Be careful, when uploading backups or log files to the object storage, as anyone can download them when public-read is enabled.

For brevity, we will use the Minio Client (mc) to create a bucket and copy a file. Read on for installation and configuration.

Create a bucket #

$ mc mb pn-storage/test-storage.staging.planetary-quantum.com
Bucket created successfully `pn-storage/test-storage.staging.planetary-quantum.com`.

Setup DNS record #

Point the host to your cluster (via your DNS provider):

# zone: staging.planetary-quantum.com
test-storage   CNAME   IN  $endpoint.customer.planetary-quantum.net.
DNS changes can always take a bit of time.

Upload a file #

Explained, step by step:

  1. Create a file hello-world.txt (with contents, “Hallo Welt”)
  2. Copy the file to the object storage
  3. Use curl to access the file
$ echo "Hallo Welt" > ./hello-world.txt
$ mc cp \
  hello-world.txt \
  pn-storage/test-storage.staging.planetary-quantum.com/hello-world.txt
hello-world.txt:         11 B / 11 B  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  92 B/s 0s
$ curl \
  https://s3.storage.planetary-networks.de/test-storage.staging.planetary-quantum.com/hello-world.txt
Hallo Welt
For larger files, please add --disable-multipart, as this is currently not supported.
We recommend using bucket policies to manage the access to objects. If you don’t want to do this, you can run mc cp with the parameter --attr x-amz-acl=public-read to set the ACL on an individual file.

Setup a proxy #

Since we made the file accessible, it’s time to serve it on our own domain. In order to achieve that you need a small nginx proxy, which runs on your cluster. Traefik will take care of the SSL/TLS and nginx can improve the performance by caching files.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {
  listen 80;
  server_name localhost;

  # To allow special characters in headers
  ignore_invalid_headers off;

  # Allow any size file to be uploaded.
  # Set to a value such as 1000m; to restrict file size to a specific value
  client_max_body_size 0;

  # To disable buffering
  proxy_buffering off;

  location / {
    # Proxy headers
    proxy_redirect off;

    proxy_set_header Authorization     '';
    proxy_set_header Host              $http_host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_connect_timeout              300;

    # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    chunked_transfer_encoding off;

    proxy_pass https://s3.storage.planetary-networks.de;
  }
}

Caching #

Optionally, add caching to the mix:

  • cache for 10 minutes
  • up to 500 MB
  • cache eviction is 60 minutes
http {
  proxy_cache_path   /tmp/ levels=1:2 keys_zone=object_storage_cache:10m max_size=500m
                    inactive=60m use_temp_path=off;

  // ...
  server {
    // ...
    location / {
      proxy_cache            object_storage_cache;
      proxy_hide_header      x-amz-id-2;
      proxy_hide_header      x-amz-request-id;
      proxy_hide_header      x-amz-meta-server-side-encryption;
      proxy_hide_header      x-amz-server-side-encryption;
      proxy_hide_header      Set-Cookie;
      proxy_ignore_headers   Set-Cookie;
      proxy_cache_revalidate on;
      proxy_intercept_errors on;
      proxy_cache_use_stale  error timeout updating http_500 http_502 http_503 http_504;
      proxy_cache_lock       on;
      proxy_cache_valid      200 304 60m;
      add_header             Cache-Control max-age=31536000;
      add_header             X-Cache-Status $upstream_cache_status;
      // ...
}

Done #

Deploy the proxy to your cluster, and verify it is working as expected:

$ curl https://test-storage.staging.planetary-quantum.com/hello-world.txt
Hallo Welt
To re-emphasize: This example works well and requires next to no changes/maintenance, because the bucket has a DNS-style name: test-storage.staging.planetary-quantum.com

Appendix #

A complete working example (which requires minimal changes) is available on Github: https://github.com/hostwithquantum/object-storage-proxy-stack

Advantages:

  • take advantage of our managed Traefik (with Let’s Encrypt)
  • deployment workflow using quantum-cli