From a6d33fc2ef362bee8fd380a4772212d4663e6164 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 14 Jul 2026 20:00:17 +0000 Subject: [PATCH] feat: Move config and data dir creation into app * only use docker init for fixing permission * don't rely on docker init for dir creation as other distros may need this functionality (nix) * check for and create config/data dirs recursively on app start #616 --- .../etc/s6-overlay/s6-rc.d/init-ms-config/run | 32 ++++++------------- src/backend/index.ts | 29 +++++++++++++++-- src/backend/utils/FSUtils.ts | 2 ++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/docker/root/etc/s6-overlay/s6-rc.d/init-ms-config/run b/docker/root/etc/s6-overlay/s6-rc.d/init-ms-config/run index 521bc927..cad8bfe8 100755 --- a/docker/root/etc/s6-overlay/s6-rc.d/init-ms-config/run +++ b/docker/root/etc/s6-overlay/s6-rc.d/init-ms-config/run @@ -1,33 +1,19 @@ #!/usr/bin/with-contenv bash -# used https://github.com/linuxserver/docker-plex as a template - -POPULATE_EXAMPLES=false - echo "-------------------------------------" -echo -e "Setting up multi-scrobbler config directory based on CONFIG_DIR env: ${CONFIG_DIR}\n" +echo -e "Verifying multi-scrobbler directory permissions based on CONFIG_DIR env: ${CONFIG_DIR} and DATA_DIR env: ${DATA_DIR}\n" -# make config folder if it does not exist -if [ ! -d "${CONFIG_DIR}" ]; then - echo "Directory does not exist! Creating..." - POPULATE_EXAMPLES=true - mkdir -p "${CONFIG_DIR}" -else - if [ "$(ls -A ${CONFIG_DIR})" ]; then - echo "Directory is not empty, not creating examples." - else - POPULATE_EXAMPLES=true - fi +if [ -d "${CONFIG_DIR}" ]; then + echo "chown'ing config directory to ensure correct permissions." + chown -R abc:abc "${CONFIG_DIR}" + echo "Done!" fi -# add example configs -if [ "$POPULATE_EXAMPLES" = true ]; then - echo "Directory is empty, adding examples..." - cp -r /app/config/. "${CONFIG_DIR}"/ +if [ -d "${DATA_DIR}" ]; then + echo "chown'ing data directory to ensure correct permissions." + chown -R abc:abc "${DATA_DIR}" + echo "Done!" fi -# permissions -echo "chown'ing directory to ensure correct permissions." -chown -R abc:abc "${CONFIG_DIR}" echo "Done!" echo -e "-------------------------------------\n" diff --git a/src/backend/index.ts b/src/backend/index.ts index dfe66839..2ce4c471 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -25,6 +25,7 @@ import { getDbPath } from './common/database/Database.ts'; import { createRetentionCleanupTask } from './tasks/retentionCleanup.ts'; import { parseUserConfig } from './common/Cache.ts'; import { nonEmptyStringOrDefault } from '../core/StringUtils.ts'; +import { createDir, fileExists } from './utils/FSUtils.ts'; dayjs.extend(utc) dayjs.extend(isBetween); @@ -86,16 +87,38 @@ process.on('SIGINT', async () => { }) -const configDir = getConfigDir() +const configDir = getConfigDir(); +const dataDir = getDataDir(); try { - initLogger.verbose(`Config Dir ENV : ${process.env.CONFIG_DIR} -> Resolved: ${configDir}`); - initLogger.verbose(`Data Dir ENV : ${process.env.DATA_DIR} -> Resolved: ${getDataDir()}`); + initLogger.info(`Config Dir ENV : ${process.env.CONFIG_DIR} -> Resolved: ${configDir}`); + try { + const exists = fileExists(configDir); + if(!exists) { + initLogger.verbose(`Config Dir does not exist, creating now...`); + await createDir(configDir); + } + } catch (e) { + initLogger.warn(new Error('Could not access config dir. It is likely your config files will not be able to be read.', {cause: e})); + } + initLogger.info(`Data Dir ENV : ${process.env.DATA_DIR} -> Resolved: ${getDataDir()}`); + try { + const exists = fileExists(dataDir); + if(!exists) { + initLogger.verbose(`Data Dir does not exist, creating now...`); + await createDir(dataDir); + } + } catch (e) { + initLogger.warn(new Error('Could not access data dir. It is likely your data files will not be able to be read.', {cause: e})); + } // try to read a configuration file let appConfigFail: Error | undefined = undefined; let config = {}; try { config = await readJson(`${configDir}/config.json`, {throwOnNotFound: false, logger: childLogger(initLogger, 'Secrets')}); + if(config === undefined) { + initLogger.verbose(`No AIO config found at ${configDir}/config.json`); + } } catch (e) { appConfigFail = e; } diff --git a/src/backend/utils/FSUtils.ts b/src/backend/utils/FSUtils.ts index d134a54a..59f861c5 100644 --- a/src/backend/utils/FSUtils.ts +++ b/src/backend/utils/FSUtils.ts @@ -34,6 +34,8 @@ export async function readText(path: any) { // }); } +export const createDir = (location: string) => promises.mkdir(location, {recursive: true}); + export const fileOrDirectoryIsWriteable = (location: string) => { const pathInfo = pathUtil.parse(location); const isDir = pathInfo.ext === ''; -- 2.51.2