How do I run commands as root from Rails? - ruby-on-rails

I'm thinking about writing a Rails application to manage servers like cPanel.
The hardest part is to select the best way to run commands that require root privileges, like adduser, or doing things that require another user's privileges, like changing nginx config files.
I know only two ways to achieve this:
I can write a standalone daemon that will be run as root and do all the work, receiving commands through IPC or something like this.
Run Rail's server as the root user, and do anything from it or execute commands/bash scripts from it.
Which of these ways are best? Does there exist another way to to this?

sudo -i
I tried doing things like sudo bundle exec rails console but it wouldn't quite run it as root so when I tried to create a directory from the console it let me know that I did not have the correct permissions.
However, using sudo -i it enters you into an "interactive console" as the sudo root user and then you can run bundle exec rails console as the sudo root user.
Hopes that helps others.

You need to do #2.
Start your application as root, and you will be able to do all operations as root.
Writing code to run as a daemon would work also, but it's harder to debug.
In either case you have to protect against hacking attempts via unauthorized access. One slip and your system would be compromised.

Related

Permissions with sidekiq monit and capistrano

I'm having troubles with capistrano and sidekiq monit.
I setup a user for capistrano and everything was going smoothly until I installed Sidekiq.
My problem is when I try to execute cap staging sidekiq:monit:config (sidekiq:monit:start has the same permission problem).
Everytime I've tried, it "freezes" because it asks for the password.
Then I tryed to set sidekiq_monit_use_sudo to false. It's ok, it doesn't use sudo, but then it doesn't have permission to copy the /tmp/monit.conf into /etc/monit/conf.d/ folder.
It's the first time I'm setting up a server and I'm kinda lost here =|
Maybe try to config the sidekiq monit manually?
I'm using ruby 2.5 and these gems:
capistrano 3.10
capistrano-sidekiq 1.0
rails 5.1
Also I have the :pty config set to true as I don't feel comfortable not using a password.
Thank you!
You have a couple of options, of which I'll define two, the right one, and the easy/bad one.
Local User Monit
My personal usage of Monit is on a shared server on which I do not have root access. So I run Monit itself as a non-root user.
In order to do this, I compiled Monit with its prefix as $HOME/apps, so that the config files are in $HOME/apps/etc. This avoids the sudo issue. If you have access to the package manager and installed Monit that way, you can run monit as your user with the -c param to define where it should look for configuration files:
monit -c $HOME/config/monitrc
In order to get Capistrano to recognize the local monit, you will need some extra parameters in config/deploy.rb:
#set :monit_bin, '/usr/bin/monit' # Use this if you compile monit yourself.
set :sidekiq_monit_conf_dir, '/home/myuser/config/monit.d' # Feel free to customize.
set :sidekiq_monit_use_sudo, false
In the monitrc file you have defined with the -c option, you will need to make sure whatever folder you define in :sidekiq_monit_conf_dir is pulled in via includes:
include /home/myuser/config/monit.d/*.conf
Since I don't have an init system, I have Cron start Monit every 30 minutes, which is a noop if it is already running:
# Restart monit if it dies
*/30 * * * * $HOME/apps/bin/monit > /dev/null
If you have root access, you can improve upon this by having an init script (or systemd unit file) start Monit as your local user.
Bad option: give your user access to the conf dir
You can edit /etc/monit/monitrc to include your local user config directory as above. Similarly, you can allow your user to write to /etc/monit/conf.d. The major downside of these solutions is that you are now allowing your non-root user to create files which will be executes as root, opening a privilege escalation vulnerability. If your user ever got compromised, you certainly don't want an easy way for the attacker to get to root.
I include this option mostly because it's commonly considered, and should be avoided in the vast majority of cases (such as whenever you care about security). However, this might be useful in occasional rare cases (such as when you have a short term server for internal use only behind a firewall with only trusted users, and you need to set it up in a hurry).

Rails nginx passenger and rake commands

I'm running my rails application with the help of passenger. And i see in top that it run's as www-data user, but when i try to run under this user this command:
rake ts:index
i get like access denied
when i'm under root (run under root rake ts:index) - all is ok...
what is better:
to make passenger running as root (how to do that)
or
what ever could i do?
how to do, that sphinx could reindex database?
part of code in method:
def self.reindexDB
`rake ts:index`
end
I'm not sure if what you're doing is good or not, because if you run that rake command in root user, I believe the output files (index files) will be owned by the root user, with wrong permissions those files won't be accessible by your own server (www-data),
I think the best way to handle this is to add your own user ( the one you use to ssh on the server ) to the www-data group
There's 2 ways to do that
Command line: like sudo usermod -a -G www-data [your-user]
Editing /etc/group:
Edit the /etc/group file and look for the line that starts with www-data then append your own user in it, it should look something like this at the end
www-data:x:33:[your-user]
save the file then you need to logout and log back in to find the changes,
I believe after this you'll be able to run the command by your own user and it will still have access to the www-data owned files.

Running Rails Task From Cron

I have a Rails runner task that I want to run from cron, but of course cron runs as root and so the environment is set up improperly to get RVM to work properly. I've tried a number of things and none have worked thus far. The crontab entry is:
* 0 * * * root cd /home/deploy/rails_apps/supercharger/current/ && /usr/local/rvm/wrappers/ruby-1.9.3-p484/ruby bundle exec rails runner -e production "Charger.start"
Apologies for the super long command line. Anyhow, the error I'm getting from this is:
ruby: No such file or directory -- bundle (LoadError)
So ruby is being found in the RVM directory, but again, the environment is wrong.
I tried rvm alias delete [alias_name] and it seemed to do something, but darn if I know where the wrapper it generated went. I looked in /usr/local/rvm/wrappers and didn't see one with the name I had specified.
This seems like a common problem -- common enough that the whenever gem exists. The runner command I'm using is so simple, it seemed like a slam dunk to just put this entry in the crontab and go, but not so much...
Any help with this is appreciated.
It sounds like you could use a third-party tool to tether your Rails app to cron: Whenever. You already know about it, but it seems you never tried it. This gem includes a simple DSL that could be applied in your case like:
every :day # Or specify another period, or something else, see README
runner "Charger.start"
end
Once you've defined your schedule, you'll need to write it into crontab with whenever command line utility. See README file and whenever --help for details.
It should not cause any performance impact at runtime since all it does is conversion into crontab format upon deployment or explicit command. It's not needed, once the server is running, everything is done by cron after that.
If you don't want an extra gem anyway, you might as well check what command does it issue for executing your task. Still, an automated way of adding a cron task is easier to maintain and to deploy. Sure, just tossing a line into the crontab is easier — just for you and just this once. Then it starts to get repetitive and tiring, not to mention confusion for other potential developers who will have to set up something similar on their own machines.
You can run cron as different user than root. Even in your example the task begins with
* 0 * * * root cd
root is the user that runs the command. You can edit it with crontab -e -u username.
If you insist on running cron task as root or running as other user does not work for some reason, you can switch user with su. For example:
su - username -c "bundle exec rails runner -e production "Charger.start"

Rails/Passenger/Nginx user permission errors

My Rails app is having trouble writing into it's public/ directory. I've setup nginx with user root;, the capistrano recipe I'm using also is using root when connecting via ssh.
To fix this I made capistrano run chmod o+w -R #{current_path}/ but I don't think this is a good solution. What am I missing?
According to Phusion Passenger's documentation:
Under no circumstances will applications be run as root. If
environment.rb/config.ru is owned as root or by an unknown user, then
the Rails/Rack application will run as the user specified by
passenger_default_user and passenger_default_group.
http://modrails.com/documentation/Users%20guide%20Nginx.html#user_switching

Where do you put your rails app on your server? What User do you deploy with?

I've always deployed my apps to ~/apps/myApp/current (with Capistrano, that's why I have the current directory).
But I've seen users deploy to like /var/www/, or even some make a directory at the root, /myapp.
I'm wondering is there an ideal place to put my app? Or does it not matter at all.
Additionally what do you usually name your user, I'm using deploy as my username and group, but I've seen users use rails or just whatever the username they always use is.
Is there a rule of thumb here? I'm aware that some may see this as a subjective question, I just wanted to get a little census as to what most people do.
On Ubuntu, /srv is a good place to install a rails app. Do not put it in /var/www, people would be able to browse your app sources in some circumstances.
The user www-data is perfect for running your app (when running apache, that's the default user). With Passenger, you can set PassengerDefaultUser www-data in its config file to enable that.
Do NOT run your app in as root. It's very dangerous.
/var/rails/app_name/current and deploy
I put all my web stuff under /var/www/ just because I like having it all in one place and /var/www/ is the default directory for Apache. There is no 'ideal' place to put your software - just put it wherever seems most logical to you. Pretty much the same for the username - I run my rails stuff under www-data but it doesn't matter what user you run it as (as long as it's not root).
Obviously clients shouldn't be allowed access to the rails app itself.
/srv is the right place to put your http or ftp , for more info visit https://help.ubuntu.com/community/LinuxFilesystemTreeOverview

Resources