Provide host root folder to mount docker volumes

This commit is contained in:
Nicolas Meienberger 2022-05-17 18:54:04 +02:00
parent f6df848866
commit 1eec46494c
8 changed files with 39 additions and 13 deletions

View file

@ -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

View file

@ -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;

View file

@ -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 () => {

View file

@ -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);
}

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

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