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.
- package/.oclif.manifest.json +1 -1
- package/README.md +118 -127
- package/README.pdf +10950 -11893
- package/addons/eggs/theme/livecd/simple.grub.main.cfg +3 -3
- package/conf/derivatives.yaml +2 -1
- package/conf/distros/buster/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/focal/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/noble/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/distros/noble/calamares/libexec/calamares-l10n-helper.sh +2 -1
- package/conf/distros/noble/calamares/settings.yml +1 -0
- package/conf/distros/trixie/calamares/calamares-modules/cleanup/cleanup.sh +1 -1
- package/conf/exclude.list.d/var.list +11 -6
- package/dist/appimage/dependency-manager.js +1 -1
- package/dist/classes/cli-autologin.d.ts +37 -4
- package/dist/classes/cli-autologin.js +153 -115
- package/dist/classes/compressors.d.ts +7 -10
- package/dist/classes/compressors.js +44 -31
- package/dist/classes/daddy.js +4 -1
- package/dist/classes/distro.js +2 -2
- package/dist/classes/diversions.js +2 -3
- package/dist/classes/incubation/fisherman-helper/initcpio.d.ts +3 -5
- package/dist/classes/incubation/fisherman-helper/initcpio.js +28 -20
- package/dist/classes/incubation/fisherman-helper/settings.js +1 -1
- package/dist/classes/incubation/fisherman.js +1 -1
- package/dist/classes/incubation/incubator.d/manjaro.js +1 -0
- package/dist/classes/incubation/incubator.js +1 -1
- package/dist/classes/ovary.d/create-xdg-autostart.js +1 -1
- package/dist/classes/ovary.d/edit-live-fs.d.ts +2 -13
- package/dist/classes/ovary.d/edit-live-fs.js +33 -146
- package/dist/classes/ovary.d/fertilization.js +1 -1
- package/dist/classes/ovary.d/luks-home.js +33 -19
- package/dist/classes/ovary.d/luks-root.d.ts +1 -2
- package/dist/classes/ovary.d/luks-root.js +46 -27
- package/dist/classes/ovary.d/luks-shrink.d.ts +14 -0
- package/dist/classes/ovary.d/luks-shrink.js +86 -0
- package/dist/classes/ovary.d/make-dot-disk.js +1 -1
- package/dist/classes/ovary.d/produce.js +64 -22
- package/dist/classes/ovary.d/user-create-live.d.ts +4 -10
- package/dist/classes/ovary.d/user-create-live.js +82 -84
- package/dist/classes/ovary.d/users-remove.d.ts +5 -6
- package/dist/classes/ovary.d/users-remove.js +61 -31
- package/dist/classes/ovary.d.ts +5 -3
- package/dist/classes/ovary.js +5 -3
- package/dist/classes/pacman.d/alpine.js +2 -2
- package/dist/classes/pacman.d/archlinux.js +2 -2
- package/dist/classes/pacman.d/debian.js +2 -3
- package/dist/classes/pacman.d/fedora.js +2 -3
- package/dist/classes/pacman.d/openmamba.js +2 -3
- package/dist/classes/pacman.d/opensuse.js +2 -3
- package/dist/classes/pacman.d.ts +0 -5
- package/dist/classes/pacman.js +3 -16
- package/dist/classes/pve-live.js +1 -1
- package/dist/classes/settings.js +1 -1
- package/dist/classes/sys-users.d.ts +76 -0
- package/dist/classes/sys-users.js +206 -0
- package/dist/classes/utils.d/kernel.js +3 -3
- package/dist/classes/utils.d.ts +15 -6
- package/dist/classes/utils.js +80 -47
- package/dist/classes/xdg.js +1 -1
- package/dist/classes/yolk.js +3 -5
- package/dist/commands/export/appimage.js +3 -3
- package/dist/commands/export/pkg.js +3 -3
- package/dist/commands/export/tarballs.js +3 -3
- package/dist/commands/krill.js +1 -1
- package/dist/commands/produce.js +14 -5
- package/dist/commands/setup/install.js +1 -1
- package/dist/commands/setup/purge.js +1 -1
- package/dist/commands/tools/yolk.js +1 -1
- package/dist/commands/update.js +1 -2
- package/dist/interfaces/calamares/i-calamares-branding.d.ts +56 -38
- package/dist/interfaces/calamares/i-calamares-branding.js +10 -0
- package/dist/interfaces/i-exec.d.ts +1 -0
- package/dist/krill/classes/prepare.d/location.js +1 -1
- package/dist/krill/classes/prepare.d/partitions.js +1 -1
- package/dist/krill/classes/prepare.d/users.js +2 -2
- package/dist/krill/classes/prepare.js +5 -5
- package/dist/krill/classes/sequence.d/add_user.d.ts +3 -15
- package/dist/krill/classes/sequence.d/add_user.js +87 -57
- package/dist/krill/classes/sequence.d/change_password.d.ts +5 -7
- package/dist/krill/classes/sequence.d/change_password.js +25 -10
- package/dist/krill/classes/sequence.d/del_live_user.d.ts +5 -7
- package/dist/krill/classes/sequence.d/del_live_user.js +39 -25
- package/dist/krill/classes/sequence.d/fstab.js +2 -2
- package/dist/krill/classes/sequence.d/grubcfg.d.ts +3 -7
- package/dist/krill/classes/sequence.d/grubcfg.js +33 -13
- package/dist/krill/classes/sequence.d/mkfs.js +2 -3
- package/dist/krill/classes/sequence.d/unpackfs.d.ts +2 -4
- package/dist/krill/classes/sequence.d/unpackfs.js +8 -5
- package/dist/krill/classes/sequence.d.ts +1 -5
- package/dist/krill/classes/sequence.js +28 -32
- package/dist/krill/components/finished.js +2 -2
- package/dist/krill/components/install.js +2 -2
- package/dist/krill/components/keyboard.js +2 -2
- package/dist/krill/components/location.js +2 -2
- package/dist/krill/components/network.js +2 -2
- package/dist/krill/components/partitions.js +2 -2
- package/dist/krill/components/summary.js +2 -2
- package/dist/krill/components/title.js +2 -2
- package/dist/krill/components/users.js +2 -2
- package/dist/krill/components/welcome.js +2 -2
- package/dist/krill/lib/select_installation_device.js +1 -1
- package/dist/krill/lib/select_replaced_partition.js +1 -1
- package/dist/lib/utils.d.ts +52 -19
- package/dist/lib/utils.js +271 -20
- package/manpages/doc/man/eggs.1.gz +0 -0
- package/manpages/doc/man/eggs.html +8 -8
- package/package.json +9 -9
- package/perrisbrewery/template/dependencies.yaml +1 -0
- package/scripts/boot-encrypted-root.sh +220 -0
- package/scripts/mount-encrypted-home.sh +324 -0
- package/scripts/restore_homecrypt_krill.sh +93 -0
- package/dracut/create-symlink +0 -71
- package/dracut/dracut-log.txt +0 -3
- package/dracut/export +0 -4
- package/dracut/export-dracut-analysis +0 -51
- package/dracut/export-dracut-log +0 -2
- package/dracut/mkisofs +0 -10
- package/dracut/renew-initramfs +0 -17
- package/dracut/sbin2bin +0 -10
- package/dracut/update-dracut-conf-d +0 -2
- package/dracut/update-dracut-modules +0 -62
package/dist/lib/utils.js
CHANGED
|
@@ -5,34 +5,285 @@
|
|
|
5
5
|
* email: piero.proietti@gmail.com
|
|
6
6
|
* license: MIT
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
// Importiamo con alias per poter wrappare
|
|
11
|
+
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from 'child_process';
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
13
|
+
* Pulizia AppImage
|
|
14
|
+
* Variabili d'ambiente da rimuovere per evitare conflitti quando si eseguono
|
|
15
|
+
* comandi di sistema dall'interno di una AppImage.
|
|
16
|
+
*/
|
|
17
|
+
const APPIMAGE_ENV_BLACKLIST = [
|
|
18
|
+
'LD_LIBRARY_PATH', 'LD_PRELOAD', 'PYTHONPATH', 'PERLLIB',
|
|
19
|
+
'GSETTINGS_SCHEMA_DIR', 'QT_PLUGIN_PATH', 'XDG_DATA_DIRS',
|
|
20
|
+
'LIBRARY_PATH', 'PKG_CONFIG_PATH', 'GIO_MODULE_DIR', 'APPIMAGE', 'APPDIR'
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Ottiene un ambiente pulito dalle variabili AppImage
|
|
24
|
+
* @returns Oggetto process.env sanificato
|
|
25
|
+
*/
|
|
26
|
+
function getCleanEnv() {
|
|
27
|
+
const env = { ...process.env };
|
|
28
|
+
if (process.env.APPIMAGE) {
|
|
29
|
+
APPIMAGE_ENV_BLACKLIST.forEach((key) => delete env[key]);
|
|
30
|
+
}
|
|
31
|
+
return env;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* spawnSync (WRAPPER INTELLIGENTE)
|
|
35
|
+
* Supporta:
|
|
36
|
+
* 1. (command, args, options)
|
|
37
|
+
* 2. (command, options) -> args diventa []
|
|
38
|
+
* Pulisce automaticamente l'ambiente.
|
|
39
|
+
*/
|
|
40
|
+
export function spawnSync(command, arg2, arg3) {
|
|
41
|
+
let args = [];
|
|
42
|
+
let options = {};
|
|
43
|
+
// Rilevamento argomenti (Polimorfismo)
|
|
44
|
+
if (Array.isArray(arg2)) {
|
|
45
|
+
args = arg2;
|
|
46
|
+
options = arg3 || {};
|
|
47
|
+
}
|
|
48
|
+
else if (arg2 && typeof arg2 === 'object') {
|
|
49
|
+
// TypeScript fix: cast esplicito per evitare errori di tipo union
|
|
50
|
+
options = arg2;
|
|
51
|
+
}
|
|
52
|
+
const env = getCleanEnv();
|
|
53
|
+
const finalEnv = { ...env, ...(options.env || {}) };
|
|
54
|
+
return nodeSpawnSync(command, args, {
|
|
55
|
+
...options,
|
|
56
|
+
env: finalEnv
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* spawn (WRAPPER INTELLIGENTE)
|
|
61
|
+
* Supporta:
|
|
62
|
+
* 1. (command, args, options)
|
|
63
|
+
* 2. (command, options) -> args diventa []
|
|
64
|
+
* Pulisce automaticamente l'ambiente.
|
|
65
|
+
*/
|
|
66
|
+
export function spawn(command, arg2, arg3) {
|
|
67
|
+
let args = [];
|
|
68
|
+
let options = {};
|
|
69
|
+
// Rilevamento argomenti (Polimorfismo)
|
|
70
|
+
if (Array.isArray(arg2)) {
|
|
71
|
+
args = arg2;
|
|
72
|
+
options = arg3 || {};
|
|
73
|
+
}
|
|
74
|
+
else if (arg2 && typeof arg2 === 'object') {
|
|
75
|
+
// TypeScript fix: cast esplicito
|
|
76
|
+
options = arg2;
|
|
77
|
+
}
|
|
78
|
+
const env = getCleanEnv();
|
|
79
|
+
const finalEnv = { ...env, ...(options.env || {}) };
|
|
80
|
+
return nodeSpawn(command, args, {
|
|
81
|
+
...options,
|
|
82
|
+
env: finalEnv
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* shx
|
|
87
|
+
* Sostituto drop-in per shelljs che usa API native e ambiente pulito.
|
|
88
|
+
*/
|
|
89
|
+
export const shx = {
|
|
90
|
+
sed: (flag, regex, replacement, file) => {
|
|
91
|
+
if (!fs.existsSync(file))
|
|
92
|
+
return;
|
|
93
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
94
|
+
const searchRegex = typeof regex === 'string' ? new RegExp(regex, 'g') : regex;
|
|
95
|
+
const newContent = content.replace(searchRegex, replacement);
|
|
96
|
+
fs.writeFileSync(file, newContent, 'utf8');
|
|
97
|
+
},
|
|
98
|
+
touch: (file) => {
|
|
99
|
+
const time = new Date();
|
|
100
|
+
try {
|
|
101
|
+
fs.utimesSync(file, time, time);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
fs.closeSync(fs.openSync(file, 'w'));
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
cp: (arg1, arg2, arg3) => {
|
|
108
|
+
const src = arg3 ? arg2 : arg1;
|
|
109
|
+
const dest = arg3 ? arg3 : arg2;
|
|
110
|
+
// --- GESTIONE WILDCARD (*) ---
|
|
111
|
+
if (src.endsWith('*')) {
|
|
112
|
+
const srcDir = path.dirname(src);
|
|
113
|
+
if (!fs.existsSync(srcDir))
|
|
114
|
+
return;
|
|
115
|
+
if (!fs.existsSync(dest))
|
|
116
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
117
|
+
const items = fs.readdirSync(srcDir);
|
|
118
|
+
items.forEach(item => {
|
|
119
|
+
const s = path.join(srcDir, item);
|
|
120
|
+
const d = path.join(dest, item);
|
|
121
|
+
fs.cpSync(s, d, { recursive: true, force: true });
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// ----------------------------
|
|
126
|
+
let finalDest = dest;
|
|
127
|
+
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
|
|
128
|
+
finalDest = path.join(dest, path.basename(src));
|
|
129
|
+
}
|
|
130
|
+
if (fs.existsSync(src)) {
|
|
131
|
+
fs.cpSync(src, finalDest, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
rm: (arg1, arg2) => {
|
|
135
|
+
const target = arg2 ? arg2 : arg1;
|
|
136
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
137
|
+
},
|
|
138
|
+
mkdir: (arg1, arg2) => {
|
|
139
|
+
const dir = arg2 ? arg2 : arg1;
|
|
140
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
141
|
+
},
|
|
142
|
+
mv: (src, dest) => {
|
|
143
|
+
if (!fs.existsSync(src))
|
|
144
|
+
return;
|
|
145
|
+
fs.renameSync(src, dest);
|
|
146
|
+
},
|
|
147
|
+
chmod: (mode, file) => {
|
|
148
|
+
if (!fs.existsSync(file))
|
|
149
|
+
return;
|
|
150
|
+
let finalMode = mode;
|
|
151
|
+
if (mode === '+x')
|
|
152
|
+
finalMode = 0o755;
|
|
153
|
+
if (typeof mode === 'string' && !isNaN(parseInt(mode, 8))) {
|
|
154
|
+
finalMode = parseInt(mode, 8);
|
|
155
|
+
}
|
|
156
|
+
fs.chmodSync(file, finalMode);
|
|
157
|
+
},
|
|
158
|
+
test: (flag, pathToCheck) => {
|
|
159
|
+
try {
|
|
160
|
+
const stats = fs.statSync(pathToCheck);
|
|
161
|
+
if (flag === '-f')
|
|
162
|
+
return stats.isFile();
|
|
163
|
+
if (flag === '-d')
|
|
164
|
+
return stats.isDirectory();
|
|
165
|
+
return true; // -e
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
which: (cmd) => {
|
|
172
|
+
const result = shx.exec(`command -v ${cmd}`, { silent: true });
|
|
173
|
+
return result.code === 0 ? result.stdout.trim() : null;
|
|
174
|
+
},
|
|
175
|
+
ln: (flag, target, link) => {
|
|
176
|
+
if (fs.existsSync(link) || fs.lstatSync(link, { throwIfNoEntry: false })) {
|
|
177
|
+
fs.rmSync(link, { force: true });
|
|
178
|
+
}
|
|
179
|
+
fs.symlinkSync(target, link);
|
|
180
|
+
},
|
|
181
|
+
ls: (arg1, arg2) => {
|
|
182
|
+
let options = '';
|
|
183
|
+
let paths = [];
|
|
184
|
+
// Rilevamento argomenti: ls('-R', path) vs ls(path)
|
|
185
|
+
if (typeof arg1 === 'string' && arg1.startsWith('-')) {
|
|
186
|
+
options = arg1;
|
|
187
|
+
// Se c'è arg2 lo usa, altrimenti default a '.'
|
|
188
|
+
paths = arg2 ? (Array.isArray(arg2) ? arg2 : [arg2]) : ['.'];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Nessuna opzione, arg1 sono i path. Se null, default a '.'
|
|
192
|
+
paths = arg1 ? (Array.isArray(arg1) ? arg1 : [arg1]) : ['.'];
|
|
193
|
+
}
|
|
194
|
+
const recursive = options.includes('R');
|
|
195
|
+
let results = [];
|
|
196
|
+
paths.forEach(p => {
|
|
197
|
+
if (!fs.existsSync(p))
|
|
198
|
+
return;
|
|
199
|
+
const stat = fs.statSync(p);
|
|
200
|
+
if (stat.isDirectory()) {
|
|
201
|
+
if (recursive) {
|
|
202
|
+
// Funzione ricorsiva interna
|
|
203
|
+
const walk = (dir) => {
|
|
204
|
+
const files = fs.readdirSync(dir);
|
|
205
|
+
files.forEach(f => {
|
|
206
|
+
const fullPath = path.join(dir, f);
|
|
207
|
+
results.push(fullPath); // Aggiunge il path completo
|
|
208
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
209
|
+
walk(fullPath);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
walk(p);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Comportamento standard: ritorna solo i nomi dei file nella cartella
|
|
217
|
+
results = results.concat(fs.readdirSync(p));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// È un file singolo
|
|
222
|
+
results.push(p);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
return results;
|
|
226
|
+
},
|
|
227
|
+
exec: (command, options = {}) => {
|
|
228
|
+
const env = getCleanEnv();
|
|
229
|
+
const spawnOpts = {
|
|
230
|
+
stdio: options.silent ? 'pipe' : 'inherit',
|
|
231
|
+
env: env,
|
|
232
|
+
shell: '/bin/bash',
|
|
233
|
+
encoding: 'utf-8'
|
|
234
|
+
};
|
|
235
|
+
// Usiamo nodeSpawnSync perché calcoliamo l'env qui sopra
|
|
236
|
+
const result = nodeSpawnSync(command, [], spawnOpts);
|
|
237
|
+
return {
|
|
238
|
+
code: result.status ?? 1,
|
|
239
|
+
stdout: result.stdout ? result.stdout.toString() : '',
|
|
240
|
+
stderr: result.stderr ? result.stderr.toString() : ''
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* execSync
|
|
246
|
+
*/
|
|
247
|
+
export function execSync(command, options = {}) {
|
|
248
|
+
const { echo = false, ignore = false, stdio } = options;
|
|
249
|
+
if (echo)
|
|
250
|
+
console.log(command);
|
|
251
|
+
const isSilent = ignore || stdio === 'ignore';
|
|
252
|
+
const result = shx.exec(command, { silent: isSilent });
|
|
253
|
+
if (result.code !== 0) {
|
|
254
|
+
throw new Error(`Command failed: ${command}\nExit Code: ${result.code}\nStderr: ${result.stderr}`);
|
|
255
|
+
}
|
|
256
|
+
return result.stdout.trim();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* exec (Async)
|
|
14
260
|
*/
|
|
15
261
|
export async function exec(command, { echo = false, ignore = false, capture = false } = {}) {
|
|
16
262
|
return new Promise((resolve, reject) => {
|
|
17
|
-
if (echo)
|
|
263
|
+
if (echo)
|
|
18
264
|
console.log(command);
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
const
|
|
22
|
-
stdio: ignore ? 'ignore' : capture ? 'pipe' : 'inherit'
|
|
23
|
-
|
|
24
|
-
|
|
265
|
+
const env = getCleanEnv();
|
|
266
|
+
// Usiamo nodeSpawn direttamente qui per coerenza
|
|
267
|
+
const child = nodeSpawn(command, [], {
|
|
268
|
+
stdio: ignore ? 'ignore' : (capture ? 'pipe' : 'inherit'),
|
|
269
|
+
env: env,
|
|
270
|
+
shell: '/bin/bash'
|
|
271
|
+
});
|
|
25
272
|
let stdout = '';
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
273
|
+
let stderr = '';
|
|
274
|
+
if (capture && child.stdout)
|
|
275
|
+
child.stdout.on('data', d => stdout += d.toString());
|
|
276
|
+
if (capture && child.stderr)
|
|
277
|
+
child.stderr.on('data', d => stderr += d.toString());
|
|
31
278
|
child.on('error', (error) => {
|
|
32
|
-
reject({ code: 1, error });
|
|
279
|
+
reject({ code: 1, error, stderr });
|
|
33
280
|
});
|
|
34
|
-
child.on('
|
|
35
|
-
resolve({
|
|
281
|
+
child.on('close', (code) => {
|
|
282
|
+
resolve({
|
|
283
|
+
code: code || 0,
|
|
284
|
+
data: stdout.trim(),
|
|
285
|
+
error: code !== 0 ? stderr.trim() : undefined
|
|
286
|
+
});
|
|
36
287
|
});
|
|
37
288
|
});
|
|
38
289
|
}
|
|
Binary file
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
7
|
</head>
|
|
8
8
|
<body>
|
|
9
|
-
<h1>eggs(1) -- the reproductive system of penguins: eggs v25.
|
|
9
|
+
<h1>eggs(1) -- the reproductive system of penguins: eggs v25.12.8</h1>
|
|
10
10
|
<h1>SYNOPSIS</h1>
|
|
11
11
|
<p>eggs is a console utility, in active development, who let you to remaster your system and redistribuite it as live ISO image.</p>
|
|
12
12
|
<h1>INSTALL</h1>
|
|
13
13
|
<p>penguins-eggs as an AppImage, it can be installed on all supported distributions. Download it from https://github.com/pieroproietti/penguins-eggs/releases, then run the following commands:</p>
|
|
14
|
-
<pre><code>$ chmod +x penguins-eggs_25.
|
|
14
|
+
<pre><code>$ chmod +x penguins-eggs_25.12.8-1_amd64-x86_64.AppImage
|
|
15
15
|
$ sudo mv /usr/local/bin
|
|
16
16
|
$ sudo eggs setup
|
|
17
17
|
</code></pre>
|
|
@@ -19,30 +19,30 @@ $ sudo eggs setup
|
|
|
19
19
|
<pre><code>$ doas apk add penguins-eggs@testing
|
|
20
20
|
</code></pre>
|
|
21
21
|
<p>AlmaLinux/RockyLinux</p>
|
|
22
|
-
<pre><code>$ sudo dnf install ./penguins-eggs_25.
|
|
22
|
+
<pre><code>$ sudo dnf install ./penguins-eggs_25.12.8-1_amd64-1rocky9.5..x86_64.rpm
|
|
23
23
|
|
|
24
24
|
</code></pre>
|
|
25
25
|
<p>Arch</p>
|
|
26
26
|
<pre><code>$ sudo pacman -S penguins-eggs
|
|
27
|
-
$ sudo pacman -U penguins-eggs_25.
|
|
27
|
+
$ sudo pacman -U penguins-eggs_25.12.8-1_amd64-1-x86_64.pkg.tar.zst
|
|
28
28
|
</code></pre>
|
|
29
29
|
<p>Debian/Devuan/Ubuntu</p>
|
|
30
30
|
<pre><code>$ sudo apt install penguins-eggs
|
|
31
|
-
$ sudo dpkg -i penguins-eggs_25.
|
|
31
|
+
$ sudo dpkg -i penguins-eggs_25.12.8-1_amd64.deb
|
|
32
32
|
</code></pre>
|
|
33
33
|
<p>Fedora</p>
|
|
34
|
-
<pre><code>$ sudo dnf install ./penguins-eggs_25.
|
|
34
|
+
<pre><code>$ sudo dnf install ./penguins-eggs_25.12.8-1_amd64-1fedora.x86_64.rpm
|
|
35
35
|
</code></pre>
|
|
36
36
|
<p>Manjaro</p>
|
|
37
37
|
<pre><code>$ sudo pamac install penguins-eggs
|
|
38
38
|
</code></pre>
|
|
39
39
|
<p>OpenMamba</p>
|
|
40
|
-
<pre><code>$ sudo dnf install ./penguins-eggs_25.
|
|
40
|
+
<pre><code>$ sudo dnf install ./penguins-eggs_25.12.8-1_amd64-1mamba.x86_64.rpm
|
|
41
41
|
</code></pre>
|
|
42
42
|
<h1>USAGE</h1>
|
|
43
43
|
<pre><code>$ eggs (-v|--version|version)
|
|
44
44
|
|
|
45
|
-
penguins-eggs/25.
|
|
45
|
+
penguins-eggs/25.12.8
|
|
46
46
|
$ eggs --help [COMMAND]
|
|
47
47
|
|
|
48
48
|
USAGE
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "penguins-eggs",
|
|
3
3
|
"shortName": "eggs",
|
|
4
4
|
"description": "A remaster system tool, compatible with Almalinux, Alpine, Arch, Debian, Devuan, Fedora, Manjaro, Opensuse, Ubuntu and derivatives",
|
|
5
|
-
"version": "25.
|
|
5
|
+
"version": "25.12.15",
|
|
6
6
|
"author": "Piero Proietti",
|
|
7
7
|
"bin": {
|
|
8
8
|
"eggs": "./bin/run.js"
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
"@oclif/plugin-autocomplete": "^3.2.39",
|
|
14
14
|
"@oclif/plugin-help": "^6.2.36",
|
|
15
15
|
"@oclif/plugin-version": "^2.2.36",
|
|
16
|
-
"@types/express": "^5.0.
|
|
16
|
+
"@types/express": "^5.0.6",
|
|
17
17
|
"ansis": "^4.2.0",
|
|
18
18
|
"axios": "^1.13.2",
|
|
19
|
+
"bcryptjs": "^3.0.3",
|
|
19
20
|
"chalk": "^5.6.2",
|
|
20
21
|
"cli-cursor": "^5.0.0",
|
|
21
22
|
"debug": "^4.4.3",
|
|
22
|
-
"express": "^5.1
|
|
23
|
+
"express": "^5.2.1",
|
|
23
24
|
"ink": "^5",
|
|
24
25
|
"ink-progress-bar": "^3.0.0",
|
|
25
26
|
"ink-spinner": "^5.0.0",
|
|
@@ -29,7 +30,6 @@
|
|
|
29
30
|
"netmask": "^2.0.2",
|
|
30
31
|
"react": "^18.3.1",
|
|
31
32
|
"read": "^4.1.0",
|
|
32
|
-
"shelljs": "^0.10.0",
|
|
33
33
|
"systeminformation": "^5.27.11",
|
|
34
34
|
"tftp": "^0.1.2",
|
|
35
35
|
"ws": "^8.18.3"
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@oclif/prettier-config": "^0.2.1",
|
|
39
39
|
"@oclif/test": "^4.1.15",
|
|
40
|
+
"@types/bcryptjs": "^3.0.0",
|
|
40
41
|
"@types/chai": "^5.2.3",
|
|
41
42
|
"@types/debug": "^4.1.12",
|
|
42
43
|
"@types/glob": "^9.0.0",
|
|
@@ -48,24 +49,23 @@
|
|
|
48
49
|
"@types/node": "^22.15.30",
|
|
49
50
|
"@types/react": "^18.3.18",
|
|
50
51
|
"@types/read": "^0.0.32",
|
|
51
|
-
"@types/shelljs": "^0.8.17",
|
|
52
52
|
"@types/ws": "^8.18.1",
|
|
53
53
|
"chai": "^6.2.1",
|
|
54
54
|
"eslint": "^9.39.1",
|
|
55
|
-
"eslint-config-oclif": "^6.0.
|
|
55
|
+
"eslint-config-oclif": "^6.0.124",
|
|
56
56
|
"eslint-config-prettier": "^10.1.8",
|
|
57
57
|
"glob": "^13.0.0",
|
|
58
58
|
"mocha": "^11.7.5",
|
|
59
|
-
"oclif": "^4.22.
|
|
59
|
+
"oclif": "^4.22.55",
|
|
60
60
|
"perrisbrewery": "^25.9.16",
|
|
61
|
-
"prettier": "^3.7.
|
|
61
|
+
"prettier": "^3.7.4",
|
|
62
62
|
"shx": "^0.4.0",
|
|
63
63
|
"ts-node": "10.9.2",
|
|
64
64
|
"ts-prune": "^0.10.3",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|
|
68
|
-
"node": ">=
|
|
68
|
+
"node": ">=22.0.0"
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
".oclif.manifest.json",
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# /scripts/live-premount/boot-encrypted-root.sh
|
|
3
|
+
#
|
|
4
|
+
# This script is designed to Boot Encrypted Linux Live (BELL).
|
|
5
|
+
#
|
|
6
|
+
# Its main purpose is to find an encrypted root image file (root.img)
|
|
7
|
+
# on a live USB/DVD, ask the user for a passphrase to unlock it,
|
|
8
|
+
# and then copy the main system filesystem (filesystem.squashfs)
|
|
9
|
+
# from inside the encrypted image into RAM.
|
|
10
|
+
#
|
|
11
|
+
# the process continue with standard live-boot
|
|
12
|
+
|
|
13
|
+
# enable echo
|
|
14
|
+
# set -e
|
|
15
|
+
|
|
16
|
+
echo "BELL: Boot Encrypted Linux Live"
|
|
17
|
+
|
|
18
|
+
#################################################
|
|
19
|
+
# 1. Setup and Find Media
|
|
20
|
+
|
|
21
|
+
# 1.1 load modules
|
|
22
|
+
echo "BELL: loading modules..."
|
|
23
|
+
modprobe loop 2>/dev/null || true
|
|
24
|
+
modprobe dm_mod 2>/dev/null || true
|
|
25
|
+
modprobe dm_crypt 2>/dev/null || true
|
|
26
|
+
modprobe overlay 2>/dev/null || true
|
|
27
|
+
modprobe ext4 2>/dev/null || true
|
|
28
|
+
modprobe squashfs 2>/dev/null || true
|
|
29
|
+
sleep 2
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# 1.2 find BELL media drive
|
|
33
|
+
echo "BELL: find BELL media drive..."
|
|
34
|
+
mkdir -p /mnt/live-media /mnt/ext4
|
|
35
|
+
BELL_MEDIA_MNT="/mnt/live-media"
|
|
36
|
+
LIVE_DEV=""
|
|
37
|
+
|
|
38
|
+
# find to max 20 devices
|
|
39
|
+
MAX_WAIT_DEV=20; COUNT_DEV=0
|
|
40
|
+
while [ -z "$LIVE_DEV" ] && [ $COUNT_DEV -lt $MAX_WAIT_DEV ]; do
|
|
41
|
+
ls /dev > /dev/null
|
|
42
|
+
for dev in /dev/sr* /dev/sd* /dev/vd* /dev/nvme*n*; do
|
|
43
|
+
if [ ! -b "$dev" ]; then continue; fi
|
|
44
|
+
if mount -o ro "$dev" "$BELL_MEDIA_MNT" 2>/dev/null; then
|
|
45
|
+
if [ -f "${BELL_MEDIA_MNT}/live/root.img" ]; then
|
|
46
|
+
echo "BELL: Found BELL media on $dev"
|
|
47
|
+
LIVE_DEV=$dev
|
|
48
|
+
break 2
|
|
49
|
+
else
|
|
50
|
+
umount "$BELL_MEDIA_MNT" 2>/dev/null || true
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
done
|
|
54
|
+
sleep 1
|
|
55
|
+
COUNT_DEV=$((COUNT_DEV+1))
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
if [ -z "$LIVE_DEV" ]; then
|
|
59
|
+
echo "BELL: Error: no live BELL drive found!"
|
|
60
|
+
ls /dev
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
ROOT_IMG_RO="${BELL_MEDIA_MNT}/live/root.img"
|
|
65
|
+
RAM_MEDIA_MNT="/run/live/medium" # final destination in RAM
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
#################################################
|
|
69
|
+
# 2. Prepare Encrypted Image
|
|
70
|
+
|
|
71
|
+
# 2.1 loop device
|
|
72
|
+
echo "BELL: loop device association for $ROOT_IMG_RO..."
|
|
73
|
+
LOOP_DEV_OUTPUT=$(/sbin/losetup -f --show "$ROOT_IMG_RO" 2>/dev/null); LOSETUP_EXIT_STATUS=$?
|
|
74
|
+
if [ $LOSETUP_EXIT_STATUS -ne 0 ] || [ -z "$LOOP_DEV_OUTPUT" ] || ! [ -b "$LOOP_DEV_OUTPUT" ]; then
|
|
75
|
+
echo "BELL: Error: loop association failed!"
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
LOOP_DEV="$LOOP_DEV_OUTPUT"
|
|
79
|
+
echo "BELL: loop device $ROOT_IMG_RO associated to: $LOOP_DEV"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
#################################################
|
|
84
|
+
# 3. Unlock LUKS (User Interaction)
|
|
85
|
+
|
|
86
|
+
# disable 'set -e' to let 3 tempts
|
|
87
|
+
#set +e
|
|
88
|
+
MAX_ATTEMPTS=3
|
|
89
|
+
ATTEMPT=1
|
|
90
|
+
UNLOCKED=0
|
|
91
|
+
|
|
92
|
+
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
|
93
|
+
|
|
94
|
+
# check if plymouth is active
|
|
95
|
+
if plymouth --ping 2>/dev/null; then
|
|
96
|
+
|
|
97
|
+
# request the password in plymouth and pass it to cryptsetup via stdin (--key-file -)
|
|
98
|
+
if plymouth ask-for-password --prompt="Enter passphrase ($ATTEMPT/$MAX_ATTEMPTS)" | cryptsetup open --readonly --key-file - "$LOOP_DEV" live-root; then
|
|
99
|
+
UNLOCKED=1
|
|
100
|
+
break
|
|
101
|
+
else
|
|
102
|
+
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
|
|
103
|
+
plymouth display-message --text="Incorrect passphrase. Try again..."
|
|
104
|
+
sleep 2 # wait 2 seconds to read message
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
else
|
|
108
|
+
# Fallback: Plymouth not active
|
|
109
|
+
echo "Please enter passphrase for $LOOP_DEV ($ATTEMPT/$MAX_ATTEMPTS):"
|
|
110
|
+
|
|
111
|
+
if cryptsetup open --readonly "$LOOP_DEV" live-root; then
|
|
112
|
+
UNLOCKED=1
|
|
113
|
+
break
|
|
114
|
+
else
|
|
115
|
+
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
|
|
116
|
+
echo "Incorrect passphrase. Please try again."
|
|
117
|
+
fi
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
ATTEMPT=$((ATTEMPT + 1))
|
|
122
|
+
sleep 1
|
|
123
|
+
done
|
|
124
|
+
|
|
125
|
+
# Enable echo
|
|
126
|
+
# set -e
|
|
127
|
+
|
|
128
|
+
# check if all attempts have failed
|
|
129
|
+
if [ $UNLOCKED -eq 0 ]; then
|
|
130
|
+
if plymouth --ping 2>/dev/null; then
|
|
131
|
+
plymouth display-message --text="LUKS Unlock Failed: Max attempts reached"
|
|
132
|
+
sleep 5
|
|
133
|
+
fi
|
|
134
|
+
/sbin/losetup -d "$LOOP_DEV" || true
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
echo "BELL: LUKS unlocked ($LOOP_DEV -> live-root) [readonly]. Waiting for mapper..."
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
#################################################
|
|
142
|
+
# 4. copy System to RAM
|
|
143
|
+
|
|
144
|
+
# 4.1 waiting mapper
|
|
145
|
+
MAX_WAIT_MAP=10; COUNT_MAP=0
|
|
146
|
+
while [ ! -b /dev/mapper/live-root ] && [ $COUNT_MAP -lt $MAX_WAIT_MAP ]; do
|
|
147
|
+
sleep 1
|
|
148
|
+
COUNT_MAP=$((COUNT_MAP+1))
|
|
149
|
+
done
|
|
150
|
+
|
|
151
|
+
if [ ! -b /dev/mapper/live-root ]; then
|
|
152
|
+
echo "BELL: Error: mapper did not appear."
|
|
153
|
+
cryptsetup close live-root || true
|
|
154
|
+
/sbin/losetup -d "$LOOP_DEV" || true
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# 4.2 mount ext4 filesystem
|
|
159
|
+
echo "BELL: mounting ext4 filesystem..."
|
|
160
|
+
mount -t ext4 -o ro /dev/mapper/live-root /mnt/ext4
|
|
161
|
+
|
|
162
|
+
SQFS_SRC="/mnt/ext4/filesystem.squashfs"
|
|
163
|
+
if [ ! -f "$SQFS_SRC" ]; then
|
|
164
|
+
echo "BELL: error: $SQFS_SRC not found!"
|
|
165
|
+
exit 1
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# 4.3. Prepare RAM destination /run
|
|
170
|
+
echo "BELL: preparing RAM disk ${RAM_MEDIA_MNT}..."
|
|
171
|
+
SQFS_SIZE_BYTES=$(stat -c%s "$SQFS_SRC")
|
|
172
|
+
NEEDED_SIZE_MB=$(( $SQFS_SIZE_BYTES / 1024 / 1024 + 500 )) # add 500MB buffer
|
|
173
|
+
echo "BELL: Estimated space required in /run: ${NEEDED_SIZE_MB} MB"
|
|
174
|
+
echo "BELL: increase size /run (tmpfs)..."
|
|
175
|
+
if ! mount -o remount,size=${NEEDED_SIZE_MB}M /run; then
|
|
176
|
+
echo "BELL: WARN: Remount /run failed, space may be insufficient."
|
|
177
|
+
df -h /run
|
|
178
|
+
fi
|
|
179
|
+
mkdir -p "${RAM_MEDIA_MNT}/live"
|
|
180
|
+
|
|
181
|
+
# 4.4 copy ONLY filesystem.squashfs to RAM
|
|
182
|
+
SQFS_DEST="${RAM_MEDIA_MNT}/live/filesystem.squashfs"
|
|
183
|
+
echo "BELL: copying $SQFS_SRC -> $SQFS_DEST..."
|
|
184
|
+
if command -v rsync >/dev/null; then
|
|
185
|
+
rsync -a --info=progress2 "$SQFS_SRC" "$SQFS_DEST"
|
|
186
|
+
else
|
|
187
|
+
cp "$SQFS_SRC" "$SQFS_DEST"
|
|
188
|
+
fi
|
|
189
|
+
SQFS_SIZE=$(du -h "$SQFS_DEST" | cut -f1)
|
|
190
|
+
echo "BELL: filesystem.squashfs ($SQFS_SIZE) copied to RAM."
|
|
191
|
+
|
|
192
|
+
# 4.5 copy .disk
|
|
193
|
+
if [ -d "${BELL_MEDIA_MNT}/.disk" ]; then
|
|
194
|
+
cp -a "${BELL_MEDIA_MNT}/.disk" "${RAM_MEDIA_MNT}/"
|
|
195
|
+
echo "BELL: .disk copied."
|
|
196
|
+
else
|
|
197
|
+
echo "BELL: Warning: .disk not found."
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# 4.6 Copy vmlinuz and initrd (we need to install the system)
|
|
201
|
+
cp -a "${BELL_MEDIA_MNT}/live/vmlinuz"* "${RAM_MEDIA_MNT}/live/" 2>/dev/null || true
|
|
202
|
+
cp -a "${BELL_MEDIA_MNT}/live/initrd"* "${RAM_MEDIA_MNT}/live/" 2>/dev/null || true
|
|
203
|
+
echo "BELL: Attempted kernel/initrd copy (any errors ignored)."
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
#################################################
|
|
207
|
+
# 6. Cleanup and Hand-off
|
|
208
|
+
echo "BELL: cleaning used mounts and devices..."
|
|
209
|
+
umount /mnt/ext4 || echo "BELL: WARN: umount /mnt/ext4 failed ($?)"
|
|
210
|
+
cryptsetup close live-root || echo "BELL: WARN: cryptsetup close live-root failed ($?)"
|
|
211
|
+
/sbin/losetup -d "$LOOP_DEV" || echo "BELL: WARN: losetup -d $LOOP_DEV failed ($?)"
|
|
212
|
+
umount "$BELL_MEDIA_MNT" || echo "BELL: WARN: umount ${BELL_MEDIA_MNT} failed ($?)"
|
|
213
|
+
echo "BELL: cleaning complete."
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# 6.1 switching to live boot
|
|
217
|
+
echo "BELL: live ISO image built in RAM on ${RAM_MEDIA_MNT}"
|
|
218
|
+
# ls -l "$RAM_MEDIA_MNT"
|
|
219
|
+
# ls -l "${RAM_MEDIA_MNT}/live"
|
|
220
|
+
exit 0
|