penguins-eggs 25.10.6 → 25.10.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oclif.manifest.json +51 -145
- package/README.md +3 -829
- package/addons/eggs/theme/livecd/isolinux.main.simple.cfg +3 -3
- package/conf/distros/trixie/calamares/modules/shellprocess@boot_deploy.yml +3 -4
- package/conf/love.yaml +1 -1
- package/dist/classes/distro.js +9 -2
- package/dist/classes/diversions.d.ts +1 -1
- package/dist/classes/diversions.js +27 -8
- package/dist/classes/incubation/incubator.d/archlinux.js +1 -0
- package/dist/classes/incubation/incubator.d/trixie.js +7 -10
- package/dist/classes/ovary.d/edit-live-fs.d.ts +1 -1
- package/dist/classes/ovary.d/edit-live-fs.js +1 -7
- package/dist/classes/ovary.d/fertilization.js +1 -0
- package/dist/classes/ovary.d/finished.js +1 -5
- package/dist/classes/ovary.d/initrd.d.ts +1 -1
- package/dist/classes/ovary.d/initrd.js +17 -19
- package/dist/classes/ovary.d/live-create-structure.js +1 -4
- package/dist/classes/ovary.d/luks-get-password.d.ts +12 -0
- package/dist/classes/ovary.d/luks-get-password.js +57 -0
- package/dist/classes/ovary.d/luks-home-support.d.ts +12 -0
- package/dist/classes/ovary.d/luks-home-support.js +75 -0
- package/dist/classes/ovary.d/luks-home.d.ts +15 -0
- package/dist/classes/ovary.d/luks-home.js +140 -0
- package/dist/classes/ovary.d/luks-root-bootstrap-builder.d.ts +11 -0
- package/dist/classes/ovary.d/luks-root-bootstrap-builder.js +45 -0
- package/dist/classes/ovary.d/luks-root.d.ts +15 -0
- package/dist/classes/ovary.d/luks-root.js +126 -0
- package/dist/classes/ovary.d/make-efi.js +1 -1
- package/dist/classes/ovary.d/make-squashfs.d.ts +1 -1
- package/dist/classes/ovary.d/make-squashfs.js +7 -3
- package/dist/classes/ovary.d/produce.d.ts +3 -3
- package/dist/classes/ovary.d/produce.js +76 -48
- package/dist/classes/ovary.d/syslinux.js +1 -1
- package/dist/classes/ovary.d/xorriso-command.d.ts +2 -2
- package/dist/classes/ovary.d/xorriso-command.js +27 -29
- package/dist/classes/ovary.d.ts +35 -16
- package/dist/classes/ovary.js +42 -16
- package/dist/classes/utils.d.ts +1 -0
- package/dist/classes/utils.js +3 -0
- package/dist/commands/config.d.ts +1 -1
- package/dist/commands/config.js +2 -2
- package/dist/commands/love.d.ts +3 -0
- package/dist/commands/love.js +40 -2
- package/dist/commands/produce.d.ts +3 -2
- package/dist/commands/produce.js +14 -17
- package/dist/commands/tools/{ppa.d.ts → repo.d.ts} +2 -2
- package/dist/commands/tools/{ppa.js → repo.js} +69 -67
- package/dracut/create-symlink +71 -0
- package/dracut/dracut-log.txt +3 -0
- package/dracut/dracut.conf.d/50-live.conf +24 -6
- package/dracut/dracut.conf.d/README.md +10 -0
- package/dracut/export +4 -0
- package/dracut/export-dracut-analysis +51 -0
- package/dracut/export-dracut-log +2 -0
- package/dracut/mkisofs +10 -0
- package/dracut/modules.d/00debug-shell/debug-hook.sh +13 -0
- package/dracut/modules.d/00debug-shell/module-setup.sh +20 -0
- package/dracut/modules.d/90block/README.md +7 -0
- package/dracut/modules.d/90block/block-cmdline.sh +3 -0
- package/dracut/modules.d/90block/module-setup.sh +15 -0
- package/dracut/modules.d/95iso-scan/README.md +3 -0
- package/dracut/modules.d/95iso-scan/iso-scan-fallback.sh +12 -0
- package/dracut/modules.d/95iso-scan/iso-scan.sh +92 -0
- package/dracut/modules.d/95iso-scan/module-setup.sh +18 -0
- package/dracut/modules.d/95luks-loop/README.md +9 -0
- package/dracut/modules.d/95luks-loop/luks-loop.sh +90 -0
- package/dracut/modules.d/95luks-loop/module-setup.sh +17 -0
- package/dracut/renew-initramfs +17 -0
- package/dracut/sbin2bin +10 -0
- package/dracut/update-dracut-conf-d +2 -0
- package/dracut/update-dracut-modules +62 -0
- package/manpages/doc/man/eggs.1.gz +0 -0
- package/manpages/doc/man/eggs.html +7 -661
- package/package.json +9 -8
- package/perrisbrewery/template/dependencies.yaml +6 -5
- package/scripts/_eggs +16 -31
- package/scripts/eggs.bash +4 -6
- package/scripts/luks-root-bootstrap-create.sh +235 -0
- package/scripts/luks-root-unlock.sh +172 -0
- package/scripts/mount-encrypted-home.sh +223 -0
- package/dist/commands/syncfrom.d.ts +0 -45
- package/dist/commands/syncfrom.js +0 -152
- package/dist/commands/syncto.d.ts +0 -40
- package/dist/commands/syncto.js +0 -175
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Script per sbloccare e montare home.img LUKS cifrato
|
|
3
|
+
# Con logging robusto e gestione errori
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Configurazione
|
|
8
|
+
HOME_IMG="__HOME_IMG_PATH__"
|
|
9
|
+
LUKS_NAME="live-home"
|
|
10
|
+
MOUNT_POINT="/home"
|
|
11
|
+
LOG_FILE="/var/log/mount-encrypted-home.log"
|
|
12
|
+
|
|
13
|
+
# Funzione di logging
|
|
14
|
+
log() {
|
|
15
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
log_error() {
|
|
19
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" | tee -a "$LOG_FILE" >&2
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Cleanup in caso di errore
|
|
23
|
+
cleanup() {
|
|
24
|
+
log "Cleanup in progress..."
|
|
25
|
+
if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then
|
|
26
|
+
umount "$MOUNT_POINT" 2>/dev/null || true
|
|
27
|
+
fi
|
|
28
|
+
if [ -e "/dev/mapper/$LUKS_NAME" ]; then
|
|
29
|
+
cryptsetup close "$LUKS_NAME" 2>/dev/null || true
|
|
30
|
+
fi
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
trap cleanup EXIT
|
|
34
|
+
|
|
35
|
+
log "=== Starting encrypted home mount process ==="
|
|
36
|
+
|
|
37
|
+
# Verifica memoria disponibile
|
|
38
|
+
AVAILABLE_MEM=$(free -m | awk '/^Mem:/{print $7}')
|
|
39
|
+
log "Available memory: ${AVAILABLE_MEM}MB"
|
|
40
|
+
|
|
41
|
+
if [ "$AVAILABLE_MEM" -lt 1024 ]; then
|
|
42
|
+
log_error "Low memory warning: only ${AVAILABLE_MEM}MB available"
|
|
43
|
+
log "This might cause issues with LUKS operations"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Attendi che il media sia disponibile (max 30 secondi)
|
|
47
|
+
log "Waiting for live media to be available..."
|
|
48
|
+
COUNTER=0
|
|
49
|
+
while [ ! -f "$HOME_IMG" ] && [ $COUNTER -lt 30 ]; do
|
|
50
|
+
sleep 1
|
|
51
|
+
COUNTER=$((COUNTER + 1))
|
|
52
|
+
done
|
|
53
|
+
|
|
54
|
+
if [ ! -f "$HOME_IMG" ]; then
|
|
55
|
+
log_error "home.img not found at $HOME_IMG after 30 seconds"
|
|
56
|
+
log "Available mounts:"
|
|
57
|
+
mount | grep live | tee -a "$LOG_FILE"
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
log "Found home.img at $HOME_IMG"
|
|
62
|
+
|
|
63
|
+
# Copia in RAM se è su media read-only
|
|
64
|
+
TEMP_HOME_IMG="/var/tmp/home.img" # /var/tmp è su overlay, non tmpfs
|
|
65
|
+
log "Copying home.img to RAM..."
|
|
66
|
+
cp "$HOME_IMG" "$TEMP_HOME_IMG"
|
|
67
|
+
HOME_IMG="$TEMP_HOME_IMG"
|
|
68
|
+
log "home.img copied to $HOME_IMG"
|
|
69
|
+
|
|
70
|
+
# Verifica dimensione file
|
|
71
|
+
IMG_SIZE=$(stat -c %s "$HOME_IMG")
|
|
72
|
+
log "home.img size: $((IMG_SIZE / 1024 / 1024))MB"
|
|
73
|
+
|
|
74
|
+
# Verifica dimensione file
|
|
75
|
+
IMG_SIZE=$(stat -c %s "$HOME_IMG")
|
|
76
|
+
log "home.img size: $((IMG_SIZE / 1024 / 1024))MB"
|
|
77
|
+
|
|
78
|
+
# Verifica se è un volume LUKS
|
|
79
|
+
if ! cryptsetup isLuks "$HOME_IMG" 2>&1 | tee -a "$LOG_FILE"; then
|
|
80
|
+
log_error "$HOME_IMG is not a valid LUKS volume"
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
log "Verified: home.img is a valid LUKS volume"
|
|
85
|
+
|
|
86
|
+
# Mostra prompt per la passphrase
|
|
87
|
+
echo ""
|
|
88
|
+
echo "╔════════════════════════════════════════╗"
|
|
89
|
+
echo "║ Encrypted Home Directory Detected ║"
|
|
90
|
+
echo "╚════════════════════════════════════════╝"
|
|
91
|
+
echo ""
|
|
92
|
+
echo "Please enter your passphrase to unlock your home directory"
|
|
93
|
+
echo "(Press Ctrl+C to skip and continue with temporary home)"
|
|
94
|
+
echo ""
|
|
95
|
+
|
|
96
|
+
echo "(Press Ctrl+C to skip and continue with temporary home)"
|
|
97
|
+
echo ""
|
|
98
|
+
|
|
99
|
+
# Aspetta che il TTY sia completamente inizializzato
|
|
100
|
+
sleep 2
|
|
101
|
+
|
|
102
|
+
# Prima del while loop dei tentativi
|
|
103
|
+
if [ -e "/dev/mapper/$LUKS_NAME" ]; then
|
|
104
|
+
log "LUKS device already exists, closing it first..."
|
|
105
|
+
cryptsetup close "$LUKS_NAME" 2>&1 | tee -a "$LOG_FILE" || true
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Tentativi multipli per la passphrase
|
|
109
|
+
MAX_ATTEMPTS=3
|
|
110
|
+
ATTEMPT=1
|
|
111
|
+
|
|
112
|
+
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
|
|
113
|
+
log "Unlock attempt $ATTEMPT of $MAX_ATTEMPTS"
|
|
114
|
+
|
|
115
|
+
if cryptsetup open "$HOME_IMG" "$LUKS_NAME" 2>&1 | tee -a "$LOG_FILE"; then
|
|
116
|
+
log "LUKS volume unlocked successfully"
|
|
117
|
+
break
|
|
118
|
+
else
|
|
119
|
+
log_error "Failed to unlock LUKS volume (attempt $ATTEMPT)"
|
|
120
|
+
|
|
121
|
+
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
|
|
122
|
+
log_error "Maximum attempts reached. Continuing without encrypted home."
|
|
123
|
+
echo ""
|
|
124
|
+
echo "╔════════════════════════════════════════╗"
|
|
125
|
+
echo "║ Failed to unlock encrypted home ║"
|
|
126
|
+
echo "║ System will continue with default ║"
|
|
127
|
+
echo "╚════════════════════════════════════════╝"
|
|
128
|
+
echo ""
|
|
129
|
+
sleep 3
|
|
130
|
+
exit 0
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
ATTEMPT=$((ATTEMPT + 1))
|
|
134
|
+
echo "Incorrect passphrase. Please try again ($ATTEMPT/$MAX_ATTEMPTS)"
|
|
135
|
+
echo ""
|
|
136
|
+
fi
|
|
137
|
+
done
|
|
138
|
+
|
|
139
|
+
# Verifica che il device mapper esista
|
|
140
|
+
if [ ! -e "/dev/mapper/$LUKS_NAME" ]; then
|
|
141
|
+
log_error "Device /dev/mapper/$LUKS_NAME not found after unlock"
|
|
142
|
+
exit 1
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
log "LUKS device available at /dev/mapper/$LUKS_NAME"
|
|
146
|
+
|
|
147
|
+
# Crea mount point
|
|
148
|
+
mkdir -p "$MOUNT_POINT"
|
|
149
|
+
|
|
150
|
+
# Monta il filesystem
|
|
151
|
+
log "Mounting decrypted volume to $MOUNT_POINT"
|
|
152
|
+
if mount "/dev/mapper/$LUKS_NAME" "$MOUNT_POINT" 2>&1 | tee -a "$LOG_FILE"; then
|
|
153
|
+
log "Home directory mounted successfully"
|
|
154
|
+
else
|
|
155
|
+
log_error "Failed to mount decrypted volume"
|
|
156
|
+
cryptsetup close "$LUKS_NAME"
|
|
157
|
+
exit 1
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Ripristina gli utenti se esistono
|
|
161
|
+
if [ -d "$MOUNT_POINT/.system-backup" ]; then
|
|
162
|
+
log "Restoring user accounts..."
|
|
163
|
+
|
|
164
|
+
# Rimuovi utente live temporaneo
|
|
165
|
+
if id live >/dev/null 2>&1; then
|
|
166
|
+
log "Removing temporary 'live' user"
|
|
167
|
+
userdel -r live 2>&1 | tee -a "$LOG_FILE" || true
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# Ripristina gli utenti
|
|
171
|
+
if [ -f "$MOUNT_POINT/.system-backup/passwd" ]; then
|
|
172
|
+
cat "$MOUNT_POINT/.system-backup/passwd" >> /etc/passwd
|
|
173
|
+
log "Restored $(wc -l < "$MOUNT_POINT/.system-backup/passwd") user entries"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
if [ -f "$MOUNT_POINT/.system-backup/shadow" ]; then
|
|
177
|
+
cat "$MOUNT_POINT/.system-backup/shadow" >> /etc/shadow
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# Ripristina gli utenti
|
|
181
|
+
if [ -f "$MOUNT_POINT/.system-backup/passwd" ]; then
|
|
182
|
+
cat "$MOUNT_POINT/.system-backup/passwd" >> /etc/passwd
|
|
183
|
+
log "Restored $(wc -l < "$MOUNT_POINT/.system-backup/passwd") user entries"
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
if [ -f "$MOUNT_POINT/.system-backup/shadow" ]; then
|
|
187
|
+
cat "$MOUNT_POINT/.system-backup/shadow" >> /etc/shadow
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Ripristina i gruppi (sostituisci completamente)
|
|
191
|
+
if [ -f "$MOUNT_POINT/.system-backup/group" ]; then
|
|
192
|
+
cp "$MOUNT_POINT/.system-backup/group" /etc/group
|
|
193
|
+
log "Restored group memberships"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
if [ -f "$MOUNT_POINT/.system-backup/gshadow" ]; then
|
|
197
|
+
cp "$MOUNT_POINT/.system-backup/gshadow" /etc/gshadow
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
log "User accounts restored successfully"
|
|
201
|
+
|
|
202
|
+
# Riavvia display manager per ricaricare gli utenti
|
|
203
|
+
log "Restarting display manager..."
|
|
204
|
+
if systemctl is-active --quiet gdm; then
|
|
205
|
+
systemctl restart gdm 2>&1 | tee -a "$LOG_FILE"
|
|
206
|
+
log "GDM restarted"
|
|
207
|
+
elif systemctl is-active --quiet lightdm; then
|
|
208
|
+
systemctl restart lightdm 2>&1 | tee -a "$LOG_FILE"
|
|
209
|
+
log "LightDM restarted"
|
|
210
|
+
elif systemctl is-active --quiet sddm; then
|
|
211
|
+
systemctl restart sddm 2>&1 | tee -a "$LOG_FILE"
|
|
212
|
+
log "SDDM restarted"
|
|
213
|
+
else
|
|
214
|
+
log "No active display manager found to restart"
|
|
215
|
+
fi
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
log "=== Encrypted home mount completed successfully ==="
|
|
219
|
+
|
|
220
|
+
# Non fare cleanup al successo
|
|
221
|
+
trap - EXIT
|
|
222
|
+
|
|
223
|
+
exit 0
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ./src/commands/syncfrom.ts
|
|
3
|
-
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
-
* author: Piero Proietti
|
|
5
|
-
* email: piero.proietti@gmail.com
|
|
6
|
-
* license: MIT
|
|
7
|
-
*/
|
|
8
|
-
import { Command } from '@oclif/core';
|
|
9
|
-
import { IRemix } from '../interfaces/index.js';
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
export default class Syncfrom extends Command {
|
|
14
|
-
static description: string;
|
|
15
|
-
static examples: string[];
|
|
16
|
-
static flags: {
|
|
17
|
-
delete: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
-
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
-
help: import("@oclif/core/interfaces").BooleanFlag<void>;
|
|
20
|
-
rootdir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
|
-
};
|
|
23
|
-
echo: {};
|
|
24
|
-
luksName: string;
|
|
25
|
-
luksDevice: string;
|
|
26
|
-
luksFile: string;
|
|
27
|
-
luksMountpoint: string;
|
|
28
|
-
remix: IRemix;
|
|
29
|
-
rootDir: string;
|
|
30
|
-
verbose: boolean;
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
*/
|
|
34
|
-
luksClose(): Promise<void>;
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
*/
|
|
38
|
-
luksOpen(): Promise<void>;
|
|
39
|
-
run(): Promise<void>;
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
* @param verbose
|
|
43
|
-
*/
|
|
44
|
-
private restorePrivateData;
|
|
45
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ./src/commands/syncfrom.ts
|
|
3
|
-
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
-
* author: Piero Proietti
|
|
5
|
-
* email: piero.proietti@gmail.com
|
|
6
|
-
* license: MIT
|
|
7
|
-
*/
|
|
8
|
-
import { Command, Flags } from '@oclif/core';
|
|
9
|
-
import fs from 'node:fs';
|
|
10
|
-
import path from 'node:path';
|
|
11
|
-
import Distro from '../classes/distro.js';
|
|
12
|
-
import Utils from '../classes/utils.js';
|
|
13
|
-
import { exec } from '../lib/utils.js';
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
*/
|
|
17
|
-
export default class Syncfrom extends Command {
|
|
18
|
-
static description = 'restore users and user data from a LUKS volumes';
|
|
19
|
-
static examples = ['sudo eggs syncfrom', 'sudo eggs syncfrom --file /path/to/luks-volume'];
|
|
20
|
-
static flags = {
|
|
21
|
-
delete: Flags.string({ description: 'rsync --delete delete extraneous files from dest dirs' }),
|
|
22
|
-
file: Flags.string({ char: 'f', description: 'file containing luks-volume encrypted' }),
|
|
23
|
-
help: Flags.help({ char: 'h' }),
|
|
24
|
-
rootdir: Flags.string({ char: 'r', description: 'rootdir of the installed system, when used from live' }),
|
|
25
|
-
verbose: Flags.boolean({ char: 'v', description: 'verbose' })
|
|
26
|
-
};
|
|
27
|
-
echo = {};
|
|
28
|
-
luksName = 'luks-volume';
|
|
29
|
-
luksDevice = `/dev/mapper/${this.luksName}`;
|
|
30
|
-
luksFile = '';
|
|
31
|
-
luksMountpoint = `/tmp/mnt/${this.luksName}`;
|
|
32
|
-
remix = {};
|
|
33
|
-
rootDir = '/';
|
|
34
|
-
verbose = false;
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
*/
|
|
38
|
-
async luksClose() {
|
|
39
|
-
if (Utils.isMountpoint(this.luksMountpoint)) {
|
|
40
|
-
await exec(`umount ${this.luksMountpoint}`, this.echo);
|
|
41
|
-
}
|
|
42
|
-
if (fs.existsSync(this.luksDevice)) {
|
|
43
|
-
Utils.warning(`LUKS close volume: ${this.luksName}`);
|
|
44
|
-
await exec(`cryptsetup luksClose ${this.luksName}`, this.echo);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
*/
|
|
50
|
-
async luksOpen() {
|
|
51
|
-
if (fs.existsSync(this.luksDevice)) {
|
|
52
|
-
Utils.warning(`LUKS volume: ${this.luksName} already open`);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
Utils.warning(`LUKS open volume: ${this.luksName}`);
|
|
56
|
-
await exec(`cryptsetup luksOpen --type luks2 ${this.luksFile} ${this.luksName}`, Utils.setEcho(true));
|
|
57
|
-
}
|
|
58
|
-
if (!fs.existsSync(this.luksMountpoint)) {
|
|
59
|
-
await exec(`mkdir -p ${this.luksMountpoint}`, this.echo);
|
|
60
|
-
}
|
|
61
|
-
if (Utils.isMountpoint(this.luksMountpoint)) {
|
|
62
|
-
Utils.warning(`mount volume: ${this.luksDevice} already mounted on ${this.luksMountpoint}`);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
Utils.warning(`mount volume: ${this.luksDevice} on ${this.luksMountpoint}`);
|
|
66
|
-
await exec(`mount ${this.luksDevice} ${this.luksMountpoint}`, this.echo);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async run() {
|
|
70
|
-
const { flags } = await this.parse(Syncfrom);
|
|
71
|
-
if (flags.verbose) {
|
|
72
|
-
this.verbose = true;
|
|
73
|
-
}
|
|
74
|
-
this.echo = Utils.setEcho(this.verbose);
|
|
75
|
-
let fileVolume = '';
|
|
76
|
-
if (flags.file) {
|
|
77
|
-
fileVolume = flags.file;
|
|
78
|
-
}
|
|
79
|
-
let destDelete = false;
|
|
80
|
-
if (flags.delete) {
|
|
81
|
-
destDelete = true;
|
|
82
|
-
}
|
|
83
|
-
if (Utils.isLive()) {
|
|
84
|
-
if (flags.rootdir) {
|
|
85
|
-
this.rootDir = flags.rootdir;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
Utils.pressKeyToExit('Argument --rootdir is mandatory, when running live! Process will terminate');
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (Utils.isRoot()) {
|
|
92
|
-
if (fileVolume === '') {
|
|
93
|
-
const distro = new Distro();
|
|
94
|
-
fileVolume = `${distro.liveMediumPath}live/${this.luksName}`;
|
|
95
|
-
}
|
|
96
|
-
if (Utils.isLive()) {
|
|
97
|
-
/**
|
|
98
|
-
* WORKING FROM LIVE
|
|
99
|
-
*/
|
|
100
|
-
this.luksName = path.basename(fileVolume);
|
|
101
|
-
this.luksFile = fileVolume;
|
|
102
|
-
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
103
|
-
this.luksMountpoint = `/tmp/${this.luksName}`;
|
|
104
|
-
await this.restorePrivateData();
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
/**
|
|
108
|
-
* WORKING FROM INSTALLED
|
|
109
|
-
*/
|
|
110
|
-
if (fs.existsSync(fileVolume)) {
|
|
111
|
-
this.luksName = path.basename(fileVolume);
|
|
112
|
-
this.luksFile = fileVolume;
|
|
113
|
-
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
114
|
-
this.luksMountpoint = `/tmp/${this.luksName}`;
|
|
115
|
-
await this.restorePrivateData();
|
|
116
|
-
if (await Utils.customConfirm('Your system was updated! Press a key to reboot')) {
|
|
117
|
-
await exec('reboot');
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
Utils.pressKeyToExit(`Can't find ${this.luksFile}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
Utils.useRoot(this.id);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
*
|
|
131
|
-
* @param verbose
|
|
132
|
-
*/
|
|
133
|
-
async restorePrivateData(destDelete = false) {
|
|
134
|
-
if (!fs.existsSync(this.luksMountpoint)) {
|
|
135
|
-
await exec(`mkdir ${this.luksMountpoint}`, this.echo);
|
|
136
|
-
}
|
|
137
|
-
await this.luksOpen();
|
|
138
|
-
if (Utils.isLive() && this.rootDir !== '/') {
|
|
139
|
-
Utils.warning('Restoring crypted data');
|
|
140
|
-
// Rimozione dei file esistenti
|
|
141
|
-
await exec(`rm -rf ${this.rootDir}/etc/lightdm/lightdm.conf`, this.echo);
|
|
142
|
-
await exec(`rm -rf ${this.rootDir}/etc/passwd`, this.echo);
|
|
143
|
-
await exec(`rm -rf ${this.rootDir}/etc/group`, this.echo);
|
|
144
|
-
await exec(`rm -rf ${this.rootDir}/etc/shadow`, this.echo);
|
|
145
|
-
await exec(`rm -rf ${this.rootDir}/home/*`, this.echo);
|
|
146
|
-
// unsquashfs
|
|
147
|
-
const cmd = `unsquashfs -d ${this.rootDir} -f ${this.luksMountpoint}/private.squashfs`;
|
|
148
|
-
await exec(cmd, Utils.setEcho(true));
|
|
149
|
-
}
|
|
150
|
-
await this.luksClose();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ./src/commands/syncto.ts
|
|
3
|
-
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
-
* author: Piero Proietti
|
|
5
|
-
* email: piero.proietti@gmail.com
|
|
6
|
-
* license: MIT
|
|
7
|
-
*/
|
|
8
|
-
import { Command } from '@oclif/core';
|
|
9
|
-
import Settings from '../classes/settings.js';
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
export default class Syncto extends Command {
|
|
14
|
-
static description: string;
|
|
15
|
-
static examples: string[];
|
|
16
|
-
static flags: {
|
|
17
|
-
excludes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
-
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
-
help: import("@oclif/core/interfaces").BooleanFlag<void>;
|
|
20
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
|
-
};
|
|
22
|
-
echo: {};
|
|
23
|
-
exclude: boolean;
|
|
24
|
-
excludeHome: string;
|
|
25
|
-
luksName: string;
|
|
26
|
-
luksDevice: string;
|
|
27
|
-
luksFile: string;
|
|
28
|
-
luksMountpoint: string;
|
|
29
|
-
privateSquashfs: string;
|
|
30
|
-
settings: Settings;
|
|
31
|
-
verbose: boolean;
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
*/
|
|
35
|
-
luksCreate(): Promise<void>;
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
-
*/
|
|
39
|
-
run(): Promise<void>;
|
|
40
|
-
}
|
package/dist/commands/syncto.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ./src/commands/syncto.ts
|
|
3
|
-
* penguins-eggs v.25.7.x / ecmascript 2020
|
|
4
|
-
* author: Piero Proietti
|
|
5
|
-
* email: piero.proietti@gmail.com
|
|
6
|
-
* license: MIT
|
|
7
|
-
*/
|
|
8
|
-
// https://gist.github.com/ansemjo/6f1cf9d9b8f7ce8f70813f52c63b74a6
|
|
9
|
-
import { Command, Flags } from '@oclif/core';
|
|
10
|
-
import fs from 'node:fs';
|
|
11
|
-
import Compressors from '../classes/compressors.js';
|
|
12
|
-
import Settings from '../classes/settings.js';
|
|
13
|
-
import Utils from '../classes/utils.js';
|
|
14
|
-
import { exec } from '../lib/utils.js';
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
18
|
-
export default class Syncto extends Command {
|
|
19
|
-
static description = "Save users and users' data ENCRYPTED";
|
|
20
|
-
static examples = ['sudo eggs syncto', 'sudo eggs syncto --file /path/to/luks-volume', 'sudo eggs syncto --excludes'];
|
|
21
|
-
static flags = {
|
|
22
|
-
excludes: Flags.boolean({ char: 'e', description: 'use: exclude.list.d/home.list' }),
|
|
23
|
-
file: Flags.string({ char: 'f', description: 'file luks-volume encrypted' }),
|
|
24
|
-
help: Flags.help({ char: 'h' }),
|
|
25
|
-
verbose: Flags.boolean({ char: 'v', description: 'verbose' })
|
|
26
|
-
};
|
|
27
|
-
echo = {};
|
|
28
|
-
exclude = false;
|
|
29
|
-
excludeHome = '/etc/penguins-eggs.d/exclude.list.d/home.list';
|
|
30
|
-
luksName = 'luks-volume';
|
|
31
|
-
luksDevice = `/dev/mapper/${this.luksName}`;
|
|
32
|
-
luksFile = `/tmp/${this.luksName}`;
|
|
33
|
-
luksMountpoint = `/tmp/mnt/${this.luksName}`;
|
|
34
|
-
privateSquashfs = `private.squashfs`;
|
|
35
|
-
settings = {};
|
|
36
|
-
verbose = false;
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
*/
|
|
40
|
-
async luksCreate() {
|
|
41
|
-
await exec(`rm -rf ${this.luksFile}`);
|
|
42
|
-
// ==========================================================================
|
|
43
|
-
// Create squashfs
|
|
44
|
-
// ==========================================================================
|
|
45
|
-
Utils.warning(`Creating private.squashfs`);
|
|
46
|
-
const compressors = new Compressors();
|
|
47
|
-
await compressors.populate();
|
|
48
|
-
// comp
|
|
49
|
-
let comp = '';
|
|
50
|
-
this.settings = new Settings();
|
|
51
|
-
if (await this.settings.load()) {
|
|
52
|
-
let compression = compressors.fast();
|
|
53
|
-
if (this.settings.config.compression == `max`) {
|
|
54
|
-
compression = compressors.max();
|
|
55
|
-
}
|
|
56
|
-
else if (this.settings.config.compression == `standard`) {
|
|
57
|
-
compression = compressors.standard();
|
|
58
|
-
}
|
|
59
|
-
comp = `-comp ${compression}`;
|
|
60
|
-
}
|
|
61
|
-
// exclude /home/eggs
|
|
62
|
-
let exclude_nest = '';
|
|
63
|
-
if (fs.existsSync(this.settings.work_dir.workdir)) {
|
|
64
|
-
exclude_nest = `-e ${this.settings.config.snapshot_dir}`;
|
|
65
|
-
}
|
|
66
|
-
// exclude file
|
|
67
|
-
let exclude_home = '';
|
|
68
|
-
if (this.exclude) {
|
|
69
|
-
exclude_home = `-ef ${this.excludeHome}`;
|
|
70
|
-
}
|
|
71
|
-
// creato dummyfs per /etc/
|
|
72
|
-
await exec(`mkdir -p /tmp/dummyfs/etc`, this.echo);
|
|
73
|
-
await exec(`cp -a /etc/passwd /tmp/dummyfs/etc`, this.echo);
|
|
74
|
-
await exec(`cp -a /etc/group /tmp/dummyfs/etc`, this.echo);
|
|
75
|
-
await exec(`cp -a /etc/shadow /tmp/dummyfs/etc`, this.echo);
|
|
76
|
-
await exec(`mkdir -p /tmp/dummyfs/etc/lightdm`, this.echo); // lightdm
|
|
77
|
-
await exec(`cp -a /etc/lightdm/lightdm.conf /tmp/dummyfs/etc/lightdm/`, this.echo); // lightdm
|
|
78
|
-
let mkPrivateSquashfs = `mksquashfs \
|
|
79
|
-
/tmp/dummyfs/etc \
|
|
80
|
-
/home \
|
|
81
|
-
/tmp/${this.privateSquashfs} \
|
|
82
|
-
${comp} \
|
|
83
|
-
${exclude_nest} \
|
|
84
|
-
${exclude_home} \
|
|
85
|
-
-keep-as-directory \
|
|
86
|
-
-noappend`;
|
|
87
|
-
mkPrivateSquashfs = mkPrivateSquashfs.replaceAll(/\s\s+/g, ` `);
|
|
88
|
-
await exec(mkPrivateSquashfs, Utils.setEcho(true));
|
|
89
|
-
// remove dummyfs
|
|
90
|
-
await exec(`rm /tmp/dummyfs/ -rf`, this.echo);
|
|
91
|
-
// ==========================================================================
|
|
92
|
-
// Create LUKS volume
|
|
93
|
-
// ==========================================================================
|
|
94
|
-
Utils.titles('Creating LUKS Volume');
|
|
95
|
-
// calcolo size
|
|
96
|
-
const sizeString = (await exec(`unsquashfs -s /tmp/${this.privateSquashfs} | grep "Filesystem size" | sed -e 's/.*size //' -e 's/ .*//'`, { capture: true, echo: false })).data;
|
|
97
|
-
let size = Number.parseInt(sizeString) + 2048;
|
|
98
|
-
console.log('size private.squashfs:', bytesToGB(size), size);
|
|
99
|
-
const luksBlockSize = 512;
|
|
100
|
-
const luksBlocks = Math.ceil(size / luksBlockSize);
|
|
101
|
-
size = luksBlockSize * luksBlocks;
|
|
102
|
-
// Aggiungo un 20% in più per ottenere luksSize
|
|
103
|
-
const luksSize = Math.ceil(size * 1.2);
|
|
104
|
-
console.log('luksSize:', bytesToGB(luksSize), luksSize);
|
|
105
|
-
// truncate * 2048 è cruciale
|
|
106
|
-
const truncateAt = luksSize * 2048;
|
|
107
|
-
Utils.warning(`Preparing file ${this.luksFile} for ${this.luksDevice}, size ${truncateAt}`);
|
|
108
|
-
await exec(`truncate --size ${luksSize} ${this.luksFile}`, this.echo);
|
|
109
|
-
Utils.warning(`Creating LUKS Volume on ${this.luksFile}`);
|
|
110
|
-
await exec(`cryptsetup --batch-mode luksFormat ${this.luksFile}`, Utils.setEcho(true));
|
|
111
|
-
console.log('');
|
|
112
|
-
// open LUKS volume temp
|
|
113
|
-
Utils.warning(`Opening LUKS Volume on ${this.luksFile}`);
|
|
114
|
-
const { code } = await exec(`cryptsetup luksOpen ${this.luksFile} ${this.luksName}`, Utils.setEcho(true));
|
|
115
|
-
if (code != 0) {
|
|
116
|
-
Utils.error(`cryptsetup luksOpen ${this.luksFile} ${this.luksName} failed`);
|
|
117
|
-
process.exit(code);
|
|
118
|
-
}
|
|
119
|
-
await exec('udevadm settle', this.echo);
|
|
120
|
-
// formatta ext4 il volume
|
|
121
|
-
await exec(`mkfs.ext4 ${this.luksDevice}`, this.echo);
|
|
122
|
-
console.log('');
|
|
123
|
-
// mount LUKS volume
|
|
124
|
-
if (!fs.existsSync(`this.luksMountpoint)`)) {
|
|
125
|
-
Utils.warning(`creating mountpoint ${this.luksMountpoint}`);
|
|
126
|
-
await exec(`mkdir -p ${this.luksMountpoint}`, this.echo);
|
|
127
|
-
}
|
|
128
|
-
if (!Utils.isMountpoint(`${this.luksMountpoint}`)) {
|
|
129
|
-
Utils.warning(`mounting volume: ${this.luksDevice} on ${this.luksMountpoint}`);
|
|
130
|
-
const { code } = await exec(`mount ${this.luksDevice} ${this.luksMountpoint}`, Utils.setEcho(true));
|
|
131
|
-
if (code != 0) {
|
|
132
|
-
Utils.error(`mount ${this.luksDevice} ${this.luksMountpoint} failed`);
|
|
133
|
-
process.exit(code);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// copy private.squashfs
|
|
137
|
-
Utils.warning(`moving /tmp/${this.privateSquashfs} to ${this.luksMountpoint}`);
|
|
138
|
-
await exec(`mv /tmp/${this.privateSquashfs} ${this.luksMountpoint}`, this.echo);
|
|
139
|
-
Utils.warning(`Umounting ${this.luksMountpoint}`);
|
|
140
|
-
await exec(`umount ${this.luksMountpoint}`, this.echo);
|
|
141
|
-
Utils.warning(`Vlosing ${this.luksMountpoint}`);
|
|
142
|
-
await exec(`cryptsetup luksClose ${this.luksName}`, this.echo);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
*/
|
|
147
|
-
async run() {
|
|
148
|
-
Utils.titles(this.id + ' ' + this.argv);
|
|
149
|
-
const { flags } = await this.parse(Syncto);
|
|
150
|
-
if (flags.verbose) {
|
|
151
|
-
this.verbose = true;
|
|
152
|
-
}
|
|
153
|
-
this.echo = Utils.setEcho(this.verbose);
|
|
154
|
-
let fileLuks = '';
|
|
155
|
-
if (flags.file) {
|
|
156
|
-
fileLuks = flags.file;
|
|
157
|
-
}
|
|
158
|
-
if (flags.excludes) {
|
|
159
|
-
this.exclude = true;
|
|
160
|
-
}
|
|
161
|
-
if (Utils.isRoot()) {
|
|
162
|
-
await this.luksCreate();
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
Utils.useRoot(this.id);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Convert bytes to gigabytes
|
|
171
|
-
*/
|
|
172
|
-
function bytesToGB(bytes) {
|
|
173
|
-
const gigabytes = bytes / 1_073_741_824;
|
|
174
|
-
return gigabytes.toFixed(2) + ' GB';
|
|
175
|
-
}
|