Running nobody (or dynamic user) with CAP_NET_RAW in systemd - networking

I want to run service with cap_net_raw capabilities but with no any interaction with filesystem and/or other processes. My program will use raw sockets and normal sockets (for API), stdout/err for logging and that's all.
I want to write systemd.service file to do this, but I couldn't produce a proper combination for DynamicUser, User and CapabilityBoundingSet.
My (non-working) unit looks like this:
[Unit]
Description=my daemon (%I)
ConditionFileNotEmpty=/etc/daemon/%i.conf
Wants=network-online.target
BindsTo=daemon.target
[Service]
Type=simple
WorkingDirectory=/etc/daemon
EnvironmentFile=/etc/daemon/%i.conf
ExecStart=/usr/bin/daemon ${OPTIONS}
CapabilityBoundingSet=CAP_NET_RAW
ProtectSystem=true
ProtectHome=true
RestartSec=5s
Restart=on-failure
User=daemon-%i
Group=nobody
DynamicUser=true
[Install]
WantedBy=daemon.target
How can I configure dynamic user 'nobody' together with CAP_NET_RAW?

You also need:
AmbientCapabilities=CAP_NET_RAW
See this question about the difference between AmbientCapabilities and CapabilityBoundingSet, as well as the documentation.

Related

How to open a qml interface using systemd?

I want to open a qml interface using systemd and when the user closes the window, the system automatically restarts the process to open the window again, but the interface doesn't open.
I tried this configuration:
[Unit]
Description=test
After=graphical.target
Wants=graphical.target
[Service]
Type=simple
ExecStart=~/test
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
Alias=test.Service
test is my binary, that runs my qml interface.
How can I do this?
Please if possible provide an example for my case.

Camera (/dev/video0) dependencies in systemd service Ubuntu 16.04

I need to run some services on boot up which I have successfully accomplished using systemd services. (Lots of answers already available).
Now, one of my service requires access to /dev/video0 while bootup when a certain user is logged in. (I am doing auto login which is working fine).
So how do I check that whether the /dev/video0 is available before starting my systemd service while bootup.
I came across something called udev for doing this, I followed this link
but I am not getting desired output as after editing /lib/udev/rules.d/99-systemd.rules files as mentioned in the link and starting my service manually it's not starting, any help is appreciated.
Finally after struggling for a day I found the answer -
I made a script in /etc/systemd/system which contains
[Unit]
Description='some description of my file write according to you'
[Service]
Type=forking
ExecStart='path to script'
[Install]
WantedBy=multi-user.target
and It executes a script which contains
#!/bin/bash
modprobe uvcvideo
Now after rebooting all the services are running properly
mod probe uvcvideo command check for running video driver and enable it at the time of bootup so that It is available for my systemd process
Thanks

systemd execute after a oneshot service

Hi is it possible to run a service after a "oneshot" type service
I want to run a script that started before display-manager.service but after gpu-manager.service, gpu-manager.service is a oneshot service that detect available gpu. This is my service :
[Unit]
After=gpu-manager.service
Before=display-manager.service
[Service]
Type=oneshot
ExecStart=myscript
[Install]
WantedBy=multi-user.target
Will my service be started after gpu-manager and before display started ?
Are you sure that you need 3 services?
You can use ExecStop or other directives to run multiple scripts and use 1 systemd service.
Try this solution
[Unit]
Description=example
[Service]
Type=oneshot
ExecStart=/usr/local/bin/on_start.sh
RemainAfterExit=true
ExecStop=/usr/local/bin/with_stopped.sh
[Install]
WantedBy=graphical.target

How to start services in early stage of beaglebone boot?

I am trying to change the Beaglebone black splash screen.
I am using Angstrom-Cloud9-IDE-GNOME-eglibc-ipk-v2012.12-beaglebone-2013.06.20.img.xz image.
I compiled the psplash source (as explained in https://groups.google.com/forum/#!msg/beagleboard/HRDjAtsPO68/dc7gIZTynQkJ) and now psplash works fine.
In order to automatically start psplash I create a new system service called psplash.service and I enabled it with the command "systemctl enable psplash.service".
The problem is: when Beaglebone boots, the psplash is launched a little bit late and you can see for several
seconds the standard beaglebone logo. How can I configure the service in order to run the psplash as soon as possible ?
Is there a better way than the system services for starting psplash program ?
Here is the system service file:
[Unit]
Description=Splash screen
[Service]
WorkingDirectory=/home/root/
ExecStart=/usr/local/bin/psplash
SyslogIdentifier=psplash
[Install]
WantedBy=multi-user.target
Systemd services by default have dependencies so removing the dependencies will allow it to start the service early.
[Unit]
Description=Splash screen
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/local/bin/psplash
[Install]
WantedBy=basic.target
This will cause it to start before other dependencies. You may add dependencies within the [Unit] block with After=... or Before=.... But be careful with the Before=... as it will wait for psplash to end and since psplash will run uninterrupted on its own it may cause start-up to hang.
This will cause the service to run earlier in the systemd process but I am still looking into other ways to get it to start even earlier.

Writing a unix daemon

I'm trying to code a daemon in Unix. I understand the part how to make a daemon up and running . Now I want the daemon to respond when I type commands in the shell if they are targeted to the daemon.
For example:
Let us assume the daemon name is "mydaemon"
In terminal 1 I type mydaemon xxx.
In terminal 2 I type mydaemon yyy.
"mydaemon" should be able to receive the argument "xxx" and "yyy".
If I interpret your question correctly, then you have to do this as an application-level construct. That is, this is something specific to your program you're going to have to code up yourself.
The approach I would take is to write "mydaemon" with the idea of it being a wrapper: it checks the process table or a pid file to see if a "mydaemon" is already running. If not, then fork/exec your new daemon. If so, then send the arguments to it.
For "send the arguments to it", I would use named pipes, like are explained here: What are named pipes? Essentially, you can think of named pipes as being like "stdin", except they appear as a file to the rest of the system, so you can open them in your running "mydaemon" and check them for inputs.
Finally, it should be noted that all of this check-if-running-send-to-pipe stuff can either be done in your daemon program, using the API of the *nix OS, or it can be done in a script by using e.g. 'ps', 'echo', etc...
The easiest, most common, and most robust way to do this in Linux is using a systemd socket service.
Example contents of /usr/lib/systemd/system/yoursoftware.socket:
[Unit]
Description=This is a description of your software
Before=yoursoftware.service
[Socket]
ListenStream=/run/yoursoftware.sock
Service=yourservicename.service
# E.x.: use SocketMode=0666 to give rw access to everyone
# E.x.: use SocketMode=0640 to give rw access to root and read-only to SocketGroup
SocketMode=0660
SocketUser=root
# Use socket group to grant access only to specific processes
SocketGroup=root
[Install]
WantedBy=sockets.target
NOTE: If you are creating a local-user daemon instead of a root daemon, then your systemd files go in /usr/lib/systemd/user/ (see pulseaudio.socket for example) or ~/.config/systemd/user/ and your socket is at /run/usr/$(id -u)/yoursoftware.sock (note that you can't actually use command substitution in pathnames in systemd.)
Example contents of /lib/systemd/system/yoursoftware.service
[Unit]
Description=This is a description of your software
Requires=yoursoftware.socket
[Service]
ExecStart=/usr/local/bin/yoursoftware --daemon --yourarg yourvalue
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Also=yoursoftware.socket
Run systemctl daemon-reload && systemctl enable yoursoftware.socket yoursoftware.service as root
Use systemctl --user daemon-reload && systemctl --user enable yoursoftware.socket yoursoftware.service if you're creating the service to run as a local-user
A functional example of the software in C would be way too long, so here's an example in NodeJS. Here is /usr/local/bin/yoursoftware:
#!/usr/bin/env node
var SOCKET_PATH = "/run/yoursoftware.sock";
function errorHandle(e) {
if (e) console.error(e), process.exit(1);
}
if (process.argv[0] === "--daemon") {
var logFile = require("fs").createWriteStream(
"/var/log/yoursoftware.log", {flags: "a"});
require('net').createServer(errorHandle)
.listen(SOCKET_PATH, s => s.pipe(logFile));
} else process.stdin.pipe(
require('net')
.createConnection(SOCKET_PATH, errorHandle)
);
In the example above, you can run many yoursoftware instances at the same time, and the stdin of each of the instances will be piped through to the daemon, which appends all the stuff it receives to a log file.
For non-Linux OSes and distros without systemd, you would use the (typically shell-scripted) startup system to begin your process at boot and the user would receive an error like could not connect to socket /run/yoursoftware.sock when something goes wrong with your daemon.

Resources