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
@@ -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
+ }
@@ -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);
@@ -29,6 +29,7 @@ import { kernelCopy } from './ovary.d/kernel-copy.js';
29
29
  import { liveCreateStructure } from './ovary.d/live-create-structure.js';
30
30
  import { finished } from './ovary.d/finished.js';
31
31
  import { luksExecuteCommand, buildLuksFormatArgs } from './ovary.d/luks-helpers.js';
32
+ import { luksShrink } from './ovary.d/luks-shrink.js';
32
33
  import { luksGetPassword } from './ovary.d/luks-get-password.js';
33
34
  import { interactiveCryptoConfig, CryptoConfig } from './ovary.d/luks-interactive-crypto-config.js';
34
35
  import { luksHome } from './ovary.d/luks-home.js';
@@ -49,7 +50,7 @@ export default class Ovary {
49
50
  familyId: string;
50
51
  distroId: string;
51
52
  distroLike: string;
52
- distroLliveMediumPath: string;
53
+ distroLiveMediumPath: string;
53
54
  genisoimage: boolean;
54
55
  incubator: Incubator;
55
56
  settings: Settings;
@@ -84,6 +85,7 @@ export default class Ovary {
84
85
  luksExecuteCommand: typeof luksExecuteCommand;
85
86
  buildLuksFormatArgs: typeof buildLuksFormatArgs;
86
87
  luksGetPassword: typeof luksGetPassword;
88
+ luksShrink: typeof luksShrink;
87
89
  interactiveCryptoConfig: typeof interactiveCryptoConfig;
88
90
  luksHome: typeof luksHome;
89
91
  installHomecryptSupport: typeof installHomecryptSupport;
@@ -31,6 +31,7 @@ import { liveCreateStructure } from './ovary.d/live-create-structure.js';
31
31
  import { finished } from './ovary.d/finished.js';
32
32
  // crypt
33
33
  import { luksExecuteCommand, buildLuksFormatArgs } from './ovary.d/luks-helpers.js';
34
+ import { luksShrink } from './ovary.d/luks-shrink.js';
34
35
  import { luksGetPassword } from './ovary.d/luks-get-password.js';
35
36
  import { interactiveCryptoConfig } from './ovary.d/luks-interactive-crypto-config.js';
36
37
  // homecrypt
@@ -55,7 +56,7 @@ export default class Ovary {
55
56
  familyId = '';
56
57
  distroId = '';
57
58
  distroLike = '';
58
- distroLliveMediumPath = '';
59
+ distroLiveMediumPath = '';
59
60
  genisoimage = false;
60
61
  incubator = {};
61
62
  settings = {};
@@ -93,6 +94,7 @@ export default class Ovary {
93
94
  luksExecuteCommand = luksExecuteCommand;
94
95
  buildLuksFormatArgs = buildLuksFormatArgs;
95
96
  luksGetPassword = luksGetPassword;
97
+ luksShrink = luksShrink;
96
98
  interactiveCryptoConfig = interactiveCryptoConfig;
97
99
  // luksHome
98
100
  luksHome = luksHome;
@@ -238,7 +238,7 @@ export default class Utils {
238
238
  * @param device
239
239
  */
240
240
  static uuid(device) {
241
- const uuid = shx.exec(`blkid -s UUID -o value ${device}`).stdout.trim();
241
+ const uuid = shx.exec(`blkid -p -s UUID -o value ${device}`, { silent: true }).stdout.trim();
242
242
  return uuid;
243
243
  }
244
244
  /**
@@ -66,7 +66,7 @@ export default class Yolk {
66
66
  Utils.warning(cmd);
67
67
  await exec(cmd, { capture: true, echo: false });
68
68
  // Create Release date: Sat, 14 Aug 2021 07:42:00 UTC
69
- const now = shx.exec('date -R -u').stdout.trim();
69
+ const now = shx.exec('date -R -u', { silent: true }).stdout.trim();
70
70
  const content = `Archive: stable\nComponent: yolk\nOrigin: penguins-eggs\nArchitecture: ${Utils.uefiArch()} \nDate: ${now}\n`;
71
71
  Utils.warning('Writing Release');
72
72
  fs.writeFileSync('Release', content);
@@ -144,7 +144,7 @@ export default class Produce extends Command {
144
144
  const yolkRenew = flags.yolk;
145
145
  const { nointeractive } = flags;
146
146
  const { noicon } = flags;
147
- // if clone or homecrypt includeRootHome = true
147
+ // if clone, homecrypt, fullcrypt
148
148
  const includeRootHome = flags.includeRootHome || clone || homecrypt;
149
149
  let { kernel } = flags;
150
150
  if (kernel === undefined) {
@@ -209,19 +209,23 @@ export default class Produce extends Command {
209
209
  let message = "this is a GUI system, calamares is available, but NOT installed\n";
210
210
  Utils.warning(message);
211
211
  }
212
- if (fullcrypt && Utils.isAppImage()) {
213
- Utils.warning("eggs --fullcrypt cannot be used on AppImage");
214
- process.exit(0);
212
+ /**
213
+ * se è appImage e fullcrypt esce
214
+ */
215
+ if (Utils.isAppImage() && fullcrypt) {
216
+ Utils.warning("eggs produce --fullcrypt cannot be used on AppImage");
217
+ console.log(`\nyou can try: "sudo eggs produce --homecrypt"`);
218
+ process.exit(9);
215
219
  }
216
- else {
220
+ if (!Utils.isAppImage() && fullcrypt) {
217
221
  const distro = new Distro();
218
- //
219
222
  if (distro.familyId === 'debian' && (distro.codenameId === 'trixie' || distro.codenameId === 'excalibur')) {
220
223
  Utils.info("Use eggs --fullcrypt with extreme caution, and ALWAYS first try it out in a test environment.");
221
224
  Utils.sleep(3000);
222
225
  }
223
226
  else {
224
- Utils.warning("eggs --fullcrypt can be used only with Debian trixie or Devuan excalibur");
227
+ Utils.warning(`eggs produce --fullcrypt cannot be used on ${distro.distroId}/${distro.codenameId}`);
228
+ console.log(`\nyou can try: "sudo eggs produce --homecrypt"`);
225
229
  process.exit(9);
226
230
  }
227
231
  }
@@ -1,46 +1,64 @@
1
1
  /**
2
2
  * ./src/interfaces/i-calamares-branding.ts
3
- * penguins-eggs v.25.7.x / ecmascript 2020
3
+ * penguins-eggs v.25.x / ecmascript 2020
4
4
  * author: Piero Proietti
5
5
  * email: piero.proietti@gmail.com
6
6
  * license: MIT
7
+ *
8
+ * Questa interfaccia è allineata con la struttura reale di branding.desc
9
+ * (basata sull'output 'cat /etc/calamares/branding/eggs/branding.desc').
10
+ */
11
+ /**
12
+ * 💡 Interfaccia per la sezione 'strings'
13
+ * Contiene le informazioni testuali del prodotto.
14
+ */
15
+ export interface IBrandingStrings {
16
+ bootloaderEntryName: string;
17
+ knownIssuesUrl: string;
18
+ productName: string;
19
+ productUrl: string;
20
+ releaseNotesUrl: string;
21
+ shortProductName: string;
22
+ shortVersion: string;
23
+ shortVersionedName: string;
24
+ supportUrl: string;
25
+ version: string;
26
+ versionedName: string;
27
+ }
28
+ /**
29
+ * 💡 Interfaccia per la sezione 'images'
30
+ * Contiene i nomi dei file delle risorse grafiche.
31
+ */
32
+ export interface IBrandingImages {
33
+ productIcon: string;
34
+ productLogo: string;
35
+ productWelcome: string;
36
+ }
37
+ /**
38
+ * 💡 Interfaccia per la sezione 'style'
39
+ * Contiene le definizioni dei colori per l'interfaccia.
40
+ * Nota: Sono incluse sia le varianti con maiuscola che minuscola trovate nel tuo file.
41
+ */
42
+ export interface IBrandingStyle {
43
+ SidebarBackground: string;
44
+ SidebarBackgroundCurrent: string;
45
+ SidebarText: string;
46
+ SidebarTextCurrent: string;
47
+ sidebarBackground: string;
48
+ sidebarBackgroundCurrent: string;
49
+ sidebarText: string;
50
+ sidebarTextCurrent: string;
51
+ }
52
+ /**
53
+ * 💡 Interfaccia Principale: IBranding
54
+ * Mappa la struttura radice del file YAML branding.desc.
7
55
  */
8
56
  export interface IBranding {
9
- /** Il nome completo della distribuzione (es. "My Awesome OS"). */
10
- string_product_name: string;
11
- /** La versione della distribuzione (es. "2025.10"). */
12
- string_product_version: string;
13
- /** Un URL per il sito web del progetto. */
14
- string_product_url?: string;
15
- /** Un titolo per le note di rilascio. */
16
- string_release_title?: string;
17
- /** Il colore principale usato per gli accenti (pulsanti, selezioni). */
18
- color_accent?: string;
19
- /** Colore del testo principale. */
20
- color_text?: string;
21
- /** Colore di sfondo principale della finestra. */
22
- color_background?: string;
23
- /** Colore di sfondo della barra laterale. */
24
- color_sidebar_background?: string;
25
- /** Colore del testo nella barra laterale. */
26
- color_sidebar_text?: string;
27
- /** Logo principale mostrato nell'installer. */
28
- logo?: string;
29
- /** Icona del prodotto. */
30
- product_icon?: string;
31
- /** Icona della finestra dell'applicazione. */
32
- window_icon?: string;
33
- /** Larghezza iniziale della finestra in pixel. */
34
- window_width?: number;
35
- /** Altezza iniziale della finestra in pixel. */
36
- window_height?: number;
37
- /** Se `true`, posiziona la barra laterale a sinistra (default), altrimenti a destra. */
38
- sidebar_on_left?: boolean;
39
- /**
40
- * L'API da usare per lo slideshow. 'qml' per le slideshow tradizionali,
41
- * 'contextual' per quelle basate sul modulo in esecuzione.
42
- */
43
- slideshow_api?: 'qml' | 'contextual';
44
- /** Percorso al file QML principale dello slideshow (se slideshow_api è 'qml'). */
45
- slideshow_qml_path?: string;
57
+ componentName: string;
58
+ slideshow: string;
59
+ slideshowAPI: number;
60
+ welcomeStyleCalamares: boolean;
61
+ images: IBrandingImages;
62
+ strings: IBrandingStrings;
63
+ style: IBrandingStyle;
46
64
  }
@@ -1 +1,11 @@
1
+ /**
2
+ * ./src/interfaces/i-calamares-branding.ts
3
+ * penguins-eggs v.25.x / ecmascript 2020
4
+ * author: Piero Proietti
5
+ * email: piero.proietti@gmail.com
6
+ * license: MIT
7
+ *
8
+ * Questa interfaccia è allineata con la struttura reale di branding.desc
9
+ * (basata sull'output 'cat /etc/calamares/branding/eggs/branding.desc').
10
+ */
1
11
  export {};
@@ -36,7 +36,7 @@ export async function users() {
36
36
  }
37
37
  let hostname = this.krillConfig.hostname;
38
38
  if (hostname === '' || hostname === undefined) {
39
- hostname = shx.exec('cat /etc/hostname').stdout.trim();
39
+ hostname = shx.exec('cat /etc/hostname', { silent: true }).stdout.trim();
40
40
  }
41
41
  let autologin = true;
42
42
  let sameUserPassword = true;
@@ -231,11 +231,15 @@ export default class Krill {
231
231
  oPartitions.installationMode = InstallationMode.Luks;
232
232
  // Set default installation device if empty
233
233
  if (oPartitions.installationDevice === '') {
234
- const drives = shx.exec('lsblk |grep disk|cut -f 1 "-d "', { silent: true }).stdout.trim().split('\n');
234
+ const cmd = `lsblk -d -n -p -o NAME,RM,RO,TYPE | awk '$2 == 0 && $3 == 0 && $4 == "disk" {print $1}'`;
235
+ const result = shx.exec(cmd, { silent: true }).stdout.trim();
236
+ const drives = result ? result.split('\n') : [];
235
237
  if (drives.length > 0) {
236
- oPartitions.installationDevice = `/dev/` + drives[0];
238
+ oPartitions.installationDevice = drives[0];
237
239
  }
238
240
  else {
241
+ console.error("[Krll] No suitable disc found for installation. Debug info:");
242
+ shx.exec('lsblk -o NAME,RM,RO,TYPE,SIZE,MODEL', { silent: false });
239
243
  throw new Error("Unable to find installation drive");
240
244
  }
241
245
  }
@@ -167,7 +167,7 @@ async function isRotational(device) {
167
167
  // Check if the selected disk is a software raid
168
168
  if (device.startsWith('md')) {
169
169
  // Get the first disk from which the raid is composed
170
- device = shx.exec(`cat /proc/mdstat | grep ${device} | cut -f 5 -d " " | cut -f 1 -d "["`).stdout.trim();
170
+ device = shx.exec(`cat /proc/mdstat | grep ${device} | cut -f 5 -d " " | cut -f 1 -d "["`, { silent: true }).stdout.trim();
171
171
  }
172
172
  response = shx.exec(`cat /sys/block/${device}/queue/rotational`, { silent: true }).stdout.trim();
173
173
  if (response === '1') {
@@ -30,7 +30,7 @@ export default async function mkfs() {
30
30
  if (this.efi) {
31
31
  // usare shx.exec qui
32
32
  const efiDetectCmd = `fdisk -l | grep 'EFI System' | awk '{print $1}'`;
33
- const efiName = shx.exec(efiDetectCmd).stdout.trim();
33
+ const efiName = shx.exec(efiDetectCmd, { silent: true }).stdout.trim();
34
34
  if (efiName) {
35
35
  this.devices.efi.name = efiName;
36
36
  this.devices.efi.mountPoint = '/boot/efi';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * ./src/krill/modules/remove-installer-link.ts
3
+ * penguins-eggs v.25.7.x / ecmascript 2020
4
+ * author: Piero Proietti
5
+ * email: piero.proietti@gmail.com
6
+ * license: MIT
7
+ * https://stackoverflow.com/questions/23876782/how-do-i-split-a-typescript-class-into-multiple-files
8
+ */
9
+ import Sequence from '../sequence.js';
10
+ /**
11
+ * removeHomecryptHack
12
+ */
13
+ export default function removeHomecryptHack(this: Sequence): Promise<void>;