How to set right permission to Linux file? - ruby-on-rails

I wanted to know how can I set right permission for my file /log/production.log? Everyone is saying just use chmod or chown but no one explains what I should wright after these commands. I am beginner and would appreciate if you could explain.
In my particular example I have rails app on production server where I need to set permission to production.log file in /var/www/my_app/log/ directory.
Here is what documentation is asking from me:
By default, Phusion Passenger runs Rails applications as the owner of
config.ru. So the log file can only be written to if that user has
write permission to the log file. Please chmod or chown your log file
accordingly.
Hope you can help. Thanks.

Try chmod 0660 production.log and take a look at this explanation/diagram of chmod.

chmod allows change the permissions of a file or a directory. Exists three basic permissions (read,write,execute) for three differents groups (owner,group,other).
chown allows change who is the owner of a file or a directory.
I recommend you use chmod 640. Looking the syntax of chmod here you're defining the production.log's owner (usually root) can read and write this file. If you want, you can give read-access for all users of the same group of the owner. But you shouldn't offer permissions for other people, even less in a production environment.

I would create a deploy user for your application, say myapp (doesn't particularly matter what the name is). The use this user to deploy/manage your application. Assuming username myapp
chown -R myapp:myapp /var/www/my_app
and then restart nginx/passenger. This will cause passenger to run as the myapp user, and allow it to write logs under the logs directory. (Also make sure that you don't have /var/www as the docroot, accessible outside of passenger as it can cause information leakage)
another option, if the server isn't shared, is that you can run as the www user. so
chown -R www:www /var/www/my_app
which should allow the process to write to your logs.

Related

Handling shared/tmp in a Ruby on Rails project when the deploy user is different than the run user

I have two users on my server, an Ubuntu 12.04 virtual server that I manage myself:
projectx is used to deploy the application and is the user/group for most files in /var/www/projectx
projectx_rails and it's used to run the Rails application. That way, the running rails application doesn't have access to modify the source code.
Some directories, like public/uploads, are configured to belong to projectx_rails:projectx_rails, so that the rails app can write the uploaded files.
My problem comes to the directory tmp. This directory is located in /var/www/projectx/shared and linked to each release in the usual capistrano way of handling releases. The problem is that some files created during deployment are then not writable by the running rails app and files created by the rails app are not writable by the deployment process.
Is there a way to handle this? Having all the files there belong to projectx_rails:projectx_rails and be group writable would be good enough, but I'm not sure how to trigger this.
I'm using: Capistrano 3, Rails 3.2, Ruby 2.1.2, Unicorn 4.8.3, nginx.
Well, this is my theory. It is obviously hard to test on my end, so consider it conjecture.
First: make a group that both users belong to. Like projectx_shared.
Second: make this group the group owner of the tmp directory:
chown projectx_rails:projectx_shared tmp
Third: set the setgid bit on this directory:
chmod g+s tmp
Now, the group owner of files added to tmp should be set to projectx_shared automatically. I think this will apply to capistrano tasks as well.
I'm assuming when you deploy, files already get rw-rw-r-- permissions automatically. If not, you'll need to set your UMASK to 002 in your, e.g. .bashrc as well.
Let me know if it works...
May be use ACL for shared files? The only thing that, enable ACL support in fstab.
setfacl -m d:u:projectx:rwx,u:projectx:rwx,\
d:u:projectx_rails:rwx,u:projectx_rails:rwx /var/www/projectx/shared/tmp
You can run commands on the remote machine through capistrano. You could run a directory owner change after, lets say, symlinking the application.
In your deploy.rb file, add a callback for it:
after 'deploy:create_symlink' do
run "chown -R projectx_rails:projectx_rails #{current_release}/tmp"
end
My current solution is to have this task:
namespace :deploy do
desc "Fix permissions"
task :fix_permissions do
on roles(:app) do
execute "sudo chown -R projectx_rails:projectx_rails #{shared_path}/tmp"
execute "sudo chmod ug+rwX,o+rw #{shared_path}/tmp"
end
end
end
and run it both at the beginning and the end of my deployment:
after "deploy:started", "deploy:fix_permissions"
before "deploy:restart", "deploy:fix_permissions"
and to make it work I had to add this to my sudoers:
projectx ALL=NOPASSWD: /bin/chown -R projectx_rails\:projectx_rails /var/www/projectx/shared/tmp
projectx ALL=NOPASSWD: /bin/chmod ug+rwX\,o+rw /var/www/projectx/shared/tmp
which makes me rather uncomfortable.
1) ensure both projectx and projectx_rails are members of the group projectx
2) add this to deploy:
task :change_tmp_pems do
run "chmod -Rf 775 #{shared_path}/tmp"
end
after "deploy:started", :change_tmp_pems
the -f will silently fail / skip any files it doesn't have access to, so that wont be an issue.
4 lines of code, pretty succinct.
Dont messa about with chown as it requires sudo normally and is unnecessary.

Non-privileged, non-root, user to start or restart webserver server such as nginx without root or sudo

I'm using capistrano to deploy a rails web app. I want to give the deploy user on the webserver as few privileges as I can. I was able to do everything I need to do as a non-privileged user except restart the webserver.
I'm doing this on an ubuntu server, but this problem is not specific to my use case (rails, capistrano, deployment), and I've seen a lot of approaches to this problem that seem to involve poor security practices. Wondering whether others can vet my solution and advise whether it's secure?
First, not necessary, but I have no idea why /etc/init.d/nginx would need any (even read) access by other users. If they need to read it, make them become root (by sudo or other means), so I:
chmod 750 /etc/init.d/nginx
Since the ownership is owner root, group root (or can be set such with chown root:root /etc/init.d/nginx) only root, or a user properly sudo'ed, can read, change or run /etc/init.d/nginx, and I'm not going to give my deploy user any such broad rights. Instead, I'm only going to give the deploy user the specific sudo right to run the control script /etc/init.d/nginx. They will not be able to run an editor to edit it, because they will only have the ability to execute that script. That means that if a someone gets access to my box as the deploy user, they can restart and stop, etc, the nginx process, but they cannot do more, like change the script to do lots of other, evil things.
Specifically, I'm doing this:
visudo
visudo is a specific tool used to edit the sudoers file, and you have to have sudoer privileges to access it.
Using visudo, I add:
# Give deploy the right to control nginx
deploy ALL=NOPASSWD: /etc/init.d/nginx
Check the sudo man page, but as I understand this, the first column is the user being given the sudo rights, in this case, “deploy”. The ALL gives deploy access from all types of terminals/logins (for example, over ssh). The end, /etc/init.d/nginx, ONLY gives the deploy user root access to run /etc/init.d/nginx (and in this case, the NOPASSWD means without a password, which I need for an unattended deployment). The deploy user cannot edit the script to make it evil, they would need FULL sudo access to do that. In fact, no one can unless they have root access, in which case there's a bigger problem. (I tested that the user deploy could not edit the script after doing this, and so should you!)
What do you folks think? Does this work? Are there better ways to do this? My question is similar to this and this, but provides more explanation than I found there, sorry if it's too duplicative, if so, I'll delete it, though I'm also asking for different approaches.
The best practice is to use /etc/sudoers.d/myuser
The /etc/sudoers.d/ folder can contain multiple files that allow users to call stuff using sudo without being root.
The file usually contains a user and a list of commands that the user can run without having to specify a password. Such as
sudo service nginx restart
Note that we are running the command using sudo. Without the sudo the sudoers.d/myuser file will never be used.
An example of such a file is
myuser ALL=(ALL) NOPASSWD: /usr/sbin/service nginx start,/usr/sbin/service nginx stop,/usr/sbin/service nginx restart
This will allow the myuser user to call all start, stop and restart for the nginx service.
You could add another line with another service or continue to append them to the comma separated list, for more items to control.
Also make shure you have run the command below to secure things
chmod 0440 /etc/sudoers.d/myuser
This is also the way I start and stop services my own created upstart scripts that live in /etc/init
It can be worth checking that out if you want to be able to run your own services easily.
Instructions:
In all commands, replace myuser with the name of your user that you want to use to start, restart, and stop nginx without sudo.
Open sudoers file for your user:
$ sudo visudo -f /etc/sudoers.d/myuser
Editor will open. There you paste the following line:
$ myusername ALL=(ALL) NOPASSWD: /usr/sbin/service nginx start,/usr/sbin/service nginx stop,/usr/sbin/service nginx restart
Save by hitting ctrl+o. It will ask where you want to save, simply press enter to confirm the default. Then exit out of the editor with ctrl+x.

RoR: Shell/System commands with write property not working in production mode?

System("ls")
System("pwd")
Both these commands just work fine in both production & development mode on the same server.
However System("mkdir test") or any other command that involves creating a new file/dir does not go through in production mode, but works just fine in development mode. Any ideas here?
My guess is it has something to do with permissions but not sure where.
On your server you should have a user different from root for security reasons. Than this user should be added to sudoers list:
https://askubuntu.com/questions/7477/how-can-i-add-a-new-user-as-sudoer-using-the-command-line
now, depending where you want to create this folder, if it's in your app folder where your user has permissions to read/write, (search chmod 755 and chown to set the owner of the folder, better use chown -R to apply this to all subfolders), after this you'll be able to create that folder with:
System("mkdir test")
but only in folders where your user has access to read/write.
If you want to create the test folder in some other path where you need to use sudo you'll have to run:
System("sudo mkdir test")
normally this is running in a background and you won't be there to write the password, so you'll have to add your command to not require password while running sudo, with NOPASSWD directive you can do that:
https://askubuntu.com/questions/159007/how-do-i-run-specific-sudo-commands-without-a-password
sudo visudo -f /etc/sudoers #!important visudo, read in the upper link more about it before trying this.
after doing all this you'll be able to create a folder in your path using:
System("sudo mkdir test")
without requiring a password.

Permission denied in tmp

I just deployed a Rails 3 app with Ruby 1.9.2. I have been getting several errors.
application.css wasn't compiled. so I set pre compilation in production.rb to false;
Then I got: cannot generate tempfile, so I did rake tmp:clear;
And now I get ActionView::Template::Error (Permission denied - /srv/www/appname/tmp/cache/assets): and I haven't been able to fix this one.
Please help.
If the user:group running your web server is http:http and it's running on *nix, do this:
sudo chown -R http:http /srv/www/appname/
Also, silly question, but does /tmp/cache/assets exist?
And, if so, as #leonel points out, you may also need to change the permissions:
chmod 777 /srv/www/appname/tmp/cache
Be careful setting 777 permissions on anything. Only do this to verify a permissions issue, then reset to the most minimal permissions necessary.
Most likely you're running your app under apache passenger.
You have to change the owner of config/environment.rb to somebody who has permissions to your app's folder.
chown -R www-data:www-data /path/to/app
Make the tmp folder of your project writable:
chown -R group:user /path/to/rails/app/tmp
chmod -R 777 /path/to/rails/app/tmp
In your console, run rake tmp:cache:clear
Restart your application.
You probably didn't create your Rails application with the user running the server now. Can you paste the output of ls -alh /srv/www/appname/tmp/cache/assets and tell us the user running the webserver ?
Now for those of us that are using windows
- If you are an administrator and see this error
ActionView::Template::Error (Permission denied # utime_failed) C:/User/..../tmp/cache/assets/sprochets/v3.0/E5/E5PZx-mq8.cache
Then it is Permission and Ownership setting issue on Windows.
You can go to the tmp folder on your application and give yourself(User) permission to **Read, Write and Execute ** on the folder.
Click [here][1] to view how to give permissions.
Quick Fix. Open your terminal and run the following command as an administrator
takeown /f <location of your app tmp folder> /r /d y
Then Restart your server.
I encountered this error recently. Apache was not able to write to tmp directory
cannot generate tempfile
/tmp/RackRewindableInput2xxxxxxxxxxxxxxxxx'
/app-lib/lib/ruby/1.8/tempfile.rb:52:ininitialize'
app-dir/vendor/gems/rack-1.0.1/lib/rack/rewindable_input.rb:73:in new'
app-dir/vendor/gems/rack-1.0.1/lib/rack/rewindable_input.rb:73:inmake_rewindable'
app-dir/vendor/gems/rack-1.0.1/lib/rack/rewindable_input.rb:26:in read'
app-dir/vendor/gems/rack-1.0.1/lib/rack/request.rb:134:inPOST'
I checked permission of tmp directory and it had permission to all groups to write to it.
I changed owner of tmp directory and it didn't resolve the error either.
The culprit was tmp directory was filled with too many large files, and looks like somehow apache didn't had enough space to write this new file.
Cleared all temp and old files. It sorted out the issue.
We need to grant permissions to access the required directory for the system root user
sudo chmod 777 -R your_project_directory_to_be_access
In your case you can use:
sudo chmod 777 -R /srv/www/appname/tmp/
For security reasons, just keep in your mind:
chmod 777 gives everybody read, write and execute rights which for most problems is definitively too much.
I think a better solution without giving everyone manage rights to tmp folder is like that:
sudo rake tmp:cache:clear
This will clear the temp folder and when you run rails server again it won't give error.
In my localhost it gave this error, and the command chmod 777 C:/Sites/project_name/tmp/cache/ solved my problem.
Most probably you gave permission to your app's main folder read and execute mode. However, in order to generate new files from your app, you also need to give write permission for required folder. For example: yUML uses tmp folder for generating files. I gave tmp folder write permission:
chmod -R 777 /usr/share/nginx/html/yuml_product/tmp
solved my problem.

What permissions are needed for apache Passenger

Running Ubuntu 10.04 on Linode, RVM, Rails 3, Apache with Passenger module, carrierwave and mini-magick
I get:
Rails Error: Unable to access log file. Please ensure that /srv/www/mysite.com/testapp/log/production.log exists and is chmod 0666. The log level has been raised to WARN and the output directed to STDERR until the problem is fixed.
and Errno::EACCES (Permission denied /srv/www/mysite.com/testapp/public/uploads/tmp/20110517-1707-2938-6455):
I ran chmod -R root:root /srv/www/mysite.com/testapp
Then: chmod -R www-data:www-data /srv/www/mysite.com/testapp & chmod -R www-data:www-data /srv/www/mysite.com/testapp/public/uploads
Since the only 2 directories that should be writable is the log files and uploads directory I tried to secure the rest. Are there any other folders / files that I need to make writable?
Permissions on web sites is a little strange: on the one hand, the content needs to be readable by the webserver and FastCGI or Passenger or whatever executes the (in this case, Ruby) code. On the other hand, if the webserver user owns the files, then a hacked webserver or (more likely :) your code could modify the executable files and static files that are your website. It happens too often.
If the content of the website is owned by some other user, not writable by the web server software, then the website can not be overwritten by attackers. (Of course, you have a few open sockets to a database connection; all the database backed data can be corrupted by attackers. Also, any directory where you allow uploads could be corrupted by attackers. But the goal is to reduce the privileges of the software as far as reasonable.)
So, all that said, on to your specific question; your webserver software runs as www-data, and it makes sense for your log files and upload directory to be owned by www-data:
mkdir -p /srv/www/mysite.com/testapp/log/ # might not exist yet
chown -R pcasa:pcasa /srv/www/mysite.com/ # or some other user
chmod 755 /srv/www/mysite.com
chmod 755 /srv/www/mysite.com/testapp/
# populate the app directory with your files, if you haven't done so already
chown -R www-data:www-data /srv/www/mysite.com/testapp/log
chmod 755 /srv/www/mysite.com/testapp/log # see notes
chmod 644 /srv/www/mysite.com/testapp/log/* # see notes
I made the assumption that all users on your system can read the log. This might not be true. Use 700 in place of 755 and 600 in place of 644 if you don't want all system users to read the log files.
Next, for your uploads directory:
mkdir -p /srv/www/mysite.com/testapp/public/uploads/tmp # might not exist yet
chown -R www-data:www-data /srv/www/mysite.com/testapp/public/uploads
chmod 755 /srv/www/mysite.com/testapp/public/uploads
chmod 755 /srv/www/mysite.com/testapp/public/uploads/tmp
Again, I've made the assumption that all users on your system can be able to see all the uploaded content. Use 700 in place of 755 if you just want the webserver software to be able to read the files.
These are simple guidelines that should work; you can get more complicated if you want to keep the website software and content shared only between the user that owns the website and the user that runs the website, by running the webserver with a supplementary group (see newgrp(1) and group(5) manpages for details) and giving the files the same group owner, and using the group permission bits (the middle octal number: 750 vs 700). It's complicated enough that unless you've got a good reason, it's probably not worth going down this route. (Definitely worth doing once on a development machine somewhere, just so you're familiar enough with it that you can use it in the future. :)

Resources