penguins-eggs 25.12.7 → 25.12.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oclif.manifest.json +1 -1
- package/README.md +47 -760
- package/README.pdf +13450 -14838
- package/addons/eggs/adapt/applications/eggs-adapt.desktop +0 -0
- package/addons/eggs/pve/applications/eggs-pve.desktop +0 -0
- package/addons/eggs/rsupport/applications/eggs-rsupport.desktop +0 -0
- package/addons/eggs/theme/applications/install-system.desktop +0 -0
- package/addons/eggs/theme/livecd/simple.grub.main.cfg +3 -3
- package/assets/calamares/install-system.sh +0 -0
- package/assets/penguins-eggs.desktop +0 -0
- package/assets/penguins-krill.desktop +0 -0
- package/assets/penguins-links-add.desktop +0 -0
- package/assets/penguins-live-installer.desktop +0 -0
- package/bin/dev.js +0 -0
- package/conf/distros/alpine/calamares/calamares-modules/machineid-openrc/machineid-openrc.sh +0 -0
- package/conf/distros/buster/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/buster/calamares/calamares-modules/dpkg-unsafe-io/dpkg-unsafe-io.sh +0 -0
- package/conf/distros/buster/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
- package/conf/distros/fedora/calamares/calamares-modules/bootloaderspecification/bootloaderspecification.sh +0 -0
- package/conf/distros/focal/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/focal/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
- package/conf/distros/focal/calamares/libexec/calamares-aptsources.sh +0 -0
- package/conf/distros/focal/calamares/libexec/calamares-l10n-helper.sh +0 -0
- package/conf/distros/focal/calamares/libexec/calamares-logs-helper.sh +0 -0
- package/conf/distros/focal/calamares/libexec/calamares-nomodeset.sh +0 -0
- package/conf/distros/noble/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/noble/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
- package/conf/distros/noble/calamares/libexec/calamares-aptsources.sh +0 -0
- package/conf/distros/noble/calamares/libexec/calamares-l10n-helper.sh +2 -1
- package/conf/distros/noble/calamares/libexec/calamares-logs-helper.sh +0 -0
- package/conf/distros/noble/calamares/libexec/calamares-nomodeset.sh +0 -0
- package/conf/distros/noble/calamares/settings.yml +1 -0
- package/conf/distros/opensuse/calamares/calamares-modules/bootloaderspecification/bootloaderspecification.sh +0 -0
- package/conf/distros/opensuse/calamares/settings.yml +0 -0
- package/conf/distros/opensuse/calamares/zstd2lzo.sh +0 -0
- package/conf/distros/trixie/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/trixie/calamares/calamares-modules/dpkg-unsafe-io/dpkg-unsafe-io.sh +0 -0
- package/conf/distros/trixie/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
- package/conf/init/unattended.sh +0 -0
- package/dist/bin/dev.js +0 -0
- package/dist/bin/run.js +0 -0
- package/dist/classes/cli-autologin.d.ts +37 -4
- package/dist/classes/cli-autologin.js +125 -112
- package/dist/classes/daddy.js +4 -1
- package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +3 -2
- package/dist/classes/incubation/fisherman-helper/initcpio.js +25 -20
- package/dist/classes/incubation/incubator.d/manjaro.js +1 -0
- package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -1
- package/dist/classes/ovary.d/edit-live-fs.js +15 -122
- package/dist/classes/ovary.d/fertilization.js +1 -1
- package/dist/classes/ovary.d/luks-home-support-systemd.d.ts +12 -0
- package/dist/classes/ovary.d/luks-home-support-systemd.js +70 -0
- package/dist/classes/ovary.d/luks-home-support.d.ts +1 -0
- package/dist/classes/ovary.d/luks-home-support.js +101 -24
- package/dist/classes/ovary.d/luks-home.js +33 -19
- package/dist/classes/ovary.d/luks-root.d.ts +1 -2
- package/dist/classes/ovary.d/luks-root.js +46 -27
- package/dist/classes/ovary.d/luks-shrink.d.ts +14 -0
- package/dist/classes/ovary.d/luks-shrink.js +86 -0
- package/dist/classes/ovary.d/produce.js +63 -21
- package/dist/classes/ovary.d.ts +3 -1
- package/dist/classes/ovary.js +3 -1
- package/dist/classes/utils.js +1 -1
- package/dist/classes/yolk.js +1 -1
- package/dist/commands/produce.js +11 -7
- package/dist/interfaces/calamares/i-calamares-branding.d.ts +56 -38
- package/dist/interfaces/calamares/i-calamares-branding.js +10 -0
- package/dist/krill/classes/prepare.d/users.js +1 -1
- package/dist/krill/classes/prepare.js +6 -2
- package/dist/krill/classes/sequence.d/fstab.js +1 -1
- package/dist/krill/classes/sequence.d/mkfs.js +1 -1
- package/dist/krill/classes/sequence.d/remove-homecrypt-hack.d.ts +13 -0
- package/dist/krill/classes/sequence.d/remove-homecrypt-hack.js +65 -0
- package/dist/krill/classes/sequence.d/unpackfs.js +2 -2
- package/dist/krill/classes/sequence.d.ts +3 -5
- package/dist/krill/classes/sequence.js +31 -29
- package/dist/krill/components/finished.js +2 -2
- package/dist/krill/components/install.js +2 -2
- package/dist/krill/components/keyboard.js +2 -2
- package/dist/krill/components/location.js +2 -2
- package/dist/krill/components/network.js +2 -2
- package/dist/krill/components/partitions.js +2 -2
- package/dist/krill/components/summary.js +2 -2
- package/dist/krill/components/users.js +2 -2
- package/dist/krill/components/welcome.js +2 -2
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +46 -0
- package/dracut/modules.d/00debug-shell/debug-hook.sh +0 -0
- package/dracut/modules.d/00debug-shell/module-setup.sh +0 -0
- package/dracut/modules.d/90block/block-cmdline.sh +0 -0
- package/dracut/modules.d/90block/module-setup.sh +0 -0
- package/dracut/modules.d/95iso-scan/iso-scan-fallback.sh +0 -0
- package/dracut/modules.d/95iso-scan/iso-scan.sh +0 -0
- package/dracut/modules.d/95iso-scan/module-setup.sh +0 -0
- package/dracut/modules.d/95luks-loop/luks-loop.sh +0 -0
- package/dracut/modules.d/95luks-loop/module-setup.sh +0 -0
- package/eui/eui-autostart-cinnamon.desktop +0 -0
- package/eui/eui-autostart-xfce.desktop +0 -0
- package/eui/eui-create-image.sh +0 -0
- package/eui/eui-start.sh +0 -0
- package/manpages/doc/man/eggs.1.gz +0 -0
- package/manpages/doc/man/eggs.html +8 -8
- package/package.json +130 -124
- package/perrisbrewery/scripts/postinst +0 -0
- package/perrisbrewery/scripts/postrm +0 -0
- package/perrisbrewery/scripts/preinst +0 -0
- package/perrisbrewery/scripts/prerm +0 -0
- package/scripts/99clean +0 -0
- package/scripts/adapt.sh +0 -0
- package/scripts/boot-encrypted-root.sh +0 -0
- package/scripts/bros/waydroid-helper.sh +0 -0
- package/scripts/lsb_release +0 -0
- package/scripts/mom.sh +0 -0
- package/scripts/mount-encrypted-home.sh +0 -0
- package/scripts/pve-live.service +0 -0
- package/scripts/pve-live.sh +0 -0
- package/scripts/restore_homecrypt_krill.sh +93 -0
- package/scripts/resy +0 -0
|
@@ -8,31 +8,40 @@
|
|
|
8
8
|
import { exec } from '../../../lib/utils.js';
|
|
9
9
|
import { access } from 'fs/promises';
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @returns
|
|
11
|
+
* Cerca il file .preset per mkinitcpio appropriato per il kernel corrente.
|
|
12
|
+
* @returns Il percorso del file .preset trovato.
|
|
13
|
+
* @throws {Error} Se non è possibile trovare un file .preset valido.
|
|
13
14
|
*/
|
|
14
15
|
export async function initcpio() {
|
|
15
16
|
try {
|
|
16
|
-
const
|
|
17
|
-
const kernelVersion = result.data;
|
|
17
|
+
const kernelVersion = (await exec('uname -r', { capture: true })).data;
|
|
18
18
|
const version = kernelVersion.trim();
|
|
19
|
-
// Manjaro
|
|
19
|
+
// Logica Manjaro
|
|
20
20
|
if (version.includes('MANJARO')) {
|
|
21
21
|
try {
|
|
22
|
-
// Estrai major e minor version. Es: da "6.12.48-1-MANJARO" -> ["6", "12", "48-1-MANJARO"]
|
|
23
22
|
const parts = version.split('.');
|
|
24
|
-
// Costruisci il nome del preset come "linux" + "6" + "12" -> "linux612"
|
|
25
23
|
const kernelName = `linux${parts[0]}${parts[1]}`;
|
|
24
|
+
// Tentativo 1: Major/Minor (es. /etc/mkinitcpio.d/linux61.preset)
|
|
26
25
|
const manjaroPreset = `/etc/mkinitcpio.d/${kernelName}.preset`;
|
|
27
|
-
await access(manjaroPreset);
|
|
28
|
-
return manjaroPreset;
|
|
26
|
+
await access(manjaroPreset);
|
|
27
|
+
return manjaroPreset;
|
|
29
28
|
}
|
|
30
|
-
catch {
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
catch (e) {
|
|
30
|
+
try {
|
|
31
|
+
const parts = version.split('.');
|
|
32
|
+
const kernelName = `linux${parts[0]}${parts[1]}`;
|
|
33
|
+
// Tentativo 2: Major/Minor con Architettura (es. /etc/mkinitcpio.d/linux61-x86_64.preset)
|
|
34
|
+
const manjaroPresetArch = `/etc/mkinitcpio.d/${kernelName}-x86_64.preset`;
|
|
35
|
+
await access(manjaroPresetArch);
|
|
36
|
+
return manjaroPresetArch;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
// Fallito, si procede al FALLBACK ARCH
|
|
40
|
+
}
|
|
33
41
|
}
|
|
34
42
|
}
|
|
35
43
|
else if (version.includes('cachyos')) {
|
|
44
|
+
// Logica CachyOS
|
|
36
45
|
try {
|
|
37
46
|
let kernelType = 'linux-cachyos'; // default
|
|
38
47
|
if (version.includes('lts')) {
|
|
@@ -49,14 +58,10 @@ export async function initcpio() {
|
|
|
49
58
|
return cachyPreset;
|
|
50
59
|
}
|
|
51
60
|
catch {
|
|
52
|
-
//
|
|
53
|
-
// console.warn('Logica Manjaro fallita, si tenta il fallback per Arch...');
|
|
61
|
+
// Fallito, si procede al fallback Arch
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
|
-
|
|
57
|
-
* FALLBACK ARCH
|
|
58
|
-
*/
|
|
59
|
-
// Determina il tipo di kernel
|
|
64
|
+
// FALLBACK ARCH
|
|
60
65
|
let kernelType = 'linux'; // default
|
|
61
66
|
if (version.includes('lts')) {
|
|
62
67
|
kernelType = 'linux-lts';
|
|
@@ -73,7 +78,7 @@ export async function initcpio() {
|
|
|
73
78
|
return archPreset;
|
|
74
79
|
}
|
|
75
80
|
catch (error) {
|
|
76
|
-
//
|
|
77
|
-
throw new Error(`Impossibile trovare un file .preset valido in /etc/mkinitcpio.d
|
|
81
|
+
// Lancia un errore se tutti i tentativi falliscono.
|
|
82
|
+
throw new Error(`Impossibile trovare un file .preset valido in /etc/mkinitcpio.d/.`);
|
|
78
83
|
}
|
|
79
84
|
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* email: piero.proietti@gmail.com
|
|
6
6
|
* license: MIT
|
|
7
7
|
*/
|
|
8
|
-
// packages
|
|
9
8
|
import fs from 'fs';
|
|
10
9
|
import os from 'os';
|
|
11
10
|
import path from 'node:path';
|
|
@@ -16,11 +15,11 @@ import Systemctl from '../systemctl.js';
|
|
|
16
15
|
import { exec } from '../../lib/utils.js';
|
|
17
16
|
// _dirname
|
|
18
17
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
19
|
-
export async function editLiveFs(
|
|
18
|
+
export async function editLiveFs() {
|
|
20
19
|
if (this.verbose)
|
|
21
20
|
console.log('Ovary: editLiveFs');
|
|
22
21
|
const workDir = this.settings.work_dir.merged;
|
|
23
|
-
if (clone) {
|
|
22
|
+
if (this.clone || this.homecrypt || this.fullcrypt) {
|
|
24
23
|
await exec(`touch ${workDir}/etc/penguins-eggs.d/is_clone`, this.echo);
|
|
25
24
|
}
|
|
26
25
|
if (Pacman.packageIsInstalled('epoptes')) {
|
|
@@ -38,15 +37,6 @@ export async function editLiveFs(clone = false) {
|
|
|
38
37
|
await exec(cmd, this.echo);
|
|
39
38
|
cmd = `find ${workDir}/var/log/ -type f -exec truncate -s 0 {} \\;`;
|
|
40
39
|
await exec(cmd, this.echo);
|
|
41
|
-
// =========================================================================
|
|
42
|
-
// FIX DEFINITIVO PER DEVUAN/SYSVINIT (Init Script Hardening)
|
|
43
|
-
// =========================================================================
|
|
44
|
-
if (Utils.isSysvinit()) {
|
|
45
|
-
if (this.verbose)
|
|
46
|
-
console.log('SysVinit detected: Hardening init scripts...');
|
|
47
|
-
await patchInitScripts(workDir, this.verbose);
|
|
48
|
-
}
|
|
49
|
-
// =========================================================================
|
|
50
40
|
// Fix Symlinks /var/run e /var/lock
|
|
51
41
|
const varRun = `${workDir}/var/run`;
|
|
52
42
|
if (fs.existsSync(varRun) && !fs.lstatSync(varRun).isSymbolicLink()) {
|
|
@@ -85,16 +75,20 @@ export async function editLiveFs(clone = false) {
|
|
|
85
75
|
if (fs.existsSync(`${workDir}/etc/crypttab`)) {
|
|
86
76
|
await exec(`rm ${workDir}/etc/crypttab`, this.echo);
|
|
87
77
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
/**
|
|
79
|
+
* machine-id
|
|
80
|
+
*/
|
|
81
|
+
await exec(`rm -f ${workDir}/etc/machine-id`);
|
|
82
|
+
await exec(`rm -f ${workDir}/var/lib/dbus/machine-id`);
|
|
83
|
+
if (Utils.isSysvinit()) {
|
|
84
|
+
await exec(`chroot ${workDir} dbus-uuidgen --ensure=/etc/machine-id`);
|
|
85
|
+
await exec(`ln -sf /etc/machine-id ${workDir}/var/lib/dbus/machine-id`);
|
|
86
|
+
// const machineId = crypto.randomBytes(16).toString('hex')
|
|
87
|
+
// fs.writeFileSync(`${workDir}/etc/machine-id`, machineId + '\n')
|
|
88
|
+
// fs.writeFileSync(`${workDir}/var/lib/dbus/machine-id`, machineId + '\n')
|
|
94
89
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
await exec(`rm ${workDir}/var/lib/dbus/machine-id`, this.echo);
|
|
90
|
+
else if (Utils.isSystemd()) {
|
|
91
|
+
await exec(`touch ${workDir}/etc/machine-id`);
|
|
98
92
|
}
|
|
99
93
|
if (fs.existsSync(`${workDir}/boot/grub/fonts/unicode.pf2`)) {
|
|
100
94
|
shx.cp(`${workDir}/boot/grub/fonts/unicode.pf2`, `${workDir}/boot/grub/fonts/UbuntuMono16.pf2`);
|
|
@@ -166,104 +160,3 @@ export async function editLiveFs(clone = false) {
|
|
|
166
160
|
await exec(`chmod 1777 ${workDir}/tmp`, this.echo);
|
|
167
161
|
}
|
|
168
162
|
}
|
|
169
|
-
/**
|
|
170
|
-
* Patcha direttamente gli script di init in /etc/init.d/
|
|
171
|
-
*/
|
|
172
|
-
async function patchInitScripts(workDir, verbose) {
|
|
173
|
-
// 1. PATCH DBUS (Il più importante)
|
|
174
|
-
const dbusScript = `${workDir}/etc/init.d/dbus`;
|
|
175
|
-
if (fs.existsSync(dbusScript)) {
|
|
176
|
-
if (verbose)
|
|
177
|
-
console.log(`Patching ${dbusScript} to fix missing directories and RO fs...`);
|
|
178
|
-
let content = fs.readFileSync(dbusScript, 'utf8');
|
|
179
|
-
let modified = false;
|
|
180
|
-
// PATCH A: Header con gestione Ramdisk Fallback e Mount Proc
|
|
181
|
-
// Questa intestazione viene inserita all'inizio e prova a montare tmpfs se non può scrivere
|
|
182
|
-
const dbusFix = `
|
|
183
|
-
### EGGS-FIX-START
|
|
184
|
-
# 1. Assicuriamoci che /proc sia montato (necessario per leggere uuid kernel)
|
|
185
|
-
if ! mountpoint -q /proc/; then
|
|
186
|
-
mount -t proc proc /proc
|
|
187
|
-
fi
|
|
188
|
-
|
|
189
|
-
# 2. Gestione Filesystem Read-Only (RO)
|
|
190
|
-
# Se non possiamo scrivere in /var/lib/dbus, montiamo un tmpfs (RAM) sopra.
|
|
191
|
-
# Questo bypassa il blocco dell'overlayfs non ancora pronto tipico delle build AppImage.
|
|
192
|
-
if ! mkdir -p /var/lib/dbus 2>/dev/null || ! touch /var/lib/dbus/.rw_check 2>/dev/null; then
|
|
193
|
-
echo "EGGS-DEBUG: Filesystem Read-Only detected! Mounting tmpfs on /var/lib/dbus" > /dev/console
|
|
194
|
-
mount -t tmpfs -o size=1m tmpfs /var/lib/dbus
|
|
195
|
-
fi
|
|
196
|
-
rm -f /var/lib/dbus/.rw_check
|
|
197
|
-
|
|
198
|
-
# 3. Creazione Directory Runtime
|
|
199
|
-
mkdir -p /var/run/dbus /var/lib/dbus
|
|
200
|
-
chmod 755 /var/run/dbus /var/lib/dbus
|
|
201
|
-
|
|
202
|
-
# 4. Generazione Machine ID (Non-Blocking Strategy)
|
|
203
|
-
# Se il file non esiste (o è vuoto), lo creiamo.
|
|
204
|
-
if [ ! -s /var/lib/dbus/machine-id ]; then
|
|
205
|
-
# Prova A: Usa UUID del kernel (Istantaneo, non blocca)
|
|
206
|
-
if [ -f /proc/sys/kernel/random/uuid ]; then
|
|
207
|
-
cat /proc/sys/kernel/random/uuid | tr -d '-' > /var/lib/dbus/machine-id
|
|
208
|
-
# Prova B: Fallback statico
|
|
209
|
-
else
|
|
210
|
-
echo "00000000000000000000000000000001" > /var/lib/dbus/machine-id
|
|
211
|
-
fi
|
|
212
|
-
chmod 644 /var/lib/dbus/machine-id
|
|
213
|
-
fi
|
|
214
|
-
|
|
215
|
-
# 5. Sync /etc/machine-id (Best effort, ignora errori se /etc è RO)
|
|
216
|
-
if [ ! -s /etc/machine-id ] && [ -s /var/lib/dbus/machine-id ]; then
|
|
217
|
-
cp /var/lib/dbus/machine-id /etc/machine-id 2>/dev/null || true
|
|
218
|
-
fi
|
|
219
|
-
### EGGS-FIX-END
|
|
220
|
-
`;
|
|
221
|
-
if (!content.includes('EGGS-FIX-START')) {
|
|
222
|
-
content = content.replace('#!/bin/sh', `#!/bin/sh\n${dbusFix}`);
|
|
223
|
-
modified = true;
|
|
224
|
-
}
|
|
225
|
-
// PATCH B: SABOTAGE PREVENTION (Questa è quella che mancava!)
|
|
226
|
-
// Impediamo che create_machineid cancelli il file che abbiamo appena creato
|
|
227
|
-
// perché l'uptime è basso.
|
|
228
|
-
if (content.includes('rm -f "${MACHINEID}"')) {
|
|
229
|
-
if (verbose)
|
|
230
|
-
console.log('Patching dbus: disabling auto-delete of machine-id on boot');
|
|
231
|
-
content = content.replace('rm -f "${MACHINEID}"', ': # EGGS-PATCH: Prevent deletion of valid machine-id');
|
|
232
|
-
modified = true;
|
|
233
|
-
}
|
|
234
|
-
if (modified) {
|
|
235
|
-
fs.writeFileSync(dbusScript, content, 'utf8');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
// 2. PATCH RSYSLOG
|
|
239
|
-
const rsyslogScript = `${workDir}/etc/init.d/rsyslog`;
|
|
240
|
-
if (fs.existsSync(rsyslogScript)) {
|
|
241
|
-
let content = fs.readFileSync(rsyslogScript, 'utf8');
|
|
242
|
-
const fix = `
|
|
243
|
-
### EGGS-FIX-START
|
|
244
|
-
mkdir -p /var/spool/rsyslog
|
|
245
|
-
chmod 755 /var/spool/rsyslog
|
|
246
|
-
### EGGS-FIX-END
|
|
247
|
-
`;
|
|
248
|
-
if (!content.includes('EGGS-FIX-START')) {
|
|
249
|
-
content = content.replace('#!/bin/sh', `#!/bin/sh\n${fix}`);
|
|
250
|
-
fs.writeFileSync(rsyslogScript, content, 'utf8');
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
// 3. PATCH CRON
|
|
254
|
-
const cronScript = `${workDir}/etc/init.d/cron`;
|
|
255
|
-
if (fs.existsSync(cronScript)) {
|
|
256
|
-
let content = fs.readFileSync(cronScript, 'utf8');
|
|
257
|
-
const fix = `
|
|
258
|
-
### EGGS-FIX-START
|
|
259
|
-
mkdir -p /var/spool/cron/crontabs
|
|
260
|
-
chmod 1730 /var/spool/cron/crontabs
|
|
261
|
-
chown root:crontab /var/spool/cron/crontabs 2>/dev/null || true
|
|
262
|
-
### EGGS-FIX-END
|
|
263
|
-
`;
|
|
264
|
-
if (!content.includes('EGGS-FIX-START')) {
|
|
265
|
-
content = content.replace('#!/bin/sh', `#!/bin/sh\n${fix}`);
|
|
266
|
-
fs.writeFileSync(cronScript, content, 'utf8');
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
@@ -21,7 +21,7 @@ export async function fertilization(snapshot_prefix = '', snapshot_basename = ''
|
|
|
21
21
|
this.familyId = distro.familyId;
|
|
22
22
|
this.distroId = distro.distroId;
|
|
23
23
|
this.distroLike = distro.distroLike;
|
|
24
|
-
this.
|
|
24
|
+
this.distroLiveMediumPath = distro.liveMediumPath;
|
|
25
25
|
this.settings = new Settings();
|
|
26
26
|
if (await this.settings.load()) {
|
|
27
27
|
await this.settings.loadRemix(this.theme);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ./src/classes/ovary.d/luks-home-support.ts
|
|
3
|
+
* penguins-eggs v.25.10.x / ecmascript 2020
|
|
4
|
+
* author: Piero Proietti
|
|
5
|
+
* email: piero.proietti@gmail.com
|
|
6
|
+
* license: MIT
|
|
7
|
+
*/
|
|
8
|
+
import Ovary from '../ovary.js';
|
|
9
|
+
/**
|
|
10
|
+
* Installa i file necessari per sbloccare home.img LUKS durante il boot
|
|
11
|
+
*/
|
|
12
|
+
export declare function installHomecryptSupport(this: Ovary, squashfsRoot: string, homeImgPath: string): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ./src/classes/ovary.d/luks-home-support.ts
|
|
3
|
+
* penguins-eggs v.25.10.x / ecmascript 2020
|
|
4
|
+
* author: Piero Proietti
|
|
5
|
+
* email: piero.proietti@gmail.com
|
|
6
|
+
* license: MIT
|
|
7
|
+
*/
|
|
8
|
+
// packages
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { dirname } from 'path';
|
|
13
|
+
import Utils from '../utils.js';
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
/**
|
|
17
|
+
* Installa i file necessari per sbloccare home.img LUKS durante il boot
|
|
18
|
+
*/
|
|
19
|
+
export function installHomecryptSupport(squashfsRoot, homeImgPath) {
|
|
20
|
+
Utils.warning('installing encrypted home support...');
|
|
21
|
+
// console.log("squashfsRoot:", squashfsRoot)
|
|
22
|
+
// console.log("homeImgPath:", homeImgPath)
|
|
23
|
+
// Leggi il template bash
|
|
24
|
+
const templatePath = path.join(__dirname, '../../../scripts/mount-encrypted-home.sh');
|
|
25
|
+
let bashScript = fs.readFileSync(templatePath, 'utf8');
|
|
26
|
+
// Sostituisci il placeholder con il path reale
|
|
27
|
+
bashScript = bashScript.replace('__HOME_IMG_PATH__', homeImgPath);
|
|
28
|
+
// Systemd service
|
|
29
|
+
const systemdService = `[Unit]
|
|
30
|
+
Description=Unlock and mount encrypted home.img
|
|
31
|
+
DefaultDependencies=no
|
|
32
|
+
After=systemd-udev-settle.service local-fs-pre.target
|
|
33
|
+
Before=local-fs.target display-manager.service
|
|
34
|
+
ConditionPathExists=${homeImgPath}
|
|
35
|
+
|
|
36
|
+
[Service]
|
|
37
|
+
Type=oneshot
|
|
38
|
+
RemainAfterExit=yes
|
|
39
|
+
StandardInput=tty
|
|
40
|
+
StandardOutput=journal+console
|
|
41
|
+
StandardError=journal+console
|
|
42
|
+
TTYPath=/dev/console
|
|
43
|
+
TTYReset=yes
|
|
44
|
+
TTYVHangup=yes
|
|
45
|
+
ExecStart=/usr/local/bin/mount-encrypted-home.sh
|
|
46
|
+
ExecStop=/bin/bash -c 'umount /home && cryptsetup close live-home'
|
|
47
|
+
|
|
48
|
+
[Install]
|
|
49
|
+
WantedBy=local-fs.target
|
|
50
|
+
`;
|
|
51
|
+
// Percorsi di destinazione
|
|
52
|
+
const scriptPath = path.join(squashfsRoot, 'usr/local/bin/mount-encrypted-home.sh');
|
|
53
|
+
const servicePath = path.join(squashfsRoot, 'etc/systemd/system/mount-encrypted-home.service');
|
|
54
|
+
const symlinkDir = path.join(squashfsRoot, 'etc/systemd/system/local-fs.target.wants');
|
|
55
|
+
const symlinkPath = path.join(symlinkDir, 'mount-encrypted-home.service');
|
|
56
|
+
// Create dirs
|
|
57
|
+
fs.mkdirSync(path.dirname(scriptPath), { recursive: true });
|
|
58
|
+
fs.mkdirSync(path.dirname(servicePath), { recursive: true });
|
|
59
|
+
fs.mkdirSync(symlinkDir, { recursive: true });
|
|
60
|
+
// Scrivi lo script
|
|
61
|
+
fs.writeFileSync(scriptPath, bashScript);
|
|
62
|
+
fs.chmodSync(scriptPath, 0o755);
|
|
63
|
+
// Scrivi il service
|
|
64
|
+
fs.writeFileSync(servicePath, systemdService);
|
|
65
|
+
// Crea il symlink per abilitare il service
|
|
66
|
+
if (fs.existsSync(symlinkPath)) {
|
|
67
|
+
fs.unlinkSync(symlinkPath);
|
|
68
|
+
}
|
|
69
|
+
fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
|
|
70
|
+
}
|
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
import Ovary from '../ovary.js';
|
|
9
9
|
/**
|
|
10
10
|
* Installa i file necessari per sbloccare home.img LUKS durante il boot
|
|
11
|
+
* Supporta sia Systemd (Debian/Ubuntu) che SysVinit (Devuan)
|
|
11
12
|
*/
|
|
12
13
|
export declare function installHomecryptSupport(this: Ovary, squashfsRoot: string, homeImgPath: string): void;
|
|
@@ -15,18 +15,23 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
15
15
|
const __dirname = dirname(__filename);
|
|
16
16
|
/**
|
|
17
17
|
* Installa i file necessari per sbloccare home.img LUKS durante il boot
|
|
18
|
+
* Supporta sia Systemd (Debian/Ubuntu) che SysVinit (Devuan)
|
|
18
19
|
*/
|
|
19
20
|
export function installHomecryptSupport(squashfsRoot, homeImgPath) {
|
|
20
21
|
Utils.warning('installing encrypted home support...');
|
|
21
|
-
//
|
|
22
|
-
// console.log("homeImgPath:", homeImgPath)
|
|
23
|
-
// Leggi il template bash
|
|
22
|
+
// 1. PREPARAZIONE SCRIPT DI MONTAGGIO (Il "Motore")
|
|
24
23
|
const templatePath = path.join(__dirname, '../../../scripts/mount-encrypted-home.sh');
|
|
25
24
|
let bashScript = fs.readFileSync(templatePath, 'utf8');
|
|
26
|
-
// Sostituisci il placeholder con il path reale
|
|
27
25
|
bashScript = bashScript.replace('__HOME_IMG_PATH__', homeImgPath);
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const mountScriptPath = path.join(squashfsRoot, 'usr/local/bin/mount-encrypted-home.sh');
|
|
27
|
+
fs.mkdirSync(path.dirname(mountScriptPath), { recursive: true });
|
|
28
|
+
fs.writeFileSync(mountScriptPath, bashScript);
|
|
29
|
+
fs.chmodSync(mountScriptPath, 0o755);
|
|
30
|
+
// ---------------------------------------------------------
|
|
31
|
+
// RAMO SYSTEMD (Invariato - funziona bene con i .service)
|
|
32
|
+
// ---------------------------------------------------------
|
|
33
|
+
if (Utils.isSystemd()) {
|
|
34
|
+
const systemdService = `[Unit]
|
|
30
35
|
Description=Unlock and mount encrypted home.img
|
|
31
36
|
DefaultDependencies=no
|
|
32
37
|
After=systemd-udev-settle.service local-fs-pre.target
|
|
@@ -48,23 +53,95 @@ ExecStop=/bin/bash -c 'umount /home && cryptsetup close live-home'
|
|
|
48
53
|
[Install]
|
|
49
54
|
WantedBy=local-fs.target
|
|
50
55
|
`;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
const servicePath = path.join(squashfsRoot, 'etc/systemd/system/mount-encrypted-home.service');
|
|
57
|
+
const symlinkDir = path.join(squashfsRoot, 'etc/systemd/system/local-fs.target.wants');
|
|
58
|
+
const symlinkPath = path.join(symlinkDir, 'mount-encrypted-home.service');
|
|
59
|
+
fs.mkdirSync(path.dirname(servicePath), { recursive: true });
|
|
60
|
+
fs.mkdirSync(symlinkDir, { recursive: true });
|
|
61
|
+
fs.writeFileSync(servicePath, systemdService);
|
|
62
|
+
if (fs.existsSync(symlinkPath))
|
|
63
|
+
fs.unlinkSync(symlinkPath);
|
|
64
|
+
fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------
|
|
67
|
+
// RAMO SYSVINIT (DEVUAN) - METODO INITTAB HIJACK
|
|
68
|
+
// ---------------------------------------------------------
|
|
69
|
+
else if (Utils.isSysvinit()) {
|
|
70
|
+
Utils.warning('Configuring SysVinit via /etc/inittab hijacking (Persistent Method)...');
|
|
71
|
+
// A. Creiamo un Wrapper Script che fa: Sblocco -> Poi lancia Login
|
|
72
|
+
// Questo script prenderà il posto di 'agetty' su tty1
|
|
73
|
+
const wrapperScript = `#!/bin/sh
|
|
74
|
+
# Wrapper per sbloccare la home prima del login su TTY1
|
|
75
|
+
|
|
76
|
+
# 1. Setup ambiente minimale
|
|
77
|
+
export TERM=linux
|
|
78
|
+
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
|
79
|
+
|
|
80
|
+
# 2. Pulizia schermo e stop Plymouth
|
|
81
|
+
clear
|
|
82
|
+
if [ -x /bin/plymouth ] && /bin/plymouth --ping; then
|
|
83
|
+
/bin/plymouth quit
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# 3. Attesa dispositivi (importante per USB)
|
|
87
|
+
echo "Waiting for devices..."
|
|
88
|
+
/sbin/udevadm settle
|
|
89
|
+
|
|
90
|
+
# 4. Esecuzione script di sblocco
|
|
91
|
+
echo "------------------------------------------------"
|
|
92
|
+
echo " CHECKING ENCRYPTED HOME STORAGE"
|
|
93
|
+
echo "------------------------------------------------"
|
|
94
|
+
/usr/local/bin/mount-encrypted-home.sh
|
|
95
|
+
|
|
96
|
+
# 5. Controllo esito (visivo)
|
|
97
|
+
if mountpoint -q /home; then
|
|
98
|
+
echo ">> Home mounted successfully."
|
|
99
|
+
sleep 1
|
|
100
|
+
else
|
|
101
|
+
echo ">> Home NOT mounted. Continuing unencrypted..."
|
|
102
|
+
sleep 2
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# 6. LANCIO DEL VERO LOGIN (Sostituisce questo processo)
|
|
106
|
+
# Nota: --noclear evita di cancellare i messaggi di errore precedenti
|
|
107
|
+
exec /sbin/agetty --noclear tty1 linux
|
|
108
|
+
`;
|
|
109
|
+
const wrapperPath = path.join(squashfsRoot, 'usr/local/bin/tty1-unlock-wrapper.sh');
|
|
110
|
+
fs.writeFileSync(wrapperPath, wrapperScript);
|
|
111
|
+
fs.chmodSync(wrapperPath, 0o755);
|
|
112
|
+
// B. Modifichiamo /etc/inittab per usare il nostro wrapper
|
|
113
|
+
const inittabPath = path.join(squashfsRoot, 'etc/inittab');
|
|
114
|
+
if (fs.existsSync(inittabPath)) {
|
|
115
|
+
let content = fs.readFileSync(inittabPath, 'utf8');
|
|
116
|
+
// La riga standard è solitamente: 1:2345:respawn:/sbin/getty 38400 tty1
|
|
117
|
+
// Oppure su Devuan: 1:2345:respawn:/sbin/agetty --noclear tty1 linux
|
|
118
|
+
// Cerchiamo qualsiasi riga che inizia con "1:" (tty1)
|
|
119
|
+
const regexTTY1 = /^1:.*$/m;
|
|
120
|
+
// La nuova riga che lancia il nostro wrapper invece di agetty diretto
|
|
121
|
+
const newLine = `1:2345:respawn:/usr/local/bin/tty1-unlock-wrapper.sh`;
|
|
122
|
+
if (regexTTY1.test(content)) {
|
|
123
|
+
content = content.replace(regexTTY1, newLine);
|
|
124
|
+
Utils.warning('Patched /etc/inittab to run home unlock on TTY1');
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Se non la trova, la aggiungiamo in fondo (caso raro ma possibile)
|
|
128
|
+
content += `\n${newLine}\n`;
|
|
129
|
+
}
|
|
130
|
+
fs.writeFileSync(inittabPath, content);
|
|
131
|
+
}
|
|
132
|
+
// C. Pulizia vecchi tentativi (Rimuoviamo script init.d se presenti per evitare conflitti)
|
|
133
|
+
const badSymlinks = [
|
|
134
|
+
path.join(squashfsRoot, 'etc/rcS.d/S05mount-encrypted-home'),
|
|
135
|
+
path.join(squashfsRoot, 'etc/rcS.d/S20mount-encrypted-home'),
|
|
136
|
+
path.join(squashfsRoot, 'etc/rc2.d/S02mount-encrypted-home')
|
|
137
|
+
];
|
|
138
|
+
badSymlinks.forEach(link => {
|
|
139
|
+
if (fs.existsSync(link))
|
|
140
|
+
fs.unlinkSync(link);
|
|
141
|
+
});
|
|
142
|
+
// Rimuoviamo anche lo script init.d stesso se esiste, non serve più
|
|
143
|
+
const initdFile = path.join(squashfsRoot, 'etc/init.d/mount-encrypted-home');
|
|
144
|
+
if (fs.existsSync(initdFile))
|
|
145
|
+
fs.unlinkSync(initdFile);
|
|
68
146
|
}
|
|
69
|
-
fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
|
|
70
147
|
}
|
|
@@ -27,7 +27,7 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
27
27
|
try {
|
|
28
28
|
/**
|
|
29
29
|
* this.luksMappedName = 'home.img';
|
|
30
|
-
* this.luksFile = `/tmp/${luksMappedName}`
|
|
30
|
+
* this.luksFile = `/var/tmp/${luksMappedName}`
|
|
31
31
|
* this.luksDevice = `/dev/mapper/${luksMappedName}`
|
|
32
32
|
* this.luksMountpoint = `/tmp/mnt/${luksMappedName}`
|
|
33
33
|
* this.luksPassword = '0'
|
|
@@ -42,15 +42,21 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
42
42
|
// Utils.warning('1. Calculation of space requirements...')
|
|
43
43
|
let sizeString = (await exec('du -sb --exclude=/home/eggs /home', { capture: true })).data.trim().split(/\s+/)[0];
|
|
44
44
|
let size = Number.parseInt(sizeString, 10);
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
const fsOverhead = Math.ceil(size * 0.05);
|
|
46
|
+
const luksHeader = 32 * 1024 * 1024;
|
|
47
|
+
const safetyBuffer = 100 * 1024 * 1024;
|
|
48
|
+
let calculatedSize = size + fsOverhead + luksHeader + safetyBuffer;
|
|
49
|
+
const minSize = 64 * 1024 * 1024;
|
|
50
|
+
if (calculatedSize < minSize)
|
|
51
|
+
calculatedSize = minSize;
|
|
52
|
+
const alignment = 4 * 1024 * 1024;
|
|
53
|
+
const luksSize = Math.ceil(calculatedSize / alignment) * alignment;
|
|
54
|
+
warning(`------------------------------------------`);
|
|
55
|
+
warning(`HOME CRYPT CALCULATION (Read-Only):`);
|
|
56
|
+
warning(` Data Payload: ${bytesToGB(size)}`);
|
|
57
|
+
warning(` Overhead+Buf: ${bytesToGB(luksSize - size)}`);
|
|
58
|
+
warning(` TOTAL SIZE: ${bytesToGB(luksSize)}`);
|
|
59
|
+
warning(`------------------------------------------`);
|
|
54
60
|
warning(`creating partition LUKS: ${this.luksFile}`);
|
|
55
61
|
await this.luksExecuteCommand('truncate', ['--size', `${luksSize}`, this.luksFile]);
|
|
56
62
|
warning(`formatting ${this.luksFile} as a LUKS volume...`);
|
|
@@ -59,7 +65,7 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
59
65
|
await this.luksExecuteCommand('cryptsetup', luksFormatArgs, `${this.luksPassword}\n`);
|
|
60
66
|
warning(`opening the LUKS volume. It will be mapped to ${this.luksDevice}`);
|
|
61
67
|
await this.luksExecuteCommand('cryptsetup', ['luksOpen', this.luksFile, this.luksMappedName], `${this.luksPassword}\n`);
|
|
62
|
-
warning(`formatting
|
|
68
|
+
warning(`formatting ext4 `);
|
|
63
69
|
await exec(`mkfs.ext4 -L live-home ${this.luksDevice}`, this.echo);
|
|
64
70
|
warning(`mounting ${this.luksDevice} on ${this.luksMountpoint}`);
|
|
65
71
|
if (fs.existsSync(this.luksMountpoint)) {
|
|
@@ -74,17 +80,21 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
74
80
|
await exec(`mount /dev/mapper/${this.luksMappedName} ${this.luksMountpoint}`, this.echo);
|
|
75
81
|
warning(`copying /home on ${this.luksMountpoint}`);
|
|
76
82
|
await exec(`rsync -ah --exclude='eggs' /home/ ${this.luksMountpoint}`, this.echo);
|
|
83
|
+
/**
|
|
84
|
+
* utenti e gruppi in .system-backup
|
|
85
|
+
*/
|
|
77
86
|
warning(`saving user accounts info...`);
|
|
78
|
-
// Crea directory per backup system files
|
|
79
87
|
await exec(`mkdir -p ${this.luksMountpoint}/.system-backup`, this.echo);
|
|
80
|
-
//
|
|
88
|
+
// passwd/shadow: solo utenti con UID >= 1000
|
|
81
89
|
await exec(`awk -F: '$3 >= 1000 {print}' /etc/passwd > ${this.luksMountpoint}/.system-backup/passwd`, this.echo);
|
|
82
90
|
await exec(`awk -F: '$3 >= 1000 {print}' /etc/shadow > ${this.luksMountpoint}/.system-backup/shadow`, this.echo);
|
|
83
|
-
//
|
|
91
|
+
// group/gshadow TUTTI
|
|
84
92
|
// Gli utenti possono appartenere a gruppi di sistema (sudo, audio, video, etc.)
|
|
85
93
|
await exec(`cp /etc/group ${this.luksMountpoint}/.system-backup/group`, this.echo);
|
|
86
94
|
await exec(`cp /etc/gshadow ${this.luksMountpoint}/.system-backup/gshadow`, this.echo);
|
|
87
|
-
|
|
95
|
+
/**
|
|
96
|
+
* saving display manager (autologin) configs...
|
|
97
|
+
*/
|
|
88
98
|
warning(`saving display manager configuration...`);
|
|
89
99
|
// GDM (gdm3 è comune su Debian/Ubuntu)
|
|
90
100
|
await exec(`[ -e /etc/gdm3 ] && cp -a /etc/gdm3 ${this.luksMountpoint}/.system-backup/`, this.echo);
|
|
@@ -95,10 +105,10 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
95
105
|
// SDDM (sia file .conf che directory .conf.d)
|
|
96
106
|
await exec(`[ -e /etc/sddm.conf ] && cp -a /etc/sddm.conf ${this.luksMountpoint}/.system-backup/`, this.echo);
|
|
97
107
|
await exec(`[ -e /etc/sddm.conf.d ] && cp -a /etc/sddm.conf.d ${this.luksMountpoint}/.system-backup/`, this.echo);
|
|
98
|
-
warning(`
|
|
99
|
-
await exec(
|
|
100
|
-
|
|
101
|
-
await this.
|
|
108
|
+
warning(`Syncing filesystem on ${this.luksMountpoint}...`);
|
|
109
|
+
await exec('sync', this.echo); // Forza scrittura dati su disco
|
|
110
|
+
// Shrink()
|
|
111
|
+
await this.luksShrink();
|
|
102
112
|
warning(`moving ${this.luksMappedName} to (ISO)/live/.`);
|
|
103
113
|
await exec(`mv ${this.luksFile} ${this.settings.iso_work}/live`, this.echo);
|
|
104
114
|
warning('encryption process successfully completed!');
|
|
@@ -117,6 +127,10 @@ export async function luksHome(clone = false, homecrypt = false) {
|
|
|
117
127
|
if (fs.existsSync(this.luksDevice)) {
|
|
118
128
|
await this.luksExecuteCommand('cryptsetup', ['close', this.luksMappedName]).catch(() => { });
|
|
119
129
|
}
|
|
130
|
+
if (fs.existsSync(this.luksFile)) {
|
|
131
|
+
Utils.warning(`Removing temporary container: ${this.luksFile}`);
|
|
132
|
+
fs.unlinkSync(this.luksFile);
|
|
133
|
+
}
|
|
120
134
|
await Utils.pressKeyToExit();
|
|
121
135
|
process.exit(1);
|
|
122
136
|
}
|