Commit Graph

81 Commits

Author SHA1 Message Date
Thierry Laurion
67372063ab GUI scripts: add whiptail_error and whiptail_warning since https://github.com/linuxboot/heads/pull/1787 fixed the issue
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-10-30 14:18:20 -04:00
Thierry Laurion
0cef8e1edc cryptsetup2 toolstack version bump and script fixes to support multi-LUKS containers (BTRFS QubesOS 4.2)
cryptsetup2 2.6.1 is a new release that supports reencryption of Q4.2 release LUKS2 volumes created at installation.
 This is a critical feature for the Qubes OS 4.2 release for added data at rest protection

Cryptsetup 2.6.x internal changes:
 - Argon2 used externally and internally: requires a lot of RAM and CPU to derivate passphrase to key validated in key slots.
  - This is used to rate limit efficiently bruteforcing of LUKS key slots, requiring each offline brute force attempt to consume ~15-30 seconds per attempt
  - OF course, strong passphrases are still recommended, but bruteforcing LUKSv2 containers with Argon2 would require immense time, ram and CPU even to bruteforce low entropy passphrase/PINs.
 - passphrase change doesn't permit LUKS key slot specification anymore: key slot rotates (new one consusumed per op: then old one wiped internally. EG: LUKS key slot 1 created, then 0 deleted)
 - reencryption doesn't permit old call arguments. No more direct-io; inadmissively slow through AIO (async) calls, need workarounds for good enough perfs (arguments + newer kernel with cloudfare fixes in tree)

cryptsetup 2.6.1 requires:
 - lvm2 2.03.23, which is also included in this PR.
   - requires libaio, which is also included in this PR (could be hacked out but deep dependency at first sight: left in)
   - requires util-linux 2.39
 - patches for reproducible builds are included for above 3 packages.

luks-functions was updated to support the new cryptsetup2 version calls/changes
 - reencryption happen in direct-io, offline mode and without locking, requiring linux 5.10.9+ to bypass linux queues
   - from tests, this is best for performance and reliability in single-user mode
 - LUKS container ops now validate Disk Recovery Key (DRK) passphrase prior and DRK key slot prior of going forward if needed, failing early.
  - Heads don't expect DRK to be in static key slot anymore, and finds the DRK key slot dynamically.
  - If reencrytipn/passphrase change: make sure all LUKS containers on same block device can be unlocked with same DRK
 - Reencryption: requires to know which key slot to reencrypt.
   - Find LUKS key slot that unlocks with DRK passphrase unlock prior of reencrypt call
 - Passphrase change: no slot can be passed, but key slot of DRK rotates.

kexec-seal-key
 - TPM LUKS Disk Unlock Key key slots have changed to be set in max slots per LUKS version (LUKSv1:7 /LUKSv2: 31)
  - If key slot != default LUKS version's keyslot outside of DRK key slot: prompt the user before wiping that key slot, otherwise wipe automatically
    - This takes for granted that the DRK key slot alone is needed on the system and Heads controls the LUKS key slots.
      - If user has something else going on, ie: Using USB Security dongle + TPM DUK, then the user will need to say no when wiping keys.
      - It was suggested to leave LUKS key slots outside of DRK alone, but then: what to do when all key slots would be used?
        - Alternative implementation could be to only prompt users to wipe keyslots other then DRK when key slots are all used (LUKSv1: 0-7, LUKSv2: 0-31)
          - But then cleanup would need to happen prior of operations (LUKS passphrase change, TPM DUK setup) and could be problematic.
  - LUKS containers now checked to be same LUKS version prior of permitting to set TPM DUK and will refuse to go forward of different versions.

TODO:
- async (AIO) calls are not used. direct-io is used instead. libaio could be hacked out
  - this could be subject to future work

Notes:
- time to deprecated legacy boards the do not enough space for the new space requirements
 - x230-legacy, x230-legacy-flash, x230-hotp-legacy
 - t430-legacy, t430-legacy-flash, t430-hotp-legacy already deprecated

Unrelated:
- typos fixes found along the way

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-10-30 14:18:20 -04:00
Thierry Laurion
7f7bc7057c
init: add export BG_COLOR_MAIN_MENU="normal" so that media-scan, config-gui and others can still be called from command line without passing from gui-init which was sole exporter of it
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-09-09 09:09:28 -04:00
Thierry Laurion
f06867306e
init: make sure config.user is overriden only with new values so that going DEBUG/undoing can work reproducibly
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-09-01 21:01:04 -04:00
Matthew Drobnak
19a705c179
Add functions to handle normal, warning, and error for whiptail and fbwhiptail.
Signed-off-by: Matthew Drobnak <matthew@drobnak.com>
2024-06-25 17:26:14 +00:00
Thierry Laurion
b2629f8d4d
Merge pull request #1625 from tlaurion:LUKS_header_change_validation_upon_sealing_and_unsealing
LUKS header change validation upon sealing and unsealing ops
2024-04-25 16:39:41 -04:00
Jonathon Hall
00ce2f4d1c
ash_functions: Log board and version when entering recovery shell
Log the board and version when entering the recovery shell.  Extract
the firmware version logic from init.

Currently this is the only way to get the debug log.  If we add a way
from the GUI, we may want to log the board and version somewhere else
too.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2024-04-19 14:16:41 -04:00
Thierry Laurion
f6232aa70f
Change disk encryption -> LUKS Disk Key and other relative/relative verbiage, remove irrelevant DEBUG trace under kexec-unseal-key
TODO:
- $(pcrs) call sometimes fail in DEBUG call, outputting too many chars to be inserted in kmesg. Call removed here since redundant (PCR6 already extended with LUKS header)
- Notes added for TPM2 simplification over TPM1 in code as TODO

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-04-11 14:44:13 -04:00
Thierry Laurion
c73687a232
init: Adding checks for sysfs and runtime panic_on_oom=1
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2024-04-02 17:17:09 -04:00
Jonathon Hall
8233c6f442
init: Silence exFAT errors when mounting iso9660; reorder exfat last
Since exFAT support was enabled, mounting an iso9660 filesystem prints
spurious exFAT errors to the console.  That is because busybox mount
tries all filesystems in the order listed, and exfat precedes iso9660
(those are the last two in our config).  Most filesystems are silent
when used on the wrong type of filesystem, but exFAT logs errors, which
appear on the console.

Move exFAT after iso9660, so iso9660 filesystems won't show these
errors.  The errors will still appear if the filesystem is actually
exFAT but cannot be mounted.

There's no significant risk of misdetecting a remnant iso9660
superblock here either.  Although an iso9660 superblock could fall in
the unused space between the exFAT boot region and the FAT itself,
mkfs.exfat does zero this space so it is unlikely such a remnant
superblock would exist.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2024-02-02 13:24:34 -05:00
Jonathon Hall
0a823cb491
Allow laptops to include optional USB keyboard support
Laptops can include optional USB keyboard support (default off unless
the board also sets the default to 'y').  The setting is in the
configuration GUI.

CONFIG_USER_USB_KEYBOARD is now the user-controlled setting on those
boards.  'CONFIG_USB_KEYBOARD' is no longer used to avoid any conflict
with prior releases that expect this to be a compile-time setting only
(conflicts risk total lock out requiring hardware flash, so some
caution is justified IMO).

Boards previously exporting CONFIG_USB_KEYBOARD now export
CONFIG_USB_KEYBOARD_REQUIRED.  Those boards don't have built-in
keyboards, USB keyboard is always enabled. (librem_mini,
librem_mini_v2, librem_11, librem_l1um, librem_l1um_v2, talos-2,
kgpe-d16_workstation-usb_keyboard, x230-hotp-maximized_usb-kb).

Librem laptops now export CONFIG_SUPPORT_USB_KEYBOARD to enable
optional support.  The default is still 'off'.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2024-01-10 15:38:06 -05:00
tlaurion
133da0e48e
Merge pull request #1515 from tlaurion/inmemory_keygen-gpg_backup_usable_for_RSA_only-copy_to_card_working_for_RSA_only-gpg_auth_for_recovery_and_sub_boot
GPG User Authentication: In-memory gpg keygen + keytocard and GPG key material backup enabling  (plus a lot of code cleanup and UX improvements)
2023-11-13 16:05:26 -05:00
Thierry Laurion
504f0336ac
init: add early boot 'o' option to jump directly to oem-factory-reset for OEM provisioning of secret prior of shipping products, once OS is installed and after MRC training happened on first boot.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2023-11-03 16:41:36 -04:00
Thierry Laurion
1f28c71447
WiP: adapt dmesg in function of CONFIG_DEBUG_OUTPUT being enabled or not so and adapt further troubleshooting notes in code when keys cannot be accessed on media for whatever cause so user can understand what is happening when accessing GPG material on backup thumb drive
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
2023-11-01 10:06:55 -04:00
tlaurion
1733552fe7
Merge pull request #1505 from JonathonHall-Purism/upstream_28.1_librem_11
Add support for Librem 11
2023-10-30 15:38:02 -04:00
Thierry Laurion
65e5286b5a
init: enable cttyhack so that init launches BOOTSCRIPT in a controlled terminal. DEBUG/TRACE now output on /dev/kmsg and console. 2023-10-10 12:28:52 -04:00
Jonathon Hall
55155f6558
boards/librem_11: Add Librem 11
Add Librem 11 board.

Librem 11 uses coreboot graphics init, which is done with FSP GOP.

Set a custom keymap for the volume/power keys.  Configure the volume
keys as up/down arrows (for navigation in fbwhiptail, and for shell
history in the Linux console).  Configure the power key as Enter.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-09-29 15:36:30 -04:00
Jonathon Hall
2f329d9007
kbd: Add setfont from kbd to set large console font on large displays
Build kbd and ship setfont if enabled with CONFIG_KBD.

When CONFIG_KBD is enabled, setconsolefont.sh will double the console
font size on large displays (>1600 lines tall as a heuristic).

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-08-11 14:40:04 -04:00
Jonathon Hall
61609ff709
initrd/init: Prevent Restricted Boot bypass
The early recovery shell ("hold R") and serial recovery both could
bypass Restricted Boot since they occurred before config.user was
loaded.  Load config.user earlier before these recovery methods.

Executing a shell directly (if recovery failed) also would bypass
Restricted Boot, additionally leaking /tmp/secret.  Remove this from
the early recovery shell logic.  Also remove the final failsafe exec
and move the "just in case" recovery from normal boot here instead, in
case the regular init script fails.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-07-11 16:42:38 -04:00
Jonathon Hall
3c4a9fcf0d
Rename CONFIG_PUREBOOT_BASIC to CONFIG_BASIC
Remove brand name from this configuration variable.  For backward
compatibility, update config.user in init if the branded variable is
present.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-06-21 14:42:46 -04:00
Matt DeVillier
87eff7b775
gui-init: Implement blob jail feature
Blob jail provides device firmware blobs to the OS, so the OS does not
have to ship them.  The firmware is passed through the initrd to
/run/firmware, so it works with both installed and live OSes, and there
are no race conditions between firmware load and firmware availability.

The injection method in the initrd is specific to the style of init
script used by PureOS, since it must add a copy command to copy the
firmware from the initrd to /run.  If the init script is not of this
type, boot proceeds without device firmware.

This feature can be enabled or disabled from the config GUI.

Blob jail is enabled automatically if the Intel AX200 Wi-Fi module is
installed and the feature hasn't been explicitly configured.

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2023-06-21 13:26:47 -04:00
Jonathon Hall
d148d3136a
init: Add optional board-specific init script
Boards can place a file in $(board)/initrd/bin/board-init.sh to perform
board-specific initialization.

If present, the board's $(board)/initrd directory is included in the
initrd via board.initrd.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-06-21 13:26:47 -04:00
Matt DeVillier
4bc6159ab6
Add PureBoot Basic Mode
PureBoot Basic mode provides the full Linux userspace in firmware from
Heads without requiring verified boot or a Librem Key.  Basic and
verified boot can be switched freely without changing firmware, such as
if a Librem Key is lost.

PureBoot Basic can apply firmware updates from a USB flash drive, and
having a complete Linux userspace enables more sophisticated recovery
options.

Basic mode boots to the first boot option by default, setting a default
is not required.  This can be configured in the config GUI.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-06-21 13:26:45 -04:00
Kyle Rankin
d937426306
Use the Librem Key as a TPM work-alike in the absence of a TPM
On machines without a TPM, we'd still like some way for the BIOS to
attest that it has not been modified. With a Librem Key, we can have the
BIOS use its own ROM measurement converted to a SHA256sum and truncated
so it fits within an HOTP secret. Like with a TPM, a malicious BIOS with
access to the correct measurements can send pre-known good measurements
to the Librem Key.

This approach provides one big drawback in that we have to truncate the
SHA256sum to 20 characters so that it fits within the limitations of
HOTP secrets. This means the possibility of collisions is much higher
but again, an attacker could also capture and spoof an existing ROM's
measurements if they have prior access to it, either with this approach
or with a TPM.

Signed-off-by: Kyle Rankin <kyle.rankin@puri.sm>
2023-06-14 09:58:34 -04:00
Jonathon Hall
6a9e7e293e
fstab, init: Remove securityfs mount
This is unused, remove it.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-13 14:11:02 -04:00
Jonathon Hall
ea5b8dc30f
tpmr: Provide startsession for TPM1 and TPM2
It's a no-op on TPM1, but provide it so init doesn't have to
distinguish TPM1/TPM2.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-13 13:10:24 -04:00
Jonathon Hall
5c33130ddc
init: Fixes for legacy-flash boards
Fix `[ -a` to POSIX `[ -e`.  Only run cbfs-init, key-init on normal
boards with bash.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-13 12:52:06 -04:00
Jonathon Hall
0760b6f237
init: Use busybox ash
init must use busybox ash because it is used on legacy-flash boards.
Change shebang, move needed functions to ash_functions.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-13 12:26:41 -04:00
Jonathon Hall
719dc57970
init: Always create symlinks for bash
No need to test whether bash is a symlink, bash ships on all boards
using the normal init script now.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-08 12:45:55 -05:00
Jonathon Hall
4b58788063
init: Execute /bin/sh for interactive shell, not /bin/bash
bash will not be the default interactive shell since readline support
increases the binary size significantly.  Use /bin/sh (busybox ash) for
that.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-08 12:45:53 -05:00
Jonathon Hall
b500505312
tpm2-tools: Change sense of CONFIG_TPM to mean any TPM, not just TPM1.
Most logic throughout Heads doesn't need to know TPM1 versus TPM2 (and
shouldn't, the differences should be localized).  Some checks were
incorrect and are fixed by this change.  Most checks are now unchanged
relative to master.

There are not that many places outside of tpmr that need to
differentiate TPM1 and TPM2.  Some of those are duplicate code that
should be consolidated (seal-hotpkey, unseal-totp, unseal-hotp), and
some more are probably good candidates for abstracting in tpmr so the
business logic doesn't have to know TPM1 vs. TPM2.

Previously, CONFIG_TPM could be variously 'y', 'n', or empty.  Now it
is always 'y' or 'n', and 'y' means "any TPM".  Board configs are
unchanged, setting CONFIG_TPM2_TOOLS=y implies CONFIG_TPM=y so this
doesn't have to be duplicated and can't be mistakenly mismatched.

There were a few checks for CONFIG_TPM = n that only coincidentally
worked for TPM2 because CONFIG_TPM was empty (not 'n').  This test is
now OK, but the checks were also cleaned up to '!= "y"' for robustness.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
2023-03-08 12:45:46 -05:00
Thierry Laurion
8da5d5d723
Add dual support for real bash and busybox's bash(ash)
- modify bash to have it configured with -Os
2023-03-08 12:45:44 -05:00
Thierry Laurion
6923fb5e20
Addition of qemu-(fb)whiptail-tpm2(-hotp) boards
-coreboot support of TPM v2.0 (shared config for TPM2 support across all 4 previous variations)
-swtpm set to be launched under TPM v2.0 mode under board config
-Documentation file under each board.md softlinks to qemu-coreboot-fbwhiptail-tpm1.md (which has been generalized)
This is skeleton for TPM v2 integration under Heads

-------------
WiP

TODO:
- libcurl cannot be built as a tpm2-tools dependency as of now not sure why. curl currently needs to be added in board config to be built
- Note: tpm-reset (master and here) needs some review, no handle of no tpm use case. Caller is responsible to not call it otherwise does nothing
- init tries to bind fd and fails currently
- Note: Check if whiptail is different of fbwhiptail in clearing screen. As of now every clear seems to be removed, still whiptail clears previous console output
- When no OS' /boot can be mounted, do not try to TPM reset (will fail)

- seal-hotpkey is not working properly
- setting disk unlock key asks for TPM ownership passphrase (sealing in NV requires ownership, but text is misleading user as if reowning TPM)
  - We should cache input, feed tpm behind the scene and wipe passphrase and state clearly that this is TPM disk unlock kye passphrase.
- primary key from TPM2 is invalid most of the time from kexec-select-boot and verifying global hashes but is setuped correctly at disk unlock key setup
- would be nice to take advantage of bash function tracing to understand where we are for debugging purposes, code takes ash in consideration only
- tpmr says it implements nv calls but actually doesn't. Removing those falsely wrapped functions would help.
  - Implementing them would be better
- REVIEW TODOS IN CODE
- READD CIRCLECI CONFIG

Current state:
- TPM unseal works without disk unlock key and generates TOTP properly (was missing die condition at unseal to not produce always good TOTP even if invalid)
- TPM disk encryption key fails. Hypothesis is that sealing with USB drivers loaded and measures in inconsistent with sealed with/without.
 - TPM disk unsealing happens without USB modules being loaded in non-HOTP setup. This fails.

- Current tests are with fbwhiptail (no clear called so having traces on command line of what happens)
 - Testing with HOTP implementation for sealing/unsealing since that forces USB module loads on each boot to remove this from failing possibilities
2023-03-08 12:45:43 -05:00
Thierry Laurion
8259d3ca1e
Add TRACE function tracing function to output on console when enabled
- Add TRACE function tracing output under etc/functions, depending on CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT enabled in board configs
- Replace current DEBUG to TRACE calls in code, reserving DEBUG calls for more verbose debugging later on (output of variables etc)
- add 'export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y' in qemu-coreboot(fb)whiptail-tpm1(-hotp) boards to see it in action
2023-02-20 11:44:52 -05:00
Thierry Laurion
5bc2bc88e4
All scripts and functions: Add DEBUG calling trace on console when CONFIG_DEBUG_OUTPUT is exported in board config
-qemu-coreboot-*whiptail-tpm1(-hotp) boards have 'export CONFIG_DEBUG_OUTPUT=y' by default now
2023-02-18 21:52:44 -05:00
Sergii Dmytruk
565963d51d
Add CONFIG_BOOT_EXTRA_TTYS option
It specifies whitespace-separated list of console devices to run Heads
on in addition to the default one.

Example for board config:

    export CONFIG_BOOT_EXTRA_TTYS="tty0 tty1"

Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
2022-09-01 00:28:15 +03:00
Sergii Dmytruk
b989889e5f
init: assign CONFIG_TPM depending on /dev/tpm0 presence
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
2022-08-20 23:56:47 +03:00
Thierry Laurion
90ad708849 Apply background colors when fbwhiptail binary is present. 2021-12-17 16:50:03 -05:00
Thierry Laurion
c6a36948c5 Whiptail: move BG_COLOR default definitions from gui-init to init
- Set them only when FBWHIPTAIL is used.
- If NEWT is used (console mode without framebuffer): set default to none.
2021-10-29 13:45:22 -04:00
Thierry Laurion
57417e149a
init: remove double heads motd banner, keeping the one sent to tty0 which is both local and remote 2021-07-25 19:53:35 -04:00
Matt DeVillier
cdbd0fcf2a
gui-init: Fix RAM and firmware version strings
Show RAM in GB, since the calculation in MB is imprecise as
it excludes RAM allocated for GPU (eg).

Fix display of firmware version strings which contain spaces by
adjusting cut and simply chopping off the date at the end, which
is a fixed 10-char length.

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2020-07-01 13:42:10 -05:00
alex-nitrokey
481082f2d8
Include adaption of @MrChromebox
See
5a3f599233
2020-06-25 10:40:25 +02:00
Matt DeVillier
1bd93d6679
Eliminate use of CONFIG_USB_BOOT_DEV
mount-usb switched to dynamic USB device detection a while back,
so eliminate instances of CONFIG_BOOT_USB_DEV, and derive the
mounted USB device from /etc/mtab in the one place where it's
actually needed (usb-scan). Clean up areas around calls to
mount-usb for clarity/readability.

Addresses issue #673

Test: Build Librem 13v4, boot ISO file on USB

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2020-02-19 22:32:08 -06:00
Matt DeVillier
6b5adcca6f
init: load usb modules for devices using USB keyboard
Some (out of tree) servers require use of a USB keyboard, and need
the USB kernel modules loaded prior to checking for keypress to enter
a recovery console. Since loading the modules affects the value in PRC5
and can cause issues putting a LUKS key in TPM, guard the loading of the
USB modules with CONFIG_USB_KEYBOARD and remove the unguarded call from
gui-init.

This should resolve issues #603 and #674.

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2020-02-19 11:40:34 -06:00
Francis Lam
92e706bf1b init: fix invalid GPG_TTY variable
busyboy tty isn't working after the musl-cross-make change so
revert to known good value.
2020-01-25 20:45:03 -08:00
Matt DeVillier
6cfbc86618
initrd: don't mount efivars fs on non-linuxboot systems
it doesn't exist and produces a spurious error on Heads systems

Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
2019-06-25 10:07:10 -05:00
tlaurion
695993b593
Merge branch 'master' into gpg2 2019-02-08 13:29:02 -05:00
Jason Andryuk
ca3a5fd2eb
Set GPG_TTY before calling gpg in key-init
gpg2 needs GPG_TTY set to function properly.  We set it in /init so it
is inherited by all children.  The call to $(tty) must be after /dev and
(preferably) /dev/pts are mounted.

Signed-off-by: Jason Andryuk <jandryuk@gmail.com>
2019-01-29 11:16:19 -05:00
Thierry Laurion
fb3e2066b8
GPG_TTY is forced to /dev/console under init. Ash console is never called; trying to get console tty from the tty returns "no console". NEEDs BETTER FIX. 2019-01-29 11:15:48 -05:00
Kyle Rankin
ab0f9dd32e
Move custom configs below recovery shell
For safety it would be better if we source any custom configs after the
recovery shell in init. That way we can recover from any config mistakes.
2018-12-06 16:34:47 -08:00