diff --git a/.gitignore b/.gitignore index a5b1276..afde515 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ *.iso configs/ssh* group_vars/all +venv/ +printer-configs/ +environment.cloudcontest.org/ diff --git a/build-final.sh b/build-final.sh index 7ce0fea..fdafa4a 100755 --- a/build-final.sh +++ b/build-final.sh @@ -64,7 +64,7 @@ function waitforssh() { fi } -qemu-system-x86_64 -smp 1 -m 1024 -drive file="$IMGFILE",index=0,media=disk,format=raw -global isa-fdc.driveA= --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --daemonize --pidfile $PIDFILE -vnc :0 -vga qxl -spice port=5901,disable-ticketing -usbdevice tablet +qemu-system-x86_64 -smp 2 -m 4096 -drive file="$IMGFILE",index=0,media=disk,format=raw -global isa-fdc.driveA= --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --daemonize --pidfile $PIDFILE -vnc :0 -vga qxl -spice port=5901,disable-ticketing -usbdevice tablet ALIVE=0 waitforssh diff --git a/configs/2204_autoinstall.yaml b/configs/2204_autoinstall.yaml index adbf3e2..43bc727 100644 --- a/configs/2204_autoinstall.yaml +++ b/configs/2204_autoinstall.yaml @@ -67,6 +67,25 @@ autoinstall: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9pjASmP4wQkhJ1VEbl0l1Vgn3lsOzctRS2m0wBVlaO ICPC ImageAdmin Key allow-pw: yes + # failures at removing snap...sigh + # install the minimal version (see casper/install-sources.yaml on the iso) + # This avoids snapd being installed + # source: + # id: ubuntu-server-minimal + + # try something else to disable snapd (remove it from the installer?) + # Can't do this, subiquity (the installer) is a snap + # early-commands: + # - apt-get autoremove -y --purge snapd + + # Tried to disable snapd from being installed, and while this preference _is_ added properly, + # it doesn't actually work. + # apt: + # preferences: + # - package: snapd + # pin: release * + # pin-priority: -1 + packages: [] # updates: all # install all updates after the installer finishes (default 'security') updates: security # install all updates after the installer finishes (default 'security') @@ -74,14 +93,26 @@ autoinstall: # Fix the filesystem type of the icpc fat32 partition (curtain sets it to "Linux filesystem", even though we specify partition_type) - sfdisk --part-type /dev/sda 3 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 # TAG:USB_PARTITION_ENABLED + # This fixes a weird issue with qemu not wanting to boot the system unless you + # hold down shift, and manually pick the os to boot. + # Disable graphical grub console + # - sed -i -e 's/#\(GRUB_TERMINAL.*\)/\1/' /target/etc/default/grub + # Enable passwordless sudo - echo '%sudo ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/icpc + # TODO: what was the value of GRUB_CMDLINE_LINUX before this line nukes it? - cp /target/etc/default/grub /target/etc/default/grub.orig - sed -ie 's/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="net.ifnames=0"/' /target/etc/default/grub # Do these matter(or did they get nuked above?) - sed -ie 's/quiet splash//' /target/etc/default/grub - curtin in-target update-grub2 + # This also fails to remove snapd for some reason or another: + # https://gist.github.com/s3rj1k/55b10cd20f31542046018fcce32f103e?permalink_comment_id=4429378#gistcomment-4429378 + # - curtin in-target apt-get -y -q purge snapd + + # The original version of subiquity had a bug where specifying --target /target was required + # - curtin in-target --target /target update-grub2 # Poweroff because otherwise it'll reboot - poweroff diff --git a/configs/2404_autoinstall.yaml b/configs/2404_autoinstall.yaml new file mode 100644 index 0000000..04f2bd6 --- /dev/null +++ b/configs/2404_autoinstall.yaml @@ -0,0 +1,119 @@ +#cloud-config + +# Set up ssh/sudo access to the installer environment(so debugging any issues during installation is possible) +users: + - name: default + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9pjASmP4wQkhJ1VEbl0l1Vgn3lsOzctRS2m0wBVlaO ICPC ImageAdmin Key + - name: imageadmin + sudo: 'ALL=(ALL) NOPASSWD:ALL' + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9pjASmP4wQkhJ1VEbl0l1Vgn3lsOzctRS2m0wBVlaO ICPC ImageAdmin Key + +# Try to add a key elsewhere to enable login... +ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9pjASmP4wQkhJ1VEbl0l1Vgn3lsOzctRS2m0wBVlaO ICPC ImageAdmin Key + +# Docs on autoinstall are found here: https://ubuntu.com/server/docs/install/autoinstall-reference +# Additional useful resources: +# https://utcc.utoronto.ca/~cks/space/blog/linux/Ubuntu2004ISOAutoinst - how to bundle autoinstall with the cdrom +# https://utcc.utoronto.ca/~cks/space/blog/linux/Ubuntu2004AutoinstFormat - good example of autoinstall setup +autoinstall: + version: 1 + # Locale and keyboard layout + locale: en_US.UTF-8 + keyboard: + layout: us + variant: '' + toggle: null + timezone: America/New_York + network: + version: 2 + ethernets: + # We disable persistent network interface naming on the kernel command line, so this is always eth0 + eth0: {dhcp4: true} + storage: + version: 2 + # Disable swap + swap: {size: 0} + config: + # Docs on this section are found here: https://curtin.readthedocs.io/en/latest/topics/storage.html + # This makes 4 partitions + # 1 - bios_grub (space for grub stage2 to live) 1MiB + # 2 - EFI partition + # 3 - ICPC fat32 partition (to make files easy to load after the contest ends without booting the usb drive) + # 4 - linux root partition + - {type: disk, id: disk0, grub_device: true, ptable: gpt, wipe: superblock-recursive} + - {type: partition, device: disk0, number: 1, id: partition-bios, flag: bios_grub, size: 1M} + - {type: partition, device: disk0, number: 2, id: partition-efi, flag: boot, size: 128M} + - {type: partition, device: disk0, number: 3, id: partition-icpc, partition_type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name: icpc, size: 192M} # TAG:USB_PARTITION_ENABLED + - {type: partition, device: disk0, number: 4, id: partition-root, flag: linux, size: -1} + - {type: format, volume: partition-efi, id: format-efi, fstype: fat32, label: EFI} + - {type: format, volume: partition-icpc, id: format-icpc, fstype: fat32, label: ICPC} # TAG:USB_PARTITION_ENABLED + - {type: format, volume: partition-root, id: format-root, fstype: ext4, extra_options: ['-m', '0']} + - {type: mount, device: format-efi, id: mount-efi, path: /boot/efi} + # Set commit=60, to help improve performance + - {type: mount, device: format-root, id: mount-root, path: /, options: 'noatime,nodiratime,errors=remount-ro,commit=60'} + identity: + hostname: icpc + username: imageadmin + # This crypted password corresponds to 'imageadmin' + password: $6$D1vml7SluH/Pfw43$upy5UKqf6iZtLGXRXcAUAqCDMpFMWiZcve9tj16/5l1eD8j5YWoVYCmLvxl6eXrRmSKSngIiH5.NJBNMx.SZg0 + + # Set up ssh with a public key we'll use to bootstrap the rest of the system + ssh: + install-server: yes + authorized-keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB9pjASmP4wQkhJ1VEbl0l1Vgn3lsOzctRS2m0wBVlaO ICPC ImageAdmin Key + allow-pw: yes + + # failures at removing snap...sigh + # install the minimal version (see casper/install-sources.yaml on the iso) + # This avoids snapd being installed + # source: + # id: ubuntu-server-minimal + + # try something else to disable snapd (remove it from the installer?) + # Can't do this, subiquity (the installer) is a snap + # early-commands: + # - apt-get autoremove -y --purge snapd + + # Tried to disable snapd from being installed, and while this preference _is_ added properly, + # it doesn't actually work. + # apt: + # preferences: + # - package: snapd + # pin: release * + # pin-priority: -1 + + # Install packages for efi secure boot + packages: + - grub-efi + - grub-efi-amd64-signed + - shim-signed + + # updates: all # install all updates after the installer finishes (default 'security') + updates: security # install all updates after the installer finishes (default 'security') + late-commands: + # Fix the filesystem type of the icpc fat32 partition (curtain sets it to "Linux filesystem", even though we specify partition_type) + - sfdisk --part-type /dev/sda 3 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 # TAG:USB_PARTITION_ENABLED + + # Enable passwordless sudo + - echo '%sudo ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/icpc + # TODO: what was the value of GRUB_CMDLINE_LINUX before this line nukes it? + - cp /target/etc/default/grub /target/etc/default/grub.orig + - sed -ie 's/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="net.ifnames=0"/' /target/etc/default/grub + # Do these matter(or did they get nuked above?) + - sed -ie 's/quiet splash//' /target/etc/default/grub + + - curtin in-target update-grub2 + + # Make sure uefi/secure boot is ready to go + - curtin in-target -- grub-install --no-nvram --uefi-secure-boot --target=x86_64-efi /dev/sda + + # This also fails to remove snapd for some reason or another: + # https://gist.github.com/s3rj1k/55b10cd20f31542046018fcce32f103e?permalink_comment_id=4429378#gistcomment-4429378 + # - curtin in-target apt-get -y -q purge snapd + + # Poweroff because otherwise it'll reboot + - poweroff diff --git a/configs/2404_metadata b/configs/2404_metadata new file mode 100644 index 0000000..6df6d07 --- /dev/null +++ b/configs/2404_metadata @@ -0,0 +1 @@ +hostname: icpc diff --git a/create_baseimg.sh b/create_baseimg.sh index ac02f8a..b19c1ca 100755 --- a/create_baseimg.sh +++ b/create_baseimg.sh @@ -1,18 +1,18 @@ #!/bin/bash # Settings -ISO64="ubuntu-22.04.3-live-server-amd64.iso" +ISO64="ubuntu-24.04.1-live-server-amd64.iso" OUT64="unattended-${ISO64}" IMG64="base-amd64.img" TMPDIR="tmp" -USERDATA="configs/2204_autoinstall.yaml" -METADATA="configs/2204_metadata" +USERDATA="configs/2404_autoinstall.yaml" +METADATA="configs/2404_metadata" function usage() { echo "Usage: create_baseimage.sh [-s size]" echo "" - echo "-s|--size n Size of the resulting image(default 14700M)" + echo "-s|--size n Size of the resulting image(default 28500M)" echo "--no-usb Don't create a fat32 partition for easy usb mounting" exit 1 } @@ -79,6 +79,7 @@ function create_unattended_iso() { sed -i -e "/USB_PARTITION_ENABLED/d" "$CONTENTSDIR/autoinst/user-data" fi + # TODO: skip all this isolinux stuff, and change boot/grub/grub.cfg instead # Configure grub to start the autoinstall after 3 seconds cat < "$CONTENTSDIR/boot/grub/grub.cfg" @@ -95,7 +96,36 @@ menuentry "Install Ubuntu Server (Unattended)" { initrd /casper/initrd } EOF + + # Skip language selection menu +# chmod u+w $CONTENTSDIR/isolinux +# echo "en" > "$CONTENTSDIR/isolinux/lang" + +# cat < "$CONTENTSDIR/isolinux/txt.cfg" +# default install +# label install +# menu label ^Install Ubuntu Server (Unattended) +# kernel /casper/vmlinuz +# append initrd=/casper/initrd autoinstall ds=nocloud-net;seedfrom=/cdrom/autoinst/ net.ifnames=0 -- +# label memtest +# menu label Test ^memory +# kernel /install/mt86plus +# EOF + +# cat < "$CONTENTSDIR/isolinux/isolinux.cfg" +# # D-I config version 2.0 +# path +# include menu.cfg +# default vesamenu.c32 +# prompt 0 +# # 2.5 seconds +# timeout 25 +# ui gfxboot bootlogo +# EOF +# echo "en" > "$CONTENTSDIR/isolinux/lang" + set -x + # mkisofs -r -V "ATTENDLESS_UBUNTU" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -quiet -o $OUTISO $CONTENTSDIR # Finally pack up an ISO the new way xorriso -as mkisofs -r \ @@ -116,6 +146,8 @@ EOF $CONTENTSDIR set +x + # exit 1 + # cleanup rm -rf "$CONTENTSDIR" } diff --git a/files/firstboot.service b/files/firstboot.service index 44f54e5..c7b06d1 100644 --- a/files/firstboot.service +++ b/files/firstboot.service @@ -14,6 +14,9 @@ StandardInput=tty StandardOutput=tty ExecStart=/bin/bash -c '/bin/chvt 2; /icpc/scripts/icpc_setup' +# TODO could use type=notify along with calling `systemd-notify --ready` from the script to mark it as complete. +# TODO then systemd will restart it until successful + [Install] WantedBy=graphical.target WantedBy=multi-user.target diff --git a/files/management-server/coredns.service.j2 b/files/management-server/coredns.service.j2 deleted file mode 100644 index 6d6a8ae..0000000 --- a/files/management-server/coredns.service.j2 +++ /dev/null @@ -1,28 +0,0 @@ -[Unit] -Description=CoreDNS -Documentation=https://coredns.io -After=network-online.target -StartLimitInterval=0 - -[Service] -Type=simple -PermissionsStartOnly=true -LimitNOFILE=1048576 -LimitNPROC=512 -CapabilityBoundingSet=CAP_NET_BIND_SERVICE -AmbientCapabilities=CAP_NET_BIND_SERVICE -NoNewPrivileges=true -WorkingDirectory=/etc/coredns - -User=coredns -Group=coredns -ExecStart=/usr/local/bin/coredns \ - -conf /etc/coredns/Corefile - -SyslogIdentifier=coredns -ExecReload=/bin/kill -SIGUSR1 $MAINPID -Restart=always -RestartSec=0 - -[Install] -WantedBy=multi-user.target diff --git a/files/management-server/do-screenshots.py b/files/management-server/do-screenshots.py deleted file mode 100644 index 9ba68a7..0000000 --- a/files/management-server/do-screenshots.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python3 -import os -import os.path -import sys -import re -import subprocess -from datetime import datetime -import multiprocessing as mp -from collections import defaultdict -import pathlib -from pprint import pprint - - -home = os.environ['HOME'] -SCREENSHOT_DIR = f'/srv/contestweb/screens' -TIMESTAMP = datetime.now().strftime("%Y%m%d-%H_%M_%S") - -SITELIMIT = sys.argv[1] if len(sys.argv) > 1 else None - - -class Host: - def __init__(self, host, site): - self.host = host - self.site = site - self.filename = f"{TIMESTAMP}.png" - self.screenshot_dir = f"{SCREENSHOT_DIR}/{self.site}/{self.host}" - self.thumbnail_dir = f"{self.screenshot_dir}/thumbs" - - # actual files - self.screenshot = None - self.thumbnail = None - - def screenshot_url(self): - return self.screenshot[len(f"{SCREENSHOT_DIR}/"):] - def thumbnail_url(self): - return self.thumbnail[len(f"{SCREENSHOT_DIR}/"):] - - def take_screenshot(self): - pathlib.Path(self.screenshot_dir).mkdir(parents=True, exist_ok=True) - - cmd = f'timeout 10 ssh {self.host} sudo -u contestant env DISPLAY=:0 import -window root png:- > {self.screenshot_dir}/{self.filename}' - try: - out = subprocess.run(cmd, shell=True, check=True, capture_output=True) - print(f'Screenshot taken of {self.host}') - self.screenshot = f"{self.screenshot_dir}/{self.filename}" - except subprocess.CalledProcessError as e: - print(f'Failed to screenshot {self.host}') - print(e) - print('============================') - os.remove(f'{self.screenshot_dir}/{self.filename}') - - def create_thumbnail(self): - print(f"checking thumbnail for {self.host}") - # Nothing to do if there's no screenshot - if self.screenshot is None: - return - - # Make sure the directory exists - pathlib.Path(self.thumbnail_dir).mkdir(parents=True, exist_ok=True) - - # otherwise, make a thumbnail - print(f'Thumbnailing {self.host}') - cmd = f"cd {self.screenshot_dir} && mogrify -format png -path thumbs -thumbnail 320x {self.filename}" - out = subprocess.run(cmd, shell=True, capture_output=True) - if out.returncode != 0: - print(out) - self.thumbnail = f"{self.thumbnail_dir}/{self.filename}" - -def screenshot_wrapper(h): - h.take_screenshot() - return h -def thumbnail_wrapper(h): - h.create_thumbnail() - return h - -def main(): - now = datetime.now() - - with open(f'{home}/icpcnet_hosts', 'r') as f: - hostlines = f.readlines() - hostlines = [line.strip() for line in hostlines - if not line.startswith('#') and line.strip() != ''] - hosts = [] - for line in hostlines: - hostnames = line.split('#')[0].split()[1:] - hosts.extend(hostnames) - - # grab full hostnames, so we have site information - r = re.compile(r"[^.]+\.[^.]+\.icpcnet\.internal") - hosts = list(filter(r.match, hosts)) - hosts = list(map(lambda h: Host(*h.split('.')[:2]), hosts)) - - hosts = list(filter(lambda h: SITELIMIT is None or SITELIMIT == h.site, hosts)) - - # fetch 24 screenshots at a time - pool = mp.Pool(processes=24) - hosts = pool.map(screenshot_wrapper, hosts) - pool = mp.Pool(processes=4) - hosts = pool.map(thumbnail_wrapper, hosts) - - site_hosts = defaultdict(list) - for h in hosts: - site_hosts[h.site].append(h) - - # site content generation - site_html = defaultdict(str) - for site,hosts in site_hosts.items(): - for h in sorted(hosts, key=lambda h: h.host): - if h.screenshot is None: - site_html[site] += f'
{h.host}
\n' - else: - site_html[site] += f'
{h.host}
\n' - site_html[site] += f'' - - header = f''' - - - - - - - - - - Screenshots {TIMESTAMP}! - - - -
-
-

{TIMESTAMP}

-
- ''' - - footer = ''' -
- - - - - - - - - - - - ''' - - # Only write the index.html if there's not a sitelimit in place - if SITELIMIT is None: - with open(f'{SCREENSHOT_DIR}/index.html', 'w') as html: - html.write(header) - html.write(f'
    ') - for site,html_content in site_html.items(): - html.write(f'
  • {site}
  • ') - html.write(f'
') - - for site,html_content in site_html.items(): - html.write(f'
') - html.write(html_content) - html.write(footer) - - # make individual site pages - for site,html_content in site_html.items(): - with open(f'{SCREENSHOT_DIR}/{site}.html', 'w') as html: - html.write(header) - html.write(f'

{site}

') - html.write(html_content) - html.write(footer) - -if __name__ == '__main__': - main() diff --git a/files/management-server/dsnet.service b/files/management-server/dsnet.service deleted file mode 100644 index 6f9b3cf..0000000 --- a/files/management-server/dsnet.service +++ /dev/null @@ -1,16 +0,0 @@ -# Copy this service file to /etc/systemd/system/ to start dsnet on boot, -# assuming dsnet is installed to /usr/local/bin -[Unit] -Description=dsnet -After=network-online.target -Wants=network-online.target - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/dsnet up -ExecStop=/usr/local/bin/dsnet down -RemainAfterExit=yes -ExecReload=/usr/local/bin/dsnet sync - -[Install] -WantedBy=default.target diff --git a/files/management-server/dsnetconfig.json.j2 b/files/management-server/dsnetconfig.json.j2 deleted file mode 100644 index 8542714..0000000 --- a/files/management-server/dsnetconfig.json.j2 +++ /dev/null @@ -1,17 +0,0 @@ -{ - "ExternalHostname": "{{ wg_vpn_server_external_hostname }}", - "ExternalIP": "{{ wg_vpn_server_external_ip }}", - "ExternalIP6": "", - "ListenPort": {{ wg_vpn_server_wg_port }}, - "Domain": "icpcnet.internal", - "InterfaceName": "contest", - "Network6": "{{ wg_vpn_server_subnet }}", - "IP6": "{{ contestmanager_ip }}", - "DNS": "", - "Networks": [], - "ReportFile": "/var/lib/dsnetreport.json", - "PrivateKey": "{{ wg_vpn_server_private_key }}", - "PostUp": "", - "PostDown": "", - "Peers": [] -} diff --git a/files/management-server/nginx.conf b/files/management-server/nginx.conf deleted file mode 100644 index 5ba256e..0000000 --- a/files/management-server/nginx.conf +++ /dev/null @@ -1,70 +0,0 @@ -user www-data; -worker_processes auto; # number of cores -pid /run/nginx.pid; - -events { - worker_connections 8096; - multi_accept on; - use epoll; -} - -http { - sendfile on; - tcp_nopush on; - keepalive_timeout 65; - server_tokens off; - - tcp_nodelay on; - types_hash_max_size 2048; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - gzip on; - gzip_disable "msie6"; - - include /etc/nginx/conf.d/*.conf; - - # this is required to proxy Grafana Live WebSocket connections. - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - upstream grafana { - server localhost:3000; - } - - server { - listen 80; - - location / { - auth_basic "Contest Admin Area"; - auth_basic_user_file /etc/nginx/contestadmin_users.htpasswd; - root /srv/contestweb; - } - # Grafana server configuration for proxying - location /grafana/ { - rewrite ^/grafana/(.*) /$1 break; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # Expose grafana - proxy_pass http://grafana; - proxy_read_timeout 90; - } - location /grafana/api/live/ { - rewrite ^/grafana/(.*) /$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $http_host; - proxy_pass http://grafana; - } - - } -} diff --git a/files/management-server/register_wireguard_client b/files/management-server/register_wireguard_client deleted file mode 100644 index d798278..0000000 --- a/files/management-server/register_wireguard_client +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python3 -import os, re, secrets, subprocess, sys -from subprocess import Popen, PIPE - -# random hostname/peer entry -client_ip = os.environ.get('SSH_CLIENT').split()[0] -hostname=f"{secrets.token_hex(16)}" # 128bit; if it's good enough for ipv6, it's good enough for me - -proc = subprocess.Popen([ - '/usr/local/bin/dsnet', 'add', - '--confirm', hostname, - '--owner', client_ip, - '--description', f"{hostname} from {client_ip}" - ], stdout=PIPE, stderr=PIPE) -try: - out, err = proc.communicate(timeout=10) -except subprocess.TimeoutExpired: - proc.kill() - out, err = proc.communicate() - -if proc.returncode != 0: - raise SystemExit(f"dsnet add failed: {out.decode('utf8')}\n{err.decode('utf-8')}") - -print(err.decode('utf-8'), file=sys.stderr) -print(out.decode('utf-8'), file=sys.stdout) diff --git a/files/management-server/wg-discover b/files/management-server/wg-discover deleted file mode 100644 index 7f994cb..0000000 --- a/files/management-server/wg-discover +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 -import subprocess -import time -import requests -import re -import json -import sys -from prometheus_client.parser import text_string_to_metric_families -# sudo apt-get install python3-prometheus-client -from collections import defaultdict - -cmd='sudo wg show contest dump | tail -n +2|awk \'{gsub(/\\/128/, "", $4);print $4 " " $5}\'' -out = subprocess.run(cmd, shell=True, check=True, capture_output=True) -# out is 'IP last_handshake' - -from pprint import pprint - -now = time.time() - -def get_info(ip): - resp = None - try: - resp = requests.get(f'http://[{ip}]:9100/metrics', timeout=5) - except Exception as e: - print(e, file=sys.stderr) - return None - - # content = resp.content.decode() - # cachefile = open(f"/home/ubuntu/promcache/{ip}.metrics", "w") - # cachefile.write(content) - # cachefile.close() - - machine_info = {} - - for f in text_string_to_metric_families(resp.text): - if f.name == 'icpc_workstation_info': - for s in f.samples: - site = s.labels['site'] - team = s.labels['team'] - if len(team) == 0: - team = None - if len(site) == 0: - site = None - machine_info['team'] = team - machine_info['site'] = site - machine_info['name'] = s.labels.get('name', None) - machine_info['affiliation'] = s.labels.get('affiliation', None) - elif f.name == 'node_memory_MemTotal_bytes': - for s in f.samples: - machine_info['memory'] = s.value / (1024*1024) # in megabytes - elif f.name == 'node_cpu_frequency_max_hertz': - cores = {} - for s in f.samples: - cores[s.labels.get('cpu')] = s.value / (1000 * 1000 * 1000) # Gigahertz - machine_info['cpu_cores'] = len(cores) - machine_info['cpu_max'] = max(cores.values()) - # pprint(machine_info) - # return (machine_info['team'],machine_info['site']) - return machine_info - -num_hosts=defaultdict(int) - -targets = [] -hostlines = [] -ansible = defaultdict(list) -machines = [] -num_unknown = 0 -for line in filter(lambda f: len(f) > 0, out.stdout.decode().split('\n')): - ip, handshake = line.split(' ') - handshake = int(handshake) - if handshake > now - 300: #alive in the last 5 minutes - print(f'{ip} is alive', file=sys.stderr) - m = get_info(ip) - if m is None: # skip offline/broken hosts - continue - machines.append(m) - site = m['site'] - team = m['team'] - if site is not None and team is not None: - num_hosts[site] = num_hosts[site] + 1 - if f't{team}' in ansible[site]: # machine already exists (i.e. this is a duplicate) - suffix = 0 - while f't{team}_{suffix}' in ansible[site]: - suffix = suffix + 1 - team = f'{team}_{suffix}' - targets.append({'targets': [f'[{ip}]:9100'], 'labels': {'team': team, 'site': site, 'instance': f'team{team}'}}) - print(f' Adding t{team}.{site}.icpcnet.internal to hosts file') - hostlines.append( f'{ip} t{team}.{site}.icpcnet.internal t{team}.icpcnet.internal t{team}'.lower()) - ansible[site].append(f't{team}') - else: - num_unknown += 1 - print(f' missing team/site:\n Team: {team} Site: {site}') - hostlines.append(f'{ip} u{num_unknown}.uninitialized.icpcnet.internal u{num_unknown}.icpcnet.internal u{num_unknown}') - ansible['uninitialized'].append(f'u{num_unknown}') - - -with open("icpcnet_hosts", "w") as f: - f.write("\n".join(hostlines) + '\n') # Put a trailing newline on it - -with open("icpcnet_prometheus_targets.json", "w") as f: - f.write(json.dumps(targets) + '\n') - -with open('icpcnet_ansible', 'w') as f: - for _,hosts in ansible.items(): - for h in hosts: - f.write(f'{h}\n') - f.write('\n') - for site,hosts in ansible.items(): - f.write(f'[{site}]\n') - for h in hosts: - f.write(f'{h}\n') - -with open('/srv/contestweb/index.html', 'w') as f: - f.write(''' - - - - - - - - - - -
-
- -
-

Online Teams

- - - - - - - - - ''') - for m in sorted(machines, key=(lambda m: m.get('team') if m.get('team') is not None else 'zz')): - f.write(f""" - - - - - - - - """) - f.write(''' - - - - - ''') - -print(f"Found {len(machines)} hosts") -print(f'{num_hosts}') diff --git a/files/pam_environment b/files/pam_environment deleted file mode 100644 index 5be1d26..0000000 --- a/files/pam_environment +++ /dev/null @@ -1,8 +0,0 @@ -http_proxy OVERRIDE="" -https_proxy OVERRIDE="" -ftp_proxy OVERRIDE="" -no_proxy OVERRIDE="" -HTTP_PROXY OVERRIDE="" -HTTPS_PROXY OVERRIDE="" -FTP_PROXY OVERRIDE="" -NO_PROXY OVERRIDE="" diff --git a/files/pam_sudo b/files/pam_sudo deleted file mode 100644 index c2c6207..0000000 --- a/files/pam_sudo +++ /dev/null @@ -1,7 +0,0 @@ -#%PAM-1.0 - -session required pam_env.so readenv=1 user_readenv=1 -session required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=1 -@include common-auth -@include common-account -@include common-session-noninteractive diff --git a/files/scripts/firstLogin.sh b/files/scripts/firstLogin.sh index 5fa0a8f..5e4ccb4 100644 --- a/files/scripts/firstLogin.sh +++ b/files/scripts/firstLogin.sh @@ -29,17 +29,21 @@ done sleep 5 echo "Update the desktop background properties" -xfconf-query -c xfce4-desktop -p /backdrop/screen0 -rR -xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/last-image --create -t string -s $BACKGROUND -xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-path --create -t string -s $BACKGROUND -xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-style --create -t int -s 3 -# Reload xfdesktop to get the background image showing (--reload doesn't work, have to --quit first...) -echo "Reload xfdesktop to refresh the background" -sleep 5 -xfdesktop --quit -timeout 5 xfdesktop --reload -sleep 5 -xfdesktop --quit -timeout 5 xfdesktop --reload +screens=$(xrandr | jc --xrandr | jq -r '.screens[] | .screen_number' | sort -u) +monitors=$(xrandr | jc --xrandr | jq -r '.screens[] | .devices[] | .device_name' | sort -u) +for s in $screens; do + for m in $monitors; do + echo "Setting background for screen$s/monitor$m" + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/last-image --create -t string -s $BACKGROUND + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/image-path --create -t string -s $BACKGROUND + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/image-style --create -t int -s 3 + for ws in 0 1 2 3; do + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/workspace$ws/last-image --create -t string -s $BACKGROUND + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/workspace$ws/image-style --create -t int -s 3 + xfconf-query -c xfce4-desktop -p /backdrop/screen$s/monitor$m/workspace$ws/image-path --create -t string -s $BACKGROUND + done + done +done +xfdesktop --reload diff --git a/files/scripts/icpc_setup b/files/scripts/icpc_setup index 73b8375..2d91e4f 100755 --- a/files/scripts/icpc_setup +++ b/files/scripts/icpc_setup @@ -437,8 +437,14 @@ network: wifis: {interface}: access-points: - "{ssid}": - password: "{password}" + "{ssid}":""") + # Render the password field properly the ssid should be an empty object if the password is blank + if len(password) > 0: + f.write(f''' + password: "{password}"''') + else: + f.write(" {}") + f.write(f""" dhcp4: true dhcp-identifier: mac """ diff --git a/files/scripts/makeDist.sh b/files/scripts/makeDist.sh index 06d0bbd..62122c5 100644 --- a/files/scripts/makeDist.sh +++ b/files/scripts/makeDist.sh @@ -7,11 +7,13 @@ UTILDIR="/icpc" rm -rf /etc/skel/.git rm -rf /home/icpcadmin/.git -# Cleanup 'imageadmin' things -killall -9 -u imageadmin -sleep 5 -rm -rf /home/imageadmin -userdel imageadmin +# Cleanup 'imageadmin' things (if it exists) +if id "imageadmin" >/dev/null 2>&1; then + killall -9 -u imageadmin + sleep 5 + rm -rf /home/imageadmin + userdel imageadmin +fi # Delete proxy settings for apt(if any) rm -f /etc/apt/apt.conf.d/01proxy @@ -49,6 +51,13 @@ mkdir -p /var/lib/apt/lists/partial ufw --force enable # Delete /etc/machine-id so the image generates a new one on boot +echo +echo +mount +echo +echo +# sometimes this is a tmpfs, see https://www.freedesktop.org/software/systemd/man/latest/systemd-machine-id-setup.html +umount /etc/machine-id echo "" > /etc/machine-id # make sure wireguard config is wiped so it can be generated for each system on boot diff --git a/files/scripts/self_test b/files/scripts/self_test index 7cc88fb..0aef8ea 100644 --- a/files/scripts/self_test +++ b/files/scripts/self_test @@ -114,9 +114,10 @@ print_check "Testing access to google is blocked with a proxy error" curl -s --proxy http://127.0.0.1:3128 http://google.com 2>/dev/null | grep "

Access Denied

" > /dev/null check_return $? +echo "Testing network access is successful with proxy" while IFS="" read -r url ; do [ -z "$url" ] && continue - print_check "Testing access to $url is successful with proxy" + print_check " $url" # wget -e use_proxy=yes -T 5 -t 1 -e http_proxy=127.0.0.1:3128 -e https_proxy=127.0.0.1:3128 -O- --no-check-certificate $url 2>/dev/null | grep -i "html" > /dev/null curl --proxy http://127.0.0.1:3128 --connect-timeout 5 --max-time 10 --silent -o /dev/null --fail $url check_return $? @@ -154,7 +155,7 @@ print_version "go" "go version" print_version "gccgo" "gccgo --version" print_version "groovy" "groovy -version" print_version "haskell" "ghc --version" -print_version "java" "java -version" +print_first_version "java" "java -version" print_version "lua" "lua -v" print_version "js" "nodejs --version" print_first_version "kotlin" "kotlin -version" diff --git a/jumphost.md b/jumphost.md deleted file mode 100644 index f4501d1..0000000 --- a/jumphost.md +++ /dev/null @@ -1,82 +0,0 @@ -ssh host: - -create jumpy user, for that user, create a keypair, private key goes in the contest image(group_vars/all) -``` -root@jumpbox:~# useradd -m -U -s /bin/bash jumpy -ssh-keygen -t ed25519 -f jumpbox_key -``` -public key goes in the authorized_keys file for the jumpy user: -command="echo 'This account can only be used for opening a reverse tunnel.'",no-agent-forwarding,no-X11-forwarding ssh-ed25519 SSH_PUBKEY jumpy@ssh.yourserver.com - - -Now generate a second key, this will be used to actually ssh into the machines as root, and needs to be kept private/secret -``` -ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -``` - -Make sure the jumpbox listens on port 443 for ssh connections as wel - -install parallel-ssh `sudo apt-get update && sudo apt-get install pssh` -create discover-hosts.sh file with contents: -``` -#!/bin/bash -set -euo pipefail - -echo -n "" > ~/.ssh/config -PORTS=$(sudo lsof -i4TCP -sTCP:LISTEN -P -n | sed -r 's/.*:([0-9]+).*/\1/' | tail -n +2 ) -idx=0 -for p in $PORTS; do - let idx=idx+1 - # Skip localhost - if [[ $p == 443 || $p == 22 ]]; then continue; fi - TEAM=$(ssh localhost -p $p -i ~/.ssh/id_ed25519 -l root -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no cat /icpc/TEAM 2>/dev/null| sed 's/team//') - if [[ -z $TEAM ]]; then - HOST=unknown-$idx - else - HOST=t$TEAM - fi - echo "$HOST - $p" - cat >> ~/.ssh/config < /dev/null; printf "%%s\n" "declare -- PS1='\\[\\033[01;32m\\]\\u@\\h\\[\\033[00m\\]\\[\\033[38;5;3m\\](t\$(cat /icpc/TEAMID 2>/dev/null))\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\\$ '") - dest: /home/{{ ansible_user }}/.ssh/config - - - name: sshd config to listen on 443 - copy: - content: | - Port 22 - Port 443 - dest: /etc/ssh/sshd_config.d/ssh_port_443.conf - mode: 0644 - notify: restart ssh - - - name: use different set of host keys - copy: - src: files/secrets/contestmanager.icpcnet.internal_{{ item }} - dest: /etc/ssh/ssh_{{ item }} - with_items: - - host_ed25519_key - - host_ed25519_key.pub - - host_ed25519_key-cert.pub - notify: restart ssh - - - name: sshd host certificate - copy: - content: | - HostKey /etc/ssh/ssh_host_ed25519_key - HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub - dest: /etc/ssh/sshd_config.d/ssh_host_cert.conf - mode: 0644 - notify: restart ssh - - - name: configure ssh ca.pub (so we can verify other hosts easily) - copy: - src: files/secrets/server_ca.pub - dest: /etc/ssh/ca.pub - mode: 0644 - - name: configure ssh ca to be trusted for host verification - shell: echo "@cert-authority * $(cat /etc/ssh/ca.pub)" >>/etc/ssh/ssh_known_hosts - - - name: Flush handlers so ssh is restarted before we try to do git operations - meta: flush_handlers - - - name: create sample lastminute.yml (and commit/push it) if there isn't one - shell: | - git config --global user.name 'ICPC Admin' - git config --global user.email 'icpcadmin@{{ansible_hostname}}' - git clone git@contestmanager.icpcnet.internal:~/ansible /home/{{ansible_user}}/ansible-lastminute - cd /home/{{ansible_user}}/ansible-lastminute - - # bail if there are commits/items already here - git log -n1 >/dev/null 2>/dev/null && exit - - cat < local.yml - - name: Lastminute Setup - hosts: icpc - become: true - gather_facts: true - tasks: - - shell: 'echo "Ansible-Pull on \$(date +"%Y-%m-%d %H:%M:%S")\nRevision: \$(git rev-list --full-history --all --abbrev-commit | head -1)\n"' - register: git_revision - - name: copy version info - copy: content="{{ '{{' }}git_revision.stdout{{ '}}' }}\n" dest=/icpc/update-version - - name: remove ansible trigger file - file: path=/icpc/trigger-ansible state=absent - EOF - git add local.yml - git commit -m "Initial last minute ansible script" - git push -u origin master - args: - creates: /home/{{ ansible_user }}/ansible-lastminute - become: no - - - name: install dsnet - get_url: - url: https://github.com/naggie/dsnet/releases/latest/download/dsnet-linux-amd64 - dest: /usr/local/bin/dsnet - mode: 0755 - - - name: give dsnet cap_net_admin (so regular users can interact with it) - community.general.capabilities: - path: /usr/local/bin/dsnet - capability: cap_net_admin+eip - state: present - - - name: set up reverse ssh tunnel account (jumpy) - ansible.builtin.user: - name: jumpy - shell: /bin/bash - - - name: Set authorized key for reverse ssh tunnel account (jumpy) - ansible.posix.authorized_key: - user: jumpy - state: present - key: "{{ lookup('file', 'secrets/server_ca.pub') }}" - key_options: command="echo 'This account can only be used for opening a reverse tunnel.'",no-agent-forwarding,no-X11-forwarding,cert-authority - exclusive: yes - - - name: copy our wireguard registration script - copy: - src: files/management-server/register_wireguard_client - dest: /usr/local/bin/register_wireguard_client - mode: 0755 - - - name: set up ssh wireguard registration account - ansible.builtin.user: - name: wg_client - shell: /bin/bash - - name: Set authorized key for wireguard registration account (wg_client) - ansible.posix.authorized_key: - user: wg_client - state: present - key: "{{ lookup('file', 'secrets/server_ca.pub') }}" - key_options: command="/usr/local/bin/register_wireguard_client",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,cert-authority - exclusive: yes - - - name: configure dsnet - template: - src: files/management-server/dsnetconfig.json.j2 - dest: /etc/dsnetconfig.json - owner: root - group: wg_client - mode: 0660 - force: no # don't overwrite the file if it exists - - - name: set up dsnet service configuration - copy: src=files/management-server/dsnet.service dest=/etc/systemd/system/dsnet.service - - - name: enable dsnet wireguard service - service: name=dsnet enabled=yes state=started - - - - - - # coredns to do dns serving magic - # https://github.com/coredns/coredns/releases/download/v1.10.1/coredns_1.10.1_linux_amd64.tgz - - name: Create the coredns group - group: - name: coredns - state: present - system: true - - name: Create the coredns user - user: - name: coredns - groups: coredns - append: true - shell: /usr/sbin/nologin - system: true - createhome: false - home: / - - name: create coredns configuration directories - file: - path: /etc/coredns - state: directory - owner: root - group: root - mode: 0755 - - name: install coredns config file - copy: - dest: /etc/coredns/Corefile - content: | - # We handle this by probing our wireguard network for peers - icpcnet.internal. { - hosts /home/{{ansible_user}}/icpcnet_hosts - log - } - . { - forward . 8.8.8.8 # Forward everything else upstream - log - errors - cache - } - - name: install coredns - unarchive: - src: https://github.com/coredns/coredns/releases/download/v1.10.1/coredns_1.10.1_linux_amd64.tgz - dest: /usr/local/bin - remote_src: true - - name: install coredns service - template: - src: files/management-server/coredns.service.j2 - dest: /etc/systemd/system/coredns.service - mode: 0644 - owner: root - group: root - notify: restart coredns - - name: disable systemd-resolved - systemd: - name: systemd-resolved - enabled: false - state: stopped - - name: replace resolv.conf so we use coredns instead - copy: - dest: /etc/resolv.conf - follow: false - content: | - nameserver ::1 - nameserver 127.0.0.1 - options trust-ad - - name: enable coredns - systemd: - daemon_reload: true - name: coredns - enabled: true - state: started - - - name: install grafana - block: - - name: key for grafana apt repo - apt_key: url=https://apt.grafana.com/gpg.key state=present - - name: apt repo for grafana - apt_repository: repo="deb https://apt.grafana.com stable main" update_cache=yes - - name: install grafana - apt: - state: present - pkg: - - grafana - - prometheus - - prometheus-node-exporter - - nginx - - name: configure grafana - copy: - content: | - GRAFANA_USER=grafana - GRAFANA_GROUP=grafana - GRAFANA_HOME=/usr/share/grafana - LOG_DIR=/var/log/grafana - DATA_DIR=/var/lib/grafana - MAX_OPEN_FILES=10000 - CONF_DIR=/etc/grafana - CONF_FILE=/etc/grafana/grafana.ini - RESTART_ON_UPGRADE=true - PLUGINS_DIR=/var/lib/grafana/plugins - PROVISIONING_CFG_DIR=/etc/grafana/provisioning - # Only used on systemd systems - PID_FILE_DIR=/var/run/grafana - GF_SECURITY_ADMIN_PASSWORD={{management_server_grafana_password}} - # Run grafana from /grafana - GF_SERVER_DOMAIN={{wg_vpn_server_external_hostname}} - GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana/ - GF_SERVER_SERVE_FROM_SUB_PATH=true - dest: /etc/default/grafana-server - - name: set up grafana datasources - copy: - dest: /etc/grafana/provisioning/datasources/default.yml - content: | - apiVersion: 1 - deleteDatasources: - - name: Prometheus - orgId: 1 - datasources: - - name: Prometheus - type: prometheus - access: proxy - url: http://localhost:9090 - isDefault: true - version: 1 - editable: false - # - name: set up grafana dashboards - # copy: - # dest: /etc/grafana/provisioning/dashboards/default.yml - # content: | - # - name: 'default' # name of this dashboard configuration (not dashboard itself) - # org_id: 1 # id of the org to hold the dashboard - # folder: '' # name of the folder to put the dashboard (http://docs.grafana.org/v5.0/reference/dashboard_folders/) - # type: 'file' # type of dashboard description (json files) - # options: - # folder: '/etc/grafana/dashboards' # where dashboards ar - # - name: create dashboard directory - # file: path=/etc/grafana/dashboards state=directory - # - name: copy grafana dashboards - # copy: - # src: files/grafana/dashboards/ - # dest: /etc/grafana/dashboards/ - - - name: configure prometheus scrape config - copy: - dest: /etc/prometheus/prometheus.yml - content: | - --- - global: - scrape_interval: 15s # By default, scrape targets every 15 seconds. - evaluation_interval: 15s # By default, scrape targets every 15 seconds. - scrape_configs: - - job_name: 'self' - static_configs: - - targets: ['localhost:9100'] - - job_name: 'contestants' - file_sd_configs: - - files: - - '/home/{{ansible_user}}/icpcnet_prometheus_targets.json' - - - name: copy default nginx config - copy: src=files/management-server/nginx.conf dest=/etc/nginx/nginx.conf - notify: restart nginx - - name: disable default nginx site - file: state=absent path=/etc/nginx/sites-enabled/default - notify: restart nginx - - name: htpasswd for nginx - htpasswd: - path: /etc/nginx/contestadmin_users.htpasswd - name: admin - password: "{{management_server_grafana_password}}" - owner: root - group: www-data - mode: 0640 - - name: create web directory - file: - state: directory - dest: /srv/contestweb - owner: "{{ ansible_user }}" - group: www-data - mode: 0755 - - name: Start/enable our services - service: name={{ item }} state=started enabled=yes - with_items: - - grafana-server.service - - prometheus.service - - nginx.service - - - name: install our wg-discover tool - copy: - src: files/management-server/wg-discover - dest: /usr/local/bin/discover-clients - mode: 0755 - - name: run wg-discover tool every minute - block: - - name: sudo rule so we can run wg show - community.general.sudoers: - name: passwordless_wg_show - user: "{{ ansible_user }}" - commands: "/usr/bin/wg show contest dump" - nopassword: true - - name: systemd unit - copy: - dest: /etc/systemd/system/discover-clients.service - content: | - [Unit] - Description=Discovers clients on the wireguard interface - Wants=discover-clients.timer - [Service] - Type=oneshot - User={{ ansible_user }} - WorkingDirectory=/home/{{ ansible_user }} - ExecStart=/usr/local/bin/discover-clients - [Install] - WantedBy=multi-user.target - - name: systemd timer - copy: - dest: /etc/systemd/system/discover-clients.timer - content: | - [Unit] - Description=Periodically triggers client discovery - Requires=discover-clients.service - [Timer] - Unit=discover-clients.service - OnCalendar=*-*-* *:*:00 - [Install] - WantedBy=timers.target - - name: enable/start the timer - systemd: - name: discover-clients.timer - daemon_reload: true - state: started - enabled: true - - - name: screenshot wizardry - copy: - src: files/management-server/do-screenshots.py - dest: /usr/local/bin/do-screenshots - mode: 0755 - - name: make sure screens dir exists in web folder - file: dest=/srv/contestweb/screens state=directory owner={{ ansible_user }} group=www-data mode=0755 - - - name: make PS1 a bit more useful by including the contest id - lineinfile: - dest: /home/{{ansible_user}}/.bashrc - line: PS1='\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[38;5;5m\]({{ contest_id }})\[\033[00m\] :\[\033[01;34m\]\w\[\033[00m\]\$ ' - - # Copy some build information to the image - - shell: 'echo "Built on $(date +%Y-%m-%d)\nRevision: $(git rev-list --full-history --all --abbrev-commit | head -1)"\n' - become: false - register: git_revision - delegate_to: 127.0.0.1 - - name: copy version info - copy: content="{{git_revision.stdout}}" dest=/applied-version - - handlers: - - name: restart ssh - service: name=ssh state=restarted - - name: restart coredns - service: name=coredns state=restarted - - name: restart nginx - service: name=nginx state=restarted diff --git a/output/.gitignore b/output/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/output/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/playbooks/compilers.yml b/playbooks/compilers.yml index c4fcb9f..ab91b64 100644 --- a/playbooks/compilers.yml +++ b/playbooks/compilers.yml @@ -36,6 +36,13 @@ pkg: podman state: present + - name: Put an alias in for podman so that the shortname for ruby works right + ansible.builtin.copy: + dest: /etc/containers/registries.conf.d/ruby-shortname.conf + content: | + [aliases] + "ruby" = "docker.io/library/ruby" + - name: Gather info on a specific image become: yes containers.podman.podman_image_info: @@ -46,19 +53,13 @@ ansible.builtin.git: repo: https://github.com/freeCodeCamp/devdocs.git dest: /tmp/devdocs-build - version: '89ee4c589ddd67e817a40cd94ebb274f5aaefab6' # main on 2024-01-14 13:40:00 EST + version: '0f259e07839d1ba65f645e077b8d22d20c0dfd3f' # main on 2024-08-30 20:20:00 EST - name: update dockerfile to only fetch things we care about ansible.builtin.replace: path: /tmp/devdocs-build/Dockerfile-alpine regexp: 'thor docs:download --all' - replace: "thor docs:download c cpp python@3.10 kotlin@1.8 openjdk@11" - - - name: update dockerfile to fix the image name - ansible.builtin.replace: - path: /tmp/devdocs-build/Dockerfile-alpine - regexp: 'FROM ruby:' - replace: "FROM docker.io/ruby:" + replace: "thor docs:download c cpp python@3.12 openjdk@21 kotlin@1.8" - name: build the docker container become: true diff --git a/playbooks/devel_tools.yml b/playbooks/devel_tools.yml index 91b6e1e..5f22cea 100644 --- a/playbooks/devel_tools.yml +++ b/playbooks/devel_tools.yml @@ -6,10 +6,18 @@ - vim-gtk3 # graphical vim - neovim-qt # fork of vim that some people might like better - kate # another text editor ~181mb + - konsole # kate requires konsole (an alternate console) for it's embedded terminal + - alacritty # a fancy terminal app people might want/like - emacs # emacs(with x) - gedit # Simple gnome text editor w/ syntax highlighting - gdb - zsh # a different shell people might like more (~20MiB) + - eza # a modern ls + + - name: make sure vim-gtk3 is the default gvim (not nvim) + community.general.alternatives: + name: gvim + path: /usr/bin/vim.gtk3 - name: install codeblocks when: "'codeblocks' in devtools" @@ -23,10 +31,18 @@ when: "'vscode' in devtools" include_tasks: 'devel_tools/vscode.yml' + - name: install zed + when: "'zed' in devtools" + include_tasks: 'devel_tools/zed.yml' + - name: install netbeans when: "'netbeans' in devtools" include_tasks: 'devel_tools/netbeans.yml' + - name: install codelite + when: "'codelite' in devtools" + include_tasks: 'devel_tools/codelite.yml' + - name: install geany when: "'geany' in devtools" apt: @@ -35,17 +51,22 @@ - geany - geany-plugins - - include_tasks: 'devel_tools/eclipse.yml' + - name: install eclipse + include_tasks: 'devel_tools/eclipse.yml' when: "'eclipse' in devtools" - - include_tasks: 'devel_tools/intellij.yml' + - name: install intellij tools + include_tasks: 'devel_tools/intellij.yml' when: ('intellij-idea' in devtools) or ('intellij-clion' in devtools) or ('intellij-pycharm' in devtools) - name: install monodevelop when: "('monodevelop' in devtools)" block: - name: key for monodevelop apt repo - apt_key: keyserver=keyserver.ubuntu.com id=3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF + apt_key: + keyserver: keyserver.ubuntu.com + id: 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF + keyring: /etc/apt/trusted.gpg.d/monodevelop.gpg - name: apt repo for monodevelop apt_repository: repo="deb https://download.mono-project.com/repo/ubuntu stable-bionic main" update_cache=yes - name: install monodevelop diff --git a/playbooks/devel_tools/codelite.yml b/playbooks/devel_tools/codelite.yml new file mode 100644 index 0000000..dffbe73 --- /dev/null +++ b/playbooks/devel_tools/codelite.yml @@ -0,0 +1,6 @@ +--- +# wget -qO- http://repos.codelite.org/CodeLite.asc | sudo tee /etc/apt/trusted.gpg.d/CodeLite.asc +# sudo apt-add-repository 'deb https://repos.codelite.org/ubuntu/ jammy universe' + +# there's apparently a codelite package in ubuntu too, need to see what version it is. +# (ubuntu repos have 17, which is currently latest) diff --git a/playbooks/devel_tools/eclipse.yml b/playbooks/devel_tools/eclipse.yml index b5ec539..4bd7fa6 100644 --- a/playbooks/devel_tools/eclipse.yml +++ b/playbooks/devel_tools/eclipse.yml @@ -1,6 +1,6 @@ --- - name: install eclipse(64bit) - unarchive: src=files/eclipse-java-2023-12-R-linux-gtk-x86_64.tar.gz dest=/opt creates=/opt/eclipse + unarchive: src=files/eclipse-java-2024-06-R-linux-gtk-x86_64.tar.gz dest=/opt creates=/opt/eclipse - name: eclipse shortcut copy: @@ -32,7 +32,7 @@ shell: | /opt/eclipse/eclipse -nosplash \ -application org.eclipse.equinox.p2.director \ - -repository http://download.eclipse.org/tools/cdt/releases/latest/,http://download.eclipse.org/releases/2023-12/ \ + -repository http://download.eclipse.org/tools/cdt/releases/latest/,http://download.eclipse.org/releases/2024-06/ \ -destination /opt/eclipse \ -installIU org.eclipse.cdt.feature.group \ -installIU org.eclipse.cdt.platform.feature.group | grep -v DEBUG @@ -65,12 +65,78 @@ org.eclipse.epp.logging.aeri.ui/configured=true # default to jdk 11 compliance level (otherwise it's 17 for eclipse 2021-12) - org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=11 - org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=11 - org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 + # org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=11 + # org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=11 + # org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 + + # org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_LIB=/usr/lib/jvm/java-11-openjdk-amd64/lib/jrt-fs.jar + # org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRC=/usr/lib/jvm/java-11-openjdk-amd64/lib/src.zip # set the available jdks...(this from export/import...) - org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML=\n\n \n \n \n \n \n \n \n \n \n \n \n \n\n + # org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML= + + # # Set pydev interpreters + # org.python.pydev/INTERPRETERS_CHECKED_ONCE=true + # org.python.pydev/INTERPRETER_PATH_NEW=\npython\n3.10\n/usr/bin/python3\n/usr/lib/python3.10\n/usr/lib/python3.10/lib-dynload\n/usr/local/lib/python3.10/dist-packages\n/usr/lib/python3/dist-packages\nImage\nOpenGL\n_abc\n_ast\n_bisect\n_blake2\n_bytesio\n_codecs\n_codecs_cn\n_codecs_hk\n_codecs_iso2022\n_codecs_jp\n_codecs_kr\n_codecs_tw\n_collections\n_csv\n_datetime\n_elementtree\n_fileio\n_functools\n_heapq\n_hotshot\n_imp\n_io\n_json\n_locale\n_lsprof\n_md5\n_multibytecodec\n_operator\n_pickle\n_posixsubprocess\n_random\n_sha\n_sha1\n_sha256\n_sha3\n_sha512\n_signal\n_socket\n_sre\n_stat\n_statistics\n_string\n_struct\n_subprocess\n_symtable\n_thread\n_tracemalloc\n_warnings\n_weakref\n_winreg\narray\natexit\naudioop\nbinascii\nbuiltins\ncPickle\ncStringIO\ncmath\ncv2\ndatetime\nemail\nerrno\nexceptions\nfaulthandler\nfcntl\nfuture_builtins\ngc\ngi\ngrp\nhashlib\nimageop\nimp\nitertools\nmarshal\nmath\nmmap\nmock\nmsvcrt\nmultiprocessing\nmutagen\nnt\nnumpy\noperator\nos\nos.path\nparser\nposix\npwd\npy\npyexpat\npytest\nrandom\nre\nscipy\nselect\nsignal\nsix\nsocket\nspwd\nssl\nstrop\nsys\nsyslog\nthread\ntime\nunicodedata\nwx\nwxPython\nxxsubtype\nzipimport\nzlib\nPY310\n&&&&& - name: fixup the eclipse.ini file to use our custom configuration lineinfile: dest=/opt/eclipse/eclipse.ini insertafter="-vmargs" line="-Declipse.pluginCustomization=/opt/eclipse/eclipse_plugincustomization.ini" + + + + +# The old way would have been https://github.com/alfsch/workspacemechanic, but that's dead, and oomph seems to be the new thing +# except oomph doesn't work for everything. It does do the jvm part properly, but not pydev interpreters :( + # OOMPH things: + # installation specific oomph setup file: /opt/eclipse/configuration/org.eclipse.oomph.setup/installation.setup + # user oomph setup file: /home/.eclipse/org.eclipse.oomph.setup/setups/user.setup + # Something about oomph requires online connectivity; it downloads/caches a bunch of stuff in .eclipse, and without it the setup scripts don't work properly + # Maybe there's some way to "install" those globally, and maybe use an installation.setup file so we don't need to do anything in the home directory + +# OOMPH is there out of the box, so we don't need this + # - name: make sure the feature group for oomph setup is installed + # when: '"org.eclipse.oomph.setup.feature.group" not in eclipse_installed_pkgs.stdout' + # shell: | + # /opt/eclipse/eclipse -nosplash \ + # -application org.eclipse.equinox.p2.director \ + # -destination /opt/eclipse \ + # -installIU org.eclipse.oomph.setup.feature.group | grep -v DEBUG + + +# SIGH:oomph can't overwrite xml blobs: https://bugs.eclipse.org/bugs/show_bug.cgi?id=527920; not an issue since we are in charge of provisioning new workspaces, which won't have any +# content and we can install our xml blob properly + +# This goes in ~/.eclipse/org.eclipse.oomph.setup/setups/user.setup +# The pydev part only kinda works, you have to restart eclipse after it's applied, which is far from ideal because most people won't restart it at all +# +# +# +# +# +# +# +# +# +# +# +# diff --git a/playbooks/devel_tools/intellij.yml b/playbooks/devel_tools/intellij.yml index d1d93a9..ffd0610 100644 --- a/playbooks/devel_tools/intellij.yml +++ b/playbooks/devel_tools/intellij.yml @@ -1,12 +1,13 @@ # IntelliJ repository (unofficial ppa: https://github.com/JonasGroeger/jetbrains-ppa) - name: apt key for IntelliJ IDEA - apt_key: + ansible.builtin.get_url: url: https://s3.eu-central-1.amazonaws.com/jetbrains-ppa/0xA6E8698A.pub.asc - state: present - keyring: /etc/apt/trusted.gpg.d/jetbrains.gpg + dest: /etc/apt/keyrings/jetbrains.asc - name: apt repo for IntelliJ IDEA - apt_repository: repo='deb http://jetbrains-ppa.s3-website.eu-central-1.amazonaws.com any main' update_cache=yes + apt_repository: + repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/jetbrains.asc] http://jetbrains-ppa.s3-website.eu-central-1.amazonaws.com any main + update_cache: true # IntelliJ IDEA community(~968mb installed in /opt/intellij-idea-community) - name: install IntelliJ IDEs @@ -31,7 +32,9 @@ # TODO: figure out where 1.9.22 comes from (intellij has a default for this) # TODO: maybe from /opt/intellij-idea-community/plugins/Kotlin/kotlinc/build.txt - name: fetch some things from maven - shell: mvn dependency:get -Dartifact="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.22" -Dmaven.repo.local="/opt/m2/repository" + shell: mvn dependency:get -Dartifact="org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.24" -Dmaven.repo.local="/opt/m2/repository" +- name: fetch some things from maven + shell: mvn dependency:get -Dartifact="org.jetbrains.kotlin:kotlin-stdlib:2.0.10" -Dmaven.repo.local="/opt/m2/repository" # PyCharm Community(523mb installed in /opt/pycharm-community) - name: install PyCharm @@ -58,11 +61,11 @@ mode: 0755 content: | #!/bin/bash - mkdir -p $HOME/.config/JetBrains/CLion2023.3 + mkdir -p $HOME/.config/JetBrains/CLion2024.2 ( printf '\xFF\xFF'; echo -en "\n{{ clion_license_key }}" | iconv -f UTF-8 -t UCS2 - - ) > $HOME/.config/JetBrains/CLion2023.3/clion.key + ) > $HOME/.config/JetBrains/CLion2024.2/clion.key when: clion_license_key | length > 0 - name: add licensekey script to autostart diff --git a/playbooks/devel_tools/vscode.yml b/playbooks/devel_tools/vscode.yml index b0a493b..e2b39d1 100644 --- a/playbooks/devel_tools/vscode.yml +++ b/playbooks/devel_tools/vscode.yml @@ -1,5 +1,9 @@ - name: apt key for vscode - apt_key: url=https://packages.microsoft.com/keys/microsoft.asc state=present + apt_key: + url: https://packages.microsoft.com/keys/microsoft.asc + state: present + keyring: /etc/apt/trusted.gpg.d/microsoft.gpg + - name: apt repo for vscode apt_repository: repo="deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" update_cache=yes filename="vscode" diff --git a/playbooks/devel_tools/zed.yml b/playbooks/devel_tools/zed.yml new file mode 100644 index 0000000..8913618 --- /dev/null +++ b/playbooks/devel_tools/zed.yml @@ -0,0 +1,25 @@ +--- +# https://zed.dev/ - Zed is a next-generation code editor designed for high-performance collaboration with humans and AI. +- name: Download zed + ansible.builtin.unarchive: + src: https://zed.dev/api/releases/stable/latest/zed-linux-x86_64.tar.gz + dest: /opt + remote_src: yes + +- name: symlink zed to somewhere on the path + ansible.builtin.file: + src: /opt/zed.app/bin/zed + dest: /usr/local/bin/zed + state: link + +- name: Create a desktop entry for zed + ansible.builtin.copy: + dest: /usr/share/applications/dev.zed.Zed.desktop + src: /opt/zed.app/share/applications/zed.desktop + remote_src: true + +- name: Copy icon for zed + ansible.builtin.copy: + dest: /usr/share/icons/hicolor/512x512/apps/zed.png + src: /opt/zed.app/share/icons/hicolor/512x512/apps/zed.png + remote_src: true diff --git a/playbooks/firewall.yml b/playbooks/firewall.yml index 8e0e5f5..4b3039b 100644 --- a/playbooks/firewall.yml +++ b/playbooks/firewall.yml @@ -33,17 +33,31 @@ args: creates: /var/spool/squid/ssl_db/index.txt -- name: configure system to use the proxy by default - lineinfile: dest=/etc/environment line="{{item}}" - with_items: - - http_proxy="http://localhost:3128/" - - https_proxy="http://localhost:3128/" - - ftp_proxy="http://localhost:3128/" - - no_proxy="localhost,127.0.0.1" - - HTTP_PROXY="http://localhost:3128/" - - HTTPS_PROXY="http://localhost:3128/" - - FTP_PROXY="http://localhost:3128/" - - NO_PROXY="localhost,127.0.0.1" +- name: copy proxy environment config (to be applied to contestant user) + copy: + dest: /etc/environment-proxied + content: | + http_proxy="http://localhost:3128/" + https_proxy="http://localhost:3128/" + ftp_proxy="http://localhost:3128/" + no_proxy="localhost,127.0.0.1" + HTTP_PROXY="http://localhost:3128/" + HTTPS_PROXY="http://localhost:3128/" + FTP_PROXY="http://localhost:3128/" + NO_PROXY="localhost,127.0.0.1" +- name: copy the pam-auth-update config file to load the proxy environment for the contestant user + copy: + dest: /usr/share/pam-configs/proxyenv + content: | + Name: Load /etc/environment-proxied for the contestant user + Default: no + Priority: 0 + Session-Type: Additional + Session: + [default=1 success=ignore] pam_succeed_if.so quiet user = contestant + required pam_env.so user_readenv=0 envfile=/etc/environment-proxied +- name: run pam-auth-update to install the proxyenv pam config + command: pam-auth-update --enable proxyenv - name: Make sure inbound policy is deny ufw: direction=incoming policy=deny diff --git a/playbooks/gui.yml b/playbooks/gui.yml index b82a1f3..323c818 100644 --- a/playbooks/gui.yml +++ b/playbooks/gui.yml @@ -32,10 +32,18 @@ - xfce4-genmon-plugin -- name: add mozilla firefox ppa (because snaps are dumb) - ansible.builtin.apt_repository: - repo: ppa:mozillateam/ppa - update_cache: yes +- name: Add mozilla firefox ppa (because snaps are dumb) + block: + - name: Fetch the signing key + ansible.builtin.get_url: + url: https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x0ab215679c571d1c8325275b9bdb3d89ce49ec21 + dest: /etc/apt/keyrings/mozillateamppa.asc + + - name: Add the mozilla team ppa + ansible.builtin.apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/mozillateamppa.asc] https://ppa.launchpadcontent.net/mozillateam/ppa/ubuntu {{ ansible_distribution_release }} main" + state: present + update_cache: true - name: apt preference for firefox to only install from the ppa copy: @@ -54,6 +62,12 @@ - mupdf # Lighweight pdf viewer - mate-calc # GUI calculator + # kalgebra - seems nice, basically a graphing calculator, but it ends up in some new education submenu + # gnome-genius - way overkill/has it's own language thing. reminds me of r or ipython notebooks + # gnome-calculator - sucks + # qalculate-gtk - has a bunch of extra advanced things, might be nice to leave in there, but maybe too fancy? + # kcalc - # ok, but mate-calc is better + - name: Remove unneeded packages apt: state: absent @@ -88,3 +102,9 @@ - thunar-bulk-rename.desktop # System->Bulk Rename - xfce4-mail-reader.desktop # Mail Reader - thunar-volman-settings.desktop # Removable devices and media + +- name: copy a script to help mirror displays + copy: + src: files/mirror-displays.sh + dest: /usr/local/bin/mirror-displays + mode: 0755 diff --git a/playbooks/icpc.yml b/playbooks/icpc.yml index 488e758..36a7cb3 100644 --- a/playbooks/icpc.yml +++ b/playbooks/icpc.yml @@ -55,6 +55,7 @@ - cups - cups-bsd - enscript + - jc # for json output form various commands (used by firstLogin.sh) - python3-typing-extensions # needed for firstboot script # experimental programs to support showing a banner image to all contestants @@ -80,11 +81,15 @@ - name: setup user skeleton directory git: dest=/etc/skel repo=file:///tmp/contestant.git - - name: create icpcadmin group group: name='icpcadmin' state='present' - name: create icpcadmin user user: name='icpcadmin' comment="ICPC Local Admin" group='icpcadmin' groups='sudo,adm,lpadmin' password='{{ icpcadmin_pass | password_hash('sha512') }}' shell='/bin/bash' +- name: fix permissions so git won't complain + ansible.builtin.file: + path: /tmp/admin.git + owner: icpcadmin + recurse: true - name: setup icpcadmin home directory git: dest=/home/icpcadmin repo=file:///tmp/admin.git become: yes @@ -153,9 +158,10 @@ email = icpcadmin@icpcenv name = icpcenv -- name: disable proxy for icpcadmin - copy: src=files/pam_environment dest=/home/icpcadmin/.pam_environment - +- name: create polkit directory + ansible.builtin.file: + path: /etc/polkit-1/localauthority/50-local.d + state: directory - name: use polkit to disable mounting anything copy: src=files/99-deny-polkit-mount.pkla dest=/etc/polkit-1/localauthority/50-local.d/disable-mount.pkla mode=0644 owner=root group=root diff --git a/playbooks/languages/dart.yml b/playbooks/languages/dart.yml index 60b49e4..09fd08e 100644 --- a/playbooks/languages/dart.yml +++ b/playbooks/languages/dart.yml @@ -3,6 +3,8 @@ apt_key: url: https://dl-ssl.google.com/linux/linux_signing_key.pub id: 7FAC5991 + keyring: /etc/apt/trusted.gpg.d/google.gpg + - name: install dart repo apt_repository: repo: "deb [arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main" diff --git a/playbooks/languages/java.yml b/playbooks/languages/java.yml index e3b43a7..6f21c5a 100644 --- a/playbooks/languages/java.yml +++ b/playbooks/languages/java.yml @@ -3,8 +3,8 @@ apt: state: present pkg: - - openjdk-11-jdk - - openjdk-11-source # 60 mb + - openjdk-21-jdk + - openjdk-21-source - name: register docs when: not devdocs @@ -13,14 +13,14 @@ apt: state: present pkg: - - openjdk-11-doc # 246 mb + - openjdk-21-doc - ansible.utils.update_fact: updates: - path: "lang_docs['Java']" value: name: Java API Documentation id: java_api - path: /usr/share/doc/openjdk-11-doc/api + path: /usr/share/doc/openjdk-21-doc/api index: index.html register: updated - set_fact: diff --git a/playbooks/monitoring.yml b/playbooks/monitoring.yml index 982e6c8..260d200 100644 --- a/playbooks/monitoring.yml +++ b/playbooks/monitoring.yml @@ -127,6 +127,9 @@ # trigger metrics update whenever TEAM/SITE/version/update-version change so we can update the values in prometheus [Path] PathModified=/icpc/TEAM + PathModified=/icpc/TEAMID + PathModified=/icpc/TEAMAFFILIATION + PathModified=/icpc/TEAMNAME PathModified=/icpc/SITE PathModified=/icpc/version PathModified=/icpc/update-version @@ -136,3 +139,28 @@ - name: enable icpc-static-node-exporter.path service: name=icpc-static-node-exporter.path enabled=yes + +# - name: install s.py script +# copy: +# src: files/s.py +# dest: /usr/local/bin/s.py +# mode: 0755 + +- name: install python3-xlib for s.py library + apt: + state: present + pkg: python3-xlib + + +- name: key for grafana apt repo + apt_key: + url: https://apt.grafana.com/gpg.key + state: present + keyring: /etc/apt/trusted.gpg.d/grafana.gpg +- name: apt repo for grafana + apt_repository: repo="deb https://apt.grafana.com stable main" update_cache=yes +- name: install promtail (for sending logs to our server) + apt: + state: present + pkg: + - promtail diff --git a/playbooks/reverseproxy.yml b/playbooks/reverseproxy.yml index cc7fb93..c1a4106 100644 --- a/playbooks/reverseproxy.yml +++ b/playbooks/reverseproxy.yml @@ -12,6 +12,16 @@ state: absent notify: reload nginx +# - name: install the ssl data +# ansible.builtin.copy: +# content: "{{ item.content }}" +# dest: /etc/ssl/{{ item.dest }} +# mode: "{{ item.mode }}" +# notify: reload nginx +# loop: +# - { content: "{{ reverseproxy_key }}", dest: reverseproxy.key, mode: "0600" } +# - { content: "{{ reverseproxy_cert }}", dest: reverseproxy.cert, mode: "0644" } + - name: use the snakeoil cert, since squid will be proxying everything and mitms things/accepts any certificate ansible.builtin.copy: remote_src: true diff --git a/playbooks/reversetunnel.yml b/playbooks/reversetunnel.yml index 2deb8e0..1b58c88 100644 --- a/playbooks/reversetunnel.yml +++ b/playbooks/reversetunnel.yml @@ -23,6 +23,14 @@ group: jumpy dest: /home/jumpy/.ssh/id_ed25519-cert.pub +# not needed because we're using an ssh ca instead +# - name: set up authorized key for someone to log in to this team machine over the reverse tunnel +# authorized_key: +# user: "{{ item }}" +# key: "{{ jumpbox_authorized_key }}" +# with_items: +# - root +# - icpcadmin - name: create autossh service template: src=files/autossh.service.j2 dest=/etc/systemd/system/autossh.service diff --git a/playbooks/system.yml b/playbooks/system.yml index a14be78..2fc065e 100644 --- a/playbooks/system.yml +++ b/playbooks/system.yml @@ -4,6 +4,7 @@ pkg: # performance tools - htop + - btop # a modern resource monitor - dstat - iotop - sysstat @@ -13,6 +14,7 @@ - curl # debugging connection things - ncdu - jq + - jc # for json output form various commands # Needed for wifi - wpasupplicant - iw diff --git a/runvm.sh b/runvm.sh index ac08abb..b5a59c2 100755 --- a/runvm.sh +++ b/runvm.sh @@ -1,7 +1,7 @@ #!/bin/bash # Default group for the VM in ansible. This lets you use group_vars/$VARIANT for site specific configuration -VARIANT=${1:-all} +VARIANT=${1:-generic} SSHPORT=2222 SSHKEY="$PWD/configs/imageadmin-ssh_key" @@ -117,7 +117,7 @@ function setresolution() { runssh sudo -u contestant env DISPLAY=:0 xrandr --size 1440x900 } -qemu-system-x86_64 -smp 2 -m 4096 -drive file="output/$BASEIMG",index=0,media=disk,format=qcow2 -global isa-fdc.driveA= --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --daemonize --pidfile $PIDFILE $SNAPSHOT -vnc :0 -vga qxl -spice port=5901,disable-ticketing -usbdevice tablet +qemu-system-x86_64 -smp 2 -m 4096 -drive file="output/$BASEIMG",index=0,media=disk,format=qcow2 -global isa-fdc.driveA= --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --daemonize --pidfile $PIDFILE $SNAPSHOT -vnc :0 -device VGA,edid=on,xres=1440,yres=900 -usbdevice tablet ALIVE=0 waitforssh diff --git a/secrets/gen-secrets.sh b/secrets/gen-secrets.sh index 217b440..04d9e3d 100755 --- a/secrets/gen-secrets.sh +++ b/secrets/gen-secrets.sh @@ -42,8 +42,8 @@ ssh-keygen -s ./server_ca -h \ ssh-keygen -s ./server_ca -h \ -I "contestmanager.icpcnet.internal host key" \ - -n "contestmanager,contestmanager.icpcnet.internal,icpc.cloudcontest.org" \ ./contestmanager.icpcnet.internal_host_ed25519_key + # -n "contestmanager,contestmanager.icpcnet.internal.icpc.cloudcontest.org" # TODO: this should have the externally visible hostname of the management server # sign the icpcadmin user key (allowing to log into the icpc machine with root, icpcadmin, or contestant) ssh-keygen -s ./server_ca \ diff --git a/test_final.sh b/test_final.sh index 378d775..d8d0bfa 100755 --- a/test_final.sh +++ b/test_final.sh @@ -22,7 +22,18 @@ function cleanup() { } set -x -qemu-system-x86_64 -smp 2 -m 4096 -hda $BASEIMG -global isa-fdc.driveA= --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --daemonize --pidfile $PIDFILE $SNAPSHOT -vnc :0 -vga qxl -spice port=5901,disable-ticketing -usbdevice tablet +qemu-system-x86_64 -smp 2 \ + -m 4096 \ + -hda $BASEIMG \ + -global isa-fdc.driveA= \ + --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 \ + -net nic \ + --daemonize --pidfile $PIDFILE \ + $SNAPSHOT \ + -vnc :0 \ + -device VGA,edid=on,xres=1440,yres=900 \ + -usbdevice tablet +# qemu-system-x86_64 -smp 1 -m 1024 -hda output/$BASEIMG -global isa-fdc.driveA= -monitor stdio --enable-kvm -net user,hostfwd=tcp::$SSHPORT-:22 -net nic --pidfile $PIDFILE $SNAPSHOT -vnc :0 -vga qxl -spice port=5901,disable-ticketing -usbdevice tablet set +x CMD=1 diff --git a/test_final_efi.sh b/test_final_efi.sh index 5b3f120..88d8a35 100755 --- a/test_final_efi.sh +++ b/test_final_efi.sh @@ -6,7 +6,7 @@ PIDFILE="tmp/qemu.pid" SNAPSHOT="-snapshot" ALIVE=0 -BASEIMG="*_image-amd64.img" +BASEIMG="*12_image-amd64.img" function launchssh() { echo "Launching ssh session"
idsitenameaffiliationspecs
{m['team']}{m['site']}{m['name']}{m['affiliation']}{m.get('cpu_cores',0)}@{m.get('cpu_max',0):.2f}GHz
{m.get('memory',0) / 1024.0 :.2f}GiB Ram