[This does not directly address the issue of systemd-tmpfiles but I think you have already recognized that in this particular case you are better off just using echo.]
First up, "multi-user.target" may or may not be what you want to use. If you are familiar with the concept of runlevels from SysV style init stuff, multi-user is the systemd equivalent of runlevel 3, which is a multi-user system that boots to a console, not a GUI. The equivalent of runlevel 5, which boots to X, is graphical.target. The default is determined by a symlink in
/lib/systemd/system; the one in
/etc will overrule the one in
/lib) called default.target, use ls to find where it points:
»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target
For normal linux desktops this will be graphical.target. This is actually not important if you want the boot service you are creating to start regardless of what the default runlevel/target is -- in that case, we can just use default.target, and not worry what it is an alias for. If you use multi-user, however, and your default is graphical, your service won't happen.
Depending on the service, there may be more appropriate and specific targets or services that you want to start this one in relation to. Based on your other question, default.target is probably fine. As a note, the difference between a "target" and a "service" is that a service contains a
[Service] section which actually runs a process; a target is just a way of grouping services together via the various "depends" and "requires" directives; it doesn't do anything of its own beyond triggering other targets or services.
When a service starts is determined by what other services explicitly depend on it. In the case of a simple, stand-alone event like this that we want run late in the boot process, we can use this combination of directives:
The "Install" section is used when the service is installed; "WantedBy" specifies a target we want this service to be included with (meaning it will run if that target does, but nb. this does not determine when it will run in relation to others). Since we actually want this service to run later rather than sooner, we then specify an "After" clause. This does not actually need to be the same as the WantedBy target (it usually isn't) and can be completely omitted if you don't care when it happens; I'm just using it on the hunch that most other stuff will be run in relation to stuff that is somewhere chained to something that has specified
Before=default.target (which we could also have used; a target's wants are appraised before the target is run).
For the example, I'll just echo "hello world" to the console. The service itself is described in the
The command needs a full path. The reason I did not just use
/usr/bin/echo "hello world" is that it won't work (the output goes to /dev/null, I think), and while a service that does an
echo "hello world" > /dev/console will, experimentation demonstrates that using shell redirection in an ExecStart directive won't. So /usr/local/bin/helloworld is a shell script with that one line,
echo "hello world" > /dev/console.
Type=forking, which is necessary for a shell script.
Our complete, minimal service file is just those three sections (
[Install]). To install, place the file or a symlink to it in either /etc/systemd/system or /usr/lib/systemd/system, and:
systemctl --system enable helloworld
It should print
ln -s .... This does not run the service, it just configures it to run at boot as discussed above.
That's it in a nutshell.
man systemd.unit and
man systemd.service have more details.