Let's add a second user to our machine to test out our system.
We'll also need to add the site directory and test it all out.
```
➜ ~ sudo adduser alice
➜ ~ sudo su alice
alice@squid:/home/waldek$ cd && mkdir site && echo "this is Alice her website" > site/index.html
alice@squid:~$ cat site/index.html
this is Alice her website
alice@squid:~$ exit
exit
➜ ~ wget -q -O - localhost/alice
this is Alice her website
➜ ~
```
It's working nicely as expected but all these users will have their website running permanently and we want them only available when they are logged in.
How would we go about that?
Let's have a dive into our running services.
```
➜ ~ sudo systemctl --type=service --no-pager
UNIT LOAD ACTIVE SUB DESCRIPTION
apparmor.service loaded active exited Load AppArmor profiles
console-setup.service loaded active exited Set console font and keymap
cron.service loaded active running Regular background program processing daemon
dbus.service loaded active running D-Bus System Message Bus
getty@tty1.service loaded active running Getty on tty1
ifup@enp1s0.service loaded active exited ifup for enp1s0
ifupdown-pre.service loaded active exited Helper to synchronize boot up for ifupdown
keyboard-setup.service loaded active exited Set the console keyboard layout
kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current kernel
networking.service loaded active exited Raise network interfaces
nginx.service loaded active running A high performance web server and a reverse proxy server
ntopng.service loaded active running ntopng - High-Speed Web-based Traffic Analysis and Flow Collection Tool
redis-server.service loaded active running Advanced key-value store
rsyslog.service loaded active running System Logging Service
serial-getty@ttyS0.service loaded active running Serial Getty on ttyS0
ssh.service loaded active running OpenBSD Secure Shell server
systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running Login Service
systemd-modules-load.service loaded active exited Load Kernel Modules
systemd-random-seed.service loaded active exited Load/Save Random Seed
systemd-remount-fs.service loaded active exited Remount Root and Kernel File Systems
systemd-sysctl.service loaded active exited Apply Kernel Variables
systemd-sysusers.service loaded active exited Create System Users
systemd-timesyncd.service loaded active running Network Time Synchronization
systemd-tmpfiles-setup-dev.service loaded active exited Create Static Device Nodes in /dev
systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories
systemd-udev-trigger.service loaded active exited udev Coldplug all Devices
systemd-udevd.service loaded active running udev Kernel Device Manager
systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown
systemd-user-sessions.service loaded active exited Permit User Sessions
user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000
user@1000.service loaded active running User Manager for UID 1000
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
33 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
➜ ~
```
We're currently the only user logged in on this system.
This is verifiable with a few commands.
`waldek` is the only one logged in but over a few different connections, some running tmux, some not.
```
➜ ~ who
waldek pts/0 2021-08-29 19:54 (192.168.0.33)
waldek pts/1 2021-08-29 21:40 (tmux(1554).%4)
waldek pts/2 2021-08-29 20:37 (tmux(1554).%0)
waldek pts/3 2021-08-29 20:38 (tmux(1554).%1)
waldek pts/4 2021-08-29 20:50 (tmux(1554).%2)
waldek pts/5 2021-08-29 20:51 (tmux(1554).%3)
waldek pts/6 2021-08-29 22:01 (192.168.0.33)
➜ ~
```
The first user account created on most Linux machine is the UID 1000.
We can use the `id` command to find out which UID is assigned to a specific user or vice a versa.
```
➜ ~ id -u -n 1000
waldek
➜ ~ id -u alice
1002
```
Now going back to the list of running service for our UID or just 'user' we get the following.
If we try out this script, as `sudo` because we need to modify files owned by other users, we get the following.
It's a proof of concept but more than enough to continue with the service files.
```
➜ ~ sudo ./site-manager.sh start 1002
created online site dir for alice
chowned all site files to alice:alice
online site installed for alice
➜ ~ wget -q -O - localhost/alice
alice logged in...
➜ ~ sudo ./site-manager.sh stop 1002
created offline site dir for alice
chowned all site files to alice:alice
moved online site to offline site for alice
offline site installed for alice
➜ ~ wget -q -O - localhost/alice
alice not logged in...
➜ ~
```
## The service
Now that we have a functional script, we can write a service file for it.
As we'll be using it for more than one user, we'll do a template.
You can name it whatever you want but I went for the following.
```
➜ ~ sudo systemctl cat user-website@.service
# /etc/systemd/system/user-website@.service
[Unit]
Description=User %i website service
PartOf=user@%i.service
After=systemd-user-sessions.service dbus.service
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/waldek/site-manager.sh start %i
ExecStop=/home/waldek/site-manager.sh stop %i
➜ ~
```
There are a couple of new thing in this service file so let's break them down.
This time we specify the `Type` of service.
We can read the `man systemd.service` for more information but the gist of it is this.
```
• Behavior of oneshot is similar to simple; however, the service manager will consider the unit started after the main
process exits. It will then start follow-up units. RemainAfterExit= is particularly useful for this type of
service. Type=oneshot is the implied default if neither Type= nor ExecStart= are specified.
```
The combination of `Type=oneshot` and `RemainAfterExit=true` make it so that the service is started and remains active even after the script has finished.
In order for the service to *stop* when the user logs out, we need the `PartOf` line.
```
PartOf=
Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or
restarts the units listed here, the action is propagated to this unit. Note that this is a one-way dependency — changes
to this unit do not affect the listed units.
When PartOf=b.service is used on a.service, this dependency will show as ConsistsOf=a.service in property listing of
b.service. ConsistsOf= dependency cannot be specified directly.
```
We can test out this service, for our alice user, as follows.
-- Logs begin at Sun 2021-08-29 22:58:12 CEST, end at Sun 2021-08-29 23:01:09 CEST. --
Aug 29 23:00:25 squid systemd[1]: Starting User 1002 website service...
Aug 29 23:00:25 squid site-manager.sh[507]: created online site dir for alice
Aug 29 23:00:25 squid site-manager.sh[507]: chowned all site files to alice:alice
Aug 29 23:00:25 squid site-manager.sh[507]: online site installed for alice
Aug 29 23:00:25 squid systemd[1]: Started User 1002 website service.
Aug 29 23:01:06 squid systemd[1]: Stopping User 1002 website service...
Aug 29 23:01:06 squid site-manager.sh[529]: created offline site dir for alice
Aug 29 23:01:06 squid site-manager.sh[529]: chowned all site files to alice:alice
Aug 29 23:01:06 squid site-manager.sh[529]: moved online site to offline site for alice
Aug 29 23:01:06 squid site-manager.sh[529]: offline site installed for alice
Aug 29 23:01:06 squid systemd[1]: user-website@1002.service: Succeeded.
Aug 29 23:01:06 squid systemd[1]: Stopped User 1002 website service.
➜ ~
```
Now the service works as expected but does it actually trigger when users log in?
Let's investigate!
When alice is logged in over SSH we get the following active services.
```
➜ ~ sudo systemctl --type=service --no-pager | grep user
systemd-sysusers.service loaded active exited Create System Users
systemd-user-sessions.service loaded active exited Permit User Sessions
user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000
user-runtime-dir@1002.service loaded active exited User Runtime Directory /run/user/1002
user@1000.service loaded active running User Manager for UID 1000
user@1002.service loaded active running User Manager for UID 1002
➜ ~
```
It does not seem to works, let's try starting the service to see if it *actually* lists itself.
```
➜ ~ sudo systemctl --type=service --no-pager | grep user
systemd-sysusers.service loaded active exited Create System Users
systemd-user-sessions.service loaded active exited Permit User Sessions
user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000
user-runtime-dir@1002.service loaded active exited User Runtime Directory /run/user/1002
user-website@1002.service loaded active exited User 1002 website service
user@1000.service loaded active running User Manager for UID 1000
user@1002.service loaded active running User Manager for UID 1002
➜ ~
```
It does list itself as active, thanks to the `RemainAfterExit` setting but how do we link our template service to the `user@.service` template?
## Overriding service files
Our `PartOf` setting links the shutdown of our service.
We can try this by logging alice back out.
The `user-website@1002.service` will stop but if we log back in it won't be started again!
```
➜ ~ sudo systemctl --type=service --no-pager | grep user
systemd-sysusers.service loaded active exited Create System Users
systemd-user-sessions.service loaded active exited Permit User Sessions
user-runtime-dir@1000.service loaded active exited User Runtime Directory /run/user/1000
user@1000.service loaded active running User Manager for UID 1000
➜ ~
```
In order to have the service start we need to attach it to the `user@.service file`.
Up until now we made our changes into the actual file but we can be smarter that that!
The service files supplied by Debian are very good and if they would make changes to them it would destroy *our* changes after an update.
To mitigate this we've been user `service.d/` directories and systemd has the same on an individual service level.
You can create the structure by hand but the *easiest* way is to use the built in `edit` subcommand to `systemctl`.
By invoking `sudo systemctl edit user@.service` your favorite text editor will open up with a blank file.
Here we'll add our additions to.
```
[Unit]
Requires=user-website@%i.service
```
We simply state that `user@.service` requires `user-website@.service` to start as well.
If we now inspect the service file of `user@.service` we see it sources it's configuration form **two** places.
One is the default `/usr/lib/systemd/system/user@.service`, which can be modified by upstream changes, the other one is in our classic `/etc/systemd/system/user@.service.d/override.conf` path.
```
➜ ~ sudo systemctl cat user@.service
# /usr/lib/systemd/system/user@.service
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or