How to create a directory in /run for each Supervisor program? - linux

I have an Ubuntu 14.04 LTS server running a few different programs under Supervisor. Many of the programs need to store sockets and other named pipes on the filesystem, and /run seems like the ideal choice for these types of files. Unfortunately, /run is tmpfs and removed on every reboot, and root privileges are needed to (re)create the directories that each program can write to.
I need a way to create a few subdirectories in /run and set the owner/mode to something that each program can work with, and do so on each reboot before Supervisor tries to start them. It does not look like Supervisor supports a mechanism to run pre-start commands before it starts a program.
Most other answers for this type of question suggest doing it in the init script, but that belongs to Supervisor's package and I do not want to mess with it (or have to maintain it when it changes upstream).
If this machine had Systemd it seems like I could use /etc/tmpfiles.d, but it does not.
The best idea I came up with was to use a separate Upstart pre-start script for each program that only creates the directories without actually launching any processes. Something like:
/etc/init/myapp1.conf
start on runlevel [2345]
pre-start script
mkdir -p -m 0755 /var/run/myapp1
chown app1user: /var/run/myapp1
end script
...without any exec line. I'm not 100% sure this is valid or sane, but it appears to work. Are there cleaner ways to do something like this?

Do you run your apps under supervisor under a specific user? Because by default applications are run with root as owner.
What I would do is a simple script which does the following:
Checks if the required files/folders are created.
Sets the owner if necessary.
Then starts your application
Put this script into your supervisor config instead of directly starting your application. Make sure that it is run with root (remove user from the config or set user=root).
This way you can always make sure that your environment is set up and your directories exist. So if you clear the tempfs for some reasons, your scripts will still run without reboot.
If you NEED to run your applications under a specific user, you can do the following:
Move the first 2 points into a separate setup script (as you would do now using your solution).
Create another script which calls your setup script with sudo and starts your application
Add your custom user and script to the sudo file so that your user can call that script as root without a password prompt. (Be aware: this is a security risk, if someone gets access to your server. Make sure that your setup script is NOT writable)

Related

chroot process jail with arbitrary directory set as root on each run

I am trying to run a command that needs to be limited to one directory and is executed in a shell function from a web application.
My goal is to run that program but limit it to one directory. This directory will change each time I want to run the program and multiple instances need to be able to run on different directories at the same time.
I have looked at chroot and it seems that a file system needs to be explicitly created each time. I am looking for a more temporary solution that accepts the desired root directory and dose not require me to copy files all over the place or do weird mounting of things.
What you most likely want is containers.
A container takes milliseconds to start, and creates what is basically a complete chroot jail every time it runs. A command like docker run --rm --volume /var/chroot/jail/whatever:/workdir ubuntu stat /workdir will run stat on the chroot jail directory, with all environment being the latest Ubuntu release. It will then scrap the chroot jail. Running it again will create a whole new jail.
You will need to build your web application as a docker image on top of whatever jail you need (Ubuntu, CentOS etc.), which means adjusting your build system to create such an image.

How to know who is deleting the files/directory

We have a directory /home/test/abc
Sometimes we found that the directory is not present. Most probably it is deleted by someone. We have lots of users who log in and out from the system.
I have checked the bash_history of all the users but nobody seems to have executed the rm command.
I would like to know if there is a way to monitor this directory and notify if a user or a script is trying to modify this directory.
I am using Centos
You can do two things:
You can install a utility that called acct (psacct), to monitoring on the user's activity on your machine.
You can install a tool that called inotify-tool, and after that, run the command: sudo inotifywait -m <your_file_path_here>, and it will monitor on your file activity in LIVE.

node.js read protected files without running as root

I'd like to read/write files using nodejs that live in a protected directory (/etc/apache2/sites-available). I understand that I can run the script with sudo but the idea of that makes me worried. Is there some way I can have node try to elevate for certain functions/calls without having the whole script run with root access?
If you do not provide elevated rights to your script, the script will be unable to mysteriously obtain those rights out of the thin air.
Granted you still need to modify the files, then consider giving write permissinos to your app.
If you are running app as user joe, and owner of sites-available files is root, then do: chown -R joe:joe sites-available.
But if some other user already uses those files, then you might get into permissions conflict. In this case, you can workaround using shared group, or SSH as that user.
Shortly, there are several ways of achieving your goal. But it is completely unrelated to Node.js technology, and all about linux, chown and chmod.

How do i get the user name in a Makefile?

I'm making a simple game for Ubuntu and to update the highscore list, it needs a single file at runtime, called 'highscores.bin'.
I wish to put this file at
/home/(USER)/.game_name
I've researched a little and found that from inside a Makefile i can get the environment variable $USER.
So in the Makefile, at the 'install' target, i've added:
mkdir -p $(DESTDIR)home/$$USER/.game_name
But when i run 'sudo make install', the Makefile installs it as:
/home/root/.game_name
How can i get the (non-root) user name in a Makefile?
P.S.: I'm writing the Makefile by hand. No ./configure
P.S.2: I dont want to do
mkdir -p ~/.game_name
because i want to be able to change DESTDIR if i want to install to a temporary directory.
Well, if you want that file during runtime I would recommend that you create it during runtime. The Makefile is considered only during compile time. This is obviously a problem if the program is compiled and then executed by different users, some of which may not even exist at compile time.
During runtime you can get the home directory as shown here (if you are using C/C++). Then you can check for existance of the highscore folder/file and create it if you need to. If you want a highscore file for all users, you should put it in the home directory of a special user, but rather somewhere else in the file system. This is for example done by the game xjump.
And about your Makefile, the $USER variable is translated to root because of the sudo command on
sudo make install
The user actually running make is the superuser: root.
You want to install your program for every users? So it's better if you create the /home/user/.game_name directory when the user run the game, not when root installs it. Otherwise, only the user who call sudo make install will have it's highscore list. If you have only one user, do not install it system-wide, but in the user directory.
I suggest to initialize users files at game first run. So every users, even users that didn't exist when the game was installed, can have their highscore list. You can add the initializing code into your game (c++, java or anything else) or just call an external script that does it (not so elegant). Avoid to create user-related files at installation time.

Can oprofile be made to use a directory other than /root/.oprofile?

We're trying to use oprofile to track down performance problems on a server cluster. However, the servers in question have a read-only file system, where /var/tmp is the only writeable directory.
OProfile wants to create two directories whenever it runs: /root/.oprofile and /var/lib/oprofile, but it can't, because the filesystem is read-only. I can use the --session-dir command line option to make it write its logs to elsewhere than /var/lib, but I can't find any such option to make it use some other directory than /root/.oprofile.
The filesystem is read-only because it is on nonwriteable media, not because of permissions -- ie, not even superuser can write to those directories. We can cook a new ROM image of the filesystem (which is how we installed oprofile, obviously), but there is no way for a runtime program to write to /root, whether it is superuser or not.
I tried creating a symlink in the ROM that points /root/.oprofile -> /var/tmp/oprofile, but apparently oprofile doesn't see this symlink as a directory, and fails when run:
redacted#redacted:~$ sudo opcontrol --no-vmlinux --start --session-dir=/var/tmp/oprofile/foo
mkdir: cannot create directory `/root/.oprofile': File exists
Couldn't mkdir -p /root/.oprofile
We must run our profilers on this particular system, because the performance issues we're trying to investigate don't manifest if we build and run the app on a development server. We can't just run our tests on a programmer's workstation and profile the app there, because the problem doesn't happen there.
Is there some way to configure oprofile so that it doesn't use /root ?
I guess it should be as simple as overriding the HOME environment variable:
HOME=/tmp/fakehome sudo -E opcontrol --no-vmlinux --start --session-dir=/var/tmp/oprofile/foo
If that doesn't work out, you could have a look at
unionfs
aufs
to create a writable overlay. You might even just mount tmpfs on /root,or something simple like that.
It turns out that this directory is hardcoded into the opcontrol bash script:
# location for daemon setup information
SETUP_DIR="/root/.oprofile"
SETUP_FILE="$SETUP_DIR/daemonrc"
Editing those lines seemed to get it working, more or less.

Resources