3

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.

Community
  • 1
  • 1
Allanon
  • 547
  • 4
  • 24
  • Hi, did you manage to find a solution to this problem. I am also trying to figure out where to store the application log files. – kobra Jun 17 '15 at 01:31
  • Hi, sadly I haven't figured those out yet. I asked the carrierwave guys on github, but they told me to ask it here. But as You can see no answer. – Allanon Jun 17 '15 at 08:33
  • I also asked the Paperclip guys at Github, and I got this suggestion: "Have you tried exploding the war file? I'm doing that with Tomcat and uploading files seems to work. Otherwise, I'd probably have a look at specifying a path somewhere else: https://github.com/thoughtbot/paperclip#understanding-storage" - I haven't had the time to try this though. If it works for You please share it here, because it might work for Carrierwave too. – Allanon Jun 17 '15 at 08:36
  • Have you tried my solution? I have a working app in production where I solved it like this. – amiuhle Aug 13 '15 at 13:10

4 Answers4

1

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

bbozo
  • 7,075
  • 3
  • 30
  • 56
  • Hi bbozo! Thanks for the reply. Yes I thought about that, but I would still like to know how can I make this work without a cloud based storage service. – Allanon Aug 11 '15 at 10:22
  • Me too :) I'll be watching :) As a matter of interest, how do you do development? I tried doing a project with Rails&Torquebox and in the end gave it up to Sinatra&Puma because it took 4 minutes to restart, it was ridiculous to work with in development – bbozo Aug 11 '15 at 10:31
1

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.

amiuhle
  • 2,673
  • 1
  • 19
  • 28
  • I tried this recently, but I still get a 404 error from rails when I try to access an uploaded asset. Maybe its a misunderstanding on my part: I couldn't find a Context in server.xml ( Tomcat 8 ), but there was a context.xml file, where I made the above changes without success. Should I add a Context block inside server.xml and try it that way? – Allanon Aug 13 '15 at 14:24
  • Sorry, guess my answer wasn't that clear. I updated it. – amiuhle Aug 13 '15 at 14:30
  • Another problem is that, as far I know ( from here: http://stackoverflow.com/questions/6691413/jruby-warbler-does-not-preserve-symbolic-links ), the warbler gem doesn't support symlinks ( but please correct me if I am wrong ) so I need to create them after Tomcat exploded the war file on the server. Is there a way which allows me to put app specific context.xml or server.xml inside my rails app which accomplishes the same ( of course warbler would place these inside META-INF or WEB-INF )? – Allanon Aug 13 '15 at 14:36
  • I think you're right, Warbler doesn't support symlinks. You could have the configuraiton `server.xml` in your app in `config/tomcat` and then symlink it. I don't know if it's possible to split up `server.xml` into different files though. – amiuhle Aug 13 '15 at 15:03
1

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.

smallbutton
  • 3,377
  • 15
  • 27
  • Thanks for the input. Yes, You described the problem well here. I updated my question recently with a working solution, however I still don't know if it is the "best practice" or not. – Allanon Aug 12 '15 at 21:10
  • I guess the method above is somewhat hacky, since you loose all what the war file is about. I've looked into it and I think aliases are the Tomcat way to handle such things (https://blog.openshift.com/multipart-forms-and-file-uploads-with-tomcat-7/ look under Step 5). If you can live with the exploded war and the mount-points, or some extra scripts that create symlinks after the war explodes this should be fine as well, although serving those files directly in tomcat is definitly faster than serving them through rails. – smallbutton Aug 12 '15 at 21:48
  • I've just tried to set the aliases but no success. I created a context.xml in rails config directory and configged warbler ( config.script_files << 'config/context.xml' ) to include it in the war file, inside META-INF. I also allowed overrides in Tomcat's default context xml. The result is still 404 error when I try to access user uploaded files. I would like this solution better than the one I posted. Any ideas why it doesn't work? – Allanon Aug 13 '15 at 08:21
  • I think you are supposed to make this configuration in tomcat rather than in a Rails file: http://th1rty7.blogspot.de/2009/05/tomcat-is-often-considered-to-be-too.html . Maybe there is also an option to put that information into the War, but i guess you could try the tomcat config first and see if it works. In there you can specify a path, where the files are served and a path to the directory. You can see how the path config has to be done from what links rails generates you. – smallbutton Aug 13 '15 at 11:21
-1

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.

Jesse Whitham
  • 824
  • 9
  • 32
  • I think You did not understand my question/problem. The questions is how can I store ( this is solved if You read my update ) and serve user uploaded files from outside of the .war file that the warbler, or torquebox 4 gems generate. – Allanon Aug 11 '15 at 10:25
  • I read the question (and the update), and my understanding was that you were now able to store it but were still having problems retrieving it with a 404 error, seeing what your logs said about that 404 would help to figure out what the issue is (your question also asked how to access the logs so I included details of this). – Jesse Whitham Aug 11 '15 at 23:32
  • Yes, the problem is to retrieve the user uploaded files. When I try to access an uploaded file, then I get a 404 from rails, however I cannot access the production log since the log directory ( in WEB-INF ) is empty. The problem is most likely related to what smallbutton said above. – Allanon Aug 12 '15 at 21:18
  • I updated my question with a working solution, but I still don't know if it is the best way to solve this or not ( and I also need to test this on Wildfly too ). – Allanon Aug 12 '15 at 21:18