Warbler: Where are my images - ruby-on-rails

I'm using Jruby and Warbler to deploy a Jruby on Rails application to a Tomcat server. I can see all of my images when I deploy the server with Webrick: jruby -S server/script. However, when I create a .war file out of the rails directory using jruby -S warble and deploy to Tomcat, none of my images show up on the tomcat server. I noticed that image location has changed to the root of the directory in the war file.
It seems that /images/picturename.jpg would be appropriate, but my images are not showing up.

"not showing up" -> 404? You said you noticed the image location changed, did you check that the specific images are present? (jar tf myapp.war will show you.)
Did you deploy your war under a context path? I.e., if the home page is at /myapp/, then images will be at /myapp/images/picturename.jpg. JRuby-Rack tries to adjust the Rails asset paths for you to include the context path, but there may be some cases where it doesn't. You may want to resort to just setting config.action_controller.asset_host in config/environments/production.rb to '/myapp' as well.

Did you set up the correct symlinks to your images folder?
f.e. /var/www/website.com/current/20090807200123/public/images --> /var/www/website.com/shared/public
?

Related

Finding the application path after deployment

I successfully deployed my Rails application fireworks_app with Dokku in a Ubuntu 18.04 LTS machine, and now I would like to add a logrotate file for my Rails logs. What is the path of my application and thus of my log files? There is a /home/dokku/fireworks_app folder but this folder contains only the following items:
$ ls
CONTAINER.web.1 DOCKER_OPTIONS_RUN HEAD URLS cache hooks maintenance objects
DOCKER_OPTIONS_BUILD DOKKU_SCALE IP.web.1 VHOST config info nginx.conf refs
DOCKER_OPTIONS_DEPLOY ENV PORT.web.1 branches description letsencrypt nginx.conf.d
I suppose somewhere in the system there is a folder containing my application with the known Rails file structure, but I cannot find it.
Inside your rails application you can do something like Rails.root to get the path to the root directory of your project.
For instance, if the log files are in fireworks_app/lib/log/ you could do Rails.root.join('lib','log','log_file.log') to get the path to that file.

Capistrano and XSendFile configuration

I am trying to configure Rails production server with Apache 2.2, Passenger 4.0.59 and XSendFile 0.12. Application is deployed via Capistrano.
Deployed application produces (maybe large) PDF to #{Rails.root}/tmp and serves this file using send_file.
The problem is that Capistrano uses symlinks to point to currently deployed version of application. XSendFile on the other hand dereferences symlinks and refuses to serve a file if its real location is outside document root even if it is allowed by XSendFilePath. Apache's error.log states:
(20023)The given path was above the root path: xsendfile: unable to find file: /resolved/path/to/file.pdf
Everything works well when I set PassengerAppRoot and XSendFilePath to the real location of current version of application, without symlinks on the path. But it's OK until next deploy, which requires apache reconfiguration. Not very useful.
How should I configure Capistrano deploy and XSendFile parameters to make it work together?
I tried solutions with ln -nFs described in Capistrano & X-Sendfile and in mod_xsendfile with symbolic links but none works.
I finally managed to make it work. A few tips for the ones who will have problems with XSendFile
I set XSendFilePath to user's $HOME, there are no symlinks on the path to $HOME, so it works. I can accept this from functional and security point of view, but it is obviously a workaround.
Be aware that XSendFilePath is sensitive to paths containing multiple slashes /like//this. I am using apache macros and while concatenatingXSendFilePath parameter from a few macro parameters I put some obsolete slashes. This caused XSendFile to refuse to send files.
Good luck!

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

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.
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
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.
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.
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.

Rails 4.2 capistrano 3 deployment

I am totally new to rails deployment. After googling, I still find it hard to understand how to deploy rails apps.
So, my questions are:
After setting up the VPS with all rails dependencies, where do I store my codebase? The root directory of the VPS or some specific locations e.g. www/ or public/?
Should I upload the whole rails app folder or just part of it? I have paperclip in my rails app, and paperclip creates a system/ directory in the public/ folder, so should I upload system/?
In Capistrano 3, there is a repo_url field, I know they support file://, https://, ssh://, or svn+ssh://, but most of the articles about capistrano put github repositories into that. However, I do not have such a github repo. What should I input then?
Thank you for your attention.
Answers to the specific questions raised:
After setting up the VPS with all rails dependencies, where do I store
my codebase? The root directory of the VPS or some specific locations
e.g. www/ or public/?
It will be deployed to the folder pointed by :deploy_to parameter. If not specified, :deploy_to defaults to /var/www/#{fetch(:application) See: https://github.com/capistrano/capistrano/blob/05f63f5f333bb261f2a4c4497174361c48143252/lib/capistrano/defaults.rb#L3
Should I upload the whole rails app folder or just part of it? I have
paperclip in my rails app, and paperclip creates a system/ directory
in the public/ folder, so should I upload system/?
Paperclip system folder is specific to the environment; each environment (development, production,...) will have its own system folder which will store the files uploaded on that specific environment. This folder should not be part of the code being deployed.
The recommended way of handing such folders is the keep them in a shared folder on the server, and create symlinks in the current version of the code so that the same folder is used for storing/retrieving attachments. See Section 3. Update custom links section in http://robmclarty.com/blog/how-to-deploy-a-rails-4-app-with-git-and-capistrano for more details about this.
As mentioned there, the same applies to config/database.yml file, and any other file containing environment specific configurations.
In Capistrano 3, there is a repo_url field, I know they support
file://, https://, ssh://, or svn+ssh://, but most of the articles
about capistrano put github repositories into that. However, I do not
have such a github repo. What should I input then?
Depends on where the code you are deploying is stored. If it is in a local folder, use the file::// format to specify where the files are located.
You can set up your own private git server, then in deploy.rb you can put something like
set :repo_url, 'ssh://user#server_ip/path/to/your_git_repo.git'
When you commit your changes to the git repo, you do not have to upload the app to the server. Capistrano will upload the app for you when you deploy.
where do i put my code base? This is determined by what you put in deploy.rb e.g
set :deploy_to, '/path/to/my_codebase'
Whether to upload the /system directory will depend on whether you want the paperclip images on your version control. If not you can add the directory to gitignore. Here is a tutorial on how to deploy on ubuntu 14.04 passenger and NGINX. if you are not using Passenger and Nginx you can skip to how to configure capistrano and make adjustments depending on your setup.
EDIT
You need to install git on your development machine and set up a git server on your VPS as explained on the link above, add your remote server to your local machine using
git remote add origin <server>
where 'server' is the url to your git repo in the VPS e.g.
ssh://VPS_user#VPS_ip/path/to/your_git_repo.git
Now when you commit and push your changes to the server, capistrano will deploy the latest version on your git server.
Here is a link with a guide on how to get started with git

Deploying a .war made by Warbler to Tomcat

I was trying to simply make a .war file and put it into Tomcat's webapps directory. Simple, right? :)
What is puzzling me is that the directory structure of a JRuby app has the index.html file somewhere far in the application structure and Tomcat just can not find it by default.
Here is what I get when I point my url to the Tomcat install of the application:
http://128.48.204.195:8080/blog/index.html
How should I structure the build/deploy of a JRuby application so that it works on Tomcat when unwrapped out of a .war file?
first try http://128.48.204.195/blog
that will serve the root route (if defined in config/routes.rb) or a error saying nor route.
If you see this: http://krokinet.files.wordpress.com/2010/11/rails-welcome1.png
there is a default index.html file in /public/index.html
that file is generated with the app and you should remove it once your done an initial 'smoke test' (running your newly generated app the first time).
More information on the root route here: http://edgeguides.rubyonrails.org/routing.html#using-root

Resources