feat(cli): create tipi group and assign it to user and folders
This commit is contained in:
parent
93282a051e
commit
7926c45d88
7 changed files with 60 additions and 16 deletions
|
@ -5,4 +5,4 @@ APPS_REPO_URL=https://test.com/test
|
|||
ROOT_FOLDER_HOST=/runtipi
|
||||
STORAGE_PATH=/runtipi
|
||||
TIPI_VERSION=1
|
||||
|
||||
REDIS_PASSWORD=redis
|
||||
|
|
|
@ -168,10 +168,14 @@ export class AppExecutors {
|
|||
await compose(appId, 'down --remove-orphans --volumes --rmi all');
|
||||
|
||||
this.logger.info(`Deleting folder ${appDirPath}`);
|
||||
await fs.promises.rm(appDirPath, { recursive: true, force: true });
|
||||
await fs.promises.rm(appDirPath, { recursive: true, force: true }).catch((err) => {
|
||||
this.logger.error(`Error deleting folder ${appDirPath}: ${err.message}`);
|
||||
});
|
||||
|
||||
this.logger.info(`Deleting folder ${appDataDirPath}`);
|
||||
await fs.promises.rm(appDataDirPath, { recursive: true, force: true });
|
||||
await fs.promises.rm(appDataDirPath, { recursive: true, force: true }).catch((err) => {
|
||||
this.logger.error(`Error deleting folder ${appDataDirPath}: ${err.message}`);
|
||||
});
|
||||
|
||||
this.logger.info(`App ${appId} uninstalled`);
|
||||
return { success: true, message: `App ${appId} uninstalled successfully` };
|
||||
|
|
|
@ -192,5 +192,7 @@ export const copyDataDir = async (id: string) => {
|
|||
);
|
||||
|
||||
// Remove any .gitkeep files from the app-data folder at any level
|
||||
await execAsync(`find ${storagePath}/app-data/${id}/data -name .gitkeep -delete`);
|
||||
if (await pathExists(`${storagePath}/app-data/${id}/data`)) {
|
||||
await execAsync(`find ${storagePath}/app-data/${id}/data -name .gitkeep -delete`).catch(() => {});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -56,18 +56,43 @@ export class SystemExecutors {
|
|||
};
|
||||
|
||||
private ensureFilePermissions = async (rootFolderHost: string, logSudoRequest = true) => {
|
||||
const logger = new TerminalSpinner('');
|
||||
// if we are running as root, we don't need to change permissions
|
||||
if (process.getuid && process.getuid() === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (logSudoRequest) {
|
||||
const logger = new TerminalSpinner('');
|
||||
logger.log('Tipi needs to change permissions on some files and folders and will ask for your password.');
|
||||
}
|
||||
|
||||
// Create group tipi if it does not exist
|
||||
try {
|
||||
await execAsync('getent group tipi');
|
||||
} catch (e) {
|
||||
try {
|
||||
await execAsync('sudo groupadd tipi');
|
||||
logger.done('Created group tipi');
|
||||
} catch (e2) {
|
||||
logger.fail('Failed to create group tipi');
|
||||
fileLogger.error(e2);
|
||||
}
|
||||
}
|
||||
|
||||
// Add current user to group tipi
|
||||
if (!(await execAsync(`groups ${process.env.USER}`)).stdout.includes('tipi')) {
|
||||
try {
|
||||
await execAsync(`sudo usermod -aG tipi ${process.env.USER}`);
|
||||
// Reload permissions
|
||||
await execAsync('newgrp tipi');
|
||||
} catch (e) {
|
||||
logger.fail('Failed to add current user to group tipi');
|
||||
}
|
||||
}
|
||||
|
||||
const filesAndFolders = [
|
||||
path.join(rootFolderHost, 'apps'),
|
||||
// path.join(rootFolderHost, 'app-data'),
|
||||
path.join(rootFolderHost, 'logs'),
|
||||
path.join(rootFolderHost, 'media'),
|
||||
path.join(rootFolderHost, 'repos'),
|
||||
|
@ -82,11 +107,12 @@ export class SystemExecutors {
|
|||
await Promise.all(
|
||||
filesAndFolders.map(async (fileOrFolder) => {
|
||||
if (await pathExists(fileOrFolder)) {
|
||||
if (process.getgid && process.getuid) {
|
||||
await execAsync(`sudo chown -R ${process.getuid()}:${process.getgid()} ${fileOrFolder}`);
|
||||
}
|
||||
|
||||
await execAsync(`sudo chmod -R 750 ${fileOrFolder}`);
|
||||
await execAsync(`sudo chown -R :tipi ${fileOrFolder}`).catch((e) => {
|
||||
fileLogger.error(e);
|
||||
});
|
||||
await execAsync(`sudo chmod -R 770 ${fileOrFolder}`).catch((e) => {
|
||||
fileLogger.error(e);
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
@ -390,6 +416,8 @@ export class SystemExecutors {
|
|||
process.stderr.write(data);
|
||||
});
|
||||
|
||||
spinner.done(`Tipi ${targetVersion} successfully updated. Please run './runtipi-cli start' to start Tipi again.`);
|
||||
|
||||
return { success: true, message: 'Tipi updated' };
|
||||
} catch (e) {
|
||||
spinner.fail('Tipi update failed, see logs for more details (logs/error.log)');
|
||||
|
|
|
@ -33,6 +33,8 @@ type EnvKeys =
|
|||
| 'REDIS_PASSWORD'
|
||||
| 'LOCAL_DOMAIN'
|
||||
| 'DEMO_MODE'
|
||||
| 'TIPI_GID'
|
||||
| 'TIPI_UID'
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
| (string & {});
|
||||
|
||||
|
@ -177,6 +179,13 @@ export const generateSystemEnvFile = async () => {
|
|||
envMap.set('LOCAL_DOMAIN', data.localDomain || 'tipi.lan');
|
||||
envMap.set('NODE_ENV', 'production');
|
||||
|
||||
const currentUserGroup = process.getgid ? String(process.getgid()) : '1000';
|
||||
const currentUserId = process.getuid ? String(process.getuid()) : '1000';
|
||||
const { stdout: tipiGroupId } = await execAsync('getent group tipi | cut -d: -f3');
|
||||
|
||||
envMap.set('TIPI_GID', tipiGroupId.trim() || currentUserGroup);
|
||||
envMap.set('TIPI_UID', currentUserId);
|
||||
|
||||
await fs.promises.writeFile(envFilePath, envMapToString(envMap));
|
||||
|
||||
return envMap;
|
||||
|
|
|
@ -84,7 +84,11 @@ const killOtherWorkers = async () => {
|
|||
}
|
||||
|
||||
console.log(`Killing worker with pid ${pid}`);
|
||||
process.kill(Number(pid));
|
||||
try {
|
||||
process.kill(Number(pid));
|
||||
} catch (e) {
|
||||
console.error(`Error killing worker with pid ${pid}: ${e}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -188,11 +188,8 @@ chmod +x ./runtipi-cli
|
|||
# Check if user is in docker group
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
if ! groups | grep -q docker; then
|
||||
echo ""
|
||||
echo "User is not in docker group. Please make sure your user is allowed to run docker commands and restart the script."
|
||||
echo "See https://docs.docker.com/engine/install/linux-postinstall/ for more information."
|
||||
echo ""
|
||||
exit 1
|
||||
sudo usermod -aG docker "$USER"
|
||||
newgrp docker
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue