penguins-eggs 25.10.6 → 25.10.19

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 (84) hide show
  1. package/.oclif.manifest.json +51 -145
  2. package/README.md +3 -829
  3. package/addons/eggs/theme/livecd/isolinux.main.simple.cfg +3 -3
  4. package/conf/distros/trixie/calamares/modules/shellprocess@boot_deploy.yml +3 -4
  5. package/conf/love.yaml +1 -1
  6. package/dist/classes/distro.js +9 -2
  7. package/dist/classes/diversions.d.ts +1 -1
  8. package/dist/classes/diversions.js +27 -8
  9. package/dist/classes/incubation/incubator.d/archlinux.js +1 -0
  10. package/dist/classes/incubation/incubator.d/trixie.js +7 -10
  11. package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -1
  12. package/dist/classes/ovary.d/edit-live-fs.js +1 -7
  13. package/dist/classes/ovary.d/fertilization.js +1 -0
  14. package/dist/classes/ovary.d/finished.js +1 -5
  15. package/dist/classes/ovary.d/initrd.d.ts +1 -1
  16. package/dist/classes/ovary.d/initrd.js +17 -19
  17. package/dist/classes/ovary.d/live-create-structure.js +1 -4
  18. package/dist/classes/ovary.d/luks-get-password.d.ts +12 -0
  19. package/dist/classes/ovary.d/luks-get-password.js +57 -0
  20. package/dist/classes/ovary.d/luks-home-support.d.ts +12 -0
  21. package/dist/classes/ovary.d/luks-home-support.js +75 -0
  22. package/dist/classes/ovary.d/luks-home.d.ts +15 -0
  23. package/dist/classes/ovary.d/luks-home.js +140 -0
  24. package/dist/classes/ovary.d/luks-root-bootstrap-builder.d.ts +11 -0
  25. package/dist/classes/ovary.d/luks-root-bootstrap-builder.js +45 -0
  26. package/dist/classes/ovary.d/luks-root.d.ts +15 -0
  27. package/dist/classes/ovary.d/luks-root.js +126 -0
  28. package/dist/classes/ovary.d/make-efi.js +1 -1
  29. package/dist/classes/ovary.d/make-squashfs.d.ts +1 -1
  30. package/dist/classes/ovary.d/make-squashfs.js +7 -3
  31. package/dist/classes/ovary.d/produce.d.ts +3 -3
  32. package/dist/classes/ovary.d/produce.js +76 -48
  33. package/dist/classes/ovary.d/syslinux.js +1 -1
  34. package/dist/classes/ovary.d/xorriso-command.d.ts +2 -2
  35. package/dist/classes/ovary.d/xorriso-command.js +27 -29
  36. package/dist/classes/ovary.d.ts +35 -16
  37. package/dist/classes/ovary.js +42 -16
  38. package/dist/classes/utils.d.ts +1 -0
  39. package/dist/classes/utils.js +3 -0
  40. package/dist/commands/config.d.ts +1 -1
  41. package/dist/commands/config.js +2 -2
  42. package/dist/commands/love.d.ts +3 -0
  43. package/dist/commands/love.js +40 -2
  44. package/dist/commands/produce.d.ts +3 -2
  45. package/dist/commands/produce.js +14 -17
  46. package/dist/commands/tools/{ppa.d.ts → repo.d.ts} +2 -2
  47. package/dist/commands/tools/{ppa.js → repo.js} +69 -67
  48. package/dracut/create-symlink +71 -0
  49. package/dracut/dracut-log.txt +3 -0
  50. package/dracut/dracut.conf.d/50-live.conf +24 -6
  51. package/dracut/dracut.conf.d/README.md +10 -0
  52. package/dracut/export +4 -0
  53. package/dracut/export-dracut-analysis +51 -0
  54. package/dracut/export-dracut-log +2 -0
  55. package/dracut/mkisofs +10 -0
  56. package/dracut/modules.d/00debug-shell/debug-hook.sh +13 -0
  57. package/dracut/modules.d/00debug-shell/module-setup.sh +20 -0
  58. package/dracut/modules.d/90block/README.md +7 -0
  59. package/dracut/modules.d/90block/block-cmdline.sh +3 -0
  60. package/dracut/modules.d/90block/module-setup.sh +15 -0
  61. package/dracut/modules.d/95iso-scan/README.md +3 -0
  62. package/dracut/modules.d/95iso-scan/iso-scan-fallback.sh +12 -0
  63. package/dracut/modules.d/95iso-scan/iso-scan.sh +92 -0
  64. package/dracut/modules.d/95iso-scan/module-setup.sh +18 -0
  65. package/dracut/modules.d/95luks-loop/README.md +9 -0
  66. package/dracut/modules.d/95luks-loop/luks-loop.sh +90 -0
  67. package/dracut/modules.d/95luks-loop/module-setup.sh +17 -0
  68. package/dracut/renew-initramfs +17 -0
  69. package/dracut/sbin2bin +10 -0
  70. package/dracut/update-dracut-conf-d +2 -0
  71. package/dracut/update-dracut-modules +62 -0
  72. package/manpages/doc/man/eggs.1.gz +0 -0
  73. package/manpages/doc/man/eggs.html +7 -661
  74. package/package.json +9 -8
  75. package/perrisbrewery/template/dependencies.yaml +6 -5
  76. package/scripts/_eggs +16 -31
  77. package/scripts/eggs.bash +4 -6
  78. package/scripts/luks-root-bootstrap-create.sh +235 -0
  79. package/scripts/luks-root-unlock.sh +172 -0
  80. package/scripts/mount-encrypted-home.sh +223 -0
  81. package/dist/commands/syncfrom.d.ts +0 -45
  82. package/dist/commands/syncfrom.js +0 -152
  83. package/dist/commands/syncto.d.ts +0 -40
  84. package/dist/commands/syncto.js +0 -175
@@ -13,20 +13,20 @@ label Live
13
13
  say "Booting {{{fullname}}} GNU/Linux (kernel {{{kernel}}})"
14
14
  linux {{{vmlinuz}}}
15
15
  append initrd={{{initrdImg}}} {{{kernel_parameters}}}
16
-
16
+ # RIMUOVERE O CONTROLLARE evm=off per overlayfs
17
17
 
18
18
  label Safe
19
19
  menu label {{{fullname}}} Safe Mode
20
20
  say "Booting {{{fullname}}} GNU/Linux (kernel {{{kernel}}})"
21
21
  linux {{{vmlinuz}}}
22
- append initrd={{{initrdImg}}} {{{kernel_parameters}}}
22
+ append initrd={{{initrdImg}}} {{{kernel_parameters}}}
23
23
 
24
24
 
25
25
  label Text
26
26
  menu label {{{fullname}}} Text Mode
27
27
  say "Booting {{{fullname}}} GNU/Linux (kernel {{{kernel}}})"
28
28
  linux {{{vmlinuz}}}
29
- append initrd={{{initrdImg}}} {{{kernel_parameters}}}
29
+ append initrd={{{initrdImg}}} {{{kernel_parameters}}}
30
30
 
31
31
  label local
32
32
  menu label Boot from local disk
@@ -17,8 +17,7 @@ script:
17
17
  # Riconfigureremo il kernel nel modulo boot_reconfigure per garantire che gli hook
18
18
  # vengano eseguiti secondo necessità.
19
19
 
20
- # ubuntu
21
- # cp --preserve=timestamps /lib/live/mount/medium/live/vmlinuz-`uname -r` ${ROOT}/boot/vmlinuz-`uname -r`
22
-
23
- # debian
20
+ # INITRAMFS = '/run/live/medium/'
21
+ # DRACUT = '/run/initramfs/live/'
24
22
  - cp --preserve=timestamps /run/live/medium/live/vmlinuz-`uname -r` ${ROOT}/boot/vmlinuz-`uname -r`
23
+ #- cp --preserve=timestamps /run/initramfs/live/live/vmlinuz-`uname -r` ${ROOT}/boot/vmlinuz-`uname -r`
package/conf/love.yaml CHANGED
@@ -4,5 +4,5 @@
4
4
  - eggs kill
5
5
  - eggs dad --default
6
6
  - eggs tools clean
7
- - eggs produce --pendrive --addons adapt
7
+ - eggs produce --addons adapt
8
8
 
@@ -101,7 +101,7 @@ class Distro {
101
101
  }
102
102
  else if (this.distroId === 'Openmamba') {
103
103
  this.familyId = 'openmamba';
104
- this.distroLike = 'openmamba';
104
+ this.distroLike = 'Openmamba';
105
105
  this.codenameId = 'rolling'; // viene rimosso dal nome
106
106
  this.distroUniqueId = this.familyId; // per krill
107
107
  this.liveMediumPath = '/run/initramfs/live/';
@@ -176,7 +176,14 @@ class Distro {
176
176
  else if (this.codenameId === 'trixie') {
177
177
  this.distroLike = 'Debian';
178
178
  this.distroUniqueId = 'trixie';
179
- this.liveMediumPath = '/run/live/medium/';
179
+ this.liveMediumPath = '/run/live/medium/'; //initramfs
180
+ // this.liveMediumPath = '/run/initramfs/live/' // dracut
181
+ /**
182
+ * dracut su trixie
183
+ if (Pacman.packageIsInstalled('dracut')) {
184
+ this.liveMediumPath = '/run/initramfs/live/'
185
+ }
186
+ */
180
187
  /**
181
188
  * Debian 14 forky
182
189
  */
@@ -39,7 +39,7 @@ export default class Diversions {
39
39
  * @param volid
40
40
  * @returns
41
41
  */
42
- static kernelParameters(familyId: string, volid: string): string;
42
+ static kernelParameters(familyId: string, volid: string, luksUuid?: string): string;
43
43
  /**
44
44
  *
45
45
  * @returns
@@ -6,6 +6,7 @@
6
6
  * license: MIT
7
7
  */
8
8
  import Distro from './distro.js';
9
+ import Pacman from './pacman.js';
9
10
  export default class Diversions {
10
11
  /**
11
12
  *
@@ -66,14 +67,10 @@ export default class Diversions {
66
67
  * @param volid
67
68
  * @returns
68
69
  */
69
- static kernelParameters(familyId, volid) {
70
+ static kernelParameters(familyId, volid, luksUuid = '') {
70
71
  // GRUB_CMDLINE_LINUX='ipv6.disable=1'
71
72
  let kp = "";
72
- if (familyId === 'aldos') {
73
- kp += `root=live:CDLABEL=${volid} rd.live.image rd.live.dir=/live rd.live.squashimg=filesystem.squashfs selinux=0 rootfstype=auto rd.locale.LANG=en_US.UTF-8 KEYBOARDTYPE=pc rd.vconsole.keymap=us rootflags=defaults,relatime,commit=60 nmi_watchdog=0 rhgb rd_NO_LUKS rd_NO_MD rd_NO_DM`;
74
- // root=live:CDLABEL=ALDOS6420241128 rootfstype=auto ro liveimg quiet rd.locale.LANG=es_MX.UTF-8 KEYBOARDTYPE=pc SYSFONT=latarcyrheb-sun16 rd.vconsole.keymap=es rootflags=defaults,relatime,commit=60 selinux=0 nmi_watchdog=0 rhgb rd_NO_LUKS rd_NO_MD rd_NO_DM
75
- }
76
- else if (familyId === 'alpine') {
73
+ if (familyId === 'alpine') {
77
74
  kp += `alpinelivelabel=${volid} alpinelivesquashfs=/mnt/live/filesystem.squashfs`;
78
75
  }
79
76
  else if (familyId === 'archlinux') {
@@ -81,14 +78,36 @@ export default class Diversions {
81
78
  const distroId = this.distro().distroId;
82
79
  if (this.isManjaroBased(distroId)) {
83
80
  kp += ` misobasedir=manjaro misolabel=${volid}`;
84
- // shx.exec(`mkdir -p ${this.settings.iso_work}.miso`)
85
81
  }
86
82
  else {
87
83
  kp += ` archisobasedir=arch archisolabel=${volid}`;
88
84
  }
89
85
  }
90
86
  else if (familyId === 'debian') {
91
- kp += `boot=live components locales=${process.env.LANG} cow_spacesize=2G`;
87
+ /**
88
+ * da rivedere dracut/initramfs
89
+ */
90
+ if (Pacman.packageIsInstalled('dracut')) {
91
+ if (luksUuid !== '') {
92
+ let append = `boot=live \
93
+ root=live:LABEL=${volid} \
94
+ rd.luks.loop=/live/luks.img \
95
+ eggs.luks.uuid=${luksUuid} \
96
+ rd.live.squashimg=filesystem.squashfs \
97
+ rd.live.overlay.overlayfs=1 \
98
+ nomodeset \
99
+ rd.break=pre-mount \
100
+ rd.shell`;
101
+ kp += append.replaceAll(/\s\s+/g, ' ');
102
+ }
103
+ else {
104
+ // dracut: rd.live.squashimg
105
+ kp += `root=live:CDLABEL=${volid} rd.live.image rd.live.dir=/live rd.live.squashimg=filesystem.squashfs`;
106
+ }
107
+ }
108
+ else {
109
+ kp += `boot=live components locales=${process.env.LANG} cow_spacesize=2G`;
110
+ }
92
111
  }
93
112
  else if (familyId === 'fedora') {
94
113
  kp += `root=live:CDLABEL=${volid} rd.live.image rd.live.dir=/live rd.live.squashimg=filesystem.squashfs selinux=0`;
@@ -59,6 +59,7 @@ export class Archlinux {
59
59
  await fisherman.buildModule('users', this.theme);
60
60
  await fisherman.buildModule('displaymanager');
61
61
  await fisherman.buildModule('hwclock');
62
+ await fisherman.shellprocess('disable-grub-btrfs');
62
63
  await fisherman.buildModule('grubcfg');
63
64
  await fisherman.buildModule('bootloader');
64
65
  await fisherman.buildModulePackages(this.distro, this.release);
@@ -62,24 +62,21 @@ export class Trixie {
62
62
  await fisherman.buildModule('networkcfg');
63
63
  await fisherman.buildModule('hwclock');
64
64
  await fisherman.buildModule('services-systemd');
65
+ await fisherman.buildModule('luksbootkeyfile');
66
+ await fisherman.shellprocess('boot_deploy'); // contiene this.liveMediumPath
65
67
  await fisherman.buildCalamaresModule('bootloader-config', true);
66
68
  await fisherman.buildModule('grubcfg');
67
69
  await fisherman.buildModule('bootloader');
68
- await fisherman.buildModulePackages(this.distro, this.release);
69
- await fisherman.buildModule('luksbootkeyfile');
70
- await fisherman.buildModule('plymouthcfg');
70
+ await fisherman.shellprocess('boot_reconfigure');
71
71
  await fisherman.buildModule('initramfscfg');
72
- await fisherman.buildModule('initramfs');
72
+ await fisherman.shellprocess('mkinitramfs');
73
+ await fisherman.buildModule('plymouthcfg');
74
+ await fisherman.buildModulePackages(this.distro, this.release);
73
75
  await fisherman.buildCalamaresModule('dpkg-unsafe-io-undo', false);
74
76
  await fisherman.buildModuleRemoveuser(this.user_opt);
75
77
  await fisherman.buildCalamaresModule('sources-yolk-undo', false);
76
78
  await fisherman.buildCalamaresModule('cleanup', true);
77
- // contextualprocess
78
- // await fisherman.contextualprocess('before_bootloader_context')
79
- // shellprocess
80
- await fisherman.shellprocess('mkinitramfs');
81
- await fisherman.shellprocess('boot_deploy');
82
- await fisherman.shellprocess('boot_reconfigure');
79
+ // await fisherman.buildModule('initramfs')
83
80
  // libexec recreate
84
81
  await exec(`rm -rf /usr/libexec/calamares`);
85
82
  await exec(`mkdir -p /usr/libexec/calamares`);
@@ -17,4 +17,4 @@ import Ovary from '../ovary.js';
17
17
  * - Add some basic files to /dev
18
18
  * - Clear configs from /etc/network/interfaces, wicd and NetworkManager and netman
19
19
  */
20
- export declare function editLiveFs(this: Ovary, clone?: boolean, cryptedclone?: boolean): Promise<void>;
20
+ export declare function editLiveFs(this: Ovary, clone?: boolean): Promise<void>;
@@ -27,7 +27,7 @@ const __dirname = path.dirname(new URL(import.meta.url).pathname);
27
27
  * - Add some basic files to /dev
28
28
  * - Clear configs from /etc/network/interfaces, wicd and NetworkManager and netman
29
29
  */
30
- export async function editLiveFs(clone = false, cryptedclone = false) {
30
+ export async function editLiveFs(clone = false) {
31
31
  if (this.verbose) {
32
32
  console.log('Ovary: editLiveFs');
33
33
  }
@@ -37,12 +37,6 @@ export async function editLiveFs(clone = false, cryptedclone = false) {
37
37
  if (clone) {
38
38
  await exec(`touch ${this.settings.work_dir.merged}/etc/penguins-eggs.d/is_clone`, this.echo);
39
39
  }
40
- /**
41
- * /etc/penguins-eggs.d/is_crypted_clone file created on live
42
- */
43
- if (cryptedclone) {
44
- await exec(`touch ${this.settings.work_dir.merged}/etc/penguins-eggs.d/is_crypted_clone`, this.echo);
45
- }
46
40
  /**
47
41
  * /etc/default/epoptes-client created on live
48
42
  */
@@ -21,6 +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
25
  this.settings = new Settings();
25
26
  if (await this.settings.load()) {
26
27
  await this.settings.loadRemix(this.theme);
@@ -8,17 +8,13 @@
8
8
  import chalk from 'chalk';
9
9
  // packages
10
10
  import path from 'path';
11
- // interfaces
12
- // libraries
13
- // classes
14
- import Utils from './../utils.js';
15
11
  // _dirname
16
12
  /**
17
13
  * finished = show the results
18
14
  * @param scriptOnly
19
15
  */
20
16
  export function finished(scriptOnly = false) {
21
- Utils.titles('produce');
17
+ // Utils.titles('produce')
22
18
  if (scriptOnly) {
23
19
  const pathOvarium = path.join(this.settings.config.snapshot_dir, 'ovarium');
24
20
  console.log('eggs is finished!\n\nYou can find the scripts to build iso: ' + chalk.cyanBright(this.settings.isoFilename) + '\nin the ovarium: ' + chalk.cyanBright(pathOvarium) + '.');
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ./src/classes/ovary.d/initrd-arch.ts
2
+ * ./src/classes/ovary.d/initrd.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
4
  * author: Piero Proietti
5
5
  * email: piero.proietti@gmail.com
@@ -1,5 +1,5 @@
1
1
  /**
2
- * ./src/classes/ovary.d/initrd-arch.ts
2
+ * ./src/classes/ovary.d/initrd.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
4
  * author: Piero Proietti
5
5
  * email: piero.proietti@gmail.com
@@ -21,7 +21,10 @@ export async function initrdAlpine() {
21
21
  let initrdImg = Utils.initrdImg();
22
22
  initrdImg = initrdImg.slice(Math.max(0, initrdImg.lastIndexOf('/') + 1));
23
23
  const pathConf = path.resolve(__dirname, `../../../mkinitfs/live.conf`);
24
- await exec(`mkinitfs -c ${pathConf} -o ${this.settings.iso_work}live/${initrdImg} ${this.kernel}`, this.echo);
24
+ const prefix = this.settings.config.snapshot_prefix;
25
+ const log = `> ${this.settings.iso_work}${prefix}mkinitfs.log.txt 2>&1`;
26
+ const cmd = `mkinitfs -c ${pathConf} -o ${this.settings.iso_work}live/${initrdImg} ${this.kernel} ${log}`;
27
+ await exec(cmd, this.echo);
25
28
  }
26
29
  /**
27
30
  * initrdArch
@@ -52,7 +55,9 @@ export async function initrdArch() {
52
55
  }
53
56
  await exec(`cp ${hookSrc} ${hookSaved}`);
54
57
  await exec(edit, this.echo);
55
- let cmd = `mkinitcpio -c ${fileConf} -g ${this.settings.iso_work}live/${path.basename(this.initrd)} -k ${this.kernel}`;
58
+ const prefix = this.settings.config.snapshot_prefix;
59
+ const log = `> ${this.settings.iso_work}${prefix}mkinitcpio.log.txt 2>&1`;
60
+ let cmd = `mkinitcpio -c ${fileConf} -g ${this.settings.iso_work}live/${path.basename(this.initrd)} -k ${this.kernel} ${log}`;
56
61
  await exec(cmd, this.echo);
57
62
  await exec(`rm -f ${hookDest}`);
58
63
  if (restore) {
@@ -65,30 +70,23 @@ export async function initrdArch() {
65
70
  */
66
71
  export async function initrdDebian(verbose = false) {
67
72
  Utils.warning(`creating ${this.initrd} using mkinitramfs on (ISO)/live`);
68
- let isCrypted = false;
69
- if (fs.existsSync('/etc/crypttab')) {
70
- isCrypted = true;
71
- await exec('mv /etc/crypttab /etc/crypttab.saved', this.echo);
72
- }
73
- await exec(`mkinitramfs -o ${this.settings.iso_work}live/${path.basename(this.initrd)} ${this.kernel} ${this.toNull}`, this.echo);
74
- if (isCrypted) {
75
- await exec('mv /etc/crypttab.saved /etc/crypttab', this.echo);
76
- }
73
+ const prefix = this.settings.config.snapshot_prefix;
74
+ const dest = `${this.settings.iso_work}live/${path.basename(this.initrd)}`;
75
+ const log = `> ${this.settings.iso_work}${prefix}mkinitramfs.log.txt 2>&1`;
76
+ const cmd = `mkinitramfs -o ${dest} ${this.kernel} ${log}`;
77
+ await exec(cmd, this.echo);
77
78
  }
78
79
  /*
79
- * initrdDracut) Almalinux/Fedora/Openmamba/Opensuse/Rocky/Voidlinux
80
+ * initrdDracut) Almalinux/Fedora/Openmamba/Opensuse/Rocky/
80
81
  */
81
82
  export async function initrdDracut() {
82
83
  Utils.warning(`creating ${path.basename(this.initrd)} using dracut on (ISO)/live`);
83
84
  const prefix = this.settings.config.snapshot_prefix;
84
- const confdir = '--confdir ' + path.resolve(__dirname, `../../../dracut/dracut.conf.d`);
85
- // const dracutdir='--dracutdir /opt/penguins-eggs/dracut'
86
- const dracutdir = '';
87
- const dest = `${this.settings.iso_work}live/${path.basename(this.initrd)}`;
88
85
  const log = `> ${this.settings.iso_work}${prefix}dracut.log.txt 2>&1`;
86
+ const confdir = '--confdir ' + path.resolve(__dirname, `../../../dracut/dracut.conf.d`);
89
87
  const kmoddir = `--kmoddir /lib/modules/${this.kernel}`;
90
- const cmd = `dracut --force --debug --no-hostonly ${confdir} ${kmoddir} ${dest} ${this.kernel} ${log}`;
91
- //const cmd=`ls -la /lib /lib/modules ${log}`
88
+ const initramfs = `${this.settings.iso_work}live/${path.basename(this.initrd)}`;
89
+ const cmd = `dracut --force ${confdir} ${kmoddir} ${initramfs} ${this.kernel} ${log}`;
92
90
  console.log(cmd);
93
91
  await exec(cmd, this.echo);
94
92
  // clean per btrfs
@@ -17,10 +17,7 @@ const __dirname = path.dirname(new URL(import.meta.url).pathname);
17
17
  * Crea la struttura della workdir
18
18
  */
19
19
  export async function liveCreateStructure() {
20
- if (this.verbose) {
21
- console.log('Ovary: liveCreateStructure');
22
- }
23
- Utils.warning(`creating egg in ${this.nest}`);
20
+ Utils.warning(`creating live structure on ${this.nest}`);
24
21
  let cmd = '';
25
22
  cmd = `# create nest\n`;
26
23
  cmd += `mkdir -p ${this.nest}\n`;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-home.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
+ * Ottiene la password LUKS dall'utente
11
+ */
12
+ export declare function luksGetPassword(this: Ovary): Promise<void>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-home.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 Utils from '../utils.js';
9
+ /**
10
+ * Ottiene la password LUKS dall'utente
11
+ */
12
+ export async function luksGetPassword() {
13
+ const inquirer = (await import('inquirer')).default;
14
+ // Chiedi se usare password di default
15
+ const useDefault = await inquirer.prompt([{
16
+ type: 'confirm',
17
+ name: 'useDefault',
18
+ message: `Use default password "${this.luksPassword}" for LUKS encryption?`,
19
+ default: false
20
+ }]);
21
+ if (useDefault.useDefault) {
22
+ Utils.warning(`Using default password: ${this.luksPassword}`);
23
+ return;
24
+ }
25
+ // Chiedi password personalizzata con conferma
26
+ let password = '';
27
+ let confirmed = false;
28
+ while (!confirmed) {
29
+ const answers = await inquirer.prompt([
30
+ {
31
+ type: 'password',
32
+ name: 'password',
33
+ message: 'Enter LUKS encryption password:',
34
+ validate: (input) => {
35
+ if (input.length < 8) {
36
+ return 'Password must be at least 8 characters';
37
+ }
38
+ return true;
39
+ }
40
+ },
41
+ {
42
+ type: 'password',
43
+ name: 'confirm',
44
+ message: 'Confirm password:'
45
+ }
46
+ ]);
47
+ if (answers.password === answers.confirm) {
48
+ password = answers.password;
49
+ confirmed = true;
50
+ Utils.success('Password confirmed!');
51
+ }
52
+ else {
53
+ Utils.error('Passwords do not match. Please try again.');
54
+ }
55
+ }
56
+ this.luksPassword = password;
57
+ }
@@ -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,75 @@
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
+ // Crea le directory necessarie
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
+ // console.log(`✓ Created: ${scriptPath}`)
64
+ // Scrivi il service
65
+ fs.writeFileSync(servicePath, systemdService);
66
+ // console.log(`✓ Created: ${servicePath}`)
67
+ // Crea il symlink per abilitare il service
68
+ if (fs.existsSync(symlinkPath)) {
69
+ fs.unlinkSync(symlinkPath);
70
+ }
71
+ fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
72
+ // console.log(`✓ Enabled: mount-encrypted-home.service`)
73
+ // console.log('Encrypted home support installed successfully')
74
+ // console.log('Logs will be available at: /var/log/mount-encrypted-home.log')
75
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-home.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
+ * luksHome()
11
+ *
12
+ * create a container LUKS with the entire
13
+ * filesystem.squashfs
14
+ */
15
+ export declare function luksHome(this: Ovary, clone?: boolean, homecrypt?: boolean): Promise<void>;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-home.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 { spawn } from 'node:child_process';
11
+ import Utils from '../utils.js';
12
+ import { exec } from '../../lib/utils.js';
13
+ /**
14
+ * luksHome()
15
+ *
16
+ * create a container LUKS with the entire
17
+ * filesystem.squashfs
18
+ */
19
+ export async function luksHome(clone = false, homecrypt = false) {
20
+ try {
21
+ /**
22
+ * this.luksName = 'home.img';
23
+ * this.luksFile = `/tmp/${luksName}`
24
+ * this.luksDevice = `/dev/mapper/${luksName}`
25
+ * this.luksMappedName = this.luksName
26
+ * this.luksMountpoint = `/tmp/mnt/${luksName}`
27
+ * this.luksPassword = 'evolution'
28
+ */
29
+ console.log();
30
+ console.log('====================================');
31
+ console.log(` Creating ${this.luksName}`);
32
+ console.log('====================================');
33
+ // Utils.warning('1. Calculation of space requirements...')
34
+ let sizeString = (await exec('du -sb --exclude=/home/eggs /home', { capture: true })).data.trim().split(/\s+/)[0];
35
+ let size = Number.parseInt(sizeString, 10);
36
+ // const fsOverhead = Math.max(size * 0.1, 100 * 1024 * 1024)
37
+ // const luksSize = size + fsOverhead + (size * 0.2) // +20% di sicurezza
38
+ const luksSize = Math.ceil(size * 2);
39
+ Utils.warning(`homes size: ${bytesToGB(size)}`);
40
+ Utils.warning(`partition LUKS ${this.luksFile} size: ${bytesToGB(luksSize)}`);
41
+ Utils.warning(`creating partition LUKS: ${this.luksFile}`);
42
+ await executeCommand('truncate', ['--size', `${luksSize}`, this.luksFile]);
43
+ Utils.warning(`formatting ${this.luksFile} as a LUKS volume...`);
44
+ await executeCommand('cryptsetup', ['--batch-mode', 'luksFormat', this.luksFile], `${this.luksPassword}\n`);
45
+ this.luksUuid = (await exec(`cryptsetup luksUUID ${this.luksFile}`, { capture: true, echo: false })).data.trim();
46
+ Utils.warning(`LUKS uuid: ${this.luksUuid}`);
47
+ Utils.warning(`opening the LUKS volume. It will be mapped to ${this.luksDevice}`);
48
+ await executeCommand('cryptsetup', ['luksOpen', this.luksFile, this.luksMappedName], `${this.luksPassword}\n`);
49
+ Utils.warning(`formatting c ext4 `);
50
+ await exec(`mkfs.ext4 -L live-home ${this.luksDevice}`, this.echo);
51
+ Utils.warning(`mounting ${this.luksDevice} on ${this.luksMountpoint}`);
52
+ if (fs.existsSync(this.luksMountpoint)) {
53
+ if (!Utils.isMountpoint(this.luksMountpoint)) {
54
+ await exec(`rm -rf ${this.luksMountpoint}`, this.echo);
55
+ }
56
+ else {
57
+ throw new Error(`${this.luksMountpoint} is already mounted, process will abort!`);
58
+ }
59
+ }
60
+ await exec(`mkdir -p ${this.luksMountpoint}`, this.echo);
61
+ await exec(`mount /dev/mapper/${this.luksName} ${this.luksMountpoint}`, this.echo);
62
+ Utils.warning(`copying /home on ${this.luksMountpoint}`);
63
+ await exec(`rsync -ah --exclude='eggs' /home/ ${this.luksMountpoint}`, this.echo);
64
+ Utils.warning(`saving user accounts info...`);
65
+ // Crea directory per backup system files
66
+ await exec(`mkdir -p ${this.luksMountpoint}/.system-backup`, this.echo);
67
+ // Filtra solo utenti con UID >= 1000
68
+ await exec(`awk -F: '$3 >= 1000 {print}' /etc/passwd > ${this.luksMountpoint}/.system-backup/passwd`, this.echo);
69
+ await exec(`awk -F: '$3 >= 1000 {print}' /etc/shadow > ${this.luksMountpoint}/.system-backup/shadow`, this.echo);
70
+ // Per i gruppi: salva TUTTI (non filtrare per GID)
71
+ // Gli utenti possono appartenere a gruppi di sistema (sudo, audio, video, etc.)
72
+ await exec(`cp /etc/group ${this.luksMountpoint}/.system-backup/group`, this.echo);
73
+ await exec(`cp /etc/gshadow ${this.luksMountpoint}/.system-backup/gshadow`, this.echo);
74
+ Utils.warning(`unmount ${this.luksDevice}`);
75
+ await exec(`umount ${this.luksMountpoint}`, this.echo);
76
+ Utils.warning(`closing LUKS volume ${this.luksMappedName}.`);
77
+ await executeCommand('cryptsetup', ['close', this.luksMappedName]);
78
+ Utils.warning(`moving ${this.luksName} to (ISO)/live/.`);
79
+ await exec(`mv ${this.luksFile} ${this.settings.iso_work}/live`, this.echo);
80
+ Utils.warning('encryption process successfully completed!');
81
+ /**
82
+ * YOU MUST! unlink the key on production
83
+ */
84
+ // fs.unlinkSync(`${this.settings.iso_work}/live/home.key`)
85
+ }
86
+ catch (error) {
87
+ if (error instanceof Error) {
88
+ Utils.error(`ERROR: ${error.message}`);
89
+ }
90
+ else {
91
+ Utils.error(`An unknown error has occurred.`);
92
+ }
93
+ Utils.warning('Cleaning performed following the error...');
94
+ if (fs.existsSync(this.luksMountpoint)) {
95
+ await exec(`umount -lf ${this.luksMountpoint}`).catch(() => { });
96
+ }
97
+ if (fs.existsSync(this.luksDevice)) {
98
+ await executeCommand('cryptsetup', ['luksClose', this.luksName]).catch(() => { });
99
+ }
100
+ await Utils.pressKeyToExit();
101
+ process.exit(1);
102
+ }
103
+ }
104
+ /**
105
+ * Funzione helper per eseguire comandi esterni in modo asincrono,
106
+ * gestendo lo standard input per passare le password.
107
+ * Restituisce una Promise che si risolve al successo o si rigetta in caso di errore.
108
+ */
109
+ function executeCommand(command, args, stdinData) {
110
+ return new Promise((resolve, reject) => {
111
+ // Se passiamo dati a stdin, dobbiamo usare 'pipe'. Altrimenti, 'inherit'.
112
+ const stdioConfig = stdinData ? ['pipe', 'inherit', 'inherit'] : 'inherit';
113
+ const process = spawn(command, args, { stdio: stdioConfig });
114
+ // Se fornito, scriviamo i dati (es. la password) nello stdin del processo.
115
+ if (stdinData && process.stdin) {
116
+ process.stdin.write(stdinData);
117
+ process.stdin.end();
118
+ }
119
+ process.on('error', (err) => {
120
+ reject(new Error(`Error starting command "${command}": ${err.message}`));
121
+ });
122
+ process.on('close', (code) => {
123
+ if (code === 0) {
124
+ resolve(); // Success
125
+ }
126
+ else {
127
+ reject(new Error(`Command "${command} ${args.join(' ')}" ended with error code ${code}`));
128
+ }
129
+ });
130
+ });
131
+ }
132
+ /**
133
+ * Converte bytes in gigabytes per la visualizzazione.
134
+ */
135
+ function bytesToGB(bytes) {
136
+ if (bytes === 0)
137
+ return '0.00 GB';
138
+ const gigabytes = bytes / (1024 * 1024 * 1024);
139
+ return gigabytes.toFixed(2) + ' GB';
140
+ }