penguins-eggs 9.0.9 → 9.0.31
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/README.md +117 -20
- package/addons/eggs/theme/calamares/branding/show.qml +1 -1
- package/addons/eggs/theme/livecd/README.md +13 -15
- package/addons/eggs/theme/livecd/splash.png +0 -0
- package/addons/neon/theme/livecd/splash.png +0 -0
- package/addons/{blissos → telos}/theme/applications/install-debian.desktop +0 -0
- package/addons/{blissos → telos}/theme/artwork/install-debian.png +0 -0
- package/addons/telos/theme/calamares/branding/banner.png +0 -0
- package/addons/telos/theme/calamares/branding/branding.desc +25 -0
- package/addons/telos/theme/calamares/branding/show.qml +51 -0
- package/addons/telos/theme/calamares/branding/slide1.png +0 -0
- package/addons/telos/theme/calamares/branding/telos-logo.png +0 -0
- package/addons/telos/theme/calamares/branding/welcome.png +0 -0
- package/addons/{blissos → telos}/theme/calamares/modules/partition.yml +0 -0
- package/addons/{blissos → telos}/theme/livecd/grub.theme.cfg +2 -1
- package/addons/{blissos → telos}/theme/livecd/isolinux.theme.cfg +1 -1
- package/addons/telos/theme/livecd/splash.png +0 -0
- package/addons/templates/grub.template +2 -0
- package/addons/waydroid/theme/applications/install-debian.desktop +28 -0
- package/addons/waydroid/theme/artwork/install-debian.png +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/branding.desc +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/languages.png +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/show.qml +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/slide1.png +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/slide2.png +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/slide3.png +0 -0
- package/addons/{blissos/theme/calamares/branding/blissos-logo.png → waydroid/theme/calamares/branding/waydroid-logo.png} +0 -0
- package/addons/{blissos → waydroid}/theme/calamares/branding/welcome.png +0 -0
- package/addons/waydroid/theme/calamares/modules/partition.yml +233 -0
- package/addons/waydroid/theme/livecd/grub.theme.cfg +43 -0
- package/addons/waydroid/theme/livecd/isolinux.theme.cfg +45 -0
- package/addons/{blissos → waydroid}/theme/livecd/splash.png +0 -0
- package/conf/distros/buster/calamares/calamares-modules/sources-yolk/sources-yolk.sh +57 -38
- package/lib/classes/daddy.js +5 -5
- package/lib/classes/incubation/incubator.js +5 -0
- package/lib/classes/krill_install.d.ts +59 -30
- package/lib/classes/krill_install.js +596 -382
- package/lib/classes/krill_prepare.d.ts +7 -3
- package/lib/classes/krill_prepare.js +67 -26
- package/lib/classes/ovary.d.ts +33 -41
- package/lib/classes/ovary.js +400 -480
- package/lib/classes/systemctl.d.ts +36 -7
- package/lib/classes/systemctl.js +63 -28
- package/lib/classes/users.d.ts +21 -0
- package/lib/classes/users.js +129 -0
- package/lib/classes/utils.d.ts +8 -0
- package/lib/classes/utils.js +44 -15
- package/lib/classes/yolk.d.ts +6 -5
- package/lib/classes/yolk.js +30 -29
- package/lib/commands/analyze.d.ts +25 -0
- package/lib/commands/analyze.js +74 -0
- package/lib/commands/export/iso.js +1 -1
- package/lib/commands/install.d.ts +1 -0
- package/lib/commands/install.js +14 -3
- package/lib/commands/kill.js +1 -1
- package/lib/commands/produce.js +3 -3
- package/lib/commands/syncfrom.d.ts +37 -0
- package/lib/commands/syncfrom.js +156 -0
- package/lib/commands/syncto.d.ts +48 -0
- package/lib/commands/syncto.js +219 -0
- package/lib/components/elements/information.js +17 -1
- package/lib/components/partitions.d.ts +1 -2
- package/lib/components/partitions.js +1 -4
- package/lib/interfaces/i-analyze.d.ts +13 -0
- package/lib/interfaces/i-analyze.js +18 -0
- package/lib/interfaces/i-devices.d.ts +1 -0
- package/lib/interfaces/i-krill.d.ts +0 -1
- package/lib/lib/cli-autologin.js +8 -3
- package/lib/lib/select_installation_device.js +1 -0
- package/lib/lib/select_installation_mode.js +1 -1
- package/manpages/doc/man/eggs.html +65 -6
- package/oclif.manifest.json +1 -1
- package/package.json +19 -18
- package/scripts/_eggs +36 -6
- package/scripts/bros/waydroid-helper.sh +1 -1
- package/scripts/eggs.bash +4 -1
- package/scripts/{not-used/install-eggs-ppa.sh → install-eggs-ppa.sh} +1 -0
- package/scripts/mom-cli.sh +1 -1
- package/scripts/{not-used/pve-live.sh → pve-live.sh} +2 -6
- package/addons/blissos/theme/livecd/README.md +0 -23
- package/addons/eggs/theme/calamares/branding/4tation.png +0 -0
- package/addons/neon/theme/livecd/README.md +0 -23
- package/addons/neon/theme/livecd/splash.pcx +0 -0
- package/scripts/not-used/eggs-cleanup.sh +0 -7
- package/scripts/not-used/mkinitramfs +0 -469
- package/scripts/update-initramfs +0 -94
|
@@ -16,7 +16,7 @@ class ExportIso extends core_1.Command {
|
|
|
16
16
|
utils_1.default.warning(ExportIso.description);
|
|
17
17
|
await Tu.loadSettings();
|
|
18
18
|
if (flags.backup) {
|
|
19
|
-
Tu.snapshot_name = Tu.snapshot_name.slice(0, 7) === 'egg-of-' ? '
|
|
19
|
+
Tu.snapshot_name = Tu.snapshot_name.slice(0, 7) === 'egg-of-' ? 'egg-eb-' + Tu.snapshot_name.slice(7) : 'backup-' + Tu.snapshot_name;
|
|
20
20
|
}
|
|
21
21
|
let cmd = `ssh root@${Tu.config.remoteHost} rm -rf ${Tu.config.remotePathIso}${Tu.snapshot_name}*`;
|
|
22
22
|
if (flags.clean) {
|
|
@@ -12,6 +12,7 @@ export default class Install extends Command {
|
|
|
12
12
|
static flags: {
|
|
13
13
|
cli: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
crypted: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
pve: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
16
|
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
16
17
|
verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
17
18
|
};
|
package/lib/commands/install.js
CHANGED
|
@@ -23,26 +23,36 @@ class Install extends core_1.Command {
|
|
|
23
23
|
async run() {
|
|
24
24
|
utils_1.default.titles(this.id + ' ' + this.argv);
|
|
25
25
|
const { flags } = await this.parse(Install);
|
|
26
|
+
let cli = false;
|
|
27
|
+
if (flags.cli) {
|
|
28
|
+
cli = true;
|
|
29
|
+
}
|
|
26
30
|
let crypted = false;
|
|
27
31
|
if (flags.crypted) {
|
|
28
32
|
crypted = true;
|
|
29
33
|
}
|
|
34
|
+
let pve = false;
|
|
35
|
+
if (flags.pve) {
|
|
36
|
+
pve = true;
|
|
37
|
+
crypted = false;
|
|
38
|
+
cli = true;
|
|
39
|
+
}
|
|
30
40
|
let verbose = false;
|
|
31
41
|
if (flags.verbose) {
|
|
32
42
|
verbose = true;
|
|
33
43
|
}
|
|
34
44
|
if (utils_1.default.isRoot(this.id)) {
|
|
35
45
|
if (utils_1.default.isLive()) {
|
|
36
|
-
if (pacman_1.default.packageIsInstalled('calamares') && pacman_1.default.isRunningGui() && !
|
|
46
|
+
if (pacman_1.default.packageIsInstalled('calamares') && pacman_1.default.isRunningGui() && !cli) {
|
|
37
47
|
shelljs_1.default.exec('/usb/sbin/install-debian');
|
|
38
48
|
}
|
|
39
|
-
else if (pacman_1.default.packageIsInstalled('calamares') && !
|
|
49
|
+
else if (pacman_1.default.packageIsInstalled('calamares') && !cli) {
|
|
40
50
|
utils_1.default.warning('Calamares installer is present, start GUI and choose calamares to install the system');
|
|
41
51
|
utils_1.default.warning('If you still want to use krill, type: ' + chalk_1.default.bold('sudo eggs install --cli'));
|
|
42
52
|
}
|
|
43
53
|
else {
|
|
44
54
|
const krill = new krill_prepare_1.default();
|
|
45
|
-
await krill.prepare(crypted);
|
|
55
|
+
await krill.prepare(crypted, pve, verbose);
|
|
46
56
|
}
|
|
47
57
|
}
|
|
48
58
|
}
|
|
@@ -55,6 +65,7 @@ exports.default = Install;
|
|
|
55
65
|
Install.flags = {
|
|
56
66
|
cli: core_1.Flags.boolean({ char: 'c', description: 'force use CLI installer' }),
|
|
57
67
|
crypted: core_1.Flags.boolean({ char: 'k', description: 'crypted CLI installation' }),
|
|
68
|
+
pve: core_1.Flags.boolean({ char: 'p', description: 'Proxmox VE install' }),
|
|
58
69
|
help: core_1.Flags.help({ char: 'h' }),
|
|
59
70
|
verbose: core_1.Flags.boolean({ char: 'v', description: 'verbose' })
|
|
60
71
|
};
|
package/lib/commands/kill.js
CHANGED
|
@@ -32,7 +32,7 @@ class Kill extends core_1.Command {
|
|
|
32
32
|
await settings.load();
|
|
33
33
|
await settings.listFreeSpace();
|
|
34
34
|
if (await utils_1.default.customConfirm()) {
|
|
35
|
-
await (0, utils_2.exec)(`rm ${settings.work_dir.path} -rf`, echo);
|
|
35
|
+
await (0, utils_2.exec)(`rm ${settings.work_dir.path}/* -rf`, echo);
|
|
36
36
|
await (0, utils_2.exec)(`rm ${settings.config.snapshot_dir} -rf`, echo);
|
|
37
37
|
}
|
|
38
38
|
}
|
package/lib/commands/produce.js
CHANGED
|
@@ -125,9 +125,9 @@ class Produce extends core_1.Command {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
utils_1.default.titles(this.id + ' ' + this.argv);
|
|
128
|
-
const ovary = new ovary_1.default(
|
|
128
|
+
const ovary = new ovary_1.default();
|
|
129
129
|
utils_1.default.warning('Produce an egg...');
|
|
130
|
-
if (await ovary.fertilization()) {
|
|
130
|
+
if (await ovary.fertilization(prefix, basename, theme, compression)) {
|
|
131
131
|
await ovary.produce(backup, scriptOnly, yolkRenew, release, myAddons, verbose);
|
|
132
132
|
ovary.finished(scriptOnly);
|
|
133
133
|
}
|
|
@@ -150,7 +150,7 @@ Produce.flags = {
|
|
|
150
150
|
addons: core_1.Flags.string({ multiple: true, description: 'addons to be used: adapt, ichoice, pve, rsupport' }),
|
|
151
151
|
release: core_1.Flags.boolean({ description: 'release: configure GUI installer to remove eggs and calamares after installation' })
|
|
152
152
|
};
|
|
153
|
-
Produce.description = '
|
|
153
|
+
Produce.description = 'produce a live image from your system whithout your data';
|
|
154
154
|
Produce.aliases = ['spawn', 'lay'];
|
|
155
155
|
Produce.examples = [
|
|
156
156
|
'$ sudo eggs produce \nproduce an ISO called [hostname]-[arch]-YYYY-MM-DD_HHMM.iso, compressed xz (standard compression).\nIf hostname=ugo and arch=i386 ugo-x86-2020-08-25_1215.iso\n',
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* penguins-eggs-v9
|
|
3
|
+
* author: Piero Proietti
|
|
4
|
+
* email: piero.proietti@gmail.com
|
|
5
|
+
* license: MIT
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from '@oclif/core';
|
|
8
|
+
export default class Syncfrom extends Command {
|
|
9
|
+
luksName: string;
|
|
10
|
+
luksFile: string;
|
|
11
|
+
luksDevice: string;
|
|
12
|
+
luksMountpoint: string;
|
|
13
|
+
rootDir: string;
|
|
14
|
+
static description: string;
|
|
15
|
+
static flags: {
|
|
16
|
+
file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
17
|
+
rootdir: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
18
|
+
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
19
|
+
verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
};
|
|
21
|
+
static aliases: string[];
|
|
22
|
+
static examples: string[];
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param verbose
|
|
27
|
+
*/
|
|
28
|
+
private restorePrivateData;
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
luksOpen(verbose?: boolean): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
luksClose(verbose?: boolean): Promise<void>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
/**
|
|
5
|
+
* penguins-eggs-v9
|
|
6
|
+
* author: Piero Proietti
|
|
7
|
+
* email: piero.proietti@gmail.com
|
|
8
|
+
* license: MIT
|
|
9
|
+
*/
|
|
10
|
+
const core_1 = require("@oclif/core");
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const utils_1 = (0, tslib_1.__importDefault)(require("../classes/utils"));
|
|
14
|
+
const utils_2 = require("../lib/utils");
|
|
15
|
+
class Syncfrom extends core_1.Command {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.luksName = 'luks-eggs-backup';
|
|
19
|
+
this.luksFile = `/run/live/medium/live/${this.luksName}`;
|
|
20
|
+
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
21
|
+
this.luksMountpoint = '/tmp/eggs-backup';
|
|
22
|
+
this.rootDir = '';
|
|
23
|
+
}
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(Syncfrom);
|
|
26
|
+
let verbose = false;
|
|
27
|
+
if (flags.verbose) {
|
|
28
|
+
verbose = true;
|
|
29
|
+
}
|
|
30
|
+
let fileVolume = '';
|
|
31
|
+
if (flags.file) {
|
|
32
|
+
fileVolume = flags.file;
|
|
33
|
+
}
|
|
34
|
+
if (utils_1.default.isLive()) {
|
|
35
|
+
if (flags.rootdir) {
|
|
36
|
+
this.rootDir = flags.rootdir;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
utils_1.default.warning(`Argument --rootdir is mandatory, when running from live! Process will terminate`);
|
|
40
|
+
process.exit();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.rootDir = '/';
|
|
45
|
+
}
|
|
46
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
47
|
+
if (utils_1.default.isRoot(this.id)) {
|
|
48
|
+
if (fileVolume === '') {
|
|
49
|
+
fileVolume = '/run/live/medium/live/luks-eggs-backup';
|
|
50
|
+
}
|
|
51
|
+
if (!utils_1.default.isLive()) {
|
|
52
|
+
/**
|
|
53
|
+
* WORKING FROM INSTALLED
|
|
54
|
+
*/
|
|
55
|
+
if (fs.existsSync(fileVolume)) {
|
|
56
|
+
this.luksName = path.basename(fileVolume);
|
|
57
|
+
this.luksFile = fileVolume;
|
|
58
|
+
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
59
|
+
this.luksMountpoint = '/tmp/eggs-backup';
|
|
60
|
+
await this.restorePrivateData(verbose);
|
|
61
|
+
if (await utils_1.default.customConfirm(`Your system was updated! Press a key to reboot`)) {
|
|
62
|
+
await (0, utils_2.exec)('reboot');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
utils_1.default.warning(`Can't find ${this.luksFile}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
/**
|
|
71
|
+
* WORKING FROM LIVE
|
|
72
|
+
*/
|
|
73
|
+
this.luksName = path.basename(fileVolume);
|
|
74
|
+
this.luksFile = fileVolume;
|
|
75
|
+
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
76
|
+
this.luksMountpoint = '/tmp/eggs-backup';
|
|
77
|
+
await this.restorePrivateData(verbose);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @param verbose
|
|
84
|
+
*/
|
|
85
|
+
async restorePrivateData(verbose = false) {
|
|
86
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
87
|
+
if (!fs.existsSync(this.luksMountpoint)) {
|
|
88
|
+
await (0, utils_2.exec)(`mkdir ${this.luksMountpoint}`);
|
|
89
|
+
}
|
|
90
|
+
await this.luksOpen();
|
|
91
|
+
/**
|
|
92
|
+
* ONLY FROM LIVE
|
|
93
|
+
* rm home, subst /etc/passwd, /etc/shadow, /etc/groups
|
|
94
|
+
*/
|
|
95
|
+
if (utils_1.default.isLive()) {
|
|
96
|
+
if (this.rootDir !== '/') {
|
|
97
|
+
utils_1.default.warning('Removing live user on destination system');
|
|
98
|
+
await (0, utils_2.exec)(`rm -rf ${this.rootDir}/home/*`, echo);
|
|
99
|
+
utils_1.default.warning('Restoring accounts');
|
|
100
|
+
await (0, utils_2.exec)(`cp ${this.luksMountpoint}/etc/passwd ${this.rootDir}/etc/`, echo);
|
|
101
|
+
await (0, utils_2.exec)(`cp ${this.luksMountpoint}/etc/shadow ${this.rootDir}/etc/`, echo);
|
|
102
|
+
await (0, utils_2.exec)(`cp ${this.luksMountpoint}/etc/group ${this.rootDir}/etc/`, echo);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
utils_1.default.warning('Restoring backup data');
|
|
106
|
+
await (0, utils_2.exec)(`rsync -a ${this.luksMountpoint}/ROOT/ ${this.rootDir}/`, echo);
|
|
107
|
+
await this.luksClose();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
*/
|
|
112
|
+
async luksOpen(verbose = false) {
|
|
113
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
114
|
+
const echoYes = utils_1.default.setEcho(true); // echoYes serve solo per cryptsetup luksOpen
|
|
115
|
+
if (!fs.existsSync(this.luksDevice)) {
|
|
116
|
+
utils_1.default.warning(`LUKS open volume: ${this.luksName}`);
|
|
117
|
+
await (0, utils_2.exec)(`cryptsetup luksOpen --type luks2 ${this.luksFile} ${this.luksName}`, echoYes);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
utils_1.default.warning(`LUKS volume: ${this.luksName} already open`);
|
|
121
|
+
}
|
|
122
|
+
if (!fs.existsSync(this.luksMountpoint)) {
|
|
123
|
+
await (0, utils_2.exec)(`mkdir -p ${this.luksMountpoint}`, echo);
|
|
124
|
+
}
|
|
125
|
+
if (!utils_1.default.isMountpoint(this.luksMountpoint)) {
|
|
126
|
+
utils_1.default.warning(`mount volume: ${this.luksDevice} on ${this.luksMountpoint}`);
|
|
127
|
+
await (0, utils_2.exec)(`mount ${this.luksDevice} ${this.luksMountpoint}`, echo);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
utils_1.default.warning(`mount volume: ${this.luksDevice} already mounted on ${this.luksMountpoint}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
*/
|
|
136
|
+
async luksClose(verbose = false) {
|
|
137
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
138
|
+
if (utils_1.default.isMountpoint(this.luksMountpoint)) {
|
|
139
|
+
await (0, utils_2.exec)(`umount ${this.luksMountpoint}`, echo);
|
|
140
|
+
}
|
|
141
|
+
if (fs.existsSync(this.luksDevice)) {
|
|
142
|
+
utils_1.default.warning(`LUKS close volume: ${this.luksName}`);
|
|
143
|
+
await (0, utils_2.exec)(`cryptsetup luksClose ${this.luksName}`, echo);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.default = Syncfrom;
|
|
148
|
+
Syncfrom.description = 'Restore users, server and datas from luks-eggs-backup';
|
|
149
|
+
Syncfrom.flags = {
|
|
150
|
+
file: core_1.Flags.string({ char: 'f', description: "file with LUKS volume encrypted" }),
|
|
151
|
+
rootdir: core_1.Flags.string({ char: 'r', description: 'rootdir of the installed system, when used from live' }),
|
|
152
|
+
help: core_1.Flags.help({ char: 'h' }),
|
|
153
|
+
verbose: core_1.Flags.boolean({ char: 'v', description: 'verbose' })
|
|
154
|
+
};
|
|
155
|
+
Syncfrom.aliases = ['restore'];
|
|
156
|
+
Syncfrom.examples = ['$ sudo eggs restore'];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* penguins-eggs-v9
|
|
3
|
+
* author: Piero Proietti
|
|
4
|
+
* email: piero.proietti@gmail.com
|
|
5
|
+
* license: MIT
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from '@oclif/core';
|
|
8
|
+
import Users from '../classes/users';
|
|
9
|
+
export default class Syncto extends Command {
|
|
10
|
+
luksName: string;
|
|
11
|
+
luksFile: string;
|
|
12
|
+
luksDevice: string;
|
|
13
|
+
luksMountpoint: string;
|
|
14
|
+
static description: string;
|
|
15
|
+
static flags: {
|
|
16
|
+
krill: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
file: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
|
|
18
|
+
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
19
|
+
verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
};
|
|
21
|
+
static aliases: string[];
|
|
22
|
+
static examples: string[];
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
run(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param verbose
|
|
30
|
+
*/
|
|
31
|
+
backup(verbose?: boolean): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* usersFill
|
|
34
|
+
*/
|
|
35
|
+
usersFill(): Promise<Users[]>;
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
luksCreate(verbose?: boolean): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
luksOpen(verbose?: boolean): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
luksClose(verbose?: boolean): Promise<void>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
/**
|
|
5
|
+
* penguins-eggs-v9
|
|
6
|
+
* author: Piero Proietti
|
|
7
|
+
* email: piero.proietti@gmail.com
|
|
8
|
+
* license: MIT
|
|
9
|
+
*/
|
|
10
|
+
const core_1 = require("@oclif/core");
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const utils_1 = (0, tslib_1.__importDefault)(require("../classes/utils"));
|
|
14
|
+
const utils_2 = require("../lib/utils");
|
|
15
|
+
// backup
|
|
16
|
+
const promises_1 = require("fs/promises");
|
|
17
|
+
const fs_1 = require("fs");
|
|
18
|
+
const users_1 = (0, tslib_1.__importDefault)(require("../classes/users"));
|
|
19
|
+
class Syncto extends core_1.Command {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.luksName = 'luks-eggs-backup';
|
|
23
|
+
this.luksFile = `/run/live/medium/live/${this.luksName}`;
|
|
24
|
+
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
25
|
+
this.luksMountpoint = '/tmp/eggs-backup';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
async run() {
|
|
31
|
+
const { flags } = await this.parse(Syncto);
|
|
32
|
+
let verbose = false;
|
|
33
|
+
if (flags.verbose) {
|
|
34
|
+
verbose = true;
|
|
35
|
+
}
|
|
36
|
+
let fileVolume = '';
|
|
37
|
+
if (flags.file) {
|
|
38
|
+
fileVolume = flags.file;
|
|
39
|
+
}
|
|
40
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
41
|
+
if (utils_1.default.isRoot(this.id)) {
|
|
42
|
+
/**
|
|
43
|
+
* restore con file
|
|
44
|
+
*/
|
|
45
|
+
if (fileVolume === '') {
|
|
46
|
+
fileVolume = '/tmp/luks-eggs-backup';
|
|
47
|
+
}
|
|
48
|
+
this.luksName = path.basename(fileVolume);
|
|
49
|
+
this.luksFile = fileVolume;
|
|
50
|
+
this.luksDevice = `/dev/mapper/${this.luksName}`;
|
|
51
|
+
this.luksMountpoint = '/tmp/eggs-backup';
|
|
52
|
+
if (!fs.existsSync(fileVolume)) {
|
|
53
|
+
await this.luksCreate(verbose);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
utils_1.default.warning(`LUKS volume: ${this.luksFile} exist, don't need create`);
|
|
57
|
+
}
|
|
58
|
+
if (fs.existsSync(fileVolume)) {
|
|
59
|
+
await this.luksOpen(verbose);
|
|
60
|
+
await this.backup(verbose);
|
|
61
|
+
await this.luksClose(verbose);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param verbose
|
|
68
|
+
*/
|
|
69
|
+
async backup(verbose = false) {
|
|
70
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
71
|
+
if (verbose) {
|
|
72
|
+
utils_1.default.warning('backup');
|
|
73
|
+
}
|
|
74
|
+
const usersArray = await this.usersFill();
|
|
75
|
+
const cmds = [];
|
|
76
|
+
for (let i = 0; i < usersArray.length; i++) {
|
|
77
|
+
if (usersArray[i].saveIt) {
|
|
78
|
+
if (fs.existsSync(usersArray[i].home)) {
|
|
79
|
+
await (0, utils_2.exec)(`mkdir -p ${this.luksMountpoint}/ROOT${usersArray[i].home}`, echo);
|
|
80
|
+
const source = usersArray[i].home;
|
|
81
|
+
let dest = this.luksMountpoint + '/ROOT' + usersArray[i].home;
|
|
82
|
+
dest = dest.substring(0, dest.lastIndexOf('/'));
|
|
83
|
+
await (0, utils_2.exec)(`rsync --archive ${source} ${dest}`, echo);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await (0, utils_2.exec)(`mkdir -p ${this.luksMountpoint}/etc`, echo);
|
|
88
|
+
await (0, utils_2.exec)(`cp /etc/passwd ${this.luksMountpoint}/etc`, echo);
|
|
89
|
+
await (0, utils_2.exec)(`cp /etc/shadow ${this.luksMountpoint}/etc`, echo);
|
|
90
|
+
await (0, utils_2.exec)(`cp /etc/group ${this.luksMountpoint}/etc`, echo);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* usersFill
|
|
94
|
+
*/
|
|
95
|
+
async usersFill() {
|
|
96
|
+
const usersArray = [];
|
|
97
|
+
await (0, promises_1.access)('/etc/passwd', fs_1.constants.R_OK | fs_1.constants.W_OK);
|
|
98
|
+
const passwd = fs.readFileSync('/etc/passwd', 'utf-8').split('\n');
|
|
99
|
+
for (let i = 0; i < passwd.length; i++) {
|
|
100
|
+
var line = passwd[i].split(':');
|
|
101
|
+
const users = new users_1.default(line[0], line[1], line[2], line[3], line[4], line[5], line[6]);
|
|
102
|
+
await users.getValues();
|
|
103
|
+
if (users.password !== undefined) {
|
|
104
|
+
usersArray.push(users);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return usersArray;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
*/
|
|
112
|
+
async luksCreate(verbose = false) {
|
|
113
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
114
|
+
const echoYes = utils_1.default.setEcho(true);
|
|
115
|
+
utils_1.default.warning(`Creating LUKS Volume on ${this.luksFile}`);
|
|
116
|
+
let totalSize = 0;
|
|
117
|
+
console.log(`I will extimate volume size from your private data:`);
|
|
118
|
+
const users = await this.usersFill();
|
|
119
|
+
for (let i = 0; i < users.length; i++) {
|
|
120
|
+
if (users[i].login !== 'root') {
|
|
121
|
+
if (users[i].saveIt) {
|
|
122
|
+
console.log(`user: ${users[i].login} \thome: ${users[i].home.padEnd(16)} \tsize: ${utils_1.default.formatBytes(users[i].size)} \tBytes: ${users[i].size} `);
|
|
123
|
+
totalSize += users[i].size;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
console.log(`Total\t\t\t\t\tSize: ${utils_1.default.formatBytes(totalSize)} \tBytes: ${totalSize}`);
|
|
128
|
+
/**
|
|
129
|
+
* after we get size, we can start building luks-volume
|
|
130
|
+
*/
|
|
131
|
+
const binaryHeaderSize = 4194304;
|
|
132
|
+
let volumeSize = totalSize * 1.2 + binaryHeaderSize;
|
|
133
|
+
// Deciding blockSize and blocks
|
|
134
|
+
let blockSize = 1024;
|
|
135
|
+
let blocks = Math.ceil(volumeSize / blockSize);
|
|
136
|
+
// We need a minimum size of 32 MB
|
|
137
|
+
let minimunSize = 134217728; // 128 * 1024 *1024
|
|
138
|
+
if (totalSize < minimunSize) {
|
|
139
|
+
}
|
|
140
|
+
if (blocks * blockSize < minimunSize) {
|
|
141
|
+
blocks = Math.ceil(minimunSize / blockSize);
|
|
142
|
+
}
|
|
143
|
+
utils_1.default.warning(`Creating an encrypted file ${this.luksFile} blocks=${blocks}, block size: ${blockSize}, size: ${utils_1.default.formatBytes(blocks * blockSize)}`);
|
|
144
|
+
await (0, utils_2.exec)(`dd if=/dev/zero of=${this.luksFile} bs=${blockSize} count=${blocks}`, echo);
|
|
145
|
+
// find first unused device
|
|
146
|
+
let findFirstUnusedDevice = await (0, utils_2.exec)(`losetup -f`, { echo: verbose, ignore: false, capture: true });
|
|
147
|
+
let firstUnusedDevice = '';
|
|
148
|
+
if (findFirstUnusedDevice.code !== 0) {
|
|
149
|
+
utils_1.default.warning(`Error: ${findFirstUnusedDevice.code} ${findFirstUnusedDevice.data}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
firstUnusedDevice = findFirstUnusedDevice.data.trim();
|
|
154
|
+
}
|
|
155
|
+
await (0, utils_2.exec)(`losetup ${firstUnusedDevice} ${this.luksFile}`, echo);
|
|
156
|
+
utils_1.default.warning('Enter a large string of random text below to setup the pre-encryption');
|
|
157
|
+
await (0, utils_2.exec)(`cryptsetup -y -v --type luks2 luksFormat ${this.luksFile}`, echoYes);
|
|
158
|
+
utils_1.default.warning(`Enter the desired passphrase for the encrypted ${this.luksName} below`);
|
|
159
|
+
let crytoSetup = await (0, utils_2.exec)(`cryptsetup luksOpen --type luks2 ${this.luksFile} ${this.luksName}`, echoYes);
|
|
160
|
+
if (crytoSetup.code !== 0) {
|
|
161
|
+
utils_1.default.warning(`Error: ${crytoSetup.code} ${crytoSetup.data}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
utils_1.default.warning(`Formatting ${this.luksDevice} to ext2`);
|
|
165
|
+
let formatting = await (0, utils_2.exec)(`sudo mkfs.ext2 ${this.luksDevice}`, echo);
|
|
166
|
+
if (formatting.code !== 0) {
|
|
167
|
+
utils_1.default.warning(`Error: ${formatting.code} ${formatting.data}`);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
// this.luksClose()
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
*
|
|
174
|
+
*/
|
|
175
|
+
async luksOpen(verbose = false) {
|
|
176
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
177
|
+
const echoYes = utils_1.default.setEcho(true); // echoYes serve solo per cryptsetup luksOpen
|
|
178
|
+
if (!fs.existsSync(this.luksDevice)) {
|
|
179
|
+
utils_1.default.warning(`LUKS open volume: ${this.luksName}`);
|
|
180
|
+
await (0, utils_2.exec)(`cryptsetup luksOpen --type luks2 ${this.luksFile} ${this.luksName}`, echoYes);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
utils_1.default.warning(`LUKS volume: ${this.luksName} already open`);
|
|
184
|
+
}
|
|
185
|
+
if (!fs.existsSync(this.luksMountpoint)) {
|
|
186
|
+
await (0, utils_2.exec)(`mkdir -p ${this.luksMountpoint}`, echo);
|
|
187
|
+
}
|
|
188
|
+
if (!utils_1.default.isMountpoint(this.luksMountpoint)) {
|
|
189
|
+
utils_1.default.warning(`mount volume: ${this.luksDevice} on ${this.luksMountpoint}`);
|
|
190
|
+
await (0, utils_2.exec)(`mount ${this.luksDevice} ${this.luksMountpoint}`, echo);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
utils_1.default.warning(`mount volume: ${this.luksDevice} already mounted on ${this.luksMountpoint}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
*
|
|
198
|
+
*/
|
|
199
|
+
async luksClose(verbose = false) {
|
|
200
|
+
const echo = utils_1.default.setEcho(verbose);
|
|
201
|
+
if (utils_1.default.isMountpoint(this.luksMountpoint)) {
|
|
202
|
+
await (0, utils_2.exec)(`umount ${this.luksMountpoint}`, echo);
|
|
203
|
+
}
|
|
204
|
+
if (fs.existsSync(this.luksDevice)) {
|
|
205
|
+
utils_1.default.warning(`LUKS close volume: ${this.luksName}`);
|
|
206
|
+
await (0, utils_2.exec)(`cryptsetup luksClose ${this.luksName}`, echo);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.default = Syncto;
|
|
211
|
+
Syncto.description = 'Backup users, server and datas to luks-eggs-backup';
|
|
212
|
+
Syncto.flags = {
|
|
213
|
+
krill: core_1.Flags.boolean({ char: 'k', description: 'krill' }),
|
|
214
|
+
file: core_1.Flags.string({ char: 'f', description: "file LUKS volume encrypted" }),
|
|
215
|
+
help: core_1.Flags.help({ char: 'h' }),
|
|
216
|
+
verbose: core_1.Flags.boolean({ char: 'v', description: 'verbose' })
|
|
217
|
+
};
|
|
218
|
+
Syncto.aliases = ['backup'];
|
|
219
|
+
Syncto.examples = ['$ sudo eggs restore'];
|
|
@@ -104,6 +104,18 @@ async function information(verbose = false) {
|
|
|
104
104
|
(0, ink_1.render)(react_1.default.createElement(CLI, null));
|
|
105
105
|
const GUI = () => (react_1.default.createElement(ink_1.Text, { backgroundColor: "green" }, "GUI"));
|
|
106
106
|
(0, ink_1.render)(react_1.default.createElement(GUI, null));
|
|
107
|
+
let initType = '';
|
|
108
|
+
if (utils_1.default.isSysvinit()) {
|
|
109
|
+
initType = 'sysvinit';
|
|
110
|
+
}
|
|
111
|
+
if (utils_1.default.isSystemd()) {
|
|
112
|
+
if (initType === 'sysvinit') {
|
|
113
|
+
initType += '/';
|
|
114
|
+
}
|
|
115
|
+
initType = 'systemd';
|
|
116
|
+
}
|
|
117
|
+
const sysvinit = utils_1.default.isSysvinit();
|
|
118
|
+
const systemd = utils_1.default.isSystemd();
|
|
107
119
|
const Checks = () => (react_1.default.createElement(ink_1.Box, { borderStyle: "round", marginRight: 2, flexDirection: "row" },
|
|
108
120
|
react_1.default.createElement(ink_1.Box, { marginRight: 2 },
|
|
109
121
|
react_1.default.createElement(ink_1.Text, null,
|
|
@@ -120,7 +132,11 @@ async function information(verbose = false) {
|
|
|
120
132
|
react_1.default.createElement(ink_1.Box, { marginRight: 2 },
|
|
121
133
|
react_1.default.createElement(ink_1.Text, null,
|
|
122
134
|
"uefi: ",
|
|
123
|
-
uefi ? react_1.default.createElement(Ok, null) : react_1.default.createElement(Ko, null)))
|
|
135
|
+
uefi ? react_1.default.createElement(Ok, null) : react_1.default.createElement(Ko, null))),
|
|
136
|
+
react_1.default.createElement(ink_1.Box, { marginRight: 2 },
|
|
137
|
+
react_1.default.createElement(ink_1.Text, null,
|
|
138
|
+
"init: ",
|
|
139
|
+
react_1.default.createElement(ink_1.Text, { color: "cyan" }, initType)))));
|
|
124
140
|
(0, ink_1.render)(react_1.default.createElement(Checks, null));
|
|
125
141
|
const Presentation = () => (react_1.default.createElement(react_1.default.Fragment, null,
|
|
126
142
|
react_1.default.createElement(ink_1.Box, null,
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
declare type partitionsProps = {
|
|
3
3
|
installationDevice?: string;
|
|
4
4
|
installationMode?: string;
|
|
5
|
-
luksPassphrase: string;
|
|
6
5
|
filesystemType?: string;
|
|
7
6
|
userSwapChoice?: string;
|
|
8
7
|
};
|
|
9
|
-
export default function Partitions({ installationDevice, installationMode,
|
|
8
|
+
export default function Partitions({ installationDevice, installationMode, filesystemType, userSwapChoice }: partitionsProps): JSX.Element;
|
|
10
9
|
export {};
|
|
@@ -10,7 +10,7 @@ const title_1 = (0, tslib_1.__importDefault)(require("./elements/title"));
|
|
|
10
10
|
const steps_1 = (0, tslib_1.__importDefault)(require("./elements/steps"));
|
|
11
11
|
const js_yaml_1 = (0, tslib_1.__importDefault)(require("js-yaml"));
|
|
12
12
|
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
13
|
-
function Partitions({ installationDevice, installationMode,
|
|
13
|
+
function Partitions({ installationDevice, installationMode, filesystemType, userSwapChoice }) {
|
|
14
14
|
let installer = 'krill';
|
|
15
15
|
let productName = 'unknown';
|
|
16
16
|
let version = 'x.x.x';
|
|
@@ -63,9 +63,6 @@ function Partitions({ installationDevice, installationMode, luksPassphrase, file
|
|
|
63
63
|
react_1.default.createElement(ink_1.Box, null,
|
|
64
64
|
react_1.default.createElement(ink_1.Text, null, "Installation mode: "),
|
|
65
65
|
react_1.default.createElement(ink_1.Text, { color: "cyan" }, installationMode)),
|
|
66
|
-
react_1.default.createElement(ink_1.Box, null,
|
|
67
|
-
react_1.default.createElement(ink_1.Text, null, "LUKS passphrase: "),
|
|
68
|
-
react_1.default.createElement(ink_1.Text, { color: "cyan" }, luksPassphrase)),
|
|
69
66
|
react_1.default.createElement(ink_1.Box, null,
|
|
70
67
|
react_1.default.createElement(ink_1.Text, null, "Filesystem: "),
|
|
71
68
|
react_1.default.createElement(ink_1.Text, { color: "cyan" }, filesystemType)),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Al momento
|
|
5
|
+
*/
|
|
6
|
+
class IAnalyze {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.login = '';
|
|
9
|
+
this.password = '';
|
|
10
|
+
this.uid = '';
|
|
11
|
+
this.gid = '';
|
|
12
|
+
this.gecos = '';
|
|
13
|
+
this.home = '';
|
|
14
|
+
this.shell = '';
|
|
15
|
+
this.size = 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.default = IAnalyze;
|