diff --git a/.gitignore b/.gitignore index 367b238..8ac91c5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ /osbuild/ /contestops/certs/ -/contestops/backups* /contestops/local.known_hosts diff --git a/contestops/configure-machines.sh b/contestops/configure-machines.sh index c3d8fd6..470ec37 100755 --- a/contestops/configure-machines.sh +++ b/contestops/configure-machines.sh @@ -3,7 +3,7 @@ set -ex # Disable WiFi. -# parallel-ssh -x "-F local.ssh_config" -h hostlist nmcli radio wifi off +parallel-ssh -x "-F local.ssh_config" -h hostlist nmcli radio wifi off # Create hosts file so we don't need DNS. parallel-scp -x "-F local.ssh_config" -h hostlist ./config-hosts /etc/hosts diff --git a/contestops/readme.md b/contestops/readme.md index 14a3f5d..a9e5623 100644 --- a/contestops/readme.md +++ b/contestops/readme.md @@ -2,8 +2,8 @@ Here are instructions and various scripts and files for running contests. -The setup consists of a machine for each contestant, a machine running the grader, and an admin machine (e.g. your personal laptop). -All these should be connected through a network. +The setup consists of a machine for each contestant, a machine running the grader, and an admin machine. +All these should be connected through a network, preferably wired. The grader can be a machine accessible over the internet or in the local network. ## Grader setup @@ -17,7 +17,7 @@ sudo apt install ntpsec ``` Configure the grader to accept client certificates. -The CA certificate (`certs/ca.pem`) is generated as part of the admin setup below. +The CA certificate (`certs/ca.pem`) is generated as part of the admin setup. ## Contestant machine setup @@ -36,30 +36,15 @@ The OS is loaded into RAM during boot, so you can remove the stick once the boot ## Network setup If there is not already an existing network, you need to set it up yourself. -You can use either WiFi or wired Ethernet. -WiFi has the advantage that you don't need to bring and install all those Ethernet cables, and avoids the ugly cable mess. +Connect all contestant machines and the admin machine to a network switch with LAN cables. +If you use multiple switches, don't forget to also link the switches together. -**Ethernet:** -Connect all contestant machines and the admin machine to a network switch with Ethernet cables. -If you use multiple switches, don't forget to also link the switches together, such that the entire network forms a tree. +If the grader must be accessed over the internet, you can connect the admin machine to WiFi or USB tethering with a phone. +You can then share the internet with the local network. -**WiFi:** -The contestant OS already has a WiFi pre-configured. -The SSID is `contest`, and the password is configured in the `contestant_wifi_password` variable in `os/config/config.toml`. -Configure the access point with this SSID and password, and the machines will connect automatically. +If you have Gnome, go to Network settings, click on the gear on the Ethernet connection, go to IPv4 tab, and select "Shared to other computers". -For larger contests (10 or more contestants) it's recommended to use a dedicated device as the Internet router. -SOI has a FRITZ!Box 4040 which can be used for this. -Here, you can easily get the list of IP addresses of contestant machines from the web interface. -It's best to connect the admin machine to the router box over LAN instead of WiFi, such that admin traffic only takes one wireless hop instead of two. - -For smaller contests, you can also use the admin machine as a router. -For Ethernet, if you have Gnome, go to Network settings, click on the gear on the Ethernet connection, go to IPv4 tab, and select "Shared to other computers". -For WiFi, you can set up a WiFi hotspot in the WiFi settings. -However, with a hotspot enabled, Gnome does not let you connect to a WiFi network for Internet access at the same time, even though the hardware would in many cases support it. -Instead, you can connect a phone to WiFi and to your laptop with USB and enable USB tethering on the phone. - -If you have Docker installed, this doesn't work yet, because docker blocks routing. +If you have docker installed, this doesn't work yet, because docker blocks routing. You can fix it by running the following commands. ```bash @@ -96,8 +81,6 @@ sudo apt install golang-cfssl ./create-certs.sh ``` -## Before the contest - Edit `local.ssh_config` and create an entry with hostname and IP address for each contestant machine. You can get the IP address by running `ip addr` in a terminal on the contestant machine. @@ -135,16 +118,7 @@ Assign users to machines. ./assign-user.sh contestant02 binna1 ``` -You may want to test on one machine that the certificate was properly installed and the grader is accessible. -This should only be done after the machines are configured and users assigned, but with a contest lock start time before the current time. -You can then set the start time and apply the contest lock config again. - -```bash -parallel-scp -x "-F local.ssh_config" -h hostlist ./contest-lock.json /etc/contest-lock.json -``` - Start periodic backup of contestant machines. -Backups are stored every 2 minutes in the folder `backups`. ```bash ./backup-create.sh timer @@ -164,19 +138,6 @@ replacing `contestant03` in the commands below with the spare machine hostname. rsync -e "ssh -F local.ssh_config" -av --chown contestant:contestant backups/contestantxx/xxxx/ contestant03:/home/contestant/ ``` -## After the contest - -Stop the periodic backup command with Ctrl+C. -Rename the `backups` folder to e.g. `backups-day1`. - -You can shut down all machines. - -``` -parallel-ssh -x "-F local.ssh_config" -h hostlist poweroff -``` - -Machines should be shut down and booted again from USB stick between contests (e.g. between practice and actual contest) to ensure all data is erased. - ## Contest lock screen The contest lock screen is a gnome extension which can lock the screen and show a countdown until the contest starts. diff --git a/os/build.py b/os/build.py index 8bae320..a072ca8 100755 --- a/os/build.py +++ b/os/build.py @@ -138,8 +138,6 @@ def main(): # Add our own configuration on top. run(["cp", "-rT", f"{script_dir}/layers/participant", "config"]) - if args.variant != "training-installer": - run(["cp", "-rT", f"{script_dir}/layers/live", "config"]) run(["cp", "-rT", f"{script_dir}/layers/{args.variant}", "config"]) if args.variant == "training-installer": @@ -174,9 +172,6 @@ def main(): mkdir("config/includes.chroot/root/.ssh") run(["cp", f"{script_dir}/config/contestant_authorized_keys", "config/includes.chroot/root/.ssh/authorized_keys"]) - edit_file("config/includes.chroot/etc/NetworkManager/system-connections/contest.nmconnection", - lambda s: s.replace("@wifi_password@", config["contestant_wifi_password"])) - # Configure boot options. grub_boot_options = '\n'.join( f'menuentry "{option["label"]}" {{\n' diff --git a/os/config-example/config.toml b/os/config-example/config.toml index 13dc93b..ce0ff38 100644 --- a/os/config-example/config.toml +++ b/os/config-example/config.toml @@ -4,6 +4,3 @@ install_admin_password = "$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkb # Example password: soi contestant_root_password = "$y$j9T$h5VhMd4KkdmbxdZD1gO0N/$1hvwZgO8pQw13Xd6jaNXbtkbqVOC4W/ia/KXOcCGYvB" - -# WiFi passwords must be at least 8 characters -contestant_wifi_password = "12345678" diff --git a/os/layers/contestant/hooks/live/2010-contestant.hook.chroot b/os/layers/contestant/hooks/live/2010-contestant.hook.chroot index e65b6fd..1e82426 100755 --- a/os/layers/contestant/hooks/live/2010-contestant.hook.chroot +++ b/os/layers/contestant/hooks/live/2010-contestant.hook.chroot @@ -21,10 +21,10 @@ $DISABLE_DESKTOP /usr/share/applications/gnome-bluetooth-panel.desktop $DISABLE_DESKTOP /usr/share/applications/gnome-online-accounts-panel.desktop $DISABLE_DESKTOP /usr/share/applications/gnome-sharing-panel.desktop +# Enable the live system configuration script at boot. +systemctl enable live-config.service + # Disable kexec-tools services. # We want to load kexec manually, and execution of kexec is already done by systemd. systemctl disable kexec-load.service systemctl disable kexec.service - -# Restrict access to the config which contains the WiFi password. -chmod og= /etc/NetworkManager/system-connections/contest.nmconnection diff --git a/os/layers/contestant/includes.chroot/etc/NetworkManager/system-connections/contest.nmconnection b/os/layers/contestant/includes.chroot/etc/NetworkManager/system-connections/contest.nmconnection deleted file mode 100644 index eb3fe88..0000000 --- a/os/layers/contestant/includes.chroot/etc/NetworkManager/system-connections/contest.nmconnection +++ /dev/null @@ -1,20 +0,0 @@ -[connection] -id=contest -uuid=b4b09615-f7b9-4777-baa0-7812d58a01dd -type=wifi - -[wifi] -mode=infrastructure -ssid=contest - -[wifi-security] -auth-alg=open -key-mgmt=wpa-psk -psk=@wifi_password@ - -[ipv4] -method=auto - -[ipv6] -addr-gen-mode=default -method=auto diff --git a/os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock b/os/layers/contestant/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock similarity index 100% rename from os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock rename to os/layers/contestant/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock diff --git a/os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disallow-updates b/os/layers/contestant/includes.chroot/etc/dconf/db/local.d/00-disallow-updates similarity index 100% rename from os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disallow-updates rename to os/layers/contestant/includes.chroot/etc/dconf/db/local.d/00-disallow-updates diff --git a/os/layers/contestant/includes.chroot/etc/polkit-1/rules.d/50-lockdown.rules b/os/layers/contestant/includes.chroot/etc/polkit-1/rules.d/50-lockdown.rules index d349da9..16b8d86 100644 --- a/os/layers/contestant/includes.chroot/etc/polkit-1/rules.d/50-lockdown.rules +++ b/os/layers/contestant/includes.chroot/etc/polkit-1/rules.d/50-lockdown.rules @@ -7,8 +7,7 @@ polkit.addRule(function (action, subject) { if ( action.id.indexOf("org.freedesktop.ModemManager1.") === 0 || - (action.id.indexOf("org.freedesktop.NetworkManager.") === 0 && - action.id !== "org.freedesktop.NetworkManager.wifi.scan") || + action.id.indexOf("org.freedesktop.NetworkManager.") === 0 || action.id === "org.freedesktop.login1.hibernate" || action.id === "org.freedesktop.packagekit.system-network-proxy-configure" || action.id.indexOf("org.freedesktop.udisks2.") === 0 diff --git a/os/layers/live/includes.chroot/etc/systemd/system/live-config.service b/os/layers/contestant/includes.chroot/etc/systemd/system/live-config.service similarity index 100% rename from os/layers/live/includes.chroot/etc/systemd/system/live-config.service rename to os/layers/contestant/includes.chroot/etc/systemd/system/live-config.service diff --git a/os/layers/contestant/includes.chroot/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js b/os/layers/contestant/includes.chroot/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js index 92c3d37..d73ab3a 100644 --- a/os/layers/contestant/includes.chroot/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js +++ b/os/layers/contestant/includes.chroot/usr/share/gnome-shell/extensions/contest-lock@soi.ch/extension.js @@ -10,7 +10,6 @@ const { const Background = imports.ui.background; const Layout = imports.ui.layout; const Main = imports.ui.main; -const ScreenShield = imports.ui.screenShield; // half of the time for which a frame is displayed const HALF_FRAME_TIME_MS = 8; @@ -255,14 +254,6 @@ function activate () { return; } - // Monkeypatch disable regular lock screen deactivation. - // It is possible to trigger this function while contest lock is active, - // by pressing Ctrl+Alt+F1. This switches to GDM, which, after the automatic - // login timeout, switches back to our session and emits an Unlock signal. - // If we did not disable it here, this would then partially unlock the screen, - // such that you can interact with the Gnome Shell but not with applications. - ScreenShield.ScreenShield.prototype.deactivate = () => {}; - actor.show(); Main.sessionMode.pushMode('unlock-dialog'); diff --git a/os/layers/live/hooks/live/2005-live.hook.chroot b/os/layers/live/hooks/live/2005-live.hook.chroot deleted file mode 100644 index 6e1f34b..0000000 --- a/os/layers/live/hooks/live/2005-live.hook.chroot +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -eu - -# Enable the live system configuration script at boot. -systemctl enable live-config.service - -# Disable automatic apt update. -systemctl disable apt-daily.timer -systemctl disable apt-daily-upgrade.timer - -# Disable autostart of Gnome Software background process. -rm /etc/xdg/autostart/org.gnome.Software.desktop diff --git a/os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disable-search-providers b/os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disable-search-providers deleted file mode 100644 index 59e3763..0000000 --- a/os/layers/live/includes.chroot/etc/dconf/db/local.d/00-disable-search-providers +++ /dev/null @@ -1,4 +0,0 @@ -# Disable Gnome Software search provider. -# This is needed to stop Gnome Software from always running in the background. -[org/gnome/desktop/search-providers] -disabled = ['org.gnome.Software.desktop'] diff --git a/os/layers/live/includes.chroot/etc/skel/.config/Code/User/settings.json b/os/layers/live/includes.chroot/etc/skel/.config/Code/User/settings.json deleted file mode 100644 index bf438f9..0000000 --- a/os/layers/live/includes.chroot/etc/skel/.config/Code/User/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // Limit cache size to 800 MB to stop it from eating all your RAM. - "C_Cpp.intelliSenseCacheSize": 800 -} diff --git a/os/layers/participant/hooks/live/2000-participant.hook.chroot b/os/layers/participant/hooks/live/2000-participant.hook.chroot index a10bb88..ae7268e 100755 --- a/os/layers/participant/hooks/live/2000-participant.hook.chroot +++ b/os/layers/participant/hooks/live/2000-participant.hook.chroot @@ -32,10 +32,6 @@ for ext in *; do fi done popd -# Some extensions contain binaries which must be made executable. -# Because the files are now owned by root, extensions can't do that themselves. -# This just makes all files executable. -chmod --recursive +x /usr/local/lib/vscode-extensions/ # Enable codeblocks template. sed -i 's|// project wizards|RegisterWizard(wizProject, _T("soi"), _T("A SOI task"), _T("Console"));|' /usr/share/codeblocks/templates/wizard/config.script diff --git a/os/layers/participant/package-lists/participant.list.chroot b/os/layers/participant/package-lists/participant.list.chroot index a35a1c5..cac11fb 100644 --- a/os/layers/participant/package-lists/participant.list.chroot +++ b/os/layers/participant/package-lists/participant.list.chroot @@ -26,8 +26,6 @@ gcc g++ gdb ddd valgrind python3 pypy3 evince gnome-terminal konsole xterm byobu make cmake nautilus-extension-gnome-terminal file-roller -# video codecs for grader gifs -libavcodec59 # for drawing on screenshots drawing # documentation diff --git a/os/layers/training-live/hooks/live/2010-training-live.hook.chroot b/os/layers/training-live/hooks/live/2010-training-live.hook.chroot new file mode 100644 index 0000000..7398a8d --- /dev/null +++ b/os/layers/training-live/hooks/live/2010-training-live.hook.chroot @@ -0,0 +1,6 @@ +#!/bin/bash + +set -eu + +# Enable the live system configuration script at boot. +systemctl enable live-config.service diff --git a/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock b/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock new file mode 100644 index 0000000..e71be0e --- /dev/null +++ b/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disable-screensaver-lock @@ -0,0 +1,3 @@ +# Disable lock on blank screen +[org/gnome/desktop/screensaver] +lock-enabled = false diff --git a/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disallow-updates b/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disallow-updates new file mode 100644 index 0000000..556d13c --- /dev/null +++ b/os/layers/training-live/includes.chroot/etc/dconf/db/local.d/00-disallow-updates @@ -0,0 +1,5 @@ +# Disable "Updates available" notifications and auto updates. +# Updates which require reboot are useless on live systems, +# and other updates would be installed on each boot. +[org/gnome/software] +allow-updates = false diff --git a/os/layers/training-live/includes.chroot/etc/systemd/system/live-config.service b/os/layers/training-live/includes.chroot/etc/systemd/system/live-config.service new file mode 100644 index 0000000..a8b5058 --- /dev/null +++ b/os/layers/training-live/includes.chroot/etc/systemd/system/live-config.service @@ -0,0 +1,14 @@ +[Unit] +Description=custom configuration of live system during boot. +Before=basic.target +After=local-fs.target systemd-tmpfiles-setup.service +DefaultDependencies=no +ConditionKernelCommandLine=boot=live + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/live-config + +[Install] +WantedBy=basic.target diff --git a/os/readme.md b/os/readme.md index 9fc0411..2da5b13 100644 --- a/os/readme.md +++ b/os/readme.md @@ -93,10 +93,9 @@ Here is a list of features. - timezone - list of locales - bootloader background image -- `live` (all live variants) +- `training-live` - disable lock on blank screen - disable software update notifications -- `training-live` - automatic login - sudo without password - `training-installer` @@ -112,6 +111,8 @@ Here is a list of features. - `contestant` - disable bluetooth - disable sleep + - disable lock on blank screen + - disable software update notifications - disable some panels in gnome-control-center - disable automatic mounting of storage media - polkit rules which block changing network settings and mounting storage media (it prompts for the root password) @@ -119,7 +120,6 @@ Here is a list of features. - install and configure ssh server - set root password - set `authorized_keys` for root - - contest WiFi connection - automatic login - set browser homepage and bookmarks to https://contest.soi.ch - Gnome Shell extension which displays the user name in the top bar