2025-06-26-13-33-49: Cronjob

This commit is contained in:
lmn-client 2025-06-26 13:33:49 +02:00
commit 29049c8da1
127 changed files with 7089 additions and 0 deletions

50
doc/custom_roles.md Normal file
View file

@ -0,0 +1,50 @@
# Custom roles
- Custom ansible roles can be stored in `roles/custom`
- To include custom roles, you can list them in `custom_roles`.
## Configuration / Variables
* **custom_roles**
List of roles which will be applied
Type: *List of Strings*
Default: []
## Example
All hosts (e.g. 10.0.2.14) will get `role_a` and `role_c`,
but hosts in group laptop (e.g. 10.0.32.14) will get `role_a` and `role_b`
```
roles/custom/
├── role_a
│   └── tasks
│   └── main.yml
├── role_b
│   └── tasks
│   └── main.yml
└── role_c
└── tasks
└── main.yml
```
inventory.yml
```yaml
all:
vars:
custom_roles:
- role_a
- role c
desktops:
hosts:
10.0.2.[1:128]:
laptops:
hosts:
10.0.32.[1:50]:
vars:
custom_roles:
- role_a
- role_b
```

27
doc/exam_mode.md Normal file
View file

@ -0,0 +1,27 @@
# exam_mode
## Description / use cases
Activating exam_mode provides following functionalities:
* when -exam user logs in, firewalld.service will start and prevent communication between devices in the same local network
* home- and media-directory of -exam users will be renamed (on the next day) and removed (after some days).
This is important due the fact, that -exam user will be new created (with new user-id) on exam-mode initialisation.
Without renaming/deleting the home- and media-directory, the -exam user couldn't log in twice on the same pc.
Particularly important on machines with localhome
## Requirements
none
## Example
Per default, all hosts will get exam_mode. But we don't want exam_mode on teacher devices
inventory.yml
```
teacherdevices:
hosts:
10.0.14.[1..75]
vars:
exam_mode: false
```

61
doc/install_ontop.md Normal file
View file

@ -0,0 +1,61 @@
# Installation on existing client
A straightforward way to test the lmn-client is to manually run the playbook on a freshly installed client.
This can be done in the following ways:
On the client using ansible-pull
On the client by checking out the lmn-client repository and running the playbook locally
On a target device by checking out the lmn-client repository locally and executing the playbook against the target device
## Direct call via ansible-pull
With two simple commands you can install the lmn-client with default configuration.
Steps:
* Install debian on client (via USB or PXE)
* Install additional packages: ansible
`sudo apt install ansible`
* Run Playbook
`sudo ansible-pull --verbose -i inventory-sample.yml -l localhost --url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git -C main lmn-client.yml`
## Checkout git and run ansible locally
When checking out the repository you can customize the installation by editing the inventory before run the playbook.
You can repeat the process as often as you like and gradually adapt your inventory settings to your needs.
Steps:
* Install debian on client (via USB or PXE)
* Install additional packages: ansible, git
`sudo apt install ansible git`
* Checkout Repository
`git clone https://codeberg.org/DigitalSouveraeneSchule/lmn-client.git`
* Change into repository directory
`cd lmn-client`
* Create inventory
`cp inventory-sample.yml inventory-myschool.yml`
* Edit inventory-myschool.yml
e.g.: `nano inventory-myschool.yml`
* Run Playbook
`ansible-playbook -i inventory-myschool.yml -l localhost lmn-client.yml`
## Run with other target device
If you want to run the play on an other target pc:
* You have to add the target IP or hostname in the inventory.
* SSH access on target must be configured (deploy ssh public-key on target host)
`ansible-playbook -i inventory-myschool.yml -l target lmn-client.yml`
## Upload changes to your own remote repository
If you are satisfied with your changes, you can upload the changes to your own remote repository.
* Create new git repository on your git service (e.g. https://codeberg.org)
* Add new remote origin
`git remote add myorigin git@codeberg.org:myname/mylmn-client.git`
* Push the repository to the new remote
`push -u myorigin main`

114
doc/install_pxe.md Normal file
View file

@ -0,0 +1,114 @@
# Installation via PXE/Grub
* **Using DigitalSouveraeneSchule repository and LinuxMuster.Net tftp**
Simplest solution. Playbook and default inventory from DigitalSouveraeneSchule codeberg repository.
Linux kernel and initial Ramdisk from debian repository.
Client must have access to the internet (noproxy group).
* **Using your own repository and LinuxMuster.Net tftp**
Here you can use your own inventory and make many custom settings.
Linux kernel and initial Ramdisk from debian repository.
Client must have access to the internet (noproxy group).
* **Using your own repository and livebox tftp**
Additional kernel and Ramdisk from your own infrastrukture.
Client does not need direct internet access.
## Using codeberg repository and LinuxMuster.Net tftp
### Requirements / firewall settings
The computer on which the linuxclient is to be installed must have access to the Internet (add host to noproxy group)
The following resources are downloaded from the internet:
* The repository is provided by codeberg.org
* the Linux kernel, the initial ramdisk and the installation files are loaded from debian.org.
* mscorefonts from Microsoft
### Modification LinuxMuster.Net server
Create grub config for device group `lmnclient` on your schools server:
/srv/linbo/boot/grub/lmnclient.cfg
```
# ### NOT managed by linuxmuster.net ###
# edit to your needs
set default=1
menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' {
echo -n "Enter domain join password: "
read adpw
set vaultpw="dummy"
# echo -n "Enter vault password"
# read vaultpw
linux (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux auto=true priority=high \
url=https://codeberg.org/DigitalSouveraeneSchule/lmn-client/raw/branch/main/misc/preseed.cfg interface=auto \
playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" ---
initrd (http,ftp.debian.org)/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
}
```
Insert host in devices.csv and set device group to `lmnclient`:
devices.csv
```
classroom;mypc01;lmnclient;F2:81:6B:C9:E3:EF;10.0.5.51;;;;classroom-studentcomputer;;1;;;;;
```
### On client PC
* In BIOS-Setting: Set boot to UEFI
* Start via PXE
* When asked for domain-join-password: Enter password of `global-admin`
* confirm `hostname` and `domain` (you will be asked in network setup)
* ... Get a cup of coffee ... wait until reboot ... login (Logging in may take a few minutes after installation)
## Using your own repository and LinuxMuster.Net tftp
If you fork the lmn-client repository, you can customize the preseeding and inventory to your needs.
Use the instructions in the previous section and customize the repository in `/srv/linbo/boot/grub/lmnclient.cfg`.
It makes sense to encrypt your inventory via `ansible-vault`.
When using encrypted inventories you have to provide the vault password by commenting in the two lines in the `/srv/linbo/boot/grub/lmnclient.cfg`.
## Using your own repository and livebox tftp
The next improvement will be to use your own livebox with following functionalities:
* Providing linux kernel and initial ramdisk for installer
* Can be used as cache for debian packages (aptcacher)
* Can provide mscorefonts and libdvdcss (multimedia codecs)
* Can be used to boot live systems (netboot) via pxe
### Installing the livebox server
* Install debian VM and configure network
* Install additional packages: ansible
`sudo apt install ansible`
* Run livebox playbook
`ansible-pull -i localhost, --url=https://salsa.debian.org/andi/debian-lan-ansible.git -C master livebox.yml`
* Set DNS entry for your new livebox server
### Modification LinuxMuster.Net server
The file `/srv/linbo/boot/grub/lmnclient.cfg` might look like this:
```
# ### NOT managed by linuxmuster.net ###
# edit to your needs
set default=1
menuentry 'Installer Debian bookworm (amd64) + preseed + ansible inventory' {
echo -n "Enter domain join password: "
read adpw
set vaultpw="dummy"
# echo -n "Enter vault password"
# read vaultpw
linux (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/linux auto=true priority=high \
url=https://codeberg.org/MySchool/lmn-client/raw/branch/main/misc/preseed-myschool.cfg interface=auto \
playbook=lmn-client.yml adpw="${adpw}" vaultpw="${vaultpw}" ---
initrd (http,livebox.example.com)/d-i/n-pkg/images/12/amd64/text/debian-installer/amd64/initrd.gz
}
```

64
doc/localhome.md Normal file
View file

@ -0,0 +1,64 @@
# localhome
## Description / Use cases
Sometimes a local home directory makes more sense than the home on a network share.
For example, with:
* Laptops with Wi-Fi connectivity
* Laptops that are also used outside the school network (e.g., teacher devices)
* Devices assigned to a specific user who synchronizes data using a sync client
## Requirements
Nothing
## Activation / Default
To enable the local home directory, set the variable `localhome` to `true` (default: false).
## Configuration / Variables
* **localhome**
This flag indicates whether to use home on local disk.
If set to `true` local user's home will be on local disk.
Type: *Boolean*
Values:
* `false` <-- (default)
* `true`
* **localhome_logout_missing_serverhome**
If this flag is set to `true`, the user will be logged out if mounting the serverhome failed.
Sometimes mounting the server homes fails, but the user still logs in.
For laptops used in schools, it's better to force the server home.
For teacher devices that can also be used outside of school, this flag must not be set.
Type:: *Boolean*
Values:
* `false`
* `true` <-- (default)
## Example
* Hosts in group `laptops` will get the localhome. Teacherlaptops will be part of the `laptop` group (children-entry).
* All computers in the desktop group, except the PC with IP address 10.0.2.33, will have their home directory on the network (default).\
The PC with IP address 10.0.2.33 also has a local home directory.
* Hosts in group `desktop` will have home on net (default).
* If mounting the server home fails on a local home device (except for teacher devices), the user is automatically logged out.
inventory.yml
```
laptops:
hosts:
10.0.1.[1-64]:
children:
teacherlaptops
vars:
localhome: true
teacherlaptops:
hosts:
10.0.3.[1-32]:
vars:
localhome_logout_missing_serverhome: false
desktops:
hosts:
10.0.2.[1-32]:
10.0.2.33:
localhome: true
10.0.2.[34-64]:
```

44
doc/localproxy.md Normal file
View file

@ -0,0 +1,44 @@
# Local http proxy
Some clients encounter difficulties with Kerberos authentication on the HTTP proxy server. To address this issue, we propose setting up a local Squid HTTP proxy that operates as a systemd process in user kontext. This local proxy will authenticate with the parent proxy using the user's Kerberos ticket. Additionally, this setup is ideal for accessing the parent proxy from virtual machines as anonymous user.
The decision to install the local proxy is contingent upon the value of the variable `localproxy`.
Choices:
* `false` <- (default)
* `true`
The parent proxy can be set with the variable `localproxy_parent`.
Default: `firewall.{{ domain }}`
## Configuration / Variables
* **localproxy**
This flag indicates whether to install the local proxy.
If set to `true` local Squid proxy will be installed.
Type: *Boolean*
Values:
* `false` <-- (default)
* "username"
* **localproxy_parent**
This variable specifies the name of the parent HTTP proxy that accepts the user's Kerberos ticket.
Default: "firewall.{{ domain }}"
Type: *String*
## Example
* Enable the local proxy on all devices.
* The parent proxy will be set to `firewall.{{ domain }}` (default).
inventory.yml
```yaml
all:
vars:
localproxy: true
classrooms:
hosts:
10.0.10.[1:80]
```

58
doc/localuser.md Normal file
View file

@ -0,0 +1,58 @@
# Local guest user
Creates a local guest user with home on tmpfs.
The decision whether a guest user is created depends on the value of the variable `localuser`.
Choices:
* `false` <- (default)
* `"username"`
The associated password can be determined using the variable `localuser_password`.
Default: `Muster!`
## Configuration / Variables
* **localuser**
Username of local guest account
If set to `false` no user will be created
Type: *String*/*Boolean*
Values:
* `false` <-- (default)
* "username"
* **localuser_password**
Password of local guest user
Default: "Muster!"
Type: *String*
* **localuser_secretsalt**
Salt for creation of password hash
Default: "4ANAxPycC3q"
Type: *String*
## Example
* Create local guest user only on devices in group laptops.
* Devices in group teacherlaptop will not get a local guest user, even though they are part of the laptop group..
* Username: guestuser
* Password: topsecret
inventory.yml
```yaml
laptops:
hosts:
10.0.14.[1:40]
children:
teacherlaptops
vars:
localuser: guestuser
localuser_password: topsecret
teacherlaptops:
hosts:
10.0.20.[1:80]
vars:
localuser: false
```

56
doc/misc_clonescreen.md Normal file
View file

@ -0,0 +1,56 @@
# CloneScreen on PresenterPCs
Presentation PCs have a habit of displaying the primary screen on the wrong device. Furthermore, the workspace is extended by default instead of mirrored.
These issues can be resolved using the 'misc_clonescreen' variable.
If the login screen appears on the wrong device, this can be corrected using the `dual_screen` variable.
Furthermore, the display devices are mirrored by default instead of extended.
If the cabling does not properly support large screen resolutions, the desired resolution and refresh rate can be set.
## Configuration / Variables
* **misc_clonescreen**
This flag indicates whether to prepare clonescreen mode.
If set to `true` clonescreen will be default.
Type: *Boolean*
Values:
* `false` <-- (default)
* "username"
* **misc_clonescreen_mode**
This variable specifies the resolution and frequency of display.
Default: "1920x1080@60"
Type: *String*
* **dual_screen**
Array with X11 and Wayland naming of desired primary display.
Type: *String*
Example: [DisplayPort-3, DP-4]
* **audio_output**
Array of audio-output device to be selected.
Example: [pci-0000_00_1f.3, analog-stereo]
## Example
* Hosts in group `classroom` will be clonescreen PCs.
* Screen will be cloned and mode 1920x1080@60 (default) will be selected.
* On host with IP 10.0.2.80 screen resolution is limited to 1024x768 at 60 Hertz
* Audio output HDMI (default) is selected.
* On host with IP 10.0.5.80 audio out is preset to analog-stereo
* On Hosts with IP 10.0.3.80 primary screen will be swapped to device with name `DisplayPort-3` (X11) / `DP-4` (Wayland)
inventory.yml
```
classroom:
hosts:
10.0.2.80:
misc_clonescreen_mode: 1024x768@60
10.0.3.80:
dual_screen: [DisplayPort-3, DP-4]
10.0.4.80:
10.0.5.80:
audio_output: [pci-0000_00_1f.3, analog-stereo]
10.0.6.80:
vars:
misc_clonescreen: true
```

44
doc/vm_support.md Normal file
View file

@ -0,0 +1,44 @@
# VM support
lmn_client provides scripts to
* create
* modify
* distribute
* run
VMs based on Qemu/KVM in school network.
## Requirements
* For distribution of VMs, you have to run a `seedbox` with aria2 server (torrent server).
Repository with ansible-playbook for seedbox install: https://codeberg.org/digitalsouveraeneschule/...
* `seedbox`-hostname must be resolvable via DNS
## Configuration / Variables
* **vm_support**
This flag indicates whether to activate VM support.
Type: *Boolean*
Values:
* `false` <-- (default)
* `true`
* **vm_torrent_serv**
Name of the torrent server.
Type: *String*
Default: `vm_torrent_serv: "seedbox.{{ domain }}"`
* **vm_uploadseed_pwd**
Password for upload-seed. Used for image upload to torrent-server.
Type: *String*
Default: `secret = "token:topsecret"`
## Example
Enable VM support on all clients.
inventory.yml
```
all:
vars:
vm_support: true
vm_torrent_serv: "myseedbox.linuxmuster.net" # default: seedbox.{{ domain }}
```

46
doc/vpn.md Normal file
View file

@ -0,0 +1,46 @@
# VPN
Provides VPN access to school network via
- Wireguard
Which vpn method is used is determined by the variable `vpn`
Choices:
* `"none"` <- (default)
* `"wg"`
## Description / use cases
* This module provides a NetworkManager Config with valid wireguard credentials.
* Private/public keys will be created and configured on wireguard-server.
* After VPN-connection is established, network shares will be connected and printers will be installed too.
## Requirements
* You need to run a wireguard server. For installation see https://codeberg....
* The user, running this playbook, must have access to the wireguard-Server via ssh.
## Example
VPN profile will be created on teacher devices
inventory.yml
```yaml
infrastructure:
hosts:
wg_server:
ansible_host: 10.0.0.16
ansible_user: ansible
teacherdevices:
hosts:
10.0.14.[1..75]
vars:
vpn: wg
wg_endpoint: "203.0.113.1:51820"
wg_allowed_ips: "10.0.0.0/16;"
wg_ip_cdr: 24
wg_dns: "9.9.9.9"
wg_dns_search: "example.com"
```

190
doc/wlan.md Normal file
View file

@ -0,0 +1,190 @@
# WLAN support
Supported modes authenticating via WLAN:
* **WPA-Personal** (WPA-PSK)
authentication via preshared key (psk)
* **WPA-Enterprise** (WPA-802.1x) with **EAP-TLS**
authentication via client certificates (eap-tls)
Which method is used is determined by the variable `wlan`
Choices:
* `"none"` <- (default)
* `"psk"`
* `"eap-tls"`
## Common Configuration / Variables
* **wlan**
Authentication mode
Type: *String*
Values:
* "none" <-- (default)
* "psk" <-- set to use WPA-Personal
* "eap-tls" <-- set to use WPA-Enterprise with EAP-TLS
* **wlan_ssid**
SSID of used WLAN
Type: *String*
* **wlan_enable_on_boot**
If set to `true` wlan will be enabled on boot
Type: *Boolean*
Default: `true`
## WPA-Personal
### Requirements
WLAN with configured WPA-Personal (WPA-PSK)
### Additional Configuration / Variables
* **wlan_password**
Password of WLAN. Only for `wlan: "psk"`
Type: *String*
### Examples
#### One class of devices with wlan access
inventory.yml
```yaml
laptop:
hosts:
10.0.13.[1-28]:
vars:
wlan: "psk"
wlan_ssid: "devicesPSK"
wlan_password: "topsecretpasswd"
```
#### Two device classes with different wlan access
inventory.yml
```yaml
laptop_students:
hosts:
10.0.13.[1-28]:
vars:
wlan: "psk"
wlan_ssid: "Students"
wlan_password: "topsecretpasswd1"
laptop_teachers:
hosts:
10.0.23.[1-82]:
vars:
wlan: "psk"
wlan_ssid: "Teachers"
wlan_password: "topsecretpasswd2"
```
## WPA-Enterprise with EAP-TLS
Authentication is based on individual certificates, which will be automaticaly created on the radius server.
Every devices gets his own certificate. When creating new certificates, the old one will be revoked.
### Requirements
* You need to run a freeradius server. For installation see https://codeberg....
* The user, running this playbook, must have access to the radius-Server via ssh.
### Additional Configuration / Variables
* **wlan_eap_ca**
CA data for certs and crl
Type: *Dictionary of Strings*Keys:
* C <-- default: "DE"
* ST <-- default: "Baden-Wuerttemberg"
* L <-- default: "Reutlingen"
* O <-- default: "Linuxschule"
* emailAddress <-- default: "admin@example.com"
* CN <-- default: "Radius Certificate Authority"
* password <-- default: "OtherVerySecurePassw0rd"
* **wlan_force_issue**
Force to issue a new certificateOnly for `wlan: "eap-tls"`
Type: *Bolean*
Values:
* true
* false <-- (default)
* **wlan_eap_ca_crl**
URL of the certificate revocation list
Type: *String*
Default: "http://radius.{{ domain }}/radius-ca.crl"
### Examples
inventory.yml:
```yaml
infrastructure:
hosts:
radius_server:
ansible_host: 10.0.0.15
ansible_user: ansible
laptop:
vars:
wlan: "eap-tls"
wlan_ssid: "devices8021x"
wlan_eap_ca:
C: "DE"
ST: "Baden-Wuerttemberg"
L: "Reutlingen"
O: "Linuxschule"
emailAddress: "admin@example.com"
CN: "Radius Certificate Authority"
password: "secret4radiusCA"
wlan_eap_ca_crl: "http://radius.example.com/radius-ca.crl"
```
## complex example with both modes
We have three groups of devices (one with psk, two with eap-tls):
inventory.yml
```yaml
all:
vars:
wlan_ssid: "WLAName" # teacher and staff are using the same ssid
wlan_eap_ca:
C: "DE"
ST: "Baden-Wuerttemberg"
L: "Reutlingen"
O: "Linuxschule"
emailAddress: "admin@example.com"
CN: "Radius Certificate Authority"
password: "secret4radiusCA"
wlan_eap_ca_crl: "http://radius.example.com/radius-ca.crl"
infrastructure:
hosts:
radius_server:
ansible_host: 10.0.0.15
ansible_user: ansible
laptop_students:
hosts:
10.0.13.[1-28]:
vars:
wlan: "psk"
wlan_ssid: "Students" # ssid "WLAN" from group "all" will be overwritten
wlan_password: "topsecretpasswd"
laptop_teachers:
hosts:
10.0.23.[1-82]:
vars:
wlan: "eap-tls"
wlan_enable_on_boot: false
laptop_staff:
hosts:
10.0.61.[1-20]:
vars:
wlan: "eap-tls"
```
## example: Force issue of new certs
The issue of certificates can be forced.
Force issue of new certs for hosts in group laptop_teacher.
If there is a valid certificate, the old one will be revoked and a new certificate will be issued.
ansible-playbook -i myinventory.yml -l laptop_teachers lmn-client.yml -e "wlan_force_issue=true"