penguins-eggs 25.11.29 → 25.12.15

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 (121) hide show
  1. package/.oclif.manifest.json +1 -1
  2. package/README.md +118 -127
  3. package/README.pdf +10950 -11893
  4. package/addons/eggs/theme/livecd/simple.grub.main.cfg +3 -3
  5. package/conf/derivatives.yaml +2 -1
  6. package/conf/distros/buster/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  7. package/conf/distros/focal/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  8. package/conf/distros/noble/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  9. package/conf/distros/noble/calamares/libexec/calamares-l10n-helper.sh +2 -1
  10. package/conf/distros/noble/calamares/settings.yml +1 -0
  11. package/conf/distros/trixie/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
  12. package/conf/exclude.list.d/var.list +11 -6
  13. package/dist/appimage/dependency-manager.js +1 -1
  14. package/dist/classes/cli-autologin.d.ts +37 -4
  15. package/dist/classes/cli-autologin.js +153 -115
  16. package/dist/classes/compressors.d.ts +7 -10
  17. package/dist/classes/compressors.js +44 -31
  18. package/dist/classes/daddy.js +4 -1
  19. package/dist/classes/distro.js +2 -2
  20. package/dist/classes/diversions.js +2 -3
  21. package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +3 -5
  22. package/dist/classes/incubation/fisherman-helper/initcpio.js +28 -20
  23. package/dist/classes/incubation/fisherman-helper/settings.js +1 -1
  24. package/dist/classes/incubation/fisherman.js +1 -1
  25. package/dist/classes/incubation/incubator.d/manjaro.js +1 -0
  26. package/dist/classes/incubation/incubator.js +1 -1
  27. package/dist/classes/ovary.d/create-xdg-autostart.js +1 -1
  28. package/dist/classes/ovary.d/edit-live-fs.d.ts +2 -13
  29. package/dist/classes/ovary.d/edit-live-fs.js +33 -146
  30. package/dist/classes/ovary.d/fertilization.js +1 -1
  31. package/dist/classes/ovary.d/luks-home.js +33 -19
  32. package/dist/classes/ovary.d/luks-root.d.ts +1 -2
  33. package/dist/classes/ovary.d/luks-root.js +46 -27
  34. package/dist/classes/ovary.d/luks-shrink.d.ts +14 -0
  35. package/dist/classes/ovary.d/luks-shrink.js +86 -0
  36. package/dist/classes/ovary.d/make-dot-disk.js +1 -1
  37. package/dist/classes/ovary.d/produce.js +64 -22
  38. package/dist/classes/ovary.d/user-create-live.d.ts +4 -10
  39. package/dist/classes/ovary.d/user-create-live.js +82 -84
  40. package/dist/classes/ovary.d/users-remove.d.ts +5 -6
  41. package/dist/classes/ovary.d/users-remove.js +61 -31
  42. package/dist/classes/ovary.d.ts +5 -3
  43. package/dist/classes/ovary.js +5 -3
  44. package/dist/classes/pacman.d/alpine.js +2 -2
  45. package/dist/classes/pacman.d/archlinux.js +2 -2
  46. package/dist/classes/pacman.d/debian.js +2 -3
  47. package/dist/classes/pacman.d/fedora.js +2 -3
  48. package/dist/classes/pacman.d/openmamba.js +2 -3
  49. package/dist/classes/pacman.d/opensuse.js +2 -3
  50. package/dist/classes/pacman.d.ts +0 -5
  51. package/dist/classes/pacman.js +3 -16
  52. package/dist/classes/pve-live.js +1 -1
  53. package/dist/classes/settings.js +1 -1
  54. package/dist/classes/sys-users.d.ts +76 -0
  55. package/dist/classes/sys-users.js +206 -0
  56. package/dist/classes/utils.d/kernel.js +3 -3
  57. package/dist/classes/utils.d.ts +15 -6
  58. package/dist/classes/utils.js +80 -47
  59. package/dist/classes/xdg.js +1 -1
  60. package/dist/classes/yolk.js +3 -5
  61. package/dist/commands/export/appimage.js +3 -3
  62. package/dist/commands/export/pkg.js +3 -3
  63. package/dist/commands/export/tarballs.js +3 -3
  64. package/dist/commands/krill.js +1 -1
  65. package/dist/commands/produce.js +14 -5
  66. package/dist/commands/setup/install.js +1 -1
  67. package/dist/commands/setup/purge.js +1 -1
  68. package/dist/commands/tools/yolk.js +1 -1
  69. package/dist/commands/update.js +1 -2
  70. package/dist/interfaces/calamares/i-calamares-branding.d.ts +56 -38
  71. package/dist/interfaces/calamares/i-calamares-branding.js +10 -0
  72. package/dist/interfaces/i-exec.d.ts +1 -0
  73. package/dist/krill/classes/prepare.d/location.js +1 -1
  74. package/dist/krill/classes/prepare.d/partitions.js +1 -1
  75. package/dist/krill/classes/prepare.d/users.js +2 -2
  76. package/dist/krill/classes/prepare.js +5 -5
  77. package/dist/krill/classes/sequence.d/add_user.d.ts +3 -15
  78. package/dist/krill/classes/sequence.d/add_user.js +87 -57
  79. package/dist/krill/classes/sequence.d/change_password.d.ts +5 -7
  80. package/dist/krill/classes/sequence.d/change_password.js +25 -10
  81. package/dist/krill/classes/sequence.d/del_live_user.d.ts +5 -7
  82. package/dist/krill/classes/sequence.d/del_live_user.js +39 -25
  83. package/dist/krill/classes/sequence.d/fstab.js +2 -2
  84. package/dist/krill/classes/sequence.d/grubcfg.d.ts +3 -7
  85. package/dist/krill/classes/sequence.d/grubcfg.js +33 -13
  86. package/dist/krill/classes/sequence.d/mkfs.js +2 -3
  87. package/dist/krill/classes/sequence.d/unpackfs.d.ts +2 -4
  88. package/dist/krill/classes/sequence.d/unpackfs.js +8 -5
  89. package/dist/krill/classes/sequence.d.ts +1 -5
  90. package/dist/krill/classes/sequence.js +28 -32
  91. package/dist/krill/components/finished.js +2 -2
  92. package/dist/krill/components/install.js +2 -2
  93. package/dist/krill/components/keyboard.js +2 -2
  94. package/dist/krill/components/location.js +2 -2
  95. package/dist/krill/components/network.js +2 -2
  96. package/dist/krill/components/partitions.js +2 -2
  97. package/dist/krill/components/summary.js +2 -2
  98. package/dist/krill/components/title.js +2 -2
  99. package/dist/krill/components/users.js +2 -2
  100. package/dist/krill/components/welcome.js +2 -2
  101. package/dist/krill/lib/select_installation_device.js +1 -1
  102. package/dist/krill/lib/select_replaced_partition.js +1 -1
  103. package/dist/lib/utils.d.ts +52 -19
  104. package/dist/lib/utils.js +271 -20
  105. package/manpages/doc/man/eggs.1.gz +0 -0
  106. package/manpages/doc/man/eggs.html +8 -8
  107. package/package.json +9 -9
  108. package/perrisbrewery/template/dependencies.yaml +1 -0
  109. package/scripts/boot-encrypted-root.sh +220 -0
  110. package/scripts/mount-encrypted-home.sh +324 -0
  111. package/scripts/restore_homecrypt_krill.sh +93 -0
  112. package/dracut/create-symlink +0 -71
  113. package/dracut/dracut-log.txt +0 -3
  114. package/dracut/export +0 -4
  115. package/dracut/export-dracut-analysis +0 -51
  116. package/dracut/export-dracut-log +0 -2
  117. package/dracut/mkisofs +0 -10
  118. package/dracut/renew-initramfs +0 -17
  119. package/dracut/sbin2bin +0 -10
  120. package/dracut/update-dracut-conf-d +0 -2
  121. package/dracut/update-dracut-modules +0 -62
@@ -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>;
@@ -12,8 +12,7 @@ import { exec } from '../../lib/utils.js';
12
12
  const noop = () => { };
13
13
  /**
14
14
  * luksRoot()
15
- *
16
- * create a container LUKS with the entire
15
+ * * create a container LUKS with the entire
17
16
  * filesystem.squashfs
18
17
  */
19
18
  export async function luksRoot() {
@@ -29,7 +28,7 @@ export async function luksRoot() {
29
28
  try {
30
29
  /**
31
30
  * this.luksMappedName = 'root.img';
32
- * this.luksFile = `/tmp/${luksMappedName}`
31
+ * this.luksFile = `/var/tmp/${luksMappedName}`
33
32
  * this.luksDevice = `/dev/mapper/${luksMappedName}`
34
33
  * this.luksMountpoint = `/tmp/mnt/${luksMappedName}`
35
34
  * this.luksPassword = '0'
@@ -45,11 +44,29 @@ export async function luksRoot() {
45
44
  throw new Error(`filesystem.squashfs not found at: ${live_fs}`);
46
45
  }
47
46
  const stats = fs.statSync(live_fs);
48
- let size = stats.size; // Dimensione REALE del file in Byte
49
- // Add overhead * 1.25 per più sicurezza con file grandi
50
- const luksSize = Math.ceil(size * 1.25);
51
- warning(`filesystem.squashfs size: ${bytesToGB(size)}`);
52
- warning(`partition LUKS ${this.luksFile} size: ${bytesToGB(luksSize)}`);
47
+ const size = stats.size; // Dimensione REALE del file in Byte
48
+ // -------------------------------------------------------------
49
+ // CALCOLO DIMENSIONE OTTIMIZZATA (No shrink, safe allocation)
50
+ // -------------------------------------------------------------
51
+ // 1. Overhead Ext4: Inode, bitmap, superblocchi. ~3-4% è standard senza journal.
52
+ const fsOverhead = Math.ceil(size * 0.04);
53
+ // 2. Header LUKS: Solitamente 16MB per LUKS2, usiamo 32MB per sicurezza.
54
+ const luksHeader = 32 * 1024 * 1024;
55
+ // 3. Margine di sicurezza (Buffer): 120MB fissi.
56
+ // Questo spazio evita errori di "Disk full" durante la copia dei metadati.
57
+ // Viene compensato dall'uso di "-m 0" nella formattazione.
58
+ const safetyBuffer = 120 * 1024 * 1024;
59
+ // 4. Somma totale
60
+ let calculatedSize = size + fsOverhead + luksHeader + safetyBuffer;
61
+ // 5. Allineamento a 4MB (Performance storage)
62
+ const alignment = 4 * 1024 * 1024;
63
+ const luksSize = Math.ceil(calculatedSize / alignment) * alignment;
64
+ warning(`------------------------------------------`);
65
+ warning(`SAFE SIZE CALCULATION (No Shrink):`);
66
+ warning(` Payload (SquashFS): ${bytesToGB(size)}`);
67
+ warning(` Calc. Overhead: ${bytesToGB(luksSize - size)}`);
68
+ warning(` TOTAL CONTAINER: ${bytesToGB(luksSize)}`);
69
+ warning(`------------------------------------------`);
53
70
  warning(`creating partition LUKS: ${this.luksFile}`);
54
71
  await this.luksExecuteCommand('truncate', ['--size', `${luksSize}`, this.luksFile]);
55
72
  warning(`formatting ${this.luksFile} as a LUKS volume...`);
@@ -57,8 +74,13 @@ export async function luksRoot() {
57
74
  await this.luksExecuteCommand('cryptsetup', luksFormatArgs, `${this.luksPassword}\n`);
58
75
  warning(`opening the LUKS volume. It will be mapped to ${this.luksDevice}`);
59
76
  await this.luksExecuteCommand('cryptsetup', ['luksOpen', this.luksFile, this.luksMappedName], `${this.luksPassword}\n`);
60
- warning(`formatting ext4 (without journal)...`);
61
- await exec(`mkfs.ext4 -O ^has_journal -L live-root ${this.luksDevice}`, this.echo);
77
+ // -------------------------------------------------------------
78
+ // FORMATTAZIONE EXT4
79
+ // -m 0 : Imposta i blocchi riservati a 0% (recupera spazio)
80
+ // -O ^has_journal : Disabilita il journal (risparmia spazio e scritture)
81
+ // -------------------------------------------------------------
82
+ warning(`formatting ext4 (without journal, 0% reserved)...`);
83
+ await exec(`mkfs.ext4 -m 0 -O ^has_journal -L live-root ${this.luksDevice}`, this.echo);
62
84
  warning(`mounting ${this.luksDevice} on ${this.luksMountpoint}`);
63
85
  if (fs.existsSync(this.luksMountpoint)) {
64
86
  if (!Utils.isMountpoint(this.luksMountpoint)) {
@@ -74,25 +96,18 @@ export async function luksRoot() {
74
96
  await exec(`mv ${live_fs} ${this.luksMountpoint}/filesystem.squashfs`, this.echo);
75
97
  warning(`Syncing filesystem on ${this.luksMountpoint}...`);
76
98
  await exec('sync', this.echo); // Forza scrittura dati su disco
77
- warning(`Attempting unmount ${this.luksMountpoint}...`);
78
- try {
79
- await exec(`umount ${this.luksMountpoint}`, this.echo);
80
- success(`Unmounted ${this.luksMountpoint} successfully.`);
81
- }
82
- catch (umountError) {
83
- Utils.error(`Failed to unmount ${this.luksMountpoint}! Trying force unmount...`);
84
- // Tenta un unmount forzato/lazy come ultima risorsa
85
- await exec(`umount -lf ${this.luksMountpoint}`).catch((forceError) => {
86
- Utils.error(`Force unmount also failed: ${forceError}`);
87
- // Considera se lanciare un errore qui per fermare il processo
88
- });
89
- // Lancia comunque l'errore originale per segnalare il problema
90
- throw umountError;
91
- }
92
- warning(`closing LUKS volume ${this.luksFile}.`);
99
+ /**
100
+ * SHRINK DISABILITATO
101
+ * Non eseguiamo this.luksShrink() per evitare corruzione dati.
102
+ * Abbiamo calcolato la dimensione corretta all'inizio.
103
+ */
104
+ // Procedura di chiusura manuale (sostituisce quella dentro shrink)
105
+ warning(`Unmounting ${this.luksMountpoint}...`);
106
+ await exec(`umount ${this.luksMountpoint}`, this.echo);
107
+ warning(`Closing LUKS volume ${this.luksMappedName}...`);
93
108
  await this.luksExecuteCommand('cryptsetup', ['close', this.luksMappedName]);
94
109
  warning(`moving ${this.luksMappedName} on (ISO)/live.`);
95
- await exec(`mv ${this.luksFile} ${this.settings.iso_work}/live`, this.echo);
110
+ await exec(`mv ${this.luksFile} ${this.settings.iso_work}/live/root.img`, this.echo);
96
111
  }
97
112
  catch (error) {
98
113
  if (error instanceof Error) {
@@ -108,6 +123,10 @@ export async function luksRoot() {
108
123
  if (fs.existsSync(this.luksDevice)) {
109
124
  await this.luksExecuteCommand('cryptsetup', ['close', this.luksMappedName]).catch(() => { });
110
125
  }
126
+ if (fs.existsSync(this.luksFile)) {
127
+ Utils.warning(`Removing temporary container: ${this.luksFile}`);
128
+ fs.unlinkSync(this.luksFile);
129
+ }
111
130
  await Utils.pressKeyToExit();
112
131
  process.exit(1);
113
132
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-shrink.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
+ * luksShrink
11
+ * Riduce in sicurezza un volume LUKS (root o home) minimizzando lo spazio
12
+ * ma garantendo l'integrità dei dati e l'allineamento dei blocchi.
13
+ */
14
+ export declare function luksShrink(this: Ovary): Promise<void>;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * ./src/classes/ovary.d/luks-shrink.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
+ import { exec } from '../../lib/utils.js';
10
+ const noop = () => { };
11
+ /**
12
+ * luksShrink
13
+ * Riduce in sicurezza un volume LUKS (root o home) minimizzando lo spazio
14
+ * ma garantendo l'integrità dei dati e l'allineamento dei blocchi.
15
+ */
16
+ export async function luksShrink() {
17
+ const loggers = {
18
+ log: this.hidden ? noop : console.log,
19
+ warning: this.hidden ? noop : Utils.warning,
20
+ success: this.hidden ? noop : Utils.success,
21
+ info: this.hidden ? noop : Utils.info,
22
+ };
23
+ const { log, warning, success, info } = loggers;
24
+ warning(`Unmounting ${this.luksMountpoint} to perform shrinking...`);
25
+ // Usa -l (lazy) se necessario, ma meglio umount pulito
26
+ await exec(`umount ${this.luksMountpoint}`, this.echo);
27
+ // 1. Controllo integrità (CRUCIALE per homecrypt: ripara eventuali errori prima di ridimensionare)
28
+ warning(`Checking filesystem integrity...`);
29
+ await exec(`e2fsck -f -y ${this.luksDevice}`, this.echo);
30
+ // 2. Riduzione del filesystem al minimo
31
+ warning(`Shrinking filesystem to minimum size...`);
32
+ // resize2fs -M è sicuro se poi lasciamo margine nel contenitore
33
+ await exec(`resize2fs -M ${this.luksDevice}`, this.echo);
34
+ // 3. Calcolo della nuova dimensione del filesystem
35
+ warning(`Calculating new sizes...`);
36
+ const tuneOutput = (await exec(`tune2fs -l ${this.luksDevice}`, { capture: true })).data;
37
+ const blockSizeMatch = tuneOutput.match(/Block size:\s+(\d+)/);
38
+ const blockCountMatch = tuneOutput.match(/Block count:\s+(\d+)/);
39
+ if (!blockSizeMatch || !blockCountMatch) {
40
+ throw new Error("Could not determine filesystem size from tune2fs");
41
+ }
42
+ const blockSize = parseInt(blockSizeMatch[1], 10);
43
+ const blockCount = parseInt(blockCountMatch[1], 10);
44
+ const fsSizeBytes = blockSize * blockCount;
45
+ warning(`Actual Ext4 payload size: ${bytesToGB(fsSizeBytes)}`);
46
+ // 4. Calcolo dell'offset LUKS (Header size)
47
+ const statusOutput = (await exec(`cryptsetup status ${this.luksMappedName}`, { capture: true })).data;
48
+ const offsetMatch = statusOutput.match(/offset:\s+(\d+)\s+sectors/);
49
+ let luksHeaderBytes = 0;
50
+ if (offsetMatch && offsetMatch[1]) {
51
+ luksHeaderBytes = parseInt(offsetMatch[1], 10) * 512;
52
+ warning(`Detected LUKS header: ${bytesToGB(luksHeaderBytes)}`);
53
+ }
54
+ else {
55
+ luksHeaderBytes = 32 * 1024 * 1024; // Fallback 32MB
56
+ warning(`Could not detect LUKS offset, using safe fallback: 32MB`);
57
+ }
58
+ // 5. Calcolo dimensione finale SICURA
59
+ // Usiamo 200MB di margine. Su una ISO da 4GB è il 5%, un prezzo onesto per la stabilità.
60
+ // Questo spazio extra protegge sia lo squashfs (root) che i metadati sparsi (home).
61
+ const safetyMargin = 200 * 1024 * 1024;
62
+ let rawFinalSize = fsSizeBytes + luksHeaderBytes + safetyMargin;
63
+ // ALLINEAMENTO A 1MB: Fondamentale per evitare errori di I/O su device fisici o loop
64
+ const alignBlock = 1024 * 1024;
65
+ const finalFileSize = Math.ceil(rawFinalSize / alignBlock) * alignBlock;
66
+ warning(`------------------------------------------------`);
67
+ warning(`SAFE SHRINK CALCULATION:`);
68
+ warning(` FS Payload: ${bytesToGB(fsSizeBytes)}`);
69
+ warning(` LUKS Header: ${bytesToGB(luksHeaderBytes)}`);
70
+ warning(` SafetyMargin: ${bytesToGB(safetyMargin)}`);
71
+ warning(` Alignment: 1 MB`);
72
+ warning(` FINAL SIZE: ${bytesToGB(finalFileSize)}`);
73
+ warning(`------------------------------------------------`);
74
+ // 6. Chiusura volume
75
+ warning(`Closing LUKS volume ${this.luksMappedName}...`);
76
+ await this.luksExecuteCommand('cryptsetup', ['close', this.luksMappedName]);
77
+ // 7. Truncate finale
78
+ warning(`Truncating ${this.luksFile} to release unused space...`);
79
+ await exec(`truncate -s ${finalFileSize} ${this.luksFile}`, this.echo);
80
+ }
81
+ function bytesToGB(bytes) {
82
+ if (bytes === 0)
83
+ return '0.00 GB';
84
+ const gigabytes = bytes / (1024 * 1024 * 1024);
85
+ return gigabytes.toFixed(2) + ' GB';
86
+ }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  // packages
9
9
  import fs from 'node:fs';
10
- import shx from 'shelljs';
10
+ import { shx } from '../../lib/utils.js';
11
11
  import path from 'path';
12
12
  // interfaces
13
13
  // libraries
@@ -9,7 +9,7 @@ import chalk from 'chalk';
9
9
  import mustache from 'mustache';
10
10
  // packages
11
11
  import fs from 'node:fs';
12
- import shx from 'shelljs';
12
+ import { shx } from '../../lib/utils.js';
13
13
  import path from 'path';
14
14
  // libraries
15
15
  import { exec } from '../../lib/utils.js';
@@ -58,7 +58,7 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
58
58
  else if (this.fullcrypt) {
59
59
  this.luksMappedName = 'root.img';
60
60
  }
61
- this.luksFile = `/tmp/${this.luksMappedName}`;
61
+ this.luksFile = `/var/tmp/${this.luksMappedName}`;
62
62
  this.luksMappedName = this.luksMappedName;
63
63
  this.luksMountpoint = `/tmp/mnt/${this.luksMappedName}`;
64
64
  this.luksDevice = `/dev/mapper/${this.luksMappedName}`;
@@ -131,8 +131,6 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
131
131
  * homecrypt/fullcrypt/clone/standard
132
132
  */
133
133
  if (this.homecrypt) {
134
- this.settings.config.user_opt = 'live'; // patch for humans
135
- this.settings.config.user_opt_passwd = 'evolution';
136
134
  Utils.warning("eggs will SAVE users and users' data ENCRYPTED on the live (ISO)/live/home.img");
137
135
  }
138
136
  else if (this.fullcrypt) {
@@ -195,10 +193,10 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
195
193
  /**
196
194
  * installer
197
195
  */
198
- this.incubator = new Incubator(this.settings.remix, this.settings.distro, this.settings.config.user_opt, this.theme, this.clone || this.fullcrypt, verbose);
196
+ this.incubator = new Incubator(this.settings.remix, this.settings.distro, this.settings.config.user_opt, this.theme, this.clone || this.fullcrypt || this.homecrypt, verbose);
199
197
  await this.incubator.config(release);
200
- // Qua inseriamo uno sleep di un minuto
201
- await Utils.sleep(5000); // 5 secondo
198
+ // 5 secondi di sleep
199
+ await Utils.sleep(5000);
202
200
  await this.bindLiveFs();
203
201
  await this.bindVfs();
204
202
  /**
@@ -228,36 +226,80 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
228
226
  await this.initrdDracut();
229
227
  }
230
228
  }
231
- // We dont' need more
229
+ // We don't need more
232
230
  await this.ubindVfs();
233
- const cleanSystem = !(this.clone || this.fullcrypt);
234
- if (cleanSystem) {
235
- /**
236
- * SOLO per homecrypt e standard
237
- */
231
+ // mistero della Fede
232
+ await this.editLiveFs();
233
+ /**
234
+ * Autologin solse per non clone
235
+ */
236
+ if (!(this.clone || this.homecrypt || this.fullcrypt)) {
238
237
  await this.usersRemove();
239
238
  await this.userCreateLive();
240
239
  if (Pacman.isInstalledGui()) {
240
+ // add GUI autologin
241
241
  await this.createXdgAutostart(this.settings.config.theme, myAddons, myLinks, noicons);
242
- /**
243
- * GUI installed but NOT Desktop Manager: just create motd and issue
244
- */
245
- // if (displaymanager().length > 0) {
246
- // this.cliAutologin.addIssue(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged)
247
- // this.cliAutologin.addMotd(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged)
248
- // }
249
242
  }
250
243
  else {
244
+ // add cli-autologin
251
245
  this.cliAutologin.add(this.settings.distro.distroId, this.settings.distro.codenameId, this.settings.config.user_opt, this.settings.config.user_opt_passwd, this.settings.config.root_passwd, this.settings.work_dir.merged);
252
246
  }
253
247
  }
254
- await this.editLiveFs(clone);
248
+ /**
249
+ * configurazione homecrytp
250
+ */
255
251
  if (this.homecrypt) {
252
+ // Occorre forzare il login CLI
253
+ if (Utils.isSystemd()) {
254
+ const systemdDir = `${this.settings.work_dir.merged}/etc/systemd/system`;
255
+ // remove eventuali autologin
256
+ if (fs.existsSync(`${systemdDir}/getty@tty1.service.d`)) {
257
+ await exec(`rm -rf ${systemdDir}/getty@tty1.service.d/*`);
258
+ }
259
+ else {
260
+ await exec(`mkdir -p ${systemdDir}/getty@tty1.service.d`);
261
+ }
262
+ let content = ``;
263
+ content += `[Service]\n`;
264
+ content += `ExecStart=\n`;
265
+ content += `ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear %I \$TERM\n`;
266
+ fs.writeFileSync(`${systemdDir}/getty@tty1.service.d/no-autologin.conf`, content);
267
+ }
268
+ else if (Utils.isSysvinit()) {
269
+ const inittabPath = `${this.settings.work_dir.merged}/etc/inittab`;
270
+ if (fs.existsSync(inittabPath)) {
271
+ // Non funziona per Devuan
272
+ let content = fs.readFileSync(inittabPath, 'utf-8');
273
+ // La riga standard per Devuan/Debian SysVinit.
274
+ // 1: ID
275
+ // 2345: Runlevels in cui attivarlo (Nota che il tuo boot è in runlevel 2)
276
+ // respawn: Riavvia getty se muore
277
+ // /sbin/getty 38400 tty1: Il comando
278
+ const tty1Line = '1:2345:respawn:/sbin/agetty --noclear tty1 linux';
279
+ // Rimuoviamo vecchie definizioni di tty1 (anche se commentate o diverse)
280
+ // Cerca righe che iniziano con "1:"
281
+ const regex = /^1:.*$/gm;
282
+ if (regex.test(content)) {
283
+ // Sostituisce la riga esistente
284
+ content = content.replace(regex, tty1Line);
285
+ console.log('Fixed tty1 in inittab (replaced)');
286
+ }
287
+ else {
288
+ // Se non c'è, la aggiunge in fondo (dopo i commenti iniziali)
289
+ content += `\n${tty1Line}\n`;
290
+ console.log('Fixed tty1 in inittab (appended)');
291
+ }
292
+ // FIX CRITICO PER --cryptedhome / LIVE:
293
+ // A volte le live commentano tutte le tty per usare i propri hook.
294
+ // Assicurati che non ci siano altre righe strane che confliggono.
295
+ fs.writeFileSync(inittabPath, content);
296
+ }
297
+ }
256
298
  /**
257
299
  * homecrypt: installa il supporto
258
300
  */
259
301
  const squashfsRoot = this.settings.work_dir.merged;
260
- const homeImgPath = this.distroLliveMediumPath + 'live/home.img';
302
+ const homeImgPath = this.distroLiveMediumPath + 'live/home.img';
261
303
  this.installHomecryptSupport(squashfsRoot, homeImgPath);
262
304
  }
263
305
  mksquashfsCmd = await this.makeSquashfs(scriptOnly, includeRootHome);
@@ -1,14 +1,8 @@
1
1
  /**
2
- * ./src/classes/ovary.d/create-user-live.ts
2
+ * src/classes/ovary.d/user-create-live.ts
3
3
  * penguins-eggs v.25.7.x / ecmascript 2020
4
- * author: Piero Proietti
5
- * email: piero.proietti@gmail.com
6
- * license: MIT
4
+ * * REFACTORED: Uses "The SysUser Master" class.
5
+ * Creates the live user directly in the merged filesystem safely.
7
6
  */
8
7
  import Ovary from '../ovary.js';
9
- /**
10
- * list degli utenti: grep -E 1[0-9]{3} /etc/passwd | sed s/:/\ / | awk '{print $1}'
11
- * create la home per user_opt
12
- * @param verbose
13
- */
14
- export declare function userCreateLive(this: Ovary): Promise<void>;
8
+ export default function userCreateLive(this: Ovary): Promise<void>;