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.
Files changed (118) hide show
  1. package/.oclif.manifest.json +1 -1
  2. package/README.md +47 -760
  3. package/README.pdf +13450 -14838
  4. package/addons/eggs/adapt/applications/eggs-adapt.desktop +0 -0
  5. package/addons/eggs/pve/applications/eggs-pve.desktop +0 -0
  6. package/addons/eggs/rsupport/applications/eggs-rsupport.desktop +0 -0
  7. package/addons/eggs/theme/applications/install-system.desktop +0 -0
  8. package/addons/eggs/theme/livecd/simple.grub.main.cfg +3 -3
  9. package/assets/calamares/install-system.sh +0 -0
  10. package/assets/penguins-eggs.desktop +0 -0
  11. package/assets/penguins-krill.desktop +0 -0
  12. package/assets/penguins-links-add.desktop +0 -0
  13. package/assets/penguins-live-installer.desktop +0 -0
  14. package/bin/dev.js +0 -0
  15. package/conf/distros/alpine/calamares/calamares-modules/machineid-openrc/machineid-openrc.sh +0 -0
  16. package/conf/distros/buster/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  17. package/conf/distros/buster/calamares/calamares-modules/dpkg-unsafe-io/dpkg-unsafe-io.sh +0 -0
  18. package/conf/distros/buster/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
  19. package/conf/distros/fedora/calamares/calamares-modules/bootloaderspecification/bootloaderspecification.sh +0 -0
  20. package/conf/distros/focal/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  21. package/conf/distros/focal/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
  22. package/conf/distros/focal/calamares/libexec/calamares-aptsources.sh +0 -0
  23. package/conf/distros/focal/calamares/libexec/calamares-l10n-helper.sh +0 -0
  24. package/conf/distros/focal/calamares/libexec/calamares-logs-helper.sh +0 -0
  25. package/conf/distros/focal/calamares/libexec/calamares-nomodeset.sh +0 -0
  26. package/conf/distros/noble/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  27. package/conf/distros/noble/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
  28. package/conf/distros/noble/calamares/libexec/calamares-aptsources.sh +0 -0
  29. package/conf/distros/noble/calamares/libexec/calamares-l10n-helper.sh +2 -1
  30. package/conf/distros/noble/calamares/libexec/calamares-logs-helper.sh +0 -0
  31. package/conf/distros/noble/calamares/libexec/calamares-nomodeset.sh +0 -0
  32. package/conf/distros/noble/calamares/settings.yml +1 -0
  33. package/conf/distros/opensuse/calamares/calamares-modules/bootloaderspecification/bootloaderspecification.sh +0 -0
  34. package/conf/distros/opensuse/calamares/settings.yml +0 -0
  35. package/conf/distros/opensuse/calamares/zstd2lzo.sh +0 -0
  36. package/conf/distros/trixie/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  37. package/conf/distros/trixie/calamares/calamares-modules/dpkg-unsafe-io/dpkg-unsafe-io.sh +0 -0
  38. package/conf/distros/trixie/calamares/calamares-modules/sources-yolk/sources-yolk.sh +0 -0
  39. package/conf/init/unattended.sh +0 -0
  40. package/dist/bin/dev.js +0 -0
  41. package/dist/bin/run.js +0 -0
  42. package/dist/classes/cli-autologin.d.ts +37 -4
  43. package/dist/classes/cli-autologin.js +125 -112
  44. package/dist/classes/daddy.js +4 -1
  45. package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +3 -2
  46. package/dist/classes/incubation/fisherman-helper/initcpio.js +25 -20
  47. package/dist/classes/incubation/incubator.d/manjaro.js +1 -0
  48. package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -1
  49. package/dist/classes/ovary.d/edit-live-fs.js +15 -122
  50. package/dist/classes/ovary.d/fertilization.js +1 -1
  51. package/dist/classes/ovary.d/luks-home-support-systemd.d.ts +12 -0
  52. package/dist/classes/ovary.d/luks-home-support-systemd.js +70 -0
  53. package/dist/classes/ovary.d/luks-home-support.d.ts +1 -0
  54. package/dist/classes/ovary.d/luks-home-support.js +101 -24
  55. package/dist/classes/ovary.d/luks-home.js +33 -19
  56. package/dist/classes/ovary.d/luks-root.d.ts +1 -2
  57. package/dist/classes/ovary.d/luks-root.js +46 -27
  58. package/dist/classes/ovary.d/luks-shrink.d.ts +14 -0
  59. package/dist/classes/ovary.d/luks-shrink.js +86 -0
  60. package/dist/classes/ovary.d/produce.js +63 -21
  61. package/dist/classes/ovary.d.ts +3 -1
  62. package/dist/classes/ovary.js +3 -1
  63. package/dist/classes/utils.js +1 -1
  64. package/dist/classes/yolk.js +1 -1
  65. package/dist/commands/produce.js +11 -7
  66. package/dist/interfaces/calamares/i-calamares-branding.d.ts +56 -38
  67. package/dist/interfaces/calamares/i-calamares-branding.js +10 -0
  68. package/dist/krill/classes/prepare.d/users.js +1 -1
  69. package/dist/krill/classes/prepare.js +6 -2
  70. package/dist/krill/classes/sequence.d/fstab.js +1 -1
  71. package/dist/krill/classes/sequence.d/mkfs.js +1 -1
  72. package/dist/krill/classes/sequence.d/remove-homecrypt-hack.d.ts +13 -0
  73. package/dist/krill/classes/sequence.d/remove-homecrypt-hack.js +65 -0
  74. package/dist/krill/classes/sequence.d/unpackfs.js +2 -2
  75. package/dist/krill/classes/sequence.d.ts +3 -5
  76. package/dist/krill/classes/sequence.js +31 -29
  77. package/dist/krill/components/finished.js +2 -2
  78. package/dist/krill/components/install.js +2 -2
  79. package/dist/krill/components/keyboard.js +2 -2
  80. package/dist/krill/components/location.js +2 -2
  81. package/dist/krill/components/network.js +2 -2
  82. package/dist/krill/components/partitions.js +2 -2
  83. package/dist/krill/components/summary.js +2 -2
  84. package/dist/krill/components/users.js +2 -2
  85. package/dist/krill/components/welcome.js +2 -2
  86. package/dist/lib/utils.d.ts +1 -0
  87. package/dist/lib/utils.js +46 -0
  88. package/dracut/modules.d/00debug-shell/debug-hook.sh +0 -0
  89. package/dracut/modules.d/00debug-shell/module-setup.sh +0 -0
  90. package/dracut/modules.d/90block/block-cmdline.sh +0 -0
  91. package/dracut/modules.d/90block/module-setup.sh +0 -0
  92. package/dracut/modules.d/95iso-scan/iso-scan-fallback.sh +0 -0
  93. package/dracut/modules.d/95iso-scan/iso-scan.sh +0 -0
  94. package/dracut/modules.d/95iso-scan/module-setup.sh +0 -0
  95. package/dracut/modules.d/95luks-loop/luks-loop.sh +0 -0
  96. package/dracut/modules.d/95luks-loop/module-setup.sh +0 -0
  97. package/eui/eui-autostart-cinnamon.desktop +0 -0
  98. package/eui/eui-autostart-xfce.desktop +0 -0
  99. package/eui/eui-create-image.sh +0 -0
  100. package/eui/eui-start.sh +0 -0
  101. package/manpages/doc/man/eggs.1.gz +0 -0
  102. package/manpages/doc/man/eggs.html +8 -8
  103. package/package.json +130 -124
  104. package/perrisbrewery/scripts/postinst +0 -0
  105. package/perrisbrewery/scripts/postrm +0 -0
  106. package/perrisbrewery/scripts/preinst +0 -0
  107. package/perrisbrewery/scripts/prerm +0 -0
  108. package/scripts/99clean +0 -0
  109. package/scripts/adapt.sh +0 -0
  110. package/scripts/boot-encrypted-root.sh +0 -0
  111. package/scripts/bros/waydroid-helper.sh +0 -0
  112. package/scripts/lsb_release +0 -0
  113. package/scripts/mom.sh +0 -0
  114. package/scripts/mount-encrypted-home.sh +0 -0
  115. package/scripts/pve-live.service +0 -0
  116. package/scripts/pve-live.sh +0 -0
  117. package/scripts/restore_homecrypt_krill.sh +93 -0
  118. 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 result = await exec('uname -r');
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); // Verifica se esiste /etc/mkinitcpio.d/linux612.preset
28
- return manjaroPreset; // Se esiste, lo restituisce e la funzione termina
26
+ await access(manjaroPreset);
27
+ return manjaroPreset;
29
28
  }
30
- catch {
31
- // Se anche questa logica fallisce, lascia che proceda al fallback per Arch
32
- // console.warn('Logica Manjaro fallita, si tenta il fallback per Arch...');
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
- // Se anche questa logica fallisce, lascia che proceda al fallback per Arch
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
- // Rimuoviamo l'errore originale dalla stringa per un messaggio più pulito
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
  }
@@ -78,5 +78,6 @@ export class Manjaro {
78
78
  }
79
79
  await fisherman.buildModule('umount');
80
80
  await fisherman.buildModuleFinished();
81
+ console.log('manjaro created');
81
82
  }
82
83
  }
@@ -6,4 +6,4 @@
6
6
  * license: MIT
7
7
  */
8
8
  import Ovary from '../ovary.js';
9
- export declare function editLiveFs(this: Ovary, clone?: boolean): Promise<void>;
9
+ export declare function editLiveFs(this: Ovary): Promise<void>;
@@ -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(clone = false) {
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
- // 🔧 [MODIFICA 1] Machine ID cleanup
89
- // Cancelliamo SEMPRE il machine-id, anche su SysVinit.
90
- // Questo garantisce che lo script patchato (dbus) trovi il file mancante e lo rigeneri.
91
- if (fs.existsSync(`${workDir}/etc/machine-id`)) {
92
- await exec(`rm ${workDir}/etc/machine-id`, this.echo);
93
- await exec(`touch ${workDir}/etc/machine-id`, this.echo); // Lo ricreiamo vuoto
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
- // Rimuoviamo anche quello in /var/lib/dbus per forzare la rigenerazione
96
- if (fs.existsSync(`${workDir}/var/lib/dbus/machine-id`)) {
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.distroLliveMediumPath = distro.liveMediumPath;
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
- // console.log("squashfsRoot:", squashfsRoot)
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
- // Systemd service
29
- const systemdService = `[Unit]
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
- // 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);
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 luksSize = Math.ceil(size * 2);
46
- /**
47
- * E' più precisa ma equivalente grazie
48
- * al truncate
49
- */
50
- // const fsOverhead = Math.max(size * 0.1, 100 * 1024 * 1024)
51
- // const luksSize = size * 1.25 + fsOverhead // +25%
52
- warning(`homes size: ${bytesToGB(size)}`);
53
- warning(`partition LUKS ${this.luksFile} size: ${bytesToGB(luksSize)}`);
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 c ext4 `);
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
- // Filtra solo utenti con UID >= 1000
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
- // Per i gruppi: salva TUTTI (non filtrare per GID)
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
- // saving display manager (autologin) configs...
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(`unmount ${this.luksDevice}`);
99
- await exec(`umount ${this.luksMountpoint}`, this.echo);
100
- warning(`closing LUKS volume ${this.luksMappedName}.`);
101
- await this.luksExecuteCommand('cryptsetup', ['close', this.luksMappedName]);
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
  }
@@ -8,8 +8,7 @@
8
8
  import Ovary from '../ovary.js';
9
9
  /**
10
10
  * luksRoot()
11
- *
12
- * create a container LUKS with the entire
11
+ * * create a container LUKS with the entire
13
12
  * filesystem.squashfs
14
13
  */
15
14
  export declare function luksRoot(this: Ovary): Promise<void>;