Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
d3a1dc8
Preserve vhost/TFTP customizations on update, add --branch, fix stick…
darksidemilk Aug 7, 2026
49091c9
Fix EXTERNAL_CA_AND_LETSENCRYPT.md: iPXE trust is not FOG's CA alone
darksidemilk Aug 7, 2026
a2b1f19
Clarify FOG's SSL CA and Secure Boot signing key are now separate
darksidemilk Aug 7, 2026
602ac99
Add design doc: --hostname/--extra-server-name flags + setupacme.sh
darksidemilk Aug 7, 2026
3984766
Add implementation plan for --hostname/--extra-server-name/setupacme.sh
darksidemilk Aug 7, 2026
b382402
Add --hostname flag for non-interactive vhost/cert hostname override
darksidemilk Aug 7, 2026
ab02a75
Fix: --hostname validation errors now exit nonzero instead of usage()…
darksidemilk Aug 7, 2026
accb793
Add repeatable --extra-server-name flag for additive vhost/cert names
darksidemilk Aug 7, 2026
825157d
Fix: --extra-server-name in updatefog.sh also exits nonzero instead o…
darksidemilk Aug 7, 2026
6b6bdfe
Mirror FOG_EXTRA_SERVER_NAMES into globalSettings for GUI visibility
darksidemilk Aug 7, 2026
3a0d336
Add bin/setupacme.sh for ACME leaf renewal against --external-ca
darksidemilk Aug 7, 2026
bd120cd
Fix: remove exitFail=1 (was masking install failures as success), add…
darksidemilk Aug 7, 2026
ca02e0b
Fix: source config.sh + doOSSpecificIncludes so systemctl/initdpath a…
darksidemilk Aug 7, 2026
deae3d4
Document bin/setupacme.sh in EXTERNAL_CA_AND_LETSENCRYPT.md
darksidemilk Aug 7, 2026
ce88f75
Fix final review findings: ACME leaf overwrite protection, setupacme.…
darksidemilk Aug 7, 2026
c8a29e5
Don't preserve ACME leaf across --recreate-keys/--recreate-ca
darksidemilk Aug 7, 2026
15ae546
Merge branch 'working-1.6' into 1013-ipxe-crosscert-doc-fix
darksidemilk Aug 7, 2026
5d84f5e
Record verified Let's Encrypt + iPXE netboot result, correct FOG_WEB_…
darksidemilk Aug 7, 2026
e9c5a0b
Add design docs: customization preservation and three-zone PKI separa…
darksidemilk Aug 7, 2026
95457da
Move iPXE background backup/restore into installfog.sh, keyed to FOG_…
darksidemilk Aug 7, 2026
a01f180
Preserve an admin-supplied Secure Boot pair outside $webdirdest
darksidemilk Aug 7, 2026
17e5299
Write the vhost as a FOG-managed block instead of replacing the whole…
darksidemilk Aug 7, 2026
d8b0f47
Add an optional custom.ipxe hook ahead of FOG's default PXE boot logic
darksidemilk Aug 7, 2026
36e3262
Cover the Setup Mode / db enrollment path in the Secure Boot PKI design
darksidemilk Aug 7, 2026
53ba117
Add versioned kernel/init backups, bin/restorekernel.sh, retire updat…
darksidemilk Aug 7, 2026
a9b071b
Document what survives an install/update in docs/SUPPORTED_CUSTOMIZAT…
darksidemilk Aug 7, 2026
6175274
Fix: managed vhost splice lost prior content because the caller moves…
darksidemilk Aug 8, 2026
745912c
Fix: customizationsDir resolved at source time, before fogprogramdir …
darksidemilk Aug 8, 2026
69f8cea
Mark bin/restorekernel.sh executable
darksidemilk Aug 8, 2026
60f9edf
Fix: restore was reverting FOG's own files in service/ipxe on every u…
darksidemilk Aug 8, 2026
a799551
Scope kernel backups to kernel/init files, and fix restorekernel.sh's…
darksidemilk Aug 8, 2026
fb28219
Back up by subtracting what FOG ships, not by enumerating kernel names
darksidemilk Aug 8, 2026
f3e55fb
Detect and report a custom kernel installed under one of FOG's own names
darksidemilk Aug 8, 2026
69ecdb7
Detect a modified kernel by checksum, since xattrs survive in-place o…
darksidemilk Aug 8, 2026
d0fb7b4
Keep the outgoing kernel in place as bzImage.<version>, and fix a fal…
darksidemilk Aug 8, 2026
ef3a1a3
Create the .<version> kernel sibling at restore time, not backup time
darksidemilk Aug 8, 2026
fabf07d
Make kernel and init selections dropdowns of what is actually on disk
darksidemilk Aug 8, 2026
cee7f1b
Keep web assets out of the kernel dropdown
darksidemilk Aug 8, 2026
f50184d
Label the blank kernel/init option as "use the default"
darksidemilk Aug 8, 2026
620a0bb
Add the split PKI: Root CA plus Web and Client Communication intermed…
darksidemilk Aug 7, 2026
67fa3ec
Remove bin/setupacme.sh -- ACME is not FOG's job
darksidemilk Aug 7, 2026
50e4fad
Add canonical-path indirection so certificates can live outside FOG's…
darksidemilk Aug 7, 2026
11d8c88
Point certDecrypt() at the client communication key when a split PKI …
darksidemilk Aug 7, 2026
a56827b
Parameterise validateExternalCA() by zone so each zone imports indepe…
darksidemilk Aug 7, 2026
40d12f9
Add the PKI selection and per-zone bring-your-own-CA flags
darksidemilk Aug 7, 2026
c19c9d8
Split netbootproto from httpproto so private-CA installs keep HTTPS web
darksidemilk Aug 7, 2026
b1dd1e2
Document the certificate zones in docs/PKI_ZONES.md
darksidemilk Aug 8, 2026
e1a735b
Correct the certDecrypt coupling: it is to the FILE, not to "the web …
darksidemilk Aug 8, 2026
12642e1
Make the split PKI the default for fresh installs
darksidemilk Aug 8, 2026
3a53982
Issue Secure Boot code-signing leaves from a FOG Secure Boot CA inter…
darksidemilk Aug 8, 2026
64b2701
Resolve pkiMode and sslpath before Secure Boot, which runs first
darksidemilk Aug 8, 2026
dabeab0
Document Secure Boot zone status and add continuation context
darksidemilk Aug 8, 2026
3db71b7
Correct the efitools availability claim
darksidemilk Aug 8, 2026
a712d28
Sharpen the efitools note with the upstream tracker evidence
darksidemilk Aug 8, 2026
07c8f54
Verify the db/Setup-Mode path with efitools built from source
darksidemilk Aug 8, 2026
7b5753f
Add --secureboot-ca-cert so the Secure Boot zone is importable like t…
darksidemilk Aug 8, 2026
86e5f47
Do not regenerate the Root CA when its key has been taken offline
darksidemilk Aug 8, 2026
af7e156
Record Secure Boot verified on real UEFI hardware, both enrolment routes
darksidemilk Aug 8, 2026
1688ecd
Record fog-client confirmed on a split server, and the root-trust fol…
darksidemilk Aug 8, 2026
b43e68d
Confirm HTTPS works once the root CA is trusted
darksidemilk Aug 8, 2026
55df7e9
Note two reported dropdown issues in the continuation context
darksidemilk Aug 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 163 additions & 2 deletions bin/installfog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,34 @@ usage() {
echo -e "\t \t\t\t\tdefaults to /opt/fog"
echo -e "\t \t\t\t\tremembered in /etc/fog/fog.conf, so it"
echo -e "\t \t\t\t\tonly needs giving on a first install"
echo -e "\t --hostname\t\tOverride the vhost/cert hostname"
echo -e "\t \t\tdefaults to \`hostname -f\`, remembered in .fogsettings"
echo -e "\t --extra-server-name\tAdd an extra vhost/cert name (repeatable)"
echo -e "\t \t\talongside the primary hostname and detected IPs"
echo -e "\t --split-pki The DEFAULT on a fresh install: a Root CA issuing"
echo -e "\t \t\t\tseparate Web and Client Communication"
echo -e "\t \t\t\tintermediates, so the web certificate can be"
echo -e "\t \t\t\treplaced without breaking fog-client"
echo -e "\t --legacy-pki Keep the single self-signed CA instead of"
echo -e "\t \t\t\tthe split PKI. Fully supported, not deprecated"
echo -e "\t --web-ca-cert/-key/-root\tBring your own CA for the WEB zone only"
echo -e "\t \t\t\t(equivalent to --external-ca --ca-*)"
echo -e "\t --client-ca-cert/-key/-root\tBring your own CA for the CLIENT zone only"
echo -e "\t --client-ca-cn\t\tCN fog-client expects on the pinned cert"
echo -e "\t \t\t\tdefaults to 'FOG Server CA'"
echo -e "\t --root-ca-cert/-key\tSupply the Root CA instead of generating one"
echo -e "\t --secureboot-ca-cert\tYour own SECURE BOOT intermediate: the"
echo -e "\t \t\t\tcertificate enrolled in firmware. Pair it with"
echo -e "\t \t\t\t--secure-boot-key/--secure-boot-cert, which name"
echo -e "\t \t\t\tthe code-signing leaf issued from it. Rotate the"
echo -e "\t \t\t\tleaf freely; the enrolled CA never changes"
echo -e "\t --kernel-backup-count\tHow many prior kernel/init generations to"
echo -e "\t \t\tkeep (default 3). Restore one with"
echo -e "\t \t\tbin/restorekernel.sh. See"
echo -e "\t \t\tdocs/SUPPORTED_CUSTOMIZATIONS.md"
echo -e "\t --restore-kernel-backup\tAlso restore the previous kernel/init set"
echo -e "\t \t\tthis run. Used by updatefog.sh when reverting;"
echo -e "\t \t\tnot normally passed by hand"
echo -e "\t-N --mysqldbname\t\tSpecify the FOG database name"
echo -e "\t \t\t\t\tdefaults to fog"
echo -e "\t-B --backuppath\t\tSpecify the backup path"
Expand All @@ -152,7 +180,12 @@ usage() {
echo -e "\t-E --no-exportbuild\t\tSkip building nfs file"
echo -e "\t-X --exitFail\t\tDo not exit if item fails"
echo -e "\t-T --no-tftpbuild\t\tDo not rebuild the tftpd config file"
echo -e "\t-F --no-vhost\t\tDo not overwrite vhost file"
echo -e "\t-F --no-vhost\t\tDo not touch the vhost file at all. FOG"
echo -e "\t \t\t\tnormally rewrites only the region between its"
echo -e "\t \t\t\tMANAGED BLOCK markers and leaves your own"
echo -e "\t \t\t\tadditions alone, so skipping also skips its"
echo -e "\t \t\t\tsecurity fixes to the parts it owns."
echo -e "\t \t\t\tSee docs/SUPPORTED_CUSTOMIZATIONS.md"
echo -e "\t-l --list-packages\t\tList of the basic packages FOG needs for install or is currently installed for FOG"
echo -e "\t --secure-boot-key\t\tPrivate key used to re-sign the FOS"
echo -e "\t \t\t\tkernels for UEFI Secure Boot"
Expand All @@ -163,8 +196,10 @@ usage() {
exit 0
}

sextraServerNames=()

shortopts="h?odEUHSCKYyXTFf:c:W:D:B:s:e:N:l"
longopts="help,uninstall,purge-db,purge-images,purge-snapins,purge-ssl,purge-user,purge-all,dry-run,force,mysqldbname:,ssl-path:,oldcopy,no-vhost,no-defaults,no-upgrade,no-htmldoc,force-https,no-force-https,recreate-keys,recreate-CA,recreate-Ca,recreate-cA,recreate-ca,external-ca,ca-cert:,ca-key:,ca-root:,autoaccept,file:,docroot:,webroot:,backuppath:,startrange:,endrange:,no-exportbuild,exitFail,no-tftpbuild,list-packages,fogprogramdir:,secure-boot-key:,secure-boot-cert:,no-secure-boot"
longopts="help,uninstall,purge-db,purge-images,purge-snapins,purge-ssl,purge-user,purge-all,dry-run,force,mysqldbname:,ssl-path:,oldcopy,no-vhost,no-defaults,no-upgrade,no-htmldoc,force-https,no-force-https,recreate-keys,recreate-CA,recreate-Ca,recreate-cA,recreate-ca,external-ca,ca-cert:,ca-key:,ca-root:,autoaccept,file:,docroot:,webroot:,backuppath:,startrange:,endrange:,no-exportbuild,exitFail,no-tftpbuild,list-packages,fogprogramdir:,secure-boot-key:,secure-boot-cert:,no-secure-boot,hostname:,extra-server-name:,kernel-backup-count:,restore-kernel-backup,split-pki,legacy-pki,netboot-proto:,client-ca-cn:,web-ca-cert:,web-ca-key:,web-ca-root:,client-ca-cert:,client-ca-key:,client-ca-root:,root-ca-cert:,root-ca-key:,secureboot-ca-cert:"

optargs=$(getopt -o $shortopts -l $longopts -n "$0" -- "$@")
[[ $? -ne 0 ]] && usage
Expand Down Expand Up @@ -225,6 +260,24 @@ while :; do
fi
shift 2
;;
--hostname)
if [[ -n "${2}" ]] && [[ $(validhostname "${2}") -eq 0 ]]; then
shostname="${2}"
else
echo "Error: --hostname requires a valid hostname"
exit 9
fi
shift 2
;;
--extra-server-name)
if [[ -n "${2}" ]] && [[ $(validhostname "${2}") -eq 0 ]]; then
sextraServerNames+=("${2}")
else
echo "Error: --extra-server-name requires a valid hostname"
exit 9
fi
shift 2
;;
-o | --oldcopy)
scopybackold=1
shift
Expand Down Expand Up @@ -441,6 +494,71 @@ while :; do
ssecureboot=0
shift
;;
--netboot-proto)
case $2 in
http|https) snetbootproto="$2" ;;
*) echo "$1 must be http or https"; usage; exit 3 ;;
esac
shift 2
;;
--split-pki)
spkiMode="split"
shift
;;
--legacy-pki)
spkiMode="flat"
shift
;;
--client-ca-cn)
if [[ -n "${2}" ]]; then
sfogClientCACN="${2}"
else
echo "$1 requires a common name after"
usage
exit 3
fi
shift 2
;;
--web-ca-cert | --web-ca-key | --web-ca-root | \
--client-ca-cert | --client-ca-key | --client-ca-root | \
--root-ca-cert | --root-ca-key | --secureboot-ca-cert)
if [[ ! -f $2 ]]; then
echo "$1 requires a readable file after"
usage
exit 3
fi
case $1 in
--web-ca-cert) swebExtCACert="$2" ;;
--web-ca-key) swebExtCAKey="$2" ;;
--web-ca-root) swebExtCARoot="$2" ;;
--client-ca-cert) sclientExtCACert="$2" ;;
--client-ca-key) sclientExtCAKey="$2" ;;
--client-ca-root) sclientExtCARoot="$2" ;;
--root-ca-cert) srootExtCACert="$2" ;;
--root-ca-key) srootExtCAKey="$2" ;;
# The Secure Boot zone's anchor: what gets ENROLLED in
# firmware. Pairs with --secure-boot-key/--secure-boot-cert,
# which name the leaf that actually signs. Supplying only the
# leaf pair (the historic form) still works and enrols that
# certificate, exactly as before.
--secureboot-ca-cert) ssecureBootMokCert="$2" ;;
esac
shift 2
;;
--kernel-backup-count)
if [[ -n "${2}" && "${2}" =~ ^[0-9]+$ && "${2}" -ge 1 ]]; then
skernelBackupCount="${2}"
else
echo "$1 requires a positive integer after"
usage
exit 3
fi
shift 2
;;
--restore-kernel-backup)
srestoreKernelBackup=1
shift
;;
--)
shift
break
Expand Down Expand Up @@ -614,6 +732,8 @@ case $doupdate in
esac
# evaluation of command line options
[[ -n $shttpproto ]] && httpproto=$shttpproto
[[ -n $shostname ]] && hostname=$shostname
[[ ${#sextraServerNames[@]} -gt 0 ]] && extraServerNames="${sextraServerNames[*]}"
[[ -n $sstartrange ]] && startrange=$sstartrange
[[ -n $sendrange ]] && endrange=$sendrange
# -s/-e imply "set DHCP up". These were written directly by the handlers, so on
Expand All @@ -636,6 +756,31 @@ esac
[[ -n $ssecureBootKey ]] && secureBootKey=$ssecureBootKey
[[ -n $ssecureBootCert ]] && secureBootCert=$ssecureBootCert
[[ -n $ssecureboot ]] && secureboot=$ssecureboot
[[ -n $skernelBackupCount ]] && kernelBackupGenerations=$skernelBackupCount
# Applied here, after .fogsettings is sourced, so an explicit flag beats a
# persisted value and a persisted value beats the caCreated-based default in
# _resolvePkiMode.
[[ -n $snetbootproto ]] && netbootproto=$snetbootproto
[[ -n $spkiMode ]] && pkiMode=$spkiMode
[[ -n $sfogClientCACN ]] && fogClientCACN=$sfogClientCACN
[[ -n $swebExtCACert ]] && webExtCACert=$swebExtCACert
[[ -n $swebExtCAKey ]] && webExtCAKey=$swebExtCAKey
[[ -n $swebExtCARoot ]] && webExtCARoot=$swebExtCARoot
[[ -n $sclientExtCACert ]] && clientExtCACert=$sclientExtCACert
[[ -n $sclientExtCAKey ]] && clientExtCAKey=$sclientExtCAKey
[[ -n $sclientExtCARoot ]] && clientExtCARoot=$sclientExtCARoot
[[ -n $srootExtCACert ]] && rootExtCACert=$srootExtCACert
[[ -n $srootExtCAKey ]] && rootExtCAKey=$srootExtCAKey
[[ -n $ssecureBootMokCert ]] && secureBootMokCert=$ssecureBootMokCert
# Supplying any web-zone CA file implies --external-ca, the same way supplying
# --ca-cert always has. Saves an admin from the "I gave you the files and
# nothing happened" failure, which produces a working install with the wrong
# CA and no error to explain it.
[[ -n $webExtCACert || -n $webExtCAKey || -n $webExtCARoot ]] && externalca="yes"
# Deliberately NOT persisted to .fogsettings: this is a one-shot instruction
# for a single run (revertUpdate passes it), not a preference. Persisting it
# would make every later update silently roll the kernels back.
restoreKernelBackup=${srestoreKernelBackup:-0}

# Secure Boot signing is generated by default now (see _ensureSecureBootKeys),
# but an explicitly supplied key is still only meaningful as a pair. Refuse half
Expand All @@ -655,6 +800,12 @@ if [[ -n $secureBootKey || -n $secureBootCert ]]; then
done
unset sbfile
fi
# Immediately after validation and long before configureHttpd() rebuilds the
# web tree, so a pair the admin parked somewhere that gets deleted is copied
# to safety first. Handles a path from .fogsettings as well as one from this
# run's flags, and no-ops once the recorded path is already protected.
# $fogprogramdir is settled by config.sh above, so the destination is real.
preserveSecureBootAdminFiles

[[ -f $fogpriorconfig ]] && grep -l webroot $fogpriorconfig >>$error_log 2>&1
case $? in
Expand Down Expand Up @@ -911,13 +1062,23 @@ while [[ -z $blGo ]]; do
# to happen for it to connect at all.
writeUpdateFile
backupReports
# Before configureHttpd(), which rm -rf's $webdirdest --
# this is the last point anything under it can be saved.
# configureMySql has already run, so the FOG_IPXE_BG_FILE
# lookup inside has a database to ask.
backupPreservedCustomizations
configureHttpd
checkWebTier
backupDB
updateDB
configureStorage
configureDHCP
configureTFTPandPXE
# After configureTFTPandPXE -> downloadfiles() has re-laid
# the default-named kernel/init set, so restoring here puts
# the admin's own files back on top of fresh defaults
# rather than being overwritten by them.
restorePreservedCustomizations
configureFTP
configureSnapins
configureUDPCast
Expand Down
Loading