Quellcode durchsuchen

Provide host root folder to mount docker volumes

Nicolas Meienberger vor 3 Jahren
Ursprung
Commit
1eec46494c

+ 1 - 1
apps/nextcloud/docker-compose.yml

@@ -52,7 +52,7 @@ services:
       - POSTGRES_DB=nextcloud
       - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
       - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
-      - NEXTCLOUD_TRUSTED_DOMAINS=${DEVICE_IP}:${APP_PORT}
+      - NEXTCLOUD_TRUSTED_DOMAINS=${INTERNAL_IP}:${APP_PORT}
     depends_on:
       - db-nextcloud
       - redis-nextcloud

+ 3 - 1
packages/system-api/src/config/config.ts

@@ -6,11 +6,12 @@ interface IConfig {
   JWT_SECRET: string;
   CLIENT_URLS: string[];
   VERSION: string;
+  ROOT_FOLDER_HOST: string;
 }
 
 dotenv.config();
 
-const { NODE_ENV = 'development', JWT_SECRET = '', INTERNAL_IP = '', TIPI_VERSION = '' } = process.env;
+const { NODE_ENV = 'development', JWT_SECRET = '', INTERNAL_IP = '', TIPI_VERSION = '', ROOT_FOLDER_HOST = '' } = process.env;
 
 const config: IConfig = {
   NODE_ENV,
@@ -18,6 +19,7 @@ const config: IConfig = {
   JWT_SECRET,
   CLIENT_URLS: ['http://localhost:3000', `http://${INTERNAL_IP}`, `http://${INTERNAL_IP}:3000`],
   VERSION: TIPI_VERSION,
+  ROOT_FOLDER_HOST,
 };
 
 export default config;

+ 6 - 6
packages/system-api/src/modules/apps/__tests__/apps.service.test.ts

@@ -84,7 +84,7 @@ describe('Install app', () => {
 
     await AppsService.installApp('test-app', { test: 'test' });
 
-    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['install', 'test-app'], {}, expect.any(Function)]);
+    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['install', 'test-app', '/tipi'], {}, expect.any(Function)]);
 
     spy.mockRestore();
   });
@@ -96,8 +96,8 @@ describe('Install app', () => {
     await AppsService.installApp('test-app', { test: 'test' });
 
     expect(spy.mock.calls.length).toBe(2);
-    expect(spy.mock.calls[0]).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['install', 'test-app'], {}, expect.any(Function)]);
-    expect(spy.mock.calls[1]).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['start', 'test-app'], {}, expect.any(Function)]);
+    expect(spy.mock.calls[0]).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['install', 'test-app', '/tipi'], {}, expect.any(Function)]);
+    expect(spy.mock.calls[1]).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['start', 'test-app', '/tipi'], {}, expect.any(Function)]);
 
     spy.mockRestore();
   });
@@ -126,7 +126,7 @@ describe('Uninstall app', () => {
 
     await AppsService.uninstallApp('test-app');
 
-    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['uninstall', 'test-app'], {}, expect.any(Function)]);
+    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['uninstall', 'test-app', '/tipi'], {}, expect.any(Function)]);
 
     spy.mockRestore();
   });
@@ -147,7 +147,7 @@ describe('Start app', () => {
 
     await AppsService.startApp('test-app');
 
-    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['start', 'test-app'], {}, expect.any(Function)]);
+    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['start', 'test-app', '/tipi'], {}, expect.any(Function)]);
 
     spy.mockRestore();
   });
@@ -193,7 +193,7 @@ describe('Stop app', () => {
 
     await AppsService.stopApp('test-app');
 
-    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['stop', 'test-app'], {}, expect.any(Function)]);
+    expect(spy.mock.lastCall).toEqual([`${config.ROOT_FOLDER}/scripts/app.sh`, ['stop', 'test-app', '/tipi'], {}, expect.any(Function)]);
   });
 
   it('Should throw if app is not installed', async () => {

+ 2 - 1
packages/system-api/src/modules/apps/apps.helpers.ts

@@ -3,6 +3,7 @@ import p from 'p-iteration';
 import { AppConfig } from '../../config/types';
 import { fileExists, readdirSync, readFile, readJsonFile, runScript, writeFile } from '../fs/fs.helpers';
 import InternalIp from 'internal-ip';
+import config from '../../config';
 
 type AppsState = { installed: string };
 
@@ -76,7 +77,7 @@ export const checkAppExists = (appName: string) => {
 
 export const runAppScript = (params: string[]): Promise<void> => {
   return new Promise((resolve, reject) => {
-    runScript('/scripts/app.sh', params, (err: string) => {
+    runScript('/scripts/app.sh', [...params, config.ROOT_FOLDER_HOST], (err: string) => {
       if (err) {
         reject(err);
       }

+ 15 - 3
scripts/app.sh

@@ -60,6 +60,7 @@ if [ -z ${2+x} ]; then
   exit 1
 else
   app="$2"
+  root_folder_host="$3"
   app_dir="${ROOT_FOLDER}/apps/${app}"
   app_data_dir="${ROOT_FOLDER}/app-data/${app}"
 
@@ -67,6 +68,11 @@ else
     echo "Error: \"${app}\" is not a valid app"
     exit 1
   fi
+
+  if [[ -z "${root_folder_host}" ]]; then
+    echo "Error: Root folder not provided"
+    exit 1
+  fi
 fi
 
 if [ -z ${3+x} ]; then
@@ -98,7 +104,7 @@ compose() {
   local app_dir="${ROOT_FOLDER}/apps/${app}"
 
   # Vars to use in compose file
-  export APP_DATA_DIR="${app_data_dir}"
+  export APP_DATA_DIR="${root_folder_host}/app-data/${app}"
   export APP_DIR="${app_dir}"
 
   export ROOT_FOLDER="${ROOT_FOLDER}"
@@ -123,6 +129,8 @@ if [[ "$command" = "install" ]]; then
     cp -r "${ROOT_FOLDER}/apps/${app}/data" "${app_data_dir}/data"
   fi
 
+  chown -R "1000:1000" "${app_data_dir}"
+
   compose "${app}" up -d
   exit
 fi
@@ -130,11 +138,12 @@ fi
 # Removes images and destroys all data for an app
 if [[ "$command" = "uninstall" ]]; then
   echo "Removing images for app ${app}..."
-  compose "${app}" down --remove-orphans
+
+  # compose "${app}" down --remove-orphans
 
   echo "Deleting app data for app ${app}..."
   if [[ -d "${app_data_dir}" ]]; then
-    sudo rm -rf "${app_data_dir}"
+    rm -rf "${app_data_dir}"
   fi
 
   echo "Successfully uninstalled app ${app}"
@@ -145,6 +154,7 @@ fi
 if [[ "$command" = "stop" ]]; then
 
   echo "Stopping app ${app}..."
+  compose "${app}" down --remove-orphans --rmi all
   compose "${app}" rm --force --stop
 
   exit
@@ -153,6 +163,8 @@ fi
 # Starts an installed app
 if [[ "$command" = "start" ]]; then
   echo "Starting app ${app}..."
+  compose "${app}" pull
+
   compose "${app}" up --detach
 
   exit

+ 10 - 0
scripts/start.sh

@@ -14,6 +14,11 @@ SED_ROOT_FOLDER="$(echo $ROOT_FOLDER | sed 's/\//\\\//g')"
 INTERNAL_IP="$(hostname -I | awk '{print $1}')"
 DNS_IP=9.9.9.9 # Default to Quad9 DNS
 USERNAME="$(id -nu 1000)"
+ARCHITECTURE="$(uname -m)"
+
+if [[ "$architecture" == "aarch64" ]]; then
+  ARCHITECTURE="arm64"
+fi
 
 if [[ $UID != 0 ]]; then
     echo "Tipi must be started as root"
@@ -106,6 +111,8 @@ for template in "${ENV_FILE}"; do
   sed -i "s/<jwt_secret>/${JWT_SECRET}/g" "${template}"
   sed -i "s/<root_folder>/${SED_ROOT_FOLDER}/g" "${template}"
   sed -i "s/<tipi_version>/$(cat "${ROOT_FOLDER}/VERSION")/g" "${template}"
+  sed -i "s/<architecture>/${ARCHITECTURE}/g" "${template}"
+
 done
 
 mv -f "$ENV_FILE" "$ROOT_FOLDER/.env"
@@ -129,6 +136,9 @@ apps_to_start=($str)
 #     "${ROOT_FOLDER}/scripts/app.sh" start $app
 # done
 
+# Give permissions 1000:1000 to app data
+chown -R 1000:1000 "${ROOT_FOLDER}/app-data"
+
 echo "Tipi is now running"
 echo ""
 cat << "EOF"

+ 1 - 1
scripts/system-info.sh

@@ -19,7 +19,7 @@ MEM_USED_BYTES=$(($MEM_TOTAL_BYTES - $MEM_AVAILABLE_BYTES))
 
 # Create temporary json file
 TEMP_JSON_FILE=$(mktemp)
-echo '{ "cpu": { "load": '"${CPU_LOAD_PERCENTAGE}"' }, "memory": { "total": '"${MEM_TOTAL_BYTES}"' , "used": '"${MEM_USED_BYTES}"', "available": '"${MEM_FREE_BYTES}"' }, "disk": { "total": '"${TOTAL_DISK_SPACE_BYTES}"' , "used": '"${USED_DISK_SPACE_BYTES}"', "available": '"${AVAILABLE_DISK_SPACE_BYTES}"' } }' > "${TEMP_JSON_FILE}"
+echo '{ "cpu": { "load": '"${CPU_LOAD_PERCENTAGE}"' }, "memory": { "total": '"${MEM_TOTAL_BYTES}"' , "used": '"${MEM_USED_BYTES}"', "available": '"${MEM_AVAILABLE_BYTES}"' }, "disk": { "total": '"${TOTAL_DISK_SPACE_BYTES}"' , "used": '"${USED_DISK_SPACE_BYTES}"', "available": '"${AVAILABLE_DISK_SPACE_BYTES}"' } }' > "${TEMP_JSON_FILE}"
 
 # Write to state file
 echo "$(cat "${TEMP_JSON_FILE}")" > "${STATE_FOLDER}/system-info.json"

+ 1 - 0
templates/env-sample

@@ -9,3 +9,4 @@ DNS_IP=<dns_ip>
 ARCHITECTURE=<architecture>
 TIPI_VERSION=<tipi_version>
 JWT_SECRET=<jwt_secret>
+ROOT_FOLDER_HOST=<root_folder>