How to handle uploads and logs in Rails when deployed as a .war file?

515 views Asked by At

I am trying to deploy rails on jRuby using a .war file with the help of Warbler (Tomcat) and/or Torquebox 4 (Wildfly). The problem I face is that I don't know how to handle uploads with Carrierwave or Paperclip in this case. Ideally uploads should be stored outside the war, as it may be replaced with a newer version of the app anytime. I tried to create a symlink (uploads) in the public directory before I packaged the app as a war file to /home/username/uploads (permissions are set to 777) directory but that doesn't work (I get a 500 error).

Also how can I access the production.log after I deployed the war file? Or where should I place the logs?

UPDATE I figured out how to config Carrierwave to store uploads outside the war file:

if Rails.env.development?
    CarrierWave.configure do |config|
      config.root = "/Users/Username/username_uploads/uploads"
    end
elsif Rails.env.production?
    CarrierWave.configure do |config|
      config.root = "/home/username/username_uploads/uploads"
    end
end

Now Carrierwave uploads the files without a problem, but I get a 404 error when I try to view them. I tried to include a symlink inside the war file to the uploads folder but no success. I tried to create it before running warble war, and also after the app was deployed to Tomcat ( inside the app_name folder ).

Any idea how to solve this?

UPDATE 2 I found a working solution here: Configure Symlinks for single directory in Tomcat

In short: cd into the exploded war directory ( you can find this under tomcat/webapps ) that tomcat created ( if the name of the uploaded war file is yourapp.war then the directory name will be yourapp in Tomcat 8 ). Create an uploads folder with sudo mkdir uploads Create a mount point: sudo mount --bind /path/to/actual/upload/directory/uploads uploads

I haven't yet tested this with Wildfly, but I will later today or tomorrow. If I remember correctly it won't automatically explode war files by default.

I would still like to know additional, simpler, different solutions for the problem though, and also opinions about the solution I found.

4

There are 4 answers

4
Jesse Whitham On

If you could provide your logs it would be much easier to diagnose the problem (I take it this problem is only in production because you are asking about how to access that log?). Goto the rails app directory and look in log/production.log these log levels are often lower so you may have to configure them to be more informative config/enviroments/prouction.rb should have a config.log.level this is probably set to info set it to debug for more verbose logging.

2
bbozo On

Just food for thought on a different approach...

Using a "cloud based" storage service would make the upload and serving of the assets problem go away, it would also make it simpler to scale the app should you ever need a second node,

it would also reduce the need to scale the app because you would effectively delegate the large data operations which ruby traditionally handles badly to a different service

Amazon S3 is an obvious choice, but check out Riak too

4
amiuhle On

By default, Tomcat does not follow symbolic links (due security reasons). To enable this, you have to add the following inside the Host tag in your server.xml:

<!-- Tomcat 7: -->
<Context allowLinking="true" />

<!-- Tomcat 8: -->
<Context>
  <Resources allowLinking="true" />
</Context>

See the docs and the latest migration guide.

4
smallbutton On

I think the problem you are experiencing with this solution:

if Rails.env.development?
    CarrierWave.configure do |config|
      config.root = "/Users/Username/username_uploads/uploads"
    end
elsif Rails.env.production?
    CarrierWave.configure do |config|
      config.root = "/home/username/username_uploads/uploads"
    end
end

is that you are storing the images outside of the rails public folder, and therefore rails cannot serve them anymore. Carrierwave is uploading everything properly as you would expect it to do, and it creates links, relative to the storage dir. If you would use the default #{Rails.root}/public storage, rails would serve your images, as any content from public is served (also static html or other assets). As Rails doesn't serve these anymore it's up to you to serve them.

Maybe you can just directly serve them through Tomcat (as I have no expertise in Tomcat configuration you have to figure this out yourself). This would maybe even be faster, as the request surpass the rails stack.