Status 0 on uploading image with Rails and Backblaze B2 (S3) - ruby-on-rails

When I try to upload a photo on my Rails app I get this error "Error storing "image.jpg" Status: 0" I am using ActiveStorage with Backblaze B2 which is based on Amazon S3. I have setup the bucket already.
I have tried changing regions but nothing happend.
This is in my storage.yml:
backblaze:
service: S3
access_key_id: keyID from my account
secret_access_key: master key from my account
region: us-east-1
bucket: my bucketID
endpoint: b2 upload url I got from b2_get_upload_url
force_path_style: true
I have set config.active_storage.service = :backblaze in both development and production environments.
This is code for file input in my form:
<%= f.file_field :image, direct_upload: true, multiple: false %>
I want to see image I posted in my file browser in my bucket but it is not uploading.

Status 0 (from my experience) relates to a failure to do with CORS. We use Azure as our storage platform (with Rails / ActiveStorage) and the root cause was the blob container not having a CORS policy configured. I'm not sure how this works with Backblaze, but if you configure a CORS policy and add the domain that you have your rails app on (with PUT/POST enabled), that should help

Related

Multiple Azure Storage Integration with Rails 6 application

I have used Azure Active Storage for all the user files that are uploaded on my application developed using Rails v6. Works perfectly fine.
Now I wanted to make a copy of the files that are getting uploaded on my application to Another Azure storage account. How can I go about this approach. Any help would be much appreciated.
There are a couple of options available. One is using mirrors in storage.yml file. There you can configure multiple storage accounts even with different cloud service providers like Amazon and Azure. This is done at configuration level
s3_mirror:
service: S3
access_key_id: ""
secret_access_key: ""
region: ""
bucket: ""
development:
service: AzureStorage
root: <%= Rails.root.join("storage") %>
container: development
storage_account_name: my_account_name
storage_access_key: my_access_key
mirror:
service: Mirror
primary: development
mirrors:
- s3_mirror
Another way which was more usable for me was this piece of code suggested by a famous AI app
# First, install the gem
gem 'azure-storage-ruby'
# Then, in your code, you can use the Azure::Storage::Client class to connect
to a storage account
# Replace ACCOUNT_NAME and ACCOUNT_KEY with your storage account name and key
client1 = Azure::Storage::Client.create(storage_account_name: 'ACCOUNT_NAME',
storage_access_key: 'ACCOUNT_KEY')
client2 = Azure::Storage::Client.create(storage_account_name: 'ACCOUNT_NAME',
storage_access_key: 'ACCOUNT_KEY')
# You can then use the client objects to perform operations on the storage
accounts
blob_client1 = client1.blob_client
blob_client2 = client2.blob_client
# For example, you can list the blobs in a container like this:
blob_client1.list_blobs('my-container').each do |blob|
puts blob.name
end
blob_client2.list_blobs('my-container').each do |blob|
puts blob.name
end

Rails 6 Active Storage: Digital Ocean Spaces does not honor public-read ACL

I'm using Rails 6 Active Storage to upload images to a Digital Ocean Spaces bucket.
My Storage.yml:
digitalocean:
service: S3
access_key_id: <%= Credential.digitalocean_access_key_id %>
secret_access_key: <%= Credential.digitalocean_secret_access_key %>
endpoint: https://sfo2.digitaloceanspaces.com
region: sfo2
bucket: mybucket
upload:
acl: "public-read"
As you can see I do specify a "public-read" upload ACL.
Images do upload fine using Active Storage direct upload, yet in the bucket, the file permission is Private, not Public.
Any help is appreciated, thank you.
I guess it's an issue with Digital Ocean S3 implementation! Try this command to force ACL to public:
s3cmd --access_key=YOUR_ACCESS_KEY--secret_key=YOUR_SECRET_KEY --host=YOUR_BUCKET_REGION.digitaloceanspaces.com --host-bucket=YOUR_BUCKET_NAME.YOUR_BUCKET_REGION.digitaloceanspaces.com --region=YOUR_BUCKET_REGION setacl s3://YOUR_BUCKET_NAME --acl-public

Production Server Uploading to Staging S3

I have an app running on a ubuntu server. I have a production mode and a staging mode.
Problem is that actions being done on the production site relative to uploading and retrieving images from an S3 bucket are being done to the same bucket as my staging. When I have my configurations set up differently.
production.rb
config.s3_bucket = 'bucket-production'
config.s3_path = 'https://bucket-production.s3.us-east-2.amazonaws.com/'
staging.rb && development.rb
config.s3_bucket = 'bucket-staging'
config.s3_path = 'https://bucket-staging.s3.us-east-2.amazonaws.com/'
storage.yml
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: us-east-2
bucket: bucket-staging
endpoint: http://bucket-staging.us-east-2.amazonaws.com
I'm thinking it could be something with storage.yml but I deleted this entire file and restarted the localhost server and it didn't change anything. Is storage.yml production only?
Also, my logs are logging to staging from production.
I would like to ask is prod server/staging server(Ubuntu) running in AWS.if yes, you must have IAM ROLE attached to the server which must be fine-grained to which env application should access which bucket of S3. Also storing access_key_id and secret access key id should not be used as best practice. IAM role can take care of that. Also, I would like to add if the server is in the private subnet you need to explore either NAT gateway or use VPC S3 Endpoint to access the bucket.
Also try printing logs of S3 connection in prod mode how it is acquiring cred to access bucket. You might be granting access using some ENV variables or IAM role. Best way to see is use
printenv
before and after of S3 connection to see the variables and which bucket access is provided.
Thanks
Ashish

Rails Active Storage push to DigitalOcean Spaces

Hi I'm trying to get active storage to push to a DigitalOcean space. However, I'm finding that the push url is being changed to amazonaws.com even though I've defined the endpoint to digital ocean.
here is what I have in storage.yml
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: sfo2
bucket: redacted_bucket_name
endpoint: https://sfo2.digitaloceanspaces.com
When I try to upload a file, I get the following error:
Aws::Errors::NoSuchEndpointError (Encountered a `SocketError` while attempting to connect to:
https://redacted_bucket_name.s3.sfo2.amazonaws.com/a8278561714955c23ee99
in my gemfile I have: gem 'aws-sdk-s3
I've followed the directions found here, and I'm still getting the error. Is it possible that there's a new way to do this?
I just set something like this up myself a few days ago. When you check the URL https://redacted_bucket_name.s3.sfo2.amazonaws.com/a8278561714955c23ee99 it's different from the actual endpoint you set up https://redacted_bucket_name.sfo2.amazonaws.com/a8278561714955c23ee99
the error is being caused by an invalid endpoint your hitting, the s3 right before the .sfo2 is offsetting the endpoint. Did you happen to add s3 to your spaces config? check your spaces dashboard and try to get the endpoint setup properly.
I had this same challenge when working on a Rails 6 application in Ubuntu 20.04.
Here's how I fixed mine:
Firstly, create a Spaces access keys in your digital ocean console. This link should help - DigitalOcean Spaces API
Secondly, add a new configuration for DigitalOcean Spaces in your config/storage.yml file. Just after the local storage definition:
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
digital_ocean:
service: S3
access_key_id: <%= SPACES_ACCESS_KEY_ID %>
secret_access_key: <%= SPACES_SECRET_ACCESS_KEY %>
region: <%= SPACES_REGION %>
bucket: <%= SPACES_BUCKET_NAME %>
endpoint: <%= SPACES_ENDPOINT %>
Note: You can give your entry any name, say digital_ocean_spaces or something else. For me I named it digital_ocean.
Thirdly, modify the config.active_storage.service configuration in the config/environments/production.rb file from:
config.active_storage.service = :local
to
config.active_storage.service = :digital_ocean
Finally, specify these environment variables file in your config/application.yml file (if you're using the Figaro gem) or your .env file. (if you're using the dotenv gem). In my case I was using the dotenv gem, so my .env file looked looked like this:
SPACES_ACCESS_KEY_ID=E4TFWVPDBLRTLUNZEIFMR
SPACES_SECRET_ACCESS_KEY=BBefjTJTFHYVNThun7GUPCeT2rNDJ4UxGLiSTM70Ac3NR
SPACES_REGION=nyc3
SPACES_BUCKET_NAME=my-spaces
SPACES_ENDPOINT=https://nyc3.digitaloceanspaces.com
That's all.
I hope this helps

Why is `region` field needed for active storage on S3?

Today I tried rails 5.2.0.
It generated following file template when rails newed.
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
# amazon:
# service: S3
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
# region: us-east-1
# bucket: your_own_bucket
Question:
As far as I know, there is no region in S3 service. If so, what does this parameter field region mean in the realm of Active Storage?
"there is no region in S3 service", that's incorrect.
Extracted from Working with Amazon S3 Buckets, official docs.
Amazon S3 creates buckets in a region you specify. You can choose any
AWS Region that is geographically close to you to optimize latency,
minimize costs, or address regulatory requirements. For example, if
you reside in Europe, you might find it advantageous to create buckets
in the EU (Ireland) or EU (Frankfurt) regions. For a list of Amazon S3
regions, see Regions and Endpoints in the AWS General Reference.

Resources