CarrierWave / AWS S3 -- can't upload images in production with heroku -- CH.13 Rails Tutorial


#1

Hi all,

I have been frustrating myself with this one for some time… Currently working through Chapter 13 (user microposts) of the Rails Tutorial, and while my app works fine in development, I cannot seem to get the image uploads to AWS S3 running in production (detailed here in the tutorial).

I am fairly confident I have my S3 bucket, policy, user permissions, and access set correctly for two reasons:

  1. I am able to use the web GUI on that user account to upload and manage files in the bucket, so I know it has access.
  2. I installed the aws command line tool, configured it with the user access key and secret key, and I’m able to retrieve information from the bucket, such as files inside (these were inserted via the S3 web gui).

Even though I can remotely access the bucket with the AWS CLI, I can’t figure out why the deployment is going wrong on heroku. When I open my production heroku app, everything works fine except the image upload. When I try to upload an image on a new micropost, I get a generic ‘We’re sorry, but something went wrong.’ error in the browser. Checking the heroku logs, it looks like I get a :status 403 error “Forbidden” when trying to reach the bucket (detailed logs below). Others seemed to have the same problem (see StackOverflow posts: 1 | 2 | I have several more…). These solutions usually involve modifying the bucket policy or user permissions, which I have done. Again I’m thinking I was successful given my ability to access via the CLI, but it hasn’t solved the heroku issues.

I know my access key and secret key are set properly in heroku’s config.

Has anyone else had this issue?

Thanks in advance for any help or suggestions.


2019-01-07T08:11:37.684074+00:00 app[web.1]: excon.error.response
2019-01-07T08:11:37.684077+00:00 app[web.1]: :body          => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>FDE*******1EC</RequestId><HostId>X13KUnVyGn*********qaWzKvdUrv0=</HostId></Error>"
2019-01-07T08:11:37.684079+00:00 app[web.1]: :cookies       => [
2019-01-07T08:11:37.684081+00:00 app[web.1]: ]
2019-01-07T08:11:37.684082+00:00 app[web.1]: :headers       => {
2019-01-07T08:11:37.684085+00:00 app[web.1]: "Connection"       => "close"
2019-01-07T08:11:37.684086+00:00 app[web.1]: "Content-Type"     => "application/xml"
2019-01-07T08:11:37.684088+00:00 app[web.1]: "Date"             => "Mon, 07 Jan 2019 08:11:36 GMT"
2019-01-07T08:11:37.684090+00:00 app[web.1]: "Server"           => "AmazonS3"
2019-01-07T08:11:37.684092+00:00 app[web.1]: "x-amz-id-2"       => "X13KUnVyG****4EqaWzKvdUrv0="
2019-01-07T08:11:37.684094+00:00 app[web.1]: "x-amz-request-id" => "FDE*******55C1EC"
2019-01-07T08:11:37.684096+00:00 app[web.1]: }
2019-01-07T08:11:37.684098+00:00 app[web.1]: :host          => "bucket-name.s3-us-west-1.amazonaws.com"
2019-01-07T08:11:37.684099+00:00 app[web.1]: :local_address => "*********"
2019-01-07T08:11:37.684101+00:00 app[web.1]: :local_port    => ******
2019-01-07T08:11:37.684103+00:00 app[web.1]: :path          => "/uploads/micropost/picture/306/ocean2.jpeg"
2019-01-07T08:11:37.684104+00:00 app[web.1]: :port          => 443
2019-01-07T08:11:37.684106+00:00 app[web.1]: :reason_phrase => "Forbidden"
2019-01-07T08:11:37.684108+00:00 app[web.1]: :remote_ip     => "*******"
2019-01-07T08:11:37.684110+00:00 app[web.1]: :status        => 403
2019-01-07T08:11:37.684111+00:00 app[web.1]: :status_line   => "HTTP/1.1 403 Forbidden\r\n"
2019-01-07T08:11:37.684113+00:00 app[web.1]: ):
2019-01-07T08:11:37.684217+00:00 app[web.1]: F, [2019-01-07T08:11:37.684147 #22] FATAL -- : [363c5115-f872-43b4-857a-10d1d7d11737]
2019-01-07T08:11:37.684392+00:00 app[web.1]: F, [2019-01-07T08:11:37.684328 #22] FATAL -- : [363c5115-f872-43b4-857a-10d1d7d11737] app/controllers/microposts_controller.rb:7:in `create'

Bucket policy:

    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::***********:user/user-name"
            },
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:DeleteObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::bucket-name/*",
                "arn:aws:s3:::bucket-name"
            ]
        }
    ]
}

#2

I remember having quite a struggle to get images to persist on heroku rails deploys… not sure if it’s quite the same issue (as it was a while ago), but I wrote up how I did it in my readme to my blogger app (waaay down the page). Maybe those notes could be helpful?