X-CI-Metadata: master@99d669d at 2025-12-06T04:39:52Z on 941bb339cd9a
Generated at : 2025-12-06T04:39:52Z
Runner Host : 941bb339cd9a
Workflow ID : 🛡️ Shell Script Linting
Git Commit : 99d669d HEAD -> master
Table of Contents
- 1. CISS.debian.live.builder
- 1.1. Preliminary Remarks
- 1.2. Match Host and Target Versions
- 1.3. Immutable Source-of-Truth System and Encrypted Live Root
- 1.4. Preview
- 1.5. Caution. Debian Installer and Security Context
- 1.6. Versioning Schema
- 1.7. Keywords
- 2. Features & Rationale
- 2.1. Kernel Hardening
- 2.1.1. Unified Hardened Boot Parameters
- 2.1.2. CPU Vulnerability Mitigations
- 2.1.3. Kernel Self-Protection
- 2.1.4. Local Kernel Hardening
- 2.2. Module Blacklisting
- 2.3. Network Hardening
- 2.4. Core Dump & Kernel Hardening
- 2.5. Entropy Collection Improvements
- 2.6. Permissions & Authentication
- 2.7. High-Security Baseline (Lynis Audit)
- 2.8. SSH Tunnel & Access Security
- 2.9. UFW Hardening
- 2.10. Fail2Ban Enhancements
- 2.11. NTPsec & Chrony
- 3. Script Features & Rationale
- 3.1. Input Validation & Security
- 3.2. Debug Mode with Detailed Logging
- 3.3. Secure Debug Logging
- 3.4. Secure Password Handling
- 3.5. Variable Declaration & Validation
- 3.6. Pure Bash Implementation
- 3.7. Bash Error Handling
- 4. Prerequisites
- 5. Installation & Usage
- 5.1. Interactive CLI / Dialog Wrapper
- 5.2. Make Wrapper, Quick Usage
- 5.3. CI/CD Gitea Runner Workflow Example
- 6. Licensing & Compliance
- 7. Disclaimer
1. CISS.debian.live.builder
Centurion Intelligence Consulting Agency Information Security Standard
Debian Live Build Generator for hardened live environment and CISS Debian Installer
Master Version: 8.13
Build: V8.13.768.2025.12.06
CISS.debian.live.builder — First of its own.
World-class CIA: Designed, handcrafted and powered by Centurion Intelligence Consulting Agency.
Developed and maintained as a one-man, security-driven engineering effort since 2024, CISS.debian.live.builder is designed to serve as a reference implementation for hardened, image-based Debian deployments.
This shell wrapper automates the creation of a Debian Trixie live ISO hardened according to the latest best practices in server
and service security. It integrates into your build pipeline to deliver an isolated, robust environment suitable for cloud
deployment or unattended installations via the forthcoming CISS.debian.installer. Additionally, automated CI workflows based
on Gitea Actions are provided, enabling reproducible ISO generation. A generic ISO is automatically built upon significant
changes and made publicly available for download. The latest generic ISO is available at:
PUBLIC CISS.debian.live.ISO
Beyond a conventional live system, CISS.debian.live.builder assembles a fully encrypted, integrity-protected live medium
in a single, deterministic build step: a LUKS2 container backed by dm-integrity hosting the SquashFS root filesystem, combined
with a hardened initramfs chain including a dedicated Dropbear build pipeline for remote LUKS unlock. The resulting ISO ships
with a hardened kernel configuration, strict sysctl and network tuning, pre-configured SSH hardening and fail2ban, and a
customised verify-checksums path providing both ISO-edge verification and runtime attestation of the live root. All components
are aligned with the CISS.debian.installer baseline, ensuring a unified cryptographic and security posture from first boot to
an installed system. For an overview of the entire build process, see:
MAN_CISS_ISO_BOOT_CHAIN.md
When built with the --dhcp-centurion profile, the live system ships with a strict network and resolver policy:
systemd-networkd and systemd-resolved are pre-configured to use DNS-over-TLS (DoT) exclusively against the
CenturionDNS resolver infrastructure; plain DNS is not used and connectivity failures are treated as hard errors. DNSSEC
validation is enforced in a fail-closed manner: zones with invalid or broken signatures result in SERVFAIL and are not
silently downgraded. Multicast name resolution via mDNS and LLMNR is disabled globally to avoid unintended name leakage
and spoofing surfaces.
Internally, the builder employs a dedicated secret-handling pipeline backed by a tmpfs-only secrets directory
(/dev/shm/cdlb_secrets). Sensitive material such as root passwords, SSH keys, and signing keys never appears on the command
line, is guarded by strict 0400 root:root permissions, and any symlink inside the secret path is treated as a hard failure
that aborts the run. Critical code paths temporarily disable Bash xtrace so that credentials never leak into debug logs, and
transient secret files are shredded (shred -fzu) as soon as they are no longer needed. GNUPG homes used for signing are
wiped, unencrypted chroot artifacts and includes are removed after lb build, and the final artifact is reduced to the
encrypted SquashFS inside the LUKS2 container. At runtime, LUKS passphrases in the live ISO and installer are transported via
named pipes inside the initramfs instead of process arguments, further minimizing exposure in process listings.
Check out more leading world-class services powered by Centurion Intelligence Consulting Agency:
- CenturionDNS Resolver
- CenturionDNS Blocklist
- CenturionMeet
- CenturionNet Services
- CenturionNet Status
Contact the author:
Legal Disclaimer:
- This project is not affiliated with, authorized, maintained, sponsored, or endorsed by the Debian Project
- Licensing & Compliance
- Disclaimer
- Centurion Imprint & Legal Notice
- Centurion Privacy Policy
1.1. Preliminary Remarks
1.1.1. HSM
Please note that all my signing keys are stored in an HSM and that the signing environment is air-gapped. The next step is to move to a room-gapped environment. ^^
1.1.2. DNSSEC, HSTS, TLS
Please note that coresecret.dev is included in the (HSTS Preload List) and always serves the headers:
add_header Expect-CT "max-age=86400, enforce" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
- The zones behind this project are dual-signed with DNSSEC. The current validation state is documented in the DNSSEC Audit Report
- The TLS surface of
git.coresecret.devis independently audited, and the findings are held in the TLS Audit Report - The topology of the underlying
CISS.debian.live.builderbuilding infrastructure is described in Centurion Net
1.1.3. Gitea Action Runner Hardening
The CI runners live on a host in a separate autonomous system, and that host has exactly one purpose: run Gitea Actions runners.
Each runner receives its own service account without a login shell, is bound to a separate directory tree, and inherits a
hardened systemd unit with DynamicUser, reduced capabilities, and restrictive sandboxing. A systemd-analyze security score
of around 2.6 is the baseline, not an aspiration. Traffic from those runners traverses both a software firewall (UFW)
and dedicated hardware firewall appliances. Docker, where used, runs unprivileged.
1.2. Match Host and Target Versions
I always build a Debian Trixie live image on a Debian Trixie host. The toolchain and all boot components that matter to
reproducibility are release-specific: live-build, live-boot, live-config, debootstrap, mksquashfs, grub,
the kernel, initramfs tooling, and even dpkg and apt defaults evolve from one release to the next. Mixing
generations produces fragile or outright broken ISOs, sometimes subtly, sometimes catastrophically. Keeping host and target in
lockstep avoids those mismatches and gives me predictable artifacts across builds.
1.3. Immutable Source-of-Truth System and Encrypted Live Root
The live ISO acts as a sealed, immutable execution environment. All relevant configuration, all installation logic, and all
security decisions are rendered into the image at build time and treated as read-only at runtime. On top of that logical
immutability, I now layer cryptographic protection of the live root file system itself. The live image contains a LUKS2 container
file with dm-integrity that wraps the SquashFS payload. The initramfs knows how to locate this container, unlock it, verify its
integrity, and then present the decrypted SquashFS as the root component of an OverlayFS stack. The detailed boot and
verification chain is documented separately in CISS ISO Boot Chain
In compact form, my expectations for the system are:
- Every bit that matters for boot and provisioning is covered by checksums that I control and that are signed with keys under my solely authoritative HSM.
- The live root runs out of a LUKS2 dm-integrity container so that a tampered or bit-rotted SquashFS never becomes a trusted root.
- Verification steps are not advisory. Any anomaly causes a hard abort during boot.
- After the live environment has reached a stable, verified state, it can hand off to
CISS.debian.installer. The installer operates from the same image, does not pull random payloads from the internet, and keeps the target system behind a hardened firewall until the entire provisioning process has completed. - For unattended, headless scenarios I also support builds where the target system is installed without ever exposing a shell over the console. After installation and reboot, the machine waits for a decryption passphrase via an embedded Dropbear SSH instance in the initramfs, limited to public key authentication and guarded by strict cryptographic policies. In such variants even
/bootcan be encrypted, with GRUB taking care of unlocking the boot partition.
These combinations give me a provisioning chain that is auditable, reproducible, and robust against both casual and targeted tampering.
Once the system is up, I can trigger a set of audits from within the live environment:
- Lynis Audit Report: Outputs a detailed security score and recommendations, confirming a 93%+ hardening baseline.
Type
lsadtat the prompt. See example report: Lynis Audit Report - SSH Audit Report: Verifies SSH daemon configuration against the latest best-practice cipher, KEX, and MAC recommendations.
Type
ssh-audit <IP>:<PORT>. See example report: SSH Audit Report
1.4. Preview
1.5. Caution. Debian Installer and Security Context
The Debian Installer (d-i) will ALWAYS boot a new system.
The classical Debian Installer (d-i) always boots its own kernel and its own initramfs. That effect is independent of the way it is launched:
- from a GRUB entry on the live medium,
- from within a running live session via a graphical shortcut,
- through kexec,
- or via helper packages such as debian-installer-launcher.
In all of these cases the running live system is discarded. The memory contents of the hardened live environment vanish, the firewall disappears, the hardened SSH daemon is terminated, and the hardened kernel is replaced by the installer kernel. The installer brings its own minimal root file system, usually BusyBox plus a limited set of udeb packages, and it does not implement my firewall, my AppArmor profiles, my logging configuration, or my remote access policies, unless I explicitly reintroduce those elements via preseed.
In that phase the security properties are therefore those of d-i, not those of CISS.debian.live.builder. This is not a defect in Debian, it is a property of how any installer that boots its own kernel behaves. It is important to keep this distinction in mind when deciding whether a workflow must stay inside the hardened live context or may trade that environment for the standard installer toolchain.
1.6. Versioning Schema
This project adheres strictly to a structured versioning scheme following the pattern x.y.z-Date.
Example: V8.13.768.2025.12.06
x.y.z represents major (x), minor (y), and patch (z) version increments.
Date (YYYY.MM.DD) denotes the build or release date, facilitating clear tracking of incremental changes and ensuring reproducibility and traceability.
1.7. Keywords
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this Repo are to be interpreted as described in [BCP 14], [RFC2119], [RFC8174] when, and only when, they appear in all capitals, as shown here.
2. Features & Rationale
Below I walk through the major hardening components, with a focus on why I implemented them the way I did and how they interact. I treat this builder as a reference implementation for my own infrastructure; it is not a toy.
2.1. Kernel Hardening
2.1.1. Unified Hardened Boot Parameters
Both the CISS.debian.live.builder LIVE ISO and the CISS.debian.installer rely on the same kernel command line. I consider
a diverging kernel baseline between installer and live system operationally dangerous, because it leads to two distinct sets of
expectations about mitigations and attack surface. The boot parameters I apply are:
apparmor=1 security=apparmor audit_backlog_limit=262144 audit=1 debugfs=off \
efi=disable_early_pci_dma hardened_usercopy=1 ia32_emulation=0 \
init_on_alloc=1 init_on_free=1 \
iommu.passthrough=0 iommu.strict=1 iommu=force \
kfence.sample_interval=100 kvm.nx_huge_pages=force \
l1d_flush=on lockdown=integrity loglevel=0 \
mitigations=auto,nosmt mmio_stale_data=full,force nosmt=force \
oops=panic page_alloc.shuffle=1 page_poison=1 panic=0 pti=on \
random.trust_bootloader=off random.trust_cpu=off randomize_kstack_offset=on \
retbleed=auto,nosmt rodata=on slab_nomerge vdso32=0 vsyscall=none
The parameters fall into several categories.
- The AppArmor-related flags
apparmor=1,security=apparmorguarantee that AppArmor is not an afterthought but an integral part of the security architecture from the first instruction. I do not accept a boot sequence that comes up without LSM enforcement and then attempts to enable it later. - The audit subsystem is configured to be always on
audit=1and to tolerate heavy bursts without dropping eventsaudit_backlog_limit=262144. I treat the audit trail as an evidentiary artifact; truncation because of backlog limits is not acceptable in that model. - The debug surface of the kernel is reduced aggressively.
debugfs=offavoids a traditional footgun that exposes kernel internals in a way that is friendly to attackers and rarely necessary in production. - Memory is hardened on several levels at allocation time and at free time.
init_on_alloc=1andinit_on_free=1provide deterministic zeroing,page_poison=1fills freed pages with a poison pattern, andpage_alloc.shuffle=1shuffles the allocator so that a process can no longer rely on stable physical patterns. Together these measures raise the cost of use-after-free exploitation and other memory corruption attacks. - The IOMMU is not optional. I force it on
iommu=force, disable passthroughiommu.passthrough=0and require strict behavioriommu.strict=1. Any environment that contains devices capable of DMA must have a correctly configured IOMMU, otherwise the trust model for the CPU and for the memory hierarchy collapses as soon as a hostile device is introduced. kfence.sample_interval=100activates KFENCE with a sampling interval that is still usable in production but sensitive enough to catch a meaningful subset of memory safety bugs under real workloads.- Virtualization-specific knobs include
kvm.nx_huge_pages=force, to keep huge pages non-executable, andl1d_flush=onso that context switches flush the L1 data cache where needed. lockdown=integrityplaces the kernel into lockdown mode with an emphasis on integrity. In this project I consider the integrity of the system more critical than the ability to introspect a running kernel from userspace.- Speculative execution and microarchitectural issues are covered by
mitigations=auto,nosmt,mmio_stale_data=full,force, andretbleed=auto,nosmt. I combine the automatic mitigation set provided by the kernel with a forced Single Thread mode where it is required because simultaneous multithreading is simply not worth the residual risk profile in many server contexts. nosmt=forceacts as a guardrail here. It prevents a misconfiguration from quietly re-enabling SMT while the system operator assumes it is disabled.- Fault handling is configured through
oops=panicandpanic=0. An oops triggers a panic so that I do not continue to run a kernel in an undefined state. At the same time I instruct the system not to reboot automatically on panic, to preserve the state for post-mortem analysis rather than cutting the ground away under a debugging session. pti=on,rodata=on, andslab_nomergeare classical hardening parameters that I still consider essential. Page-table isolation, read-only data segments, and prohibiting slab merging collectively prevent a wide range of exploits, especially under pressure from speculative execution attacks.- To avoid brittle side assumptions, I remove legacy or obsolete interfaces:
vdso32=0andvsyscall=noneshut down the remaining vestiges of 32-bit vDSO and vsyscall support on 64-bit systems.ia32_emulation=0it again narrows the attack surface by disabling full 32-bit compatibility on 64-bit kernels. - Finally, I do not trust entropy claims either from the bootloader or the CPU itself. I opt out of both with
random.trust_bootloader=offandrandom.trust_cpu=offand rely on my own entropy strategy described later.
All of these parameters are applied in exactly the same way for the live ISO and for the installer environment. That is a deliberate design decision.
2.1.2. CPU Vulnerability Mitigations
I build the kernels with the relevant mitigations for Spectre, Meltdown, L1TF, MDS, TAA, Retbleed, and related families activated.
The mitigations=auto,nosmt flag ensures that new mitigations integrated into the mainline kernel become effective as they
are added, instead of requiring that I micromanage every single toggle. The residual performance cost is acceptable in the
context I am targeting; stale mitigations can be revisited, but missing mitigations will not be.
2.1.3. Kernel Self-Protection
I enable the standard set of self-protection options, such as strict module page permissions, read-only data enforcement, and restrictions around kprobes and BPF. The builder is not a kernel configuration tool, but it carries the expectation that the kernels it runs with are compiled according to this hardening profile. I treat deviations from that profile as unsupported.
2.1.4. Local Kernel Hardening
The wrapper sysp()provides a function to apply and audit local kernel hardening rules from /etc/sysctl.d/90-ciss-local.hardened:
#######################################
# Wrapper for loading CISS hardened Kernel Parameters.
# Arguments:
# None
#######################################
sysp() {
sysctl -p /etc/sysctl.d/90-ciss-local.hardened
# shellcheck disable=SC2312
sysctl -a | grep -E 'kernel|vm|net' >| /var/log/sysctl_check"$(date +"%Y-%m-%d_%H:%M:%S")".log
}
- Key measures loaded by this file include:
- Disabling module loading
kernel.modules_disabled=1 - Restricting kernel pointers & logs
kernel.kptr_restrict=2,kernel.dmesg_restrict=1,kernel.printk=3 3 3 3 - Disabling unprivileged BPF and userfaultfd
- Disabling kexec and unprivileged user namespaces
- Locking down ptrace scope
kernel.yama.ptrace_scope=2 - Protecting filesystem links and FIFOs
fs.protected_*
- Disabling module loading
Warning
Once applied, some hardening settings cannot be undone via sysctl without a reboot, and dynamic module loading remains disabled
until the next boot. Automatic enforcement at startup is therefore omitted by design—run sysp() manually and plan a reboot to
apply or revert these controls.
In case you provide the --cdi option to the installer, the sysp() function is automatically applied at the boot process via:
9999_cdi_starter.sh.
For further details see: 90-ciss-local.hardened.md
2.2. Module Blacklisting
- Description: Disables and blacklists non-essential or insecure kernel modules.
- Rationale: Minimizes attack surface by preventing loads of drivers or modules not required by the live environment.
For further details see: 30-ciss-hardening.conf.md
2.3. Network Hardening
At the kernel level classical sysctl settings are applied that defend against spoofing and sloppy network behavior. Reverse path
filtering is enabled, ARP handling is pinned down, and loose binding of addresses is discouraged. Where appropriate, IPv6
receives the same level of attention as IPv4. The network stack is switched firmly to systemd-networkd and systemd-resolved.
The hook 0000_basic_chroot_setup.chroot removes ifupdown, wires up
systemd-networkd and systemd-resolved via explicit WantedBy symlinks, and ensures that the stub resolver at 127.0.0.53
is the canonical resolv.conf target. The same hook writes dedicated configuration snippets:
/etc/systemd/resolved.conf.d/10-ciss-dnssec.conf enforces opportunistic DNS-over-TLS and full DNSSEC validation
while disabling LLMNR and MulticastDNS.
This converges the system on a single, hardened DNS resolution path and avoids the common situation where multiple name resolution mechanisms step on each other. Where desired, this resolution chain can be plugged into CenturionDNS, a resolver infrastructure that I control and that enforces DNSSEC validation, QNAME minimisation, and a curated blocklist. For sensitive deployments, this stack is used as the default.
For further details see: 90-ciss-local.hardened.md
2.4. Core Dump & Kernel Hardening
- Description: Limits core dump generation paths, enforces
Yamarestrictions, and configureskernel.kptr_restrict. - Rationale: Prevents leakage of sensitive memory contents and reduces information disclosure from unintentional crash dumps.
2.5. Entropy Collection Improvements
- Description: Installs and configures
haveged, seeds/dev/randomearly. - Rationale: Cloud instances frequently suffer low entropy at the start; improving randomness ensures strong cryptographic key generation for SSH and other services.
2.6. Permissions & Authentication
- Description: Sets strict directory and file permissions, integrates with PAM modules (e.g.,
pam_faillock). - Rationale: Enforces the principle of least privilege at file-system level and strengthens authentication policies.
2.7. High-Security Baseline (Lynis Audit)
- Description: Run a baseline audit via Lynis after build completion. The generated live environment consistently achieves a 91%+ score in Lynis security audits.
- Rationale: Provides independent verification of security posture and flags any configuration drifts or missing hardening steps.
2.8. SSH Tunnel & Access Security
- Description: The SSH tunnel and access are secured through multiple layers of defense:
- Firewall Restriction: ufw allows connections only from defined jump host or VPN exit node IPs.
- TCP Wrappers:
/etc/hosts.allowand/etc/hosts.denyenforce anALL: ALLdeny policy, permitting only specified hosts. - One-Hit Ban: A custom Fail2Ban rule
/etc/fail2ban/jail.d/ciss-default.confimmediately bans any host that touches closed ports.- Additionally, the
fail2banservice is hardened as well according to: Arch Linux Wiki Fail2ban Hardening
- Additionally, the
- SSH Ultra-Hardening: The
/etc/sshd_configenforces strict cryptographic and connection controls with respect to SSH Audit Guide Debian 12:RekeyLimit 1G 1hHostKey /etc/ssh/ssh_host_ed25519_keyHostKey /etc/ssh/ssh_host_rsa_key (8192-bit RSA)PubkeyAuthentication yesPermitRootLogin prohibit-passwordPasswordAuthentication noPermitEmptyPasswords noLoginGraceTime 2mMaxAuthTries 3MaxSessions 2MaxStartups 08:64:16PerSourceMaxStartups 4RequiredRSASize 4096Ciphers aes256-gcm@openssh.comKexAlgorithms sntrup761x25519-sha512@openssh.com,sntrup761x25519-sha512,gss-curve25519-sha256-MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
- Rationale: These measures ensure that only authorized hosts can establish SSH tunnels, with strict cryptographic and usage policies enforced. Minimizes brute force, passive sniffing, and reduces credentials' exposure by limiting protocol features to vetted algorithms.
2.9. UFW Hardening
- Description: Defaults to
deny incomingand (optionally)deny outgoing; automatically opens only whitelisted ports. - Rationale: Implements a default-deny firewall, reducing lateral movement and data exfiltration risks immediately after deployment.
2.10. Fail2Ban Enhancements
- Description:
- Bans any connection to a closed port for 24 hours
- Automatically ignores designated bastion/jump host subnets
- Hardened via
systemdpolicy override to limit privileges of the Fail2Ban service itself
- Rationale: Provides proactive defense against port scans and brute-force attacks, while isolating the ban daemon in a minimal-privilege context.
2.11. NTPsec & Chrony
- Description: Installs
chrony, selects PTB NTPsec servers by default. - Rationale: Ensures tamper-resistant time synchronization, which is essential for log integrity, certificate validation, and forensic accuracy.
3. Script Features & Rationale
3.1. Input Validation & Security
- Description: All script arguments are validated using a robust input sanitizer.
- Rationale: Prevents injection attacks and ensures only expected data types and values are processed.
3.2. Debug Mode with Detailed Logging
-
Description: A built-in debug mode outputs clear, timestamped logs including:
- Script Name and Path of called Function,
- Line Number,
- Function Name,
- Exit Code of the previous Command,
- Executed Command.
-
Rationale: Simplifies troubleshooting and provides precise error tracing.
3.3. Secure Debug Logging
- Description: No hardcoded plaintext password fragments or sensitive artifacts appear in debug logs.
- Rationale: Prevents accidental exposure of credentials during troubleshooting.
3.4. Secure Password Handling
- Description: Password files, if provided, are shredded immediately after being hashed.
- Rationale: Prevents password recovery from temporary files.
3.5. Variable Declaration & Validation
- Description: All variables are declared and validated before use.
- Rationale: Avoids unintended behavior from unset or improperly set variables.
3.6. Pure Bash Implementation
- Description: The entire wrapper and all its functions are written in pure Bash, without external dependencies.
- Rationale: Ensures maximum portability and compatibility with standard Debian environments.
3.7. Bash Error Handling
-
Description: The implemented xtrace wrapper
set -xenforces comprehensive Bash error handling to ensure- robust,
- predictable execution,
- and early detection of failures.
and delivers full information, which command failed to execute:
- Script Name and Path of called Function,
- Line Number,
- Function Name,
- Exit Code of the previous Command,
- Executed Command,
- Environment Settings,
- Argument Counter passed to Script,
- Argument String passed to Script.
-
The following
setoptions are applied at the beginning of the script (see Bash Manual, The Set Builtin):
set -o errexit # Exit script when a command exits with non-zero status (same as "set -e").
set -o errtrace # Inherit ERR traps in subshells (same as "set -E").
set -o functrace # Inherit DEBUG and RETURN traps in subshells (same as "set -T").
set -o ignoreeof # An interactive shell will not exit upon reading EOF.
set -o nounset # Exit script on use of an undefined variable (same as "set -u").
set -o pipefail # Return the exit status of the last failed command in a pipeline.
set -o noclobber # Prevent overwriting files via redirection (same as "set -C").
- The following
shoptoptions are applied at the beginning of the script (see Bash Manual, The Shopt Builtin):
shopt -s failglob # If set, patterns that fail to match filenames during filename expansion result in an expansion error.
shopt -s inherit_errexit # If set, command substitution inherits the value of the errexit option instead of unsetting it in the
# subshell environment.
shopt -s lastpipe # If set, and job control is not active, the shell runs the last command of a pipeline not executed in
# the background in the current shell environment.
shopt -u expand_aliases # If set, aliases are expanded as described. This option is enabled by default for interactive shells.
shopt -u dotglob # If set, Bash includes filenames beginning with a '.' in the results of filename expansion.
shopt -u extglob # If set, enable the extended pattern matching features.
shopt -u nullglob # If set, filename expansion patterns that match no files expand to nothing and are removed.
- Rationale: These options enforce strict error checking and handling, reducing silent failures and ensuring predictable script behavior.
4. Prerequisites
To use CISS.debian.live.builder as intended, the following baseline is expected:
- The build host runs Debian 13 Trixie, fully updated. Building a Trixie image on an older or newer release is technically possible but explicitly not supported.
- The host has the standard live-build stack installed
live-build,live-boot,live-config,debootstrapand the cryptographic tooling required forLUKS2,dm-integrity,cryptsetup,gpg. - Disk space must be sufficient to hold the chroot, the temporary build artifacts, and the final ISO with encrypted root. For comfortable work I assume around 30–40 gigabytes of free space.
- The user running the builder has root privileges and understands that the script is capable of creating, mounting, and manipulating block devices.
5. Installation & Usage
5.1. Interactive CLI / Dialog Wrapper
-
Clone the repository:
git clone https://git.coresecret.dev/msw/CISS.debian.live.builder.git cd CISS.debian.live.builder -
Preparation:
- Ensure you are root.
- Create the build directory
mkdir /opt/cdlband the tmpfs secrets directorymkdir /dev/shm/cdlb_secrets. - Place your desired SSH public key in the
authorized_keysfile, for example, in the/dev/shm/cdlb_secretsdirectory. - Place your desired Password in the
password.txtfile, for example, in the/dev/shm/cdlb_secretsdirectory. - Make any other changes you need to.
-
Run the config builder script
./ciss_live_builder.shand the integratedlb buildcommand (example):chmod 0700 ./ciss_live_builder.sh timestamp=$(date -u +%Y-%m-%dT%H:%M:%S%z) ./ciss_live_builder.sh \ --architecture amd64 \ --autobuild=6.16.3+deb13-amd64 \ --build-directory /opt/cdlb \ --cdi \ --change-splash hexagon \ --control "${timestamp}" \ --debug \ --dhcp-centurion \ --jump-host 10.0.0.128 [c0de:4711:0815:4242::1] [2abc:4711:0815:4242::1]/64 \ --key_age=keys.txt \ --key_luks=luks.txt \ --provider-netcup-ipv6 [c0de:4711:0815:4242::ffff] \ --reionice-priority 1 2 \ --renice-priority "-19" \ --root-password-file /dev/shm/cdlb_secrets/password.txt \ --signing_key_fpr=98089A472CCF4601CD51D7C7095D36535296EA14B8DE92198723C4DC606E8F76 \ --signing_key_pass=signing_key_pass.txt \ --signing_key=signing_key.asc \ --ssh-port 4242 \ --ssh-pubkey /dev/shm/cdlb_secrets \ --sshfp \ --trixie -
Locate your ISO in the
--build-directory. -
Boot from the ISO and login to the live image via the console, or the multi-layer secured coresecret SSH tunnel.
-
Type
syspfor the final kernel hardening features. -
Check the boot log with
jbootand viassfthat all services are up. -
Finally, audit your environment with
lsadtfor a comprehensive Lynis audit. -
Type
celpfor some shortcuts.
5.2. Make Wrapper, Quick Usage
This repo ships a thin make wrapper around ./ciss_live_builder.sh, so you can compose a correctly quoted command and either
preview it or run it.
-
Clone the repository:
git clone https://git.coresecret.dev/msw/CISS.debian.live.builder.git cd CISS.debian.live.builder -
Preparation:
- Ensure you are root.
- Create the build directory
mkdir /opt/cdlband the tmpfs secrets directorymkdir /dev/shm/cdlb_secrets. - Place your desired SSH public key in the
authorized_keysfile, for example, in the/dev/shm/cdlb_secretsdirectory. - Place your desired Password in the
password.txtfile, for example, in the/dev/shm/cdlb_secretsdirectory. - Copy and edit the sample and set your options (no spaces around commas in lists):
cp config.mk.sample config.mkBUILD_DIR=/opt/cdlb ROOT_PASSWORD_FILE=/dev/shm/cdlb_secrets/password.txt SSH_PORT=4242 SSH_PUBKEY=/dev/shm/cdlb_secrets # Optional PROVIDER_NETCUP_IPV6=2001:cdb::1 # comma-separated; IPv6 in [] is fine JUMP_HOSTS=[2001:db8::1],[2001:db8::2] -
Dry-run first (prints the exact command):
make dry-run -
Execute the build:
make live
5.3. CI/CD Gitea Runner Workflow Example
-
Clone the repository:
git clone https://git.coresecret.dev/msw/CISS.debian.live.builder.git cd CISS.debian.live.builder -
Edit the
.gitea/workflows/generate-iso.yamlfile according to your requirements. Ensure that the trigger file.gitea/trigger/t_generate.iso.yamland the counter are updated. Change all the necessary{{ secrets.VAR }}. Push your commits to trigger the workflow. Then download your final ISO from the specified Location.
#...
steps:
- name: Preparing SSH Setup, SSH Deploy Key, Known Hosts, .config.
run: |
rm -rf ~/.ssh && mkdir -m700 ~/.ssh
### Private Key
echo "${{ secrets.CHANGE_ME }}" >| ~/.ssh/id_ed25519
chmod 0600 ~/.ssh/id_ed25519
#...
### https://github.com/actions/checkout/issues/1843
- name: Using manual clone via SSH to circumvent Gitea SHA-256 object issues.
run: |
git clone --branch "${GITHUB_REF_NAME}" ssh://git@CHANGE_ME .
#...
- name: Importing the 'CI PGP DEPLOY ONLY' key.
run: |
### GPG-Home relative to the Runner Workspace to avoid changing global files.
export GNUPGHOME="$(pwd)/.gnupg"
mkdir -m700 "${GNUPGHOME}"
echo "${{ secrets.CHANGE_ME }}" >| ci-bot.sec.asc
#...
- name: Configuring Git for signed CI/DEPLOY commits.
run: |
export GNUPGHOME="$(pwd)/.gnupg"
git config user.name "CHANGE_ME"
git config user.email "CHANGE_ME"
#...
- name: Preparing the build environment.
run: |
mkdir -p /opt/config
mkdir -p /opt/livebuild
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/password.txt
echo "${{ secrets.CHANGE_ME }}" >| /opt/config/authorized_keys
#...
- name: Starting CISS.debian.live.builder. This may take a while ...
run: |
chmod 0700 ciss_live_builder.sh && chown root:root ciss_live_builder.sh
timestamp=$(date -u +"%Y_%m_%d_%H_%M_Z")
### Change "--autobuild=" to the specific kernel version you need: '6.12.22+bpo-amd64'.
./ciss_live_builder.sh \
--autobuild=CHANGE_ME \
--architecture CHANGE_ME \
--build-directory /opt/livebuild \
--control "${timestamp}" \
--jump-host "${{ secrets.CHANGE_ME }}" \
--root-password-file /opt/config/password.txt \
--ssh-port CHANGE_ME \
--ssh-pubkey /opt/config
#...
### SKIP OR CHANGE ALL REMAINING STEPS
6. Licensing & Compliance
Unless stated otherwise in individual files via SPDX headers, this project is licensed under the European Union Public License (EUPL 1.2).
That license is OSI-approved and compatible with internal use in both public sector and private environments. Several files carry
dual or multi-license statements, for example LicenseRef-CNCL-1.1 and / or LicenseRef-CCLA-1.1, where I offer a
non-commercial license for community use and a commercial license for professional integration. The SPDX headers in each file
are authoritative. If you plan to integrate CISS.debian.live.builder into a commercial product or a managed service
offering, you should treat these license markers as binding and reach out for a proper agreement where required.
7. Disclaimer
This repository is designed for well-experienced administrators and security professionals who are comfortable with low-level Linux tooling, cryptography, and automation. It can and will create, format, and encrypt devices. It is entirely possible to destroy data if you use it carelessly. I publish this work in good faith and with a strong focus on correctness and robustness. Nevertheless, there is no warranty of any kind. You are responsible for understanding what you are doing, for validating your own threat model, and for ensuring that this tool fits your regulatory and operational environment. If you treat the builder, and the resulting images with the same discipline with which they were created, you will obtain a hardened, reproducible, and auditable base for serious systems. If you treat them casually, they will not save you from yourself.
no tracking | no logging | no advertising | no profiling | no bullshit
