Changes to pxe_utils

This commit is contained in:
Jan 2026-01-28 09:21:36 +01:00
parent 6e20b00f72
commit 1ea32db985
25 changed files with 805 additions and 350 deletions

3
tools/pxe_utils/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
api_key.txt
__pycache__/
*.pyc

View file

@ -1,5 +1,5 @@
# Use an official Python runtime as a base image
FROM python:3.12-bookworm
FROM python:3.12-bullseye
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
@ -11,8 +11,8 @@ WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN apt install cups
RUN apt update -y && apt install cups cups-bsd -y
# Copy the project files
COPY . .

View file

@ -3,17 +3,10 @@ import json
import requests
import os
import label
import subprocess
app = Flask(__name__)
def pretty_print_POST(req):
"""
At this point it is completely built and ready
to be fired; it is "prepared".
However pay attention at the formatting used in
this function because it is programmed to be pretty
printed and may differ from the actual request.
"""
print('{}\n{}\r\n{}\r\n\r\n{}'.format(
'-----------START-----------',
req.method + ' ' + req.url,
@ -25,18 +18,26 @@ FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
@app.route('/')
def index():
return("↑ ↑ ↓ ↓ ← → ← → B A")
@app.route('/snipe_api')
def home():
api_key = os.environ['API_KEY']
return api_key
with open("./api_key.txt", "r") as f:
return f.read().strip()
@app.route('/download_late_command')
def download_file():
@app.route('/late_command.sh')
def download_late():
try:
return send_from_directory(FILES_DIR, "late_command.sh", as_attachment=True)
except FileNotFoundError:
abort(404, description="File not found")
@app.route('/preseed_late.sh')
def download_file():
try:
return send_from_directory(FILES_DIR, "preseed_late.sh", as_attachment=True)
except FileNotFoundError:
abort(404, description="File not found")
@app.route('/preseed.cfg')
def download_pre():
try:
@ -44,8 +45,14 @@ def download_pre():
except FileNotFoundError:
abort(404, description="File not found")
@app.route('/change_language.sh')
def download_lang():
try:
return send_from_directory(FILES_DIR, "change_language.sh", as_attachment=True)
except FileNotFoundError:
abort(404, description="File not found")
@app.route("/label", methods=["POST"])
@app.route("/label-demo", methods=["POST"])
def build():
typst_bytes = request.get_data()
typst_string = typst_bytes.decode("utf-8")
@ -57,13 +64,37 @@ def build():
return "Failed"
pdf = label.compile_pdf(j)
# print(pdf)
# with open("./temp.pdf","wb") as f:
# f.write(pdf)
subprocess.run(
["lpr", "-H", "10.200.4.12", "-P", "DYMO", "-o", "landscape", "-"], input=pdf
)
return "Success"
@app.route("/label", methods=["POST"])
def batch():
typst_bytes = request.get_data()
typst_string = typst_bytes.decode("utf-8")
try:
j = json.loads(typst_string)
except json.JSONDecodeError as e:
print(e)
return "Failed"
pdf = label.compile_pdf(j,batch=True)
# print(pdf)
# with open("./temp.pdf","wb") as f:
# f.write(pdf)
print("Would print")
return "Success"
subprocess.run(
["lpr", "-H", "10.200.4.12", "-P", "DYMO", "-o", "landscape", "-"], input=pdf
)
return "Success"
if __name__ == '__main__':
app.run(debug=True)

View file

@ -0,0 +1,67 @@
#import "@preview/tiaoma:0.3.0"
#set page(width: 89mm, height: 36mm,
margin: (
top: 2mm,
bottom: 0mm,
left: 3mm,
right: 3mm,
))
#set text(font: "DejaVu Sans Mono")
#let label(computer) = block[
#table(
columns: (2cm,1fr,auto),
align: (center,left,center),
stroke: 0pt,
inset: 0mm,
// gutter: 0mm,
[#image("logo_stack.png",width: 60%)],
[
#set text(11pt)
angestoepselt e.V. \
#set text(20pt)
#computer.id
#set text(10pt)
],[
#tiaoma.barcode(
computer.id,
"QRCode",
height: 20mm,
)
]/*,
table.cell(colspan: 3)[
#set text(8pt)
#block(height: 0.5mm)
#computer.distribution/#computer.version/#computer.cpu/#computer.memory/#computer.disk/ID:#computer.id
] */
)
#set text(8pt)
#computer.distribution/#computer.version/#computer.cpu/#computer.memory/#computer.disk/
]
#let charger(computer) = block[
#table(
columns: (2cm,1fr,auto),
align: (center,left,center),
stroke: 0pt,
inset: 1mm,
[#image("logo_stack.png",width: 60%)],
[
#set text(8pt)
Ladegerät:\
#set text(20pt)
#computer.id
#set text(8pt)
],[
#tiaoma.barcode(
computer.id,
"QRCode",
height: 20mm,
)
]
)
]
#let computer = json(bytes(sys.inputs.computer))
#label(computer)

View file

@ -0,0 +1,130 @@
#!/usr/bin/env bash
# change-system-language-with-zenity.sh
# GUI (Zenity) to set system language on Debian (Cinnamon) from a restricted list.
# Run from a graphical session with sudo:
# sudo -E bash change-system-language-with-zenity.sh
set -euo pipefail
log() { printf "[*] %s\n" "$*"; }
# 0) Must be root
if [[ $EUID -ne 0 ]]; then
echo "Please run as root (e.g., sudo -E bash $0)."
exit 1
fi
# 0.1) Require a GUI session
if [[ -z "${DISPLAY:-}" ]]; then
echo "No DISPLAY detected. Run this from a graphical session."
exit 1
fi
# 1) Ensure zenity + locales
if ! command -v zenity >/dev/null 2>&1; then
log "Installing 'zenity'…"
apt-get update -y
DEBIAN_FRONTEND=noninteractive apt-get install -y zenity
fi
if ! dpkg -s locales >/dev/null 2>&1; then
log "Installing 'locales'…"
apt-get update -y
DEBIAN_FRONTEND=noninteractive apt-get install -y locales
fi
SUPPORTED_FILE="/usr/share/i18n/SUPPORTED"
if [[ ! -f "$SUPPORTED_FILE" ]]; then
zenity --error --title="Locale List Missing" \
--text="Cannot find $SUPPORTED_FILE. Aborting."
exit 1
fi
# 2) Restrict choices to ONLY these locales
# (Adjust here if you want different variants.)
REQUESTED_LOCALES=(
"en_US.UTF-8" # English (United States)
"fa_IR.UTF-8" # Persian (Iran)
"ar_SA.UTF-8" # Arabic (Saudi Arabia)
"uk_UA.UTF-8" # Ukrainian (Ukraine)
"de_DE.UTF-8" # German (Germany)
"fr_FR.UTF-8"
)
# Keep only those actually listed in SUPPORTED (prevents locale-gen errors)
mapfile -t AVAILABLE_LOCALES < <(
grep -E '^\S+\s+UTF-8' "$SUPPORTED_FILE" \
| awk '{print $1}' \
| grep -Fx -f <(printf "%s\n" "${REQUESTED_LOCALES[@]}") \
| sort -u
)
if (( ${#AVAILABLE_LOCALES[@]} == 0 )); then
zenity --error --title="No Locales Available" \
--text="None of the requested locales are available on this system."
exit 1
fi
# Friendly labels
friendly_label() {
case "$1" in
en_US.UTF-8) echo "English (United States) — en_US.UTF-8";;
fr_FR.UTF-8) echo "French (France) - fr_FR.UTF-8";;
fa_IR.UTF-8) echo "Persian (Farsi, Iran) — fa_IR.UTF-8";;
ar_SA.UTF-8) echo "Arabic (Saudi Arabia) — ar_SA.UTF-8";;
uk_UA.UTF-8) echo "Ukrainian (Ukraine) — uk_UA.UTF-8";;
de_DE.UTF-8) echo "German (Germany) — de_DE.UTF-8";;
*) echo "$1";;
esac
}
# 3) Build Zenity radiolist (default en_US if present else first)
ZENITY_ARGS=()
DEFAULT="en_US.UTF-8"
for loc in "${AVAILABLE_LOCALES[@]}"; do
selected="FALSE"
[[ "$loc" == "$DEFAULT" ]] && selected="TRUE"
ZENITY_ARGS+=("$selected" "$loc" "$(friendly_label "$loc")")
done
if ! printf '%s\n' "${AVAILABLE_LOCALES[@]}" | grep -q '^en_US\.UTF-8$'; then
ZENITY_ARGS[0]="TRUE"
fi
CHOICE="$(zenity --list \
--radiolist \
--title="Choose System Language" \
--width=700 --height=420 \
--column="Select" --column="Locale" --column="Description" \
"${ZENITY_ARGS[@]}")" || true
[[ -z "${CHOICE:-}" ]] && exit 0 # user cancelled
TARGET_LOCALE="$CHOICE"
TARGET_LANG_LINE="${TARGET_LOCALE} UTF-8"
zenity --question \
--title="Confirm Language Change" \
--text="Set the system language to:\n\n<b>${TARGET_LOCALE}</b>\n\nThis updates /etc/locale.gen, runs locale-gen, and sets defaults via update-locale.\nLog out or reboot for Cinnamon to fully apply it." \
--no-wrap \
--ok-label="Apply" --cancel-label="Cancel" || exit 0
# Generate
if ! locale-gen 2> >(tee /tmp/locale-gen.err >&2); then
zenity --error --title="locale-gen failed" \
--text="locale-gen encountered an error.\n\nSee /tmp/locale-gen.err for details."
exit 1
fi
# Set system defaults
update-locale LANG="${TARGET_LOCALE}" LANGUAGE="${TARGET_LOCALE%%.*}:en"
# Mirror LANG in /etc/environment
if grep -q '^LANG=' /etc/environment 2>/dev/null; then
sed -i "s/^LANG=.*/LANG=${TARGET_LOCALE}/" /etc/environment
else
echo "LANG=${TARGET_LOCALE}" >> /etc/environment
fi
zenity --info --title="Language Updated" \
--text="System default language set to:\n\n<b>${TARGET_LOCALE}</b>\n\nLog out and back in (or reboot) for Cinnamon to apply it to your desktop session." \
--no-wrap

View file

@ -0,0 +1,229 @@
#!/bin/bash
set -euxo pipefail
# Variables
PXE_API_SERVER="http://10.7.3.101:8888"
LABEL_PROXY_SERVER="http://10.7.5.11:8888"
SNIPE_IT_SERVER="https://computer.z31.it"
WIFI_SSID=""
WIFI_PASSWORD=""
LABEL_PROXY=false
while [[ $# -gt 0 ]]; do
case "$1" in
--table)
LABEL_PROXY=true
shift
;;
*)
echo "Unbekannte Flag/Parameter: $1"
exit 1
;;
esac
done
echo "Starte late_command Ausfuehrung"
cd "$(dirname "$0")"
### CONFIGURATION
# Move poweroff to /usr/bin so Tanja shuts up about it.
echo "Kopiere poweroff in /usr/bin"
cp /sbin/poweroff /usr/bin/poweroff
# Compile additional locales to be able to change language
echo "Generiere zusaetzliche Locales"
add_locale () {
LINE="$1"
grep -qxF "$LINE" "/etc/locale.gen" || echo "$LINE" | sudo tee -a "/etc/locale.gen" >/dev/null
}
add_locale "en_US.UTF-8 UTF-8"
add_locale "fr_FR.UTF-8 UTF-8"
add_locale "ru_RU.UTF-8 UTF-8"
add_locale "ru_UA.UTF-8 UTF-8"
add_locale "fa_IR.UTF-8 UTF-8"
add_locale "ar_SA.UTF-8 UTF-8"
sudo locale-gen
sudo update-locale LANG=de_DE.UTF-8
# Check if a Wifi device is detected and notify if no device is detected
echo "Pruefe ob Wifi erkannt wird."
category=`hostnamectl | grep Chassis | cut -d: -f2`
if nmcli -t -f TYPE device status | grep -qx "wifi"; then
echo "Wifi erkannt."
echo "Verbinde mit Setup Wifi"
nmcli device wifi connect "$WIFI_SSID" password "$WIFI_PASSWORD"
else
if [[ $category =~ "laptop" || $category =~ "notebook" ]]; then\
echo "Wifi wurde nicht erkannt. Warne User"
zenity --error --text "Es wurde kein Wifi Adapter gefunden. Bitte pruefe ob die Treiber richtig installiert sind." --width=500 --height=200
else
echo "Geraet ist kein Laptop. Wifi nicht unbedingt erwartet"
fi
fi
echo "Registriere Geraet in Snipe-IT"
### SNIPE IT AND LABEL PRINT
api_key=$(curl -s "${PXE_API_SERVER}/snipe_api")
# CPU Model
cpu_model=`cat /proc/cpuinfo | grep 'model name' | uniq | cut -c14-39 | sed -e 's/([^()]*)//g' | tr -d ' ' | cut -c -12`
# OS Distribution and Version
if [ -f /etc/os-release ]; then
. /etc/os-release
os_distro="$NAME"
os_version="$VERSION"
else
os_distro="Unknown"
os_version="Unknown"
fi
# Total RAM
total_ram=$(awk '/MemTotal:/ { print int($2/1024/1024+0.5) }' < /proc/meminfo)
# Free space on root (/)
free_space=$(df -h / | awk 'NR==2 { print $4 }')
if [[ $category =~ "laptop" || $category =~ "notebook" ]]; then\
echo "Information ueber Laptop sammeln"
model=2
battery=$(acpi -V | grep '^Battery.*%$' | tail -c 4 || echo "None")
display=`xrandr | awk '/ connected/{print sqrt( ($(NF-2)/10)^2 + ($NF/10)^2 )/2.54}' | cut -c -2 | head -n 1`
else
model=1
fi
# You can now use these variables as needed
# For example, to print them later:
if [[ $(lsblk | grep sr0) ]]; then
odd=ja
else
odd=nein
fi
mac=`ip link | sed -n "/BROADCAST.*state UP/{n;p}" | tail -1 | tr -s " " | cut -d" " -f3`
serialno=`sudo dmidecode -s system-serial-number`
name=`echo $os_distro/$os_version/$cpu_model/$total_ram/$free_space`
anydeskid=4711
echo $name
if [[ $model == 1 ]]; then
post_data() {
cat << EOF
{
"status_id": "2",
"name": "$name",
"model_id": "$model",
"serial": "$serialno",
"_snipeit_mac_address_1": "$mac",
"_snipeit_betriebssystem_2": "$os_distro $os_version",
"_snipeit_festplatte_4": "$free_space",
"_snipeit_prozessor_5": "$cpu_model",
"_snipeit_arbeitsspeicher_6": "$total_ram",
"_snipeit_optisches_laufwerk_7": "$odd",
"_snipeit_anydeskid_10": "$anydeskid"
}
EOF
}
else
post_data() {
cat << EOF
{
"status_id": "2",
"name": "$name",
"model_id": "$model",
"serial": "$serialno",
"_snipeit_mac_address_1": "$mac",
"_snipeit_betriebssystem_2": "$os_distro $os_version",
"_snipeit_festplatte_4": "$free_space",
"_snipeit_prozessor_5": "$cpu_model",
"_snipeit_arbeitsspeicher_6": "$total_ram",
"_snipeit_optisches_laufwerk_7": "$odd",
"_snipeit_display_8": "$display",
"_snipeit_akku_9": "$battery",
"_snipeit_anydeskid_10": "$anydeskid"
}
EOF
}
fi
curl --request GET \
--url "${SNIPE_IT_SERVER}/api/v1/hardware?limit=5&search=${mac}" \
--header 'accept: application/json' \
--header 'authorization: Bearer '$api_key'' \
--header 'content-type: application/x-www-form-urlencoded' > ./check_result.json
asset_tag=$(jq -j .rows[].asset_tag ./check_result.json)
echo $asset_tag
if [ ! -z ${asset_tag} ]
then
echo "Rechner wurde in Snipe-IT bereits registiert. Frage User nach erneuten Label Druck"
if zenity --question --text="Der Rechner ist ist bereits eingetragen \n RE${asset_tag} \n Soll das Label nochmal gedruckt werden?" --width=500 --height=200; then
echo "Generiere Label"
print_data() {
cat << EOF
{
"id": "$asset_tag",
"distribution": "$os_distro",
"version": "$os_version",
"cpu": "$cpu_model",
"memory": "$total_ram",
"disk": "$free_space"
}
EOF
}
echo "Drucke Label"
curl --request POST -d "$(print_data)" "${PXE_API_SERVER}/label"
else
echo "User chose No or closed the dialog"
fi
exit 0
fi
echo Registriere Computer $(post_data)
# curl --request POST \
# --url "${SNIPE_IT_SERVER}/api/v1/hardware" \
# --header 'accept: application/json' \
# --header 'authorization: Bearer '$api_key'' \
# --header 'Content-Type: application/json' \
# --data "$(post_data)" > ./result.json
# get missing information from payload
# asset_tag=$(cat ./result.json | jq -r '.payload.asset_tag')
# result_jq=$(cat ./result.json | jq -r '.status')
# erstellt_am=$(cat ./result.json | jq -r '.payload.created_at')
#
asset_tag=00000
echo "Asset Tag des Rechners: $asset_tag"
echo "Generiere Labeldaten"
print_data() {
cat << EOF
{
"id": "$asset_tag",
"distribution": "$os_distro",
"version": "$os_version",
"cpu": "$cpu_model",
"memory": "$total_ram",
"disk": "$free_space"
}
EOF
}
echo "Drucke Label"
if $LABEL_PROXY; then
echo "PROXY"
curl --request POST -d "$(print_data)" "${LABEL_PROXY_SERVER}/label"
else
echo "PXE"
curl --request POST -d "$(print_data)" "${PXE_API_SERVER}/label"
fi
# | lpr -H 10.200.4.12:631 -P DYMO -o landscape -
zenity --info --text "Label wird gedruckt \n $asset_tag \n Press OK to exit" --width=500 --height=200

View file

@ -1,4 +1,3 @@
#!/bin/bash
touch "/home/computerspende/test.txt"

View file

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -2,7 +2,7 @@
#set page(width: 89mm, height: 36mm,
margin: (
top: 2mm,
bottom: 2mm,
bottom: 0mm,
left: 3mm,
right: 3mm,
))
@ -19,7 +19,6 @@
[
#set text(11pt)
angestoepselt e.V. \
Passwort: csw \
#set text(20pt)
#computer.id
#set text(10pt)
@ -37,7 +36,7 @@
] */
)
#set text(10pt)
#set text(8pt)
#computer.distribution/#computer.version/#computer.cpu/#computer.memory/#computer.disk/ID:#computer.id
]

View file

@ -0,0 +1,151 @@
#!ipxe
:start
isset ${arch} && goto skip_arch_detect ||
cpuid --ext 29 && set arch x86_64 || set arch i386
iseq ${buildarch} arm64 && set arch arm64 ||
:skip_arch_detect
chain --autofree boot.cfg ||
echo Attempting to retrieve latest upstream version number...
chain --timeout 5000 https://boot.netboot.xyz/version.ipxe ||
ntp 0.pool.ntp.org ||
iseq ${cls} serial && goto ignore_cls ||
set cls:hex 1b:5b:4a # ANSI clear screen sequence - "^[[J"
set cls ${cls:string}
:ignore_cls
isset ${menu} && goto ${menu} ||
isset ${ip} || dhcp
:main_menu
clear menu
set space:hex 20:20
set space ${space:string}
isset ${next-server} && menu ${site_name} v${version} - next-server: ${next-server} || menu ${site_name}
item --gap Angestoepselt:
item angestoepseltdefault ${space} Boot angestoepselt ISO (Default)
item angestoepseltfallback ${space} Boot angestoepselt ISO (Fallback)
item angestoepselt2 ${space} Eigenes IPXE
item --gap Default:
item local ${space} Boot from local hdd
item --gap Distributions:
iseq ${menu_linux} 1 && item linux ${space} Linux Network Installs (64-bit) ||
iseq ${menu_linux_i386} 1 && item linux-i386 ${space} Linux Network Installs (32-bit) ||
iseq ${menu_linux_arm} 1 && item linux-arm ${space} Linux Network Installs (arm64) ||
iseq ${menu_live} 1 && item live ${space} Live CDs ||
iseq ${menu_live_arm} 1 && item live-arm ${space} Live CDs ||
iseq ${menu_bsd} 1 && item bsd ${space} BSD Installs ||
iseq ${menu_unix} 1 && item unix ${space} Unix Network Installs ||
iseq ${menu_freedos} 1 && item freedos ${space} FreeDOS ||
iseq ${menu_windows} 1 && item windows ${space} Windows ||
item --gap Tools:
iseq ${menu_utils} 1 && iseq ${platform} efi && item utils-efi ${space} Utilities (UEFI) ||
iseq ${menu_utils} 1 && iseq ${platform} pcbios && iseq ${arch} x86_64 && item utils-pcbios-64 ${space} Utilities (64-bit) ||
iseq ${menu_utils} 1 && iseq ${platform} pcbios && iseq ${arch} i386 && item utils-pcbios-32 ${space} Utilities (32-bit) ||
iseq ${menu_utils_arm} 1 && item utils-arm ${space} Utilities (arm64) ||
item change_arch ${space} Architecture: ${arch}
item shell ${space} iPXE shell
item netinfo ${space} Network card info
iseq ${menu_pci} 1 && item lspci ${space} PCI Device List ||
item about ${space} About netboot.xyz
item --gap Signature Checks:
item sig_check ${space} netboot.xyz [ enabled: ${sigs_enabled} ]
isset ${github_user} && item --gap Custom Github Menu: ||
isset ${github_user} && item custom-github ${space} ${github_user}'s Custom Menu ||
isset ${custom_url} && item --gap Custom URL Menu: ||
isset ${custom_url} && item custom-url ${space} Custom URL Menu ||
isset ${menu} && set timeout 0 || set timeout ${boot_timeout}
choose --timeout ${timeout} --default ${menu} menu || goto local
echo ${cls}
goto ${menu} ||
iseq ${sigs_enabled} true && goto verify_sigs || goto change_menu
:verify_sigs
imgverify ${menu}.ipxe ${sigs}${menu}.ipxe.sig || goto error
goto change_menu
:change_menu
chain ${menu}.ipxe || goto error
goto main_menu
:error
echo Error occurred, press any key to return to menu ...
prompt
goto main_menu
:angestoepseltdefault
imgfree
set mirror http://deb.debian.org
set dir debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64
set mirrorcfg mirror/suite=trixie
set install_params auto=true priority=critical preseed/url=http://10.7.3.101:8888/preseed.cfg
kernel ${mirror}/${dir}/linux ${install_params} ${mirrorcfg} -- quiet ${params} initrd=initrd.magic ${cmdline}
initrd ${mirror}/${dir}/initrd.gz
boot
:angestoepseltfallback
imgfree
# Basis-URL Debian netboot Installer
set base http://deb.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64
# Kernel-Parameter (Lenovo-safe + Auto-Install)
set params auto=true priority=critical \
preseed/url=http://10.7.3.101:8888/preseed.cfg \
nomodeset intel_iommu=off acpi=off noapic \
loglevel=7
echo Booting Debian 13 automated installer...
# WICHTIG: initrd Name explizit setzen (verhindert unknown-block(0,0) Panic)
kernel ${base}/linux ${params} initrd=initrd.gz ---
initrd ${base}/initrd.gz initrd.gz
boot
imgfree
set base http://deb.debian.org/debian/dists/trixie/main/installer-amd64/current/images/netboot/debian-installer/amd64
set p auto=true priority=critical preseed/url=http://10.7.3.101:8888/preseed.cfg nomodeset intel_iommu=off
set m mirror/suite=trixie
initrd ${base}/initrd.gz initrd.gz
boot
:angestoepselt2
chain angestoepselt.ipxe || goto error
goto linux_menu
:local
echo Booting from local disks ...
exit 1
:shell
echo Type "exit" to return to menu.
set menu main_menu
shell
goto main_menu
:change_arch
iseq ${arch} x86_64 && set arch i386 && set menu_linux_i386 1 && set menu_linux 0 && goto main_menu ||
iseq ${arch} i386 && set arch x86_64 && set menu_linux_i386 0 && set menu_linux 1 && goto main_menu ||
goto main_menu
:sig_check
iseq ${sigs_enabled} true && set sigs_enabled false || set sigs_enabled true
goto main_menu
:about
chain https://boot.netboot.xyz/about.ipxe || chain about.ipxe
goto main_menu
:custom-github
chain https://raw.githubusercontent.com/${github_user}/netboot.xyz-custom/master/custom.ipxe || goto error
goto main_menu
:custom-url
chain ${custom_url}/custom.ipxe || goto error
goto main_menu
:custom-user
chain custom/custom.ipxe
goto main_menu

View file

@ -0,0 +1,119 @@
### Preseed Installation fuer Debian 13 Trixie
### Vorbereitung
d-i debconf/priority string critical
d-i finish-install/reboot_in_progress note
popularity-contest popularity-contest/participate boolean false
### Lokalisierung
d-i debian-installer/language string de
d-i debian-installer/country string DE
d-i debian-installer/locale string de_DE.UTF-8
d-i localechooser/supported-locales multiselect de_DE.UTF-8
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/xkb-keymap select de
d-i keyboard-configuration/variant select Deutschland
d-i keyboard-configuration/modelcode string pc105
d-i clock-setup/utc boolean true
d-i time/zone string Europe/Berlin
d-i tzdata/Areas select Europe
d-i tzdata/Zones/Europe select Berlin
### Netzwerk
d-i netcfg/enable boolean true
d-i netcfg/choose_interface select auto
d-i netcfg/hostname string computerspende
d-i netcfg/get_domain string unassigned-domain
### APT / Mirror
d-i mirror/country string manual
d-i mirror/http/hostname string ftp2.de.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i apt-setup/use_mirror boolean true
d-i apt-setup/disable-cdrom-entries boolean true
d-i apt-setup/non-free-firmware boolean true
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
### Benutzer
d-i passwd/root-login boolean false
d-i passwd/username string computerspende
d-i passwd/user-fullname string computerspende
d-i passwd/user-uid string 1000
d-i passwd/user-password password csw
d-i passwd/user-password-again password csw
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
d-i passwd/user-default-groups string audio cdrom video sudo
### Software
tasksel tasksel/first multiselect standard, gnome-desktop
d-i pkgsel/install-language-support boolean true
d-i pkgsel/update-policy select Install security updates automatically
d-i pkgsel/upgrade select full-upgrade
d-i pkgsel/include string git vim htop curl jq acpi
### Partitionierung
# Finde die groesste nicht USB Disk. (HDD bei Desktops erst nach Installation anschliessen
d-i partman/early_command string \
DISK="$(/lib/partman/list-devices disk | while read d; do b="$(basename "$d")"; r="$(cat "/sys/block/$b/removable" 2>/dev/null || echo 1)"; s="$(cat "/sys/block/$b/size" 2>/dev/null || echo 0)"; [ "$r" = "0" ] && echo "$s $d"; done | sort -nr | head -n1 | awk '{print $2}')"; \
[ -z "$DISK" ] && DISK="$(/lib/partman/list-devices disk | head -n1)"; \
echo "Auto-selected install disk: $DISK" > /var/log/partman-auto-disk.log; \
debconf-set partman-auto/disk "$DISK"
d-i partman-partitioning/choose_label select gpt
d-i partman/choose_label select gpt
d-i partman-md/confirm boolean true
d-i partman-md/deleteverify boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/vgdelete_confirm boolean true
d-i lvmcfg/vgdelete_confirm boolean true
d-i partman-auto/method string regular
# Legt folgende Partitionen an (EFI, Root, Swap)
d-i partman-auto/expert_recipe string \
uefi-bios-atomic :: \
1 1 2 free \
$iflabel{ gpt } \
$bios_grub{ } \
method{ biosgrub } \
. \
512 512 512 fat32 \
$iflabel{ gpt } \
$primary{ } \
method{ efi } format{ } \
mountpoint{ /boot/efi } \
. \
2048 2048 2048 linux-swap \
method{ swap } format{ } \
. \
1000 10000 -1 ext4 \
$primary{ } \
method{ format } format{ } \
use_filesystem{ } filesystem{ ext4 } \
mountpoint{ / } \
.
d-i partman-auto/choose_recipe select uefi-bios-atomic
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
### GRUB
d-i grub-installer/only_debian boolean true
d-i grub-installer/bootdev string default
d-i partman-efi/non_efi_system boolean true
### late_command (WICHTIG: letzter Befehl ohne ; und ohne \)
d-i preseed/late_command string \
in-target --pass-stdout sh -c 'install -d /opt'; \
in-target --pass-stdout sh -c 'curl -fsSL --retry 5 --retry-delay 2 http://10.7.3.101:8888/preseed_late.sh -o /opt/preseed_late.sh'; \
in-target --pass-stdout sh -c 'chmod +x /opt/preseed_late.sh && /opt/preseed_late.sh'

View file

@ -0,0 +1,12 @@
#!/bin/bash
# === CONFIGURATION ===
LATE_TARGET_SCRIPT="/opt/late_command.sh"
TERMINAL="gnome-terminal"
# =====================
echo 'sudo /opt/late_command.sh' >> /home/computerspende/.bash_history
chown computerspende:computerspende /home/computerspende/.bash_history
curl -s http://10.7.3.101:8888/late_command.sh > $LATE_TARGET_SCRIPT
chmod 777 $LATE_TARGET_SCRIPT
chmod +x $LATE_TARGET_SCRIPT

18
tools/pxe_utils/label.py Normal file
View file

@ -0,0 +1,18 @@
import typst
import json
def compile_pdf(data: dict, batch=False):
data = {"computer": json.dumps(data)}
if batch==True:
temp = "files/batch.typ"
else:
temp = "files/main.typ"
try:
res = typst.compile(input=temp, sys_inputs=data)
except RuntimeError as e:
print(e)
print("Error compiling")
return False
return(res)

View file

@ -13,6 +13,6 @@ print_data() {
EOF
}
curl -X POST http://10.200.4.12:5000/label \
curl -X POST http://localhost:5000/label \
-H "Content-Type: application/json" \
-d "$(print_data)"

26
tools/pxe_utils/readme.md Normal file
View file

@ -0,0 +1,26 @@
# Angestoepselt PXE API
Diese App stellt die Basis des PXE Boots da. Die API uebernimmt folgende Funktionen waehrend des PXE Boots.
- Bereitstellung des preseed.cfg fuer die automatische Debian Installation
- Bereitstellung des Late Command Skriptes fuer die Endeinrichtung des Clients
- Kompilierung des Labels
- Weiterleitung des Label Druckauftrages and Cups
# Netboot.xyz
Der eigentliche PXE Boot erfolgt ueber ein netboot.xyz Server.
Hierbei ist die menu.ipxe anzupassen. Siehe files/netboot/menu.ipxe
# Aktuelle Aenderungen im Vergleich zur Vorgaengerversion:
- Umstieg auf Debian 13 Gnome (voll funktional)
- Volle Kompatibilitaet mit UEFI und Legacy
- Kompatibilitaet mit verschiedenen Disktypen (/dev/sdx, /dev/nvmex, mmcx, etc.)
- !Achtung! Es wird die groesste Platte als Systemplatte genommen. HDDs bei Desktop bitte erst nach der Installtion anschliessen.
- Anlegen einer Swap Partition mit 2GB
- Late Command Skript in Bash History (Im Terminal Pfeil nach oben zeigt Befehl an)
- poweroff jetzt auch ohne sudo ausfuehrbar
- wichtige locale werden generiert (RU, UA, FR, DE)
- Warnung bei Laptops wenn Wifi nicht funktioniert.
- Automatische Verbindung zu Setup Wifi moeglich
- Fehlender Akku fuehrt nicht mehr zum Skriptabbruch
- Flag hinzugefuegt um zukuenftig ueber 2 Label Drucker zu drucken.

View file

@ -1 +0,0 @@
{"error":"Unauthorized or unauthenticated."}

View file

@ -1,108 +0,0 @@
#!/bin/bash
api_key=$(curl -s http://localhost:5000/snipe_api)
# CPU Model
category=`hostnamectl | grep Chassis | cut -c 21-`
cpu_model=`cat /proc/cpuinfo | grep 'model name' | uniq | cut -c14-39 | sed -e 's/([^()]*)//g' | tr -d ' ' | cut -c -12`
# OS Distribution and Version
if [ -f /etc/os-release ]; then
. /etc/os-release
os_distro="$NAME"
os_version="$VERSION"
else
os_distro="Unknown"
os_version="Unknown"
fi
# Total RAM
total_ram=$(free -h | awk '/^Mem:/ { print $2 }')
# Free space on root (/)
free_space=$(df -h / | awk 'NR==2 { print $4 }')
if [[ $category = "laptop" || $category = "notebook" ]]; then
model=2
battery=`acpi -V | grep '^Battery.*%$' | tail -c 4`
display=`xrandr | awk '/ connected/{print sqrt( ($(NF-2)/10)^2 + ($NF/10)^2 )/2.54}' | cut -c -2 | head -n 1`
else
model=1
fi
# You can now use these variables as needed
# For example, to print them later:
if [[ $(lsblk | grep sr0) ]]; then
odd=ja
else
odd=nein
fi
mac=`ip link | sed -n "/BROADCAST.*state UP/{n;p}" | tail -1 | tr -s " " | cut -d" " -f3`
serialno=`sudo dmidecode -s system-serial-number`
name=`echo $os_distro/$os_version/$cpu/$total_ram/$free_space`
echo $name
post_data() {
cat << EOF
{
"status_id": "2",
"name": "$name",
"model_id": "$model",
"serial": "$serialno",
"_snipeit_mac_address_1": "$mac",
"_snipeit_betriebssystem_2": "$os_distro $os_version",
"_snipeit_festplatte_4": "$free_space",
"_snipeit_prozessor_5": "$cpu_model",
"_snipeit_arbeitsspeicher_6": "$total_ram",
"_snipeit_optisches_laufwerk_7": "$odd",
"_snipeit_display_8": "$display",
"_snipeit_akku_9": "$battery",
"_snipeit_anydeskid_10": "$anydeskid"
}
EOF
}
curl --request GET \
--url 'https://computer.z31.it/api/v1/hardware?limit=5&search='$mac'' \
--header 'accept: application/json' \
--header 'authorization: Bearer '$api_key'' \
--header 'content-type: application/x-www-form-urlencoded' > ./check_result.json
asset_tag=$(jq -j .rows[].asset_tag ./check_result.json)
if [ ! -z ${asset_tag} ]
then
zenity --info --text "Der Rechner ist ist bereits eingetragen RE${asset_tag}" --width=500 --height=200
#echo " Der Rechner ist bereits eingetragen RE${asset_tag}"
exit 0
fi
curl --request POST \
--url https://orga.z31.it/api/v1/hardware \
--header 'accept: application/json' \
--header 'authorization: Bearer '$api_key'' \
--header 'Content-Type: application/json' \
--data "$(post_data)" > ./result.json
# get missing information from payload
asset_tag=$(cat ./result.json | jq -r '.payload.asset_tag')
result_jq=$(cat ./result.json | jq -r '.status')
erstellt_am=$(cat ./result.json | jq -r '.payload.created_at')
print_data() {
cat << EOF
{
"id": "$asset_tag",
"distribution": "$os_distro",
"version": "$os_version",
"cpu": "$cpu_model",
"memory": "$total_ram",
"disk": "$free_space"
}
EOF
}
echo $print_data
curl --request POST -d "$(print_data)" http://10.200.4.12:8000/label | lpr -H 10.200.4.12:631 -P DYMO -o landscape -

View file

@ -1,106 +0,0 @@
### Allgemeines
# Verhindert weniger wichtige Nachfragen
# https://www.debian.org/releases/sarge/s390/ch05s02.html.en
# https://preseed.debian.net/debian-preseed/bullseye/amd64-main-full.txt
d-i debconf/priority string critical
# Deaktiviert die Meldung am Ende, dass die Installation abgeschlossen wurde und man neu starten kann
d-i finish-install/reboot_in_progress note
# Gibt an, ob Infos zum Nutzungsverhalten (installierte/verwendete Software) an Debian gesendet werden
popularity-contest popularity-contest/participate boolean false
# Proprietaere Firmware laden (falls es zu Hardwareproblemen kommt)
#d-i hw-detect/load_firmware boolean true
### Lokalisierung
d-i debian-installer/locale string de_DE
# Keymap setzen reicht nicht, layout/variantcode hilft ebenfalls nicht: https://groups.google.com/g/linux.debian.bugs.dist/c/XYcrRjLwpQM
d-i keyboard-configuration/variant select Deutschland
d-i keyboard-configuration/xkb-keymap select de
d-i clock-setup/utc boolean true
d-i tzdata/Areas select Europe
tzdata/Zones/Europe select Berlin
d-i time/zone string Europe/Berlin
### Partitionierung
# Grub wird automatisch auf den MBR installiert, wenn kein anderes OS vorhanden ist (sicher)
d-i grub-installer/only_debian boolean true
# MBR installation ebenfalls wenn andere OS vorhanden sind (koennte dazu fuehren, dass diese nicht mehr booten)
#d-i grub-installer/with_other_os boolean true
# Verhindert, dass grub alternativ fragt, wo er installiert werden soll
d-i grub-installer/bootdev string /dev/sda
# Fuer die vollautomatische Partitionierung (falls unten aktiv) - Beispiel Lenovo Tiny mit NVMe-SSD
# VirtualBox -> /dev/sda, KVM -> /dev/vda
#d-i partman-auto/disk string /dev/nvme0n1
# Fuer lvm 'lvmcfg/vgdelete_confirm', 'partman-lvm/confirm' und 'partman-lvm/confirm_nooverwrite' setzen
# Siehe https://www.debian.org/releases/stable/s390x/apbs04.de.html Abschnitt B.4.7.1.
d-i partman-auto/method string regular
# Alle Daten auf einer Partition (mit 'home' wird das Home-Verzeichnis auf eine eigene Partition gelegt)
d-i partman-auto/choose_recipe select atomic
# Komplett automatisiert ohne Bestaetigung fuer alle Partitionierungsmethoden (Mit Vorsicht verwenden!)
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman-md/confirm boolean true
d-i partman-md/deleteverify boolean true
d-i lvmcfg/vgdelete_confirm boolean true
d-i partman-lvm/vgdelete_confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
### Software
d-i mirror/country string manual
d-i mirror/http/hostname string ftp2.de.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
# Aktiviert Spiegelserver abseits der Sicherheitsupdates per Netzwerk statt Image
d-i apt-setup/use_mirror boolean true
d-i apt-setup/disable-cdrom-entries boolean true
# Aktiviert offizielle, aber unfreie Repositorys: https://wiki.debian.org/SourcesList
#d-i apt-setup/non-free boolean true
#d-i apt-setup/contrib boolean true
# Vorinstallierte Software
# Programmgruppe kann festlegen, ob z.B. Headless oder eine bestimmte Desktopumgebung (xfce-desktop, kde-desktop usw) vorinstalliert werden soll (siehe B.4.10)
tasksel tasksel/first multiselect standard, cinnamon-desktop
d-i pkgsel/install-language-support boolean true
d-i pkgsel/update-policy select Install security updates automatically
# Alle Pakete automatisch aktualisieren
d-i pkgsel/upgrade select full-upgrade
d-i pkgsel/include string git vim htop curl jq
# Stdout Weiterleitungen funktionieren in in-target nicht ohne --pass-stdout
# Siehe https://askubuntu.com/a/1248987/650986 und https://serverfault.com/questions/390122/how-do-i-pipe-commands-together-in-a-debian-preseed-file
### Benutzerkonten
d-i passwd/username string computerspende
d-i passwd/user-fullname string computerspende
d-i passwd/user-uid string 1000
d-i passwd/user-password password csw
d-i passwd/user-password-again password csw
# root
d-i passwd/root-password password csw
d-i passwd/root-password-again password csw
# Fuer Testsysteme kann die Policy strikter PWs abgeschaltet werden
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
d-i user-setup/enable sudo boolean true
### Netzwerk
d-i netcfg/enable boolean true
d-i netcfg/choose_interface select auto
d-i netcfg/hostname string computerspende
d-i preseed/late_command string \
in-target --pass-stdout bash -c "echo 'computerspende ALL=NOPASSWD:ALL' > /etc/sudoers.d/computerspende"; \
in-target wget -O /home/computerspende/late_command.sh http://10.0.2.4:8888/download_late_command; \
in-target chmod +x /home/computerspende/late_command.sh; \
in-target /root/late_command.sh;

View file

@ -1,100 +0,0 @@
### Allgemeines
# Verhindert weniger wichtige Nachfragen
# https://www.debian.org/releases/sarge/s390/ch05s02.html.en
# https://preseed.debian.net/debian-preseed/bullseye/amd64-main-full.txt
d-i debconf/priority string critical
# Deaktiviert die Meldung am Ende, dass die Installation abgeschlossen wurde und man neu starten kann
d-i finish-install/reboot_in_progress note
# Gibt an, ob Infos zum Nutzungsverhalten (installierte/verwendete Software) an Debian gesendet werden
popularity-contest popularity-contest/participate boolean false
# Proprietaere Firmware laden (falls es zu Hardwareproblemen kommt)
#d-i hw-detect/load_firmware boolean true
### Lokalisierung
d-i debian-installer/locale string de_DE
# Keymap setzen reicht nicht, layout/variantcode hilft ebenfalls nicht: https://groups.google.com/g/linux.debian.bugs.dist/c/XYcrRjLwpQM
d-i keyboard-configuration/variant select Deutschland
d-i keyboard-configuration/xkb-keymap select de
d-i clock-setup/utc boolean true
d-i tzdata/Areas select Europe
tzdata/Zones/Europe select Berlin
d-i time/zone string Europe/Berlin
### Partitionierung
# UEFI-spezifische Einstellungen
d-i partman-efi/non_efi_system boolean false
d-i partman/efi_boot_mountpoint string /boot/efi
# Automatisches Partitionieren mit einem einzelnen Root-Dateisystem
# Grub wird automatisch auf die EFI-Partition installiert, wenn UEFI aktiv ist
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select atomic
# Komplett automatisiert ohne Bestaetigung fuer alle Partitionierungsmethoden (Mit Vorsicht verwenden!)
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman-md/confirm boolean true
d-i partman-md/deleteverify boolean true
d-i lvmcfg/vgdelete_confirm boolean true
d-i partman-lvm/vgdelete_confirm boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
### GRUB Bootloader
d-i grub-installer/only_debian boolean true
# Nicht noetig für UEFI kann zu Konflikten fuehren
#d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev string /dev/sda
### Software
d-i mirror/country string manual
d-i mirror/http/hostname string ftp2.de.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
# Aktiviert Spiegelserver abseits der Sicherheitsupdates per Netzwerk statt Image
d-i apt-setup/use_mirror boolean true
d-i apt-setup/disable-cdrom-entries boolean true
# Aktiviert offizielle, aber unfreie Repositorys: https://wiki.debian.org/SourcesList
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
# Vorinstallierte Software
# Programmgruppe kann festlegen, ob z.B. Headless oder eine bestimmte Desktopumgebung (xfce-desktop, kde-desktop usw) vorinstalliert werden soll (siehe B.4.10)
tasksel tasksel/first multiselect standard, cinnamon-desktop
d-i pkgsel/install-language-support boolean true
d-i pkgsel/update-policy select Install security updates automatically
# Alle Pakete automatisch aktualisieren
d-i pkgsel/upgrade select full-upgrade
d-i pkgsel/include string git vim htop curl jq
# Stdout Weiterleitungen funktionieren in in-target nicht ohne --pass-stdout
# Siehe https://askubuntu.com/a/1248987/650986 und https://serverfault.com/questions/390122/how-do-i-pipe-commands-together-in-a-debian-preseed-file
### Benutzerkonten
d-i passwd/username string computerspende
d-i passwd/user-fullname string computerspende
d-i passwd/user-uid string 1000
d-i passwd/user-password password csw
d-i passwd/user-password-again password csw
# root
d-i passwd/root-password password csw
d-i passwd/root-password-again password csw
# Fuer Testsysteme kann die Policy strikter PWs abgeschaltet werden
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
d-i user-setup/enable sudo boolean true
### Netzwerk
d-i netcfg/enable boolean true
d-i netcfg/choose_interface select auto
d-i netcfg/hostname string computerspende
d-i preseed/late_command string \
in-target --pass-stdout bash -c "echo 'computerspende ALL=NOPASSWD:ALL' > /etc/sudoers.d/computerspende"; \
in-target --pass-stdout bash -c "curl -s 10.200.4.12:8888/download_late_command | bash -s";

View file

@ -1,14 +0,0 @@
import typst
import json
def compile_pdf(data: dict):
data = {"computer": json.dumps(data)}
try:
res = typst.compile(input="files/main.typ", sys_inputs=data)
except RuntimeError as e:
print(e)
print("Error compiling")
return False
print(res)