Provide host root folder to mount docker volumes
This commit is contained in:
parent
f6df848866
commit
1eec46494c
8 changed files with 39 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -9,3 +9,4 @@ DNS_IP=<dns_ip>
|
|||
ARCHITECTURE=<architecture>
|
||||
TIPI_VERSION=<tipi_version>
|
||||
JWT_SECRET=<jwt_secret>
|
||||
ROOT_FOLDER_HOST=<root_folder>
|
||||
|
|
Loading…
Add table
Reference in a new issue