@ -0,0 +1,62 @@ |
|||||||
|
name: "NestJS Unit Test" |
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: [develop] |
||||||
|
paths: |
||||||
|
- "packages/nocodb/**" |
||||||
|
- ".github/workflows/jest-unit-test.yml" |
||||||
|
pull_request: |
||||||
|
types: [opened, reopened, synchronize, ready_for_review, labeled] |
||||||
|
branches: [develop] |
||||||
|
paths: |
||||||
|
- "packages/nocodb/**" |
||||||
|
- ".github/workflows/jest-unit-test.yml" |
||||||
|
workflow_call: |
||||||
|
# Triggered manually |
||||||
|
workflow_dispatch: |
||||||
|
jobs: |
||||||
|
jest-unit-test: |
||||||
|
runs-on: [self-hosted, aws] |
||||||
|
timeout-minutes: 20 |
||||||
|
if: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'trigger-CI') || !github.event.pull_request.draft || inputs.force == true }} |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@v3 |
||||||
|
with: |
||||||
|
fetch-depth: 0 |
||||||
|
- name: Setup Node |
||||||
|
uses: actions/setup-node@v3 |
||||||
|
with: |
||||||
|
node-version: 18.19.1 |
||||||
|
- name: Setup pnpm |
||||||
|
uses: pnpm/action-setup@v4 |
||||||
|
with: |
||||||
|
version: 9 |
||||||
|
- name: Get pnpm store directory |
||||||
|
shell: bash |
||||||
|
timeout-minutes: 1 |
||||||
|
run: | |
||||||
|
echo "STORE_PATH=/root/setup-pnpm/node_modules/.bin/store/v3" >> $GITHUB_ENV |
||||||
|
- uses: actions/cache@v3 |
||||||
|
name: Setup pnpm cache |
||||||
|
with: |
||||||
|
path: ${{ env.STORE_PATH }} |
||||||
|
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} |
||||||
|
restore-keys: | |
||||||
|
${{ runner.os }}-pnpm-store- |
||||||
|
- name: Set CI env |
||||||
|
run: export CI=true |
||||||
|
- name: Set NC Edition |
||||||
|
run: export EE=true |
||||||
|
- name: remove use-node-version line from .npmrc |
||||||
|
run: sed -i '/^use-node-version/d' .npmrc |
||||||
|
- name: install dependencies |
||||||
|
run: pnpm bootstrap |
||||||
|
- name: build nocodb-sdk |
||||||
|
working-directory: ./packages/nocodb-sdk |
||||||
|
run: | |
||||||
|
pnpm run generate:sdk |
||||||
|
pnpm run build:main |
||||||
|
- name: run unit tests |
||||||
|
working-directory: ./packages/nocodb |
||||||
|
run: pnpm run test |
@ -0,0 +1,153 @@ |
|||||||
|
name: "Release : Secret CLI NPM & Executables" |
||||||
|
|
||||||
|
on: |
||||||
|
# Triggered manually |
||||||
|
workflow_dispatch: |
||||||
|
inputs: |
||||||
|
tag: |
||||||
|
description: "Tag name" |
||||||
|
required: true |
||||||
|
secrets: |
||||||
|
# Replace with `NC_GITHUB_TOKEN` once replaced with a token which have access to `nocodb/nc-secret-mgr` |
||||||
|
NC_GITHUB_TOKEN_TEMP: |
||||||
|
required: true |
||||||
|
jobs: |
||||||
|
build-and-publish: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v3 |
||||||
|
- name: Setup pnpm |
||||||
|
uses: pnpm/action-setup@v4 |
||||||
|
with: |
||||||
|
version: 9 |
||||||
|
- name: Setup Node 18.19.1 |
||||||
|
# Setup .npmrc file to publish to npm |
||||||
|
uses: actions/setup-node@v3 |
||||||
|
with: |
||||||
|
node-version: 18.19.1 |
||||||
|
registry-url: "https://registry.npmjs.org" |
||||||
|
|
||||||
|
- name: Cache pkg modules |
||||||
|
id: cache-pkg |
||||||
|
uses: actions/cache@v3 |
||||||
|
env: |
||||||
|
cache-name: cache-pkg |
||||||
|
with: |
||||||
|
# pkg cache files are stored in `~/.pkg-cache` |
||||||
|
path: ~/.pkg-cache |
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} |
||||||
|
restore-keys: | |
||||||
|
${{ runner.os }}-build-${{ env.cache-name }}- |
||||||
|
${{ runner.os }}-build- |
||||||
|
${{ runner.os }}- |
||||||
|
|
||||||
|
- name: Npm package build and publish |
||||||
|
env: |
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
||||||
|
run: | |
||||||
|
pnpm bootstrap |
||||||
|
cd ./packages/nocodb |
||||||
|
pnpm run build:cli:module |
||||||
|
cd ../nc-secret-mgr |
||||||
|
targetVersion=${{ github.event.inputs.tag || inputs.tag }} node ../../scripts/updateCliVersion.js |
||||||
|
pnpm run build && pnpm run npm:publish |
||||||
|
|
||||||
|
# for building images for all platforms these libraries are required in Linux |
||||||
|
- name: Install QEMU and ldid |
||||||
|
run: | |
||||||
|
sudo apt update |
||||||
|
# Install qemu |
||||||
|
sudo apt install qemu binfmt-support qemu-user-static -y |
||||||
|
# install ldid |
||||||
|
git clone https://github.com/daeken/ldid.git |
||||||
|
cd ./ldid |
||||||
|
./make.sh |
||||||
|
sudo cp ./ldid /usr/local/bin |
||||||
|
|
||||||
|
- uses: actions/setup-node@v3 |
||||||
|
with: |
||||||
|
node-version: 16 |
||||||
|
|
||||||
|
- name: Install nocodb, other dependencies and build executables |
||||||
|
run: | |
||||||
|
cd ./packages/nc-secret-mgr |
||||||
|
|
||||||
|
# install npm dependendencies |
||||||
|
pnpm i |
||||||
|
|
||||||
|
# Build sqlite binaries for all platforms |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=x64 --target_libc=unknown |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=ia32 --target_libc=unknown |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=x64 --target_libc=unknown |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=arm64 --target_libc=unknown |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=glibc |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=glibc |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=musl |
||||||
|
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=musl |
||||||
|
|
||||||
|
# clean up code to optimize size |
||||||
|
npx modclean --patterns="default:*" --run |
||||||
|
|
||||||
|
# build executables |
||||||
|
npm run build:pkg |
||||||
|
|
||||||
|
ls ./dist-pkg |
||||||
|
|
||||||
|
# Move macOS executables for signing |
||||||
|
mkdir ./mac-dist |
||||||
|
mv ./dist-pkg/nc-secret-mgr-macos-arm64 ./mac-dist/ |
||||||
|
mv ./dist-pkg/nc-secret-mgr-macos-x64 ./mac-dist/ |
||||||
|
|
||||||
|
- name: Upload executables(except mac executables) to release |
||||||
|
uses: svenstaro/upload-release-action@v2 |
||||||
|
with: |
||||||
|
repo_token: ${{ secrets.NC_GITHUB_TOKEN_TEMP }} |
||||||
|
file: packages/nc-secret-mgr/dist-pkg/** |
||||||
|
tag: ${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
overwrite: true |
||||||
|
file_glob: true |
||||||
|
repo_name: nocodb/nc-secret-mgr |
||||||
|
|
||||||
|
- uses: actions/upload-artifact@master |
||||||
|
with: |
||||||
|
name: ${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
path: packages/nc-secret-mgr/mac-dist |
||||||
|
retention-days: 1 |
||||||
|
sign-mac-executables: |
||||||
|
runs-on: macos-latest |
||||||
|
needs: build-and-publish |
||||||
|
steps: |
||||||
|
- uses: actions/download-artifact@master |
||||||
|
with: |
||||||
|
name: ${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
path: packages/nc-secret-mgr/mac-dist |
||||||
|
|
||||||
|
- name: Sign macOS executables |
||||||
|
run: | |
||||||
|
/usr/bin/codesign --force -s - ./packages/nc-secret-mgr/mac-dist/nc-secret-mgr-macos-arm64 -v |
||||||
|
/usr/bin/codesign --force -s - ./packages/nc-secret-mgr/mac-dist/nc-secret-mgr-macos-x64 -v |
||||||
|
|
||||||
|
- uses: actions/upload-artifact@master |
||||||
|
with: |
||||||
|
name: ${{ format('{0}-signed', github.event.inputs.tag || inputs.tag) }} |
||||||
|
path: packages/nc-secret-mgr/mac-dist |
||||||
|
retention-days: 1 |
||||||
|
|
||||||
|
publish-mac-executables: |
||||||
|
needs: [sign-mac-executables, build-and-publish] |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/download-artifact@master |
||||||
|
with: |
||||||
|
name: ${{ format('{0}-signed', github.event.inputs.tag || inputs.tag) }} |
||||||
|
path: packages/nc-secret-mgr/mac-dist |
||||||
|
|
||||||
|
- name: Upload executables(except mac executables) to release |
||||||
|
uses: svenstaro/upload-release-action@v2 |
||||||
|
with: |
||||||
|
repo_token: ${{ secrets.NC_GITHUB_TOKEN_TEMP }} |
||||||
|
file: packages/nc-secret-mgr/mac-dist/** |
||||||
|
tag: ${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
overwrite: true |
||||||
|
file_glob: true |
||||||
|
repo_name: nocodb/nc-secret-mgr |
@ -0,0 +1,161 @@ |
|||||||
|
name: "Release : Docker" |
||||||
|
|
||||||
|
on: |
||||||
|
# Triggered manually |
||||||
|
workflow_dispatch: |
||||||
|
inputs: |
||||||
|
tag: |
||||||
|
description: "Docker image tag" |
||||||
|
required: true |
||||||
|
targetEnv: |
||||||
|
description: "Target Environment" |
||||||
|
required: true |
||||||
|
type: choice |
||||||
|
options: |
||||||
|
- DEV |
||||||
|
- PROD |
||||||
|
# Triggered by release-nocodb.yml / release-nightly-dev.yml / release-pr.yml |
||||||
|
workflow_call: |
||||||
|
inputs: |
||||||
|
tag: |
||||||
|
description: "Docker image tag" |
||||||
|
required: true |
||||||
|
type: string |
||||||
|
targetEnv: |
||||||
|
description: "Target Environment" |
||||||
|
required: true |
||||||
|
type: string |
||||||
|
isDaily: |
||||||
|
description: "Is it triggered by daily schedule" |
||||||
|
required: false |
||||||
|
type: string |
||||||
|
currentVersion: |
||||||
|
description: "The current NocoDB version" |
||||||
|
required: false |
||||||
|
type: string |
||||||
|
secrets: |
||||||
|
DOCKERHUB_USERNAME: |
||||||
|
required: true |
||||||
|
DOCKERHUB_TOKEN: |
||||||
|
required: true |
||||||
|
|
||||||
|
jobs: |
||||||
|
buildx: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
env: |
||||||
|
working-directory: ./packages/nocodb |
||||||
|
steps: |
||||||
|
- name: Setup pnpm |
||||||
|
uses: pnpm/action-setup@v4 |
||||||
|
with: |
||||||
|
version: 9 |
||||||
|
- name: Get Docker Repository |
||||||
|
id: get-docker-repository |
||||||
|
run: | |
||||||
|
DOCKER_REPOSITORY=nocodb-daily |
||||||
|
DOCKER_BUILD_TAG=${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
DOCKER_BUILD_LATEST_TAG=latest |
||||||
|
if [[ "$DOCKER_BUILD_TAG" =~ "-beta." ]]; then |
||||||
|
DOCKER_BUILD_LATEST_TAG=$(echo $DOCKER_BUILD_TAG | awk -F '-beta.' '{print $1}')-beta.latest |
||||||
|
fi |
||||||
|
if [[ ${{ github.event.inputs.targetEnv || inputs.targetEnv }} == 'DEV' ]]; then |
||||||
|
if [[ ${{ github.event.inputs.currentVersion || inputs.currentVersion || 'N/A' }} != 'N/A' ]]; then |
||||||
|
DOCKER_BUILD_TAG=${{ github.event.inputs.currentVersion || inputs.currentVersion }}-${{ github.event.inputs.tag || inputs.tag }} |
||||||
|
fi |
||||||
|
if [[ ${{ inputs.isDaily || 'N' }} == 'Y' ]]; then |
||||||
|
DOCKER_REPOSITORY=nocodb-daily |
||||||
|
else |
||||||
|
DOCKER_REPOSITORY=nocodb-timely |
||||||
|
fi |
||||||
|
fi |
||||||
|
echo "DOCKER_REPOSITORY=${DOCKER_REPOSITORY}" >> $GITHUB_OUTPUT |
||||||
|
echo "DOCKER_BUILD_TAG=${DOCKER_BUILD_TAG}" >> $GITHUB_OUTPUT |
||||||
|
echo "DOCKER_BUILD_LATEST_TAG=${DOCKER_BUILD_LATEST_TAG}" >> $GITHUB_OUTPUT |
||||||
|
echo DOCKER_REPOSITORY: ${DOCKER_REPOSITORY} |
||||||
|
echo DOCKER_BUILD_TAG: ${DOCKER_BUILD_TAG} |
||||||
|
echo DOCKER_BUILD_LATEST_TAG: ${DOCKER_BUILD_LATEST_TAG} |
||||||
|
|
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@v3 |
||||||
|
with: |
||||||
|
fetch-depth: 1 |
||||||
|
ref: ${{ github.ref }} |
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }} |
||||||
|
uses: actions/setup-node@v3 |
||||||
|
with: |
||||||
|
node-version: 18.19.1 |
||||||
|
|
||||||
|
- name: install dependencies |
||||||
|
run: pnpm bootstrap |
||||||
|
|
||||||
|
- name: Build gui and sdk |
||||||
|
run: | |
||||||
|
|
||||||
|
pnpm bootstrap && |
||||||
|
cd packages/nc-gui && |
||||||
|
pnpm run generate |
||||||
|
|
||||||
|
# copy build to nocodb |
||||||
|
rsync -rvzh ./dist/ ../nocodb/docker/nc-gui/ |
||||||
|
|
||||||
|
|
||||||
|
- name: build nocodb |
||||||
|
run: | |
||||||
|
# build nocodb ( pack nocodb-sdk and nc-gui ) |
||||||
|
cd packages/nocodb && |
||||||
|
EE=true pnpm exec webpack --config webpack.timely.config.js && |
||||||
|
# remove bundled libraries (nocodb-sdk, knex-snowflake) |
||||||
|
pnpm uninstall --save-prod nocodb-sdk |
||||||
|
|
||||||
|
- name: Update version in package.json |
||||||
|
run: | |
||||||
|
# update package.json |
||||||
|
cd packages/nocodb && |
||||||
|
jq --arg VERSION "$VERSION" '.version = $VERSION' package.json > tmp.json && |
||||||
|
mv tmp.json package.json |
||||||
|
env: |
||||||
|
VERSION: ${{ steps.get-docker-repository.outputs.DOCKER_BUILD_TAG }} |
||||||
|
|
||||||
|
- name: Set up QEMU |
||||||
|
uses: docker/setup-qemu-action@v2.1.0 |
||||||
|
|
||||||
|
- name: Set up Docker Buildx |
||||||
|
id: buildx |
||||||
|
uses: docker/setup-buildx-action@v2.2.1 |
||||||
|
|
||||||
|
- name: Cache Docker layers |
||||||
|
uses: actions/cache@v3 |
||||||
|
with: |
||||||
|
path: /tmp/.buildx-cache |
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }} |
||||||
|
restore-keys: | |
||||||
|
${{ runner.os }}-buildx- |
||||||
|
|
||||||
|
- name: Login to DockerHub |
||||||
|
uses: docker/login-action@v2.1.0 |
||||||
|
with: |
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }} |
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }} |
||||||
|
|
||||||
|
- name: Build and push |
||||||
|
uses: docker/build-push-action@v3.2.0 |
||||||
|
with: |
||||||
|
context: ${{ env.working-directory }} |
||||||
|
file: ${{ env.working-directory }}/Dockerfile.timely |
||||||
|
build-args: NC_VERSION=${{ steps.get-docker-repository.outputs.DOCKER_BUILD_TAG }} |
||||||
|
platforms: linux/amd64,linux/arm64 |
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache |
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache-new |
||||||
|
push: true |
||||||
|
tags: | |
||||||
|
nocodb/${{ steps.get-docker-repository.outputs.DOCKER_REPOSITORY }}:${{ steps.get-docker-repository.outputs.DOCKER_BUILD_TAG }} |
||||||
|
nocodb/${{ steps.get-docker-repository.outputs.DOCKER_REPOSITORY }}:${{ steps.get-docker-repository.outputs.DOCKER_BUILD_LATEST_TAG }} |
||||||
|
|
||||||
|
# Temp fix |
||||||
|
# https://github.com/docker/build-push-action/issues/252 |
||||||
|
# https://github.com/moby/buildkit/issues/1896 |
||||||
|
- name: Move cache |
||||||
|
run: | |
||||||
|
rm -rf /tmp/.buildx-cache |
||||||
|
mv /tmp/.buildx-cache-new /tmp/.buildx-cache |
@ -0,0 +1,28 @@ |
|||||||
|
name: "Validate: Docs" |
||||||
|
|
||||||
|
on: |
||||||
|
# Triggered manually |
||||||
|
workflow_dispatch: |
||||||
|
pull_request: |
||||||
|
types: [opened, reopened, synchronize, ready_for_review, labeled] |
||||||
|
branches: [develop] |
||||||
|
paths: |
||||||
|
- "packages/noco-docs/**" |
||||||
|
|
||||||
|
jobs: |
||||||
|
validate-docs: |
||||||
|
runs-on: [self-hosted, aws] |
||||||
|
steps: |
||||||
|
- name: Checkout |
||||||
|
uses: actions/checkout@v3 |
||||||
|
with: |
||||||
|
fetch-depth: 0 |
||||||
|
- uses: actions/setup-node@v3 |
||||||
|
with: |
||||||
|
node-version: 18.19.1 |
||||||
|
- name: Build docs |
||||||
|
run: | |
||||||
|
cd packages/noco-docs |
||||||
|
npm install |
||||||
|
npm run generate |
||||||
|
npm run remark:once |
@ -1,60 +0,0 @@ |
|||||||
#!/usr/bin/env bash |
|
||||||
|
|
||||||
|
|
||||||
read -p "Enter your domain name: " domain |
|
||||||
read -p "Enter your email id: " email |
|
||||||
|
|
||||||
# Docker installation |
|
||||||
if [ -x "$(command -v docker)" ]; then |
|
||||||
echo "Docker already available" |
|
||||||
else |
|
||||||
sudo apt-get update |
|
||||||
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common |
|
||||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -- |
|
||||||
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" |
|
||||||
sudo apt-get update |
|
||||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io |
|
||||||
sudo usermod -a -G docker $USER |
|
||||||
echo "Docker installed successfully" |
|
||||||
fi |
|
||||||
|
|
||||||
# Docker compose installation |
|
||||||
if [ -x "$(command -v docker-compose)" ]; then |
|
||||||
echo "Docker-compose already available" |
|
||||||
else |
|
||||||
sudo apt-get -y install wget |
|
||||||
sudo wget https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m) -O /usr/local/bin/docker-compose |
|
||||||
sudo chmod +x /usr/local/bin/docker-compose |
|
||||||
docker-compose --version |
|
||||||
echo "Docker-compose installed successfully" |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
#wget https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion/archive/master.zip -O master.zip |
|
||||||
# |
|
||||||
#unzip -n master.zip |
|
||||||
# |
|
||||||
#cd docker-compose-letsencrypt-nginx-proxy-companion-master |
|
||||||
|
|
||||||
git clone https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion.git |
|
||||||
|
|
||||||
cd docker-compose-letsencrypt-nginx-proxy-companion |
|
||||||
|
|
||||||
OUTPUT1=$(./start.sh) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 -d --name xc-instant \ |
|
||||||
-e VIRTUAL_HOST="$domain" \ |
|
||||||
-e LETSENCRYPT_HOST="$domain" \ |
|
||||||
-e LETSENCRYPT_EMAIL="$email" \ |
|
||||||
-e VIRTUAL_PORT=8080 \ |
|
||||||
--network=webproxy nocodb/nocodb:latest |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,39 +0,0 @@ |
|||||||
version: "2.1" |
|
||||||
services: |
|
||||||
nocodb: |
|
||||||
depends_on: |
|
||||||
root_db: |
|
||||||
condition: service_healthy |
|
||||||
environment: |
|
||||||
NC_DB: "mysql2://root_db:3306?u=noco&p=password&d=root_db" |
|
||||||
image: "nocodb/nocodb:latest" |
|
||||||
ports: |
|
||||||
- "8080:8080" |
|
||||||
restart: always |
|
||||||
volumes: |
|
||||||
- "nc_data:/usr/app/data" |
|
||||||
root_db: |
|
||||||
environment: |
|
||||||
MYSQL_DATABASE: root_db |
|
||||||
MYSQL_PASSWORD: password |
|
||||||
MYSQL_ROOT_PASSWORD: password |
|
||||||
MYSQL_USER: noco |
|
||||||
healthcheck: |
|
||||||
retries: 10 |
|
||||||
test: |
|
||||||
- CMD |
|
||||||
- mysqladmin |
|
||||||
- ping |
|
||||||
- "-h" |
|
||||||
- localhost |
|
||||||
timeout: 20s |
|
||||||
image: "mysql:8.3.0" |
|
||||||
restart: always |
|
||||||
volumes: |
|
||||||
- "db_data:/var/lib/mysql" |
|
||||||
# below line shows how to change charset and collation |
|
||||||
# uncomment it if necessary |
|
||||||
# command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci |
|
||||||
volumes: |
|
||||||
db_data: {} |
|
||||||
nc_data: {} |
|
@ -1,843 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
# set -x |
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# ***************** GLOBAL VARIABLES START ********************************* |
|
||||||
|
|
||||||
RED='\033[0;31m' |
|
||||||
GREEN='\033[0;32m' |
|
||||||
YELLOW='\033[1;33m' |
|
||||||
BLUE='\033[0;34m' |
|
||||||
MAGENTA='\033[0;35m' |
|
||||||
CYAN='\033[0;36m' |
|
||||||
ORANGE='\033[0;33m' |
|
||||||
BOLD='\033[1m' |
|
||||||
NC='\033[0m' |
|
||||||
|
|
||||||
NOCO_HOME="./nocodb" |
|
||||||
# Get the current working directory |
|
||||||
CURRENT_PATH=$(pwd) |
|
||||||
|
|
||||||
# ***************** GLOBAL VARIABLES END *********************************** |
|
||||||
# ****************************************************************************** |
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# ***************** HELPER FUNCTIONS START ********************************* |
|
||||||
|
|
||||||
# Function to URL encode special characters in a string |
|
||||||
urlencode() { |
|
||||||
local string="$1" |
|
||||||
local strlen=${#string} |
|
||||||
local encoded="" |
|
||||||
local pos c o |
|
||||||
|
|
||||||
for (( pos=0 ; pos<strlen ; pos++ )); do |
|
||||||
c=${string:$pos:1} |
|
||||||
case "$c" in |
|
||||||
[-_.~a-zA-Z0-9] ) o="$c" ;; |
|
||||||
* ) printf -v o '%%%02X' "'$c" |
|
||||||
esac |
|
||||||
encoded+="$o" |
|
||||||
done |
|
||||||
echo "$encoded" |
|
||||||
} |
|
||||||
|
|
||||||
# function to print a message in a box |
|
||||||
print_box_message() { |
|
||||||
message=("$@") # Store all arguments in the array "message" |
|
||||||
edge="======================================" |
|
||||||
padding=" " |
|
||||||
|
|
||||||
echo "$edge" |
|
||||||
for element in "${message[@]}"; do |
|
||||||
echo "${padding}${element}" |
|
||||||
done |
|
||||||
echo "$edge" |
|
||||||
} |
|
||||||
|
|
||||||
# check command exists |
|
||||||
command_exists() { |
|
||||||
command -v "$1" >/dev/null 2>&1 |
|
||||||
} |
|
||||||
|
|
||||||
# install package based on platform |
|
||||||
install_package() { |
|
||||||
if command_exists yum; then |
|
||||||
sudo yum install -y "$1" |
|
||||||
elif command_exists apt; then |
|
||||||
sudo apt install -y "$1" |
|
||||||
elif command_exists brew; then |
|
||||||
brew install "$1" |
|
||||||
else |
|
||||||
echo "Package manager not found. Please install $1 manually." |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Function to check if sudo is required for Docker command |
|
||||||
check_for_docker_sudo() { |
|
||||||
if docker ps >/dev/null 2>&1; then |
|
||||||
echo "n" |
|
||||||
else |
|
||||||
echo "y" |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Function to read a number from the user |
|
||||||
read_number() { |
|
||||||
local number |
|
||||||
read -rp "$1" number |
|
||||||
|
|
||||||
# Ensure the input is a number or empty |
|
||||||
while ! [[ $number =~ ^[0-9]+$ ]] && [ -n "$number" ] ; do |
|
||||||
read -rp "Please enter a valid number: " number |
|
||||||
done |
|
||||||
|
|
||||||
echo "$number" |
|
||||||
} |
|
||||||
|
|
||||||
# Function to read a number within a range from the user |
|
||||||
read_number_range() { |
|
||||||
local number |
|
||||||
local min |
|
||||||
local max |
|
||||||
|
|
||||||
# Check if there are 3 arguments |
|
||||||
if [ "$#" -ne 3 ]; then |
|
||||||
number=$(read_number) |
|
||||||
min=$1 |
|
||||||
max=$2 |
|
||||||
else |
|
||||||
number=$(read_number "$1") |
|
||||||
min=$2 |
|
||||||
max=$3 |
|
||||||
fi |
|
||||||
|
|
||||||
# Ensure the input is in the specified range |
|
||||||
while [[ -n "$number" && ($number -lt $min || $number -gt $max) ]]; do |
|
||||||
number=$(read_number "Please enter a number between $min and $max: ") |
|
||||||
done |
|
||||||
|
|
||||||
echo "$number" |
|
||||||
} |
|
||||||
|
|
||||||
check_if_docker_is_running() { |
|
||||||
if ! $DOCKER_COMMAND ps >/dev/null 2>&1; then |
|
||||||
echo "+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+" |
|
||||||
echo -e "| ${BOLD}${YELLOW}Warning ! ${NC} |" |
|
||||||
echo "| Docker is not running. Most of the commands will not work without Docker. |" |
|
||||||
echo "| Use the following command to start Docker: |" |
|
||||||
echo -e "| ${BLUE} sudo systemctl start docker ${NC} |" |
|
||||||
echo "+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+" |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# ***************** HELPER FUNCTIONS END *********************************** |
|
||||||
# ****************************************************************************** |
|
||||||
|
|
||||||
# ***************************************************************************** |
|
||||||
# *************************** Management ************************************* |
|
||||||
|
|
||||||
# Function to display the menu |
|
||||||
show_menu() { |
|
||||||
clear |
|
||||||
check_if_docker_is_running |
|
||||||
echo "" |
|
||||||
echo "$MSG" |
|
||||||
echo -e "\t\t${BOLD}Service Management Menu${NC}" |
|
||||||
echo -e " ${GREEN}1. Start Service" |
|
||||||
echo -e " ${ORANGE}2. Stop Service" |
|
||||||
echo -e " ${CYAN}3. Logs" |
|
||||||
echo -e " ${MAGENTA}4. Restart" |
|
||||||
echo -e " ${BLUE}5. Upgrade" |
|
||||||
echo -e " 6. Scale" |
|
||||||
echo -e " 7. Monitoring" |
|
||||||
echo -e " ${RED}0. Exit${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Function to start the service |
|
||||||
start_service() { |
|
||||||
echo -e "\nStarting nocodb..." |
|
||||||
$DOCKER_COMMAND compose up -d |
|
||||||
} |
|
||||||
|
|
||||||
# Function to stop the service |
|
||||||
stop_service() { |
|
||||||
echo -e "\nStopping nocodb..." |
|
||||||
$DOCKER_COMMAND compose stop |
|
||||||
} |
|
||||||
|
|
||||||
show_logs_sub_menu() { |
|
||||||
clear |
|
||||||
echo "Select a replica for $1:" |
|
||||||
for i in $(seq 1 $2); do |
|
||||||
echo "$i. \"$1\" replica $i" |
|
||||||
done |
|
||||||
echo "A. All" |
|
||||||
echo "0. Back to Logs Menu" |
|
||||||
echo "Enter replica number: " |
|
||||||
read -r replica_choice |
|
||||||
|
|
||||||
if [[ "$replica_choice" =~ ^[0-9]+$ ]] && [ "$replica_choice" -gt 0 ] && [ "$replica_choice" -le "$2" ]; then |
|
||||||
container_id=$($DOCKER_COMMAND compose ps | grep "$1-$replica_choice" | cut -d " " -f 1) |
|
||||||
$DOCKER_COMMAND logs -f "$container_id" |
|
||||||
elif [ "$replica_choice" == "A" ] || [ "$replica_choice" == "a" ]; then |
|
||||||
$DOCKER_COMMAND compose logs -f "$1" |
|
||||||
elif [ "$replica_choice" == "0" ]; then |
|
||||||
show_logs |
|
||||||
else |
|
||||||
show_logs_sub_menu "$1" "$2" |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
# Function to show logs |
|
||||||
show_logs() { |
|
||||||
clear |
|
||||||
echo "Select a container for logs:" |
|
||||||
|
|
||||||
# Fetch the list of services |
|
||||||
services=() |
|
||||||
while IFS= read -r service; do |
|
||||||
services+=("$service") |
|
||||||
done < <($DOCKER_COMMAND compose ps --services) |
|
||||||
|
|
||||||
service_replicas=() |
|
||||||
count=0 |
|
||||||
|
|
||||||
# For each service, count the number of running instances |
|
||||||
for service in "${services[@]}"; do |
|
||||||
# Count the number of lines that have the service name, which corresponds to the number of replicas |
|
||||||
replicas=$($DOCKER_COMMAND compose ps "$service" | grep -c "$service") |
|
||||||
service_replicas["$count"]=$replicas |
|
||||||
count=$((count + 1)) |
|
||||||
done |
|
||||||
|
|
||||||
count=1 |
|
||||||
|
|
||||||
for service in "${services[@]}"; do |
|
||||||
echo "$count. $service (${service_replicas[(($count - 1))]} replicas)" |
|
||||||
count=$((count + 1)) |
|
||||||
done |
|
||||||
|
|
||||||
echo "A. All" |
|
||||||
echo "0. Back to main menu" |
|
||||||
echo "Enter your choice: " |
|
||||||
read -r log_choice |
|
||||||
echo |
|
||||||
|
|
||||||
if [[ "$log_choice" =~ ^[0-9]+$ ]] && [ "$log_choice" -gt 0 ] && [ "$log_choice" -lt "$count" ]; then |
|
||||||
service_index=$((log_choice-1)) |
|
||||||
service="${services[$service_index]}" |
|
||||||
num_replicas="${service_replicas[$service_index]}" |
|
||||||
|
|
||||||
if [ "$num_replicas" -gt 1 ]; then |
|
||||||
trap 'show_logs_sub_menu "$service" "$num_replicas"' INT |
|
||||||
show_logs_sub_menu "$service" "$num_replicas" |
|
||||||
trap - INT |
|
||||||
else |
|
||||||
trap 'show_logs' INT |
|
||||||
$DOCKER_COMMAND compose logs -f "$service" |
|
||||||
fi |
|
||||||
elif [ "$log_choice" == "A" ] || [ "$log_choice" == "a" ]; then |
|
||||||
trap 'show_logs' INT |
|
||||||
$DOCKER_COMMAND compose logs -f |
|
||||||
elif [ "$log_choice" == "0" ]; then |
|
||||||
return |
|
||||||
else |
|
||||||
show_logs |
|
||||||
fi |
|
||||||
|
|
||||||
trap - INT |
|
||||||
} |
|
||||||
|
|
||||||
# Function to restart the service |
|
||||||
restart_service() { |
|
||||||
echo -e "\nRestarting nocodb..." |
|
||||||
$DOCKER_COMMAND compose restart |
|
||||||
} |
|
||||||
|
|
||||||
# Function to upgrade the service |
|
||||||
upgrade_service() { |
|
||||||
echo -e "\nUpgrading nocodb..." |
|
||||||
$DOCKER_COMMAND compose pull |
|
||||||
$DOCKER_COMMAND compose up -d --force-recreate |
|
||||||
$DOCKER_COMMAND image prune -a -f |
|
||||||
} |
|
||||||
|
|
||||||
# Function to scale the service |
|
||||||
scale_service() { |
|
||||||
num_cores=$(nproc || sysctl -n hw.ncpu || echo 1) |
|
||||||
current_scale=$($DOCKER_COMMAND compose ps -q nocodb | wc -l) |
|
||||||
echo -e "\nCurrent number of instances: $current_scale" |
|
||||||
echo "How many instances of NocoDB do you want to run (Maximum: ${num_cores}) ? (default: 1): " |
|
||||||
scale_num=$(read_number_range 1 "$num_cores") |
|
||||||
|
|
||||||
if [ "$scale_num" -eq "$current_scale" ]; then |
|
||||||
echo "Number of instances is already set to $scale_num. Returning to main menu." |
|
||||||
return |
|
||||||
fi |
|
||||||
|
|
||||||
$DOCKER_COMMAND compose up -d --scale nocodb="$scale_num" |
|
||||||
} |
|
||||||
|
|
||||||
# Function for basic monitoring |
|
||||||
monitoring_service() { |
|
||||||
echo -e '\nLoading stats...' |
|
||||||
trap ' ' INT |
|
||||||
$DOCKER_COMMAND stats |
|
||||||
} |
|
||||||
|
|
||||||
management_menu() { |
|
||||||
# Main program loop |
|
||||||
while true; do |
|
||||||
trap - INT |
|
||||||
show_menu |
|
||||||
echo "Enter your choice: " |
|
||||||
|
|
||||||
read -r choice |
|
||||||
case $choice in |
|
||||||
1) start_service && MSG="NocoDB Started" ;; |
|
||||||
2) stop_service && MSG="NocoDB Stopped" ;; |
|
||||||
3) show_logs ;; |
|
||||||
4) restart_service && MSG="NocoDB Restarted" ;; |
|
||||||
5) upgrade_service && MSG="NocoDB has been upgraded to latest version" ;; |
|
||||||
6) scale_service && MSG="NocoDB has been scaled" ;; |
|
||||||
7) monitoring_service ;; |
|
||||||
0) exit 0 ;; |
|
||||||
*) MSG="\nInvalid choice. Please select a correct option." ;; |
|
||||||
esac |
|
||||||
done |
|
||||||
} |
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# *************************** Management END ********************************** |
|
||||||
|
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# ***************** Existing Install Test ************************************ |
|
||||||
|
|
||||||
IS_DOCKER_REQUIRE_SUDO=$(check_for_docker_sudo) |
|
||||||
DOCKER_COMMAND=$([ "$IS_DOCKER_REQUIRE_SUDO" = "y" ] && echo "sudo docker" || echo "docker") |
|
||||||
|
|
||||||
NOCO_FOUND=false |
|
||||||
|
|
||||||
# Check if $NOCO_HOME exists as directory |
|
||||||
if [ -d "$NOCO_HOME" ]; then |
|
||||||
NOCO_FOUND=true |
|
||||||
elif $DOCKER_COMMAND ps --format '{{.Names}}' | grep -q "nocodb"; then |
|
||||||
NOCO_ID=$(docker ps | grep "nocodb/nocodb" | cut -d ' ' -f 1) |
|
||||||
CUSTOM_HOME=$(docker inspect --format='{{index .Mounts 0}}' "$NOCO_ID" | cut -d ' ' -f 3) |
|
||||||
PARENT_DIR=$(dirname "$CUSTOM_HOME") |
|
||||||
|
|
||||||
ln -s "$PARENT_DIR" "$NOCO_HOME" |
|
||||||
basename "$PARENT_DIR" > "$NOCO_HOME/.COMPOSE_PROJECT_NAME" |
|
||||||
|
|
||||||
NOCO_FOUND=true |
|
||||||
else |
|
||||||
mkdir -p "$NOCO_HOME" |
|
||||||
fi |
|
||||||
|
|
||||||
cd "$NOCO_HOME" || exit 1 |
|
||||||
|
|
||||||
# Check if nocodb is already installed |
|
||||||
if [ "$NOCO_FOUND" = true ]; then |
|
||||||
echo "NocoDB is already installed. And running." |
|
||||||
echo "Do you want to reinstall NocoDB? [Y/N] (default: N): " |
|
||||||
read -r REINSTALL |
|
||||||
|
|
||||||
if [ -f "$NOCO_HOME/.COMPOSE_PROJECT_NAME" ]; then |
|
||||||
COMPOSE_PROJECT_NAME=$(cat "$NOCO_HOME/.COMPOSE_PROJECT_NAME") |
|
||||||
export COMPOSE_PROJECT_NAME |
|
||||||
fi |
|
||||||
|
|
||||||
if [ "$REINSTALL" != "Y" ] && [ "$REINSTALL" != "y" ]; then |
|
||||||
management_menu |
|
||||||
exit 0 |
|
||||||
else |
|
||||||
echo "Reinstalling NocoDB..." |
|
||||||
$DOCKER_COMMAND compose down |
|
||||||
|
|
||||||
unset COMPOSE_PROJECT_NAME |
|
||||||
cd /tmp || exit 1 |
|
||||||
rm -rf "$NOCO_HOME" |
|
||||||
|
|
||||||
cd "$CURRENT_PATH" || exit 1 |
|
||||||
mkdir -p "$NOCO_HOME" |
|
||||||
cd "$NOCO_HOME" || exit 1 |
|
||||||
fi |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# ******************** SYSTEM REQUIREMENTS CHECK START ************************* |
|
||||||
|
|
||||||
# Check if the following requirements are met: |
|
||||||
# a. docker, jq installed |
|
||||||
# b. port mapping check : 80,443 are free or being used by nginx container |
|
||||||
|
|
||||||
REQUIRED_PORTS=(80 443) |
|
||||||
|
|
||||||
echo "** Performing nocodb system check and setup. This step may require sudo permissions" |
|
||||||
|
|
||||||
# pre-install wget if not found |
|
||||||
if ! command_exists wget; then |
|
||||||
echo "wget is not installed. Setting up for installation..." |
|
||||||
install_package wget |
|
||||||
fi |
|
||||||
|
|
||||||
# d. Check if required tools are installed |
|
||||||
echo " | Checking if required tools (docker, lsof) are installed..." |
|
||||||
for tool in docker lsof openssl; do |
|
||||||
if ! command_exists "$tool"; then |
|
||||||
echo "$tool is not installed. Setting up for installation..." |
|
||||||
if [ "$tool" = "docker" ]; then |
|
||||||
wget -qO- https://get.docker.com/ | sh |
|
||||||
elif [ "$tool" = "lsof" ]; then |
|
||||||
install_package lsof |
|
||||||
fi |
|
||||||
fi |
|
||||||
done |
|
||||||
|
|
||||||
|
|
||||||
# f. Port mapping check |
|
||||||
echo " | Checking port accessibility..." |
|
||||||
for port in "${REQUIRED_PORTS[@]}"; do |
|
||||||
if lsof -Pi :"$port" -sTCP:LISTEN -t >/dev/null; then |
|
||||||
echo " | WARNING: Port $port is in use. Please make sure it is free." >&2 |
|
||||||
else |
|
||||||
echo " | Port $port is free." |
|
||||||
fi |
|
||||||
done |
|
||||||
|
|
||||||
echo "** System check completed successfully. **" |
|
||||||
|
|
||||||
|
|
||||||
# Define an array to store the messages to be printed at the end |
|
||||||
message_arr=() |
|
||||||
|
|
||||||
# extract public ip address |
|
||||||
PUBLIC_IP=$(dig +short myip.opendns.com @resolver1.opendns.com) |
|
||||||
|
|
||||||
# Check if the public IP address is not empty, if empty then use the localhost |
|
||||||
if [ -z "$PUBLIC_IP" ]; then |
|
||||||
PUBLIC_IP="localhost" |
|
||||||
fi |
|
||||||
|
|
||||||
message_arr+=("Setup folder: $NOCO_HOME") |
|
||||||
|
|
||||||
# ******************** SYSTEM REQUIREMENTS CHECK END ************************** |
|
||||||
# ****************************************************************************** |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ******************** INPUTS FROM USER START ******************************** |
|
||||||
# ****************************************************************************** |
|
||||||
|
|
||||||
echo "Enter the IP address or domain name for the NocoDB instance (default: $PUBLIC_IP): " |
|
||||||
read -r DOMAIN_NAME |
|
||||||
|
|
||||||
echo "Show Advanced Options [Y/N] (default: N): " |
|
||||||
read -r ADVANCED_OPTIONS |
|
||||||
|
|
||||||
if [ "$ADVANCED_OPTIONS" == "Y" ]; then |
|
||||||
ADVANCED_OPTIONS="y" |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -n "$DOMAIN_NAME" ]; then |
|
||||||
if [ "$ADVANCED_OPTIONS" == "y" ]; then |
|
||||||
echo "Do you want to configure SSL [Y/N] (default: N): " |
|
||||||
read -r SSL_ENABLED |
|
||||||
message_arr+=("SSL: ${SSL_ENABLED}") |
|
||||||
fi |
|
||||||
else |
|
||||||
DOMAIN_NAME="$PUBLIC_IP" |
|
||||||
fi |
|
||||||
|
|
||||||
message_arr+=("Domain: $PUBLIC_IP") |
|
||||||
|
|
||||||
if [ "$ADVANCED_OPTIONS" == "y" ]; then |
|
||||||
echo "Choose Community or Enterprise Edition [CE/EE] (default: CE): " |
|
||||||
read -r EDITION |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -n "$EDITION" ] && { [ "$EDITION" = "EE" ] || [ "$EDITION" = "ee" ]; }; then |
|
||||||
echo "Enter the NocoDB license key: " |
|
||||||
read -r LICENSE_KEY |
|
||||||
if [ -z "$LICENSE_KEY" ]; then |
|
||||||
echo "License key is required for Enterprise Edition installation" |
|
||||||
exit 1 |
|
||||||
fi |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
if [ "$ADVANCED_OPTIONS" == "y" ]; then |
|
||||||
echo "Do you want to enabled Redis for caching [Y/N] (default: Y): " |
|
||||||
read -r REDIS_ENABLED |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -z "$REDIS_ENABLED" ] || { [ "$REDIS_ENABLED" != "N" ] && [ "$REDIS_ENABLED" != "n" ]; }; then |
|
||||||
message_arr+=("Redis: Enabled") |
|
||||||
else |
|
||||||
message_arr+=("Redis: Disabled") |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
if [ "$ADVANCED_OPTIONS" == "y" ]; then |
|
||||||
echo "Do you want to enabled Watchtower for automatic updates [Y/N] (default: Y): " |
|
||||||
read -r WATCHTOWER_ENABLED |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -z "$WATCHTOWER_ENABLED" ] || { [ "$WATCHTOWER_ENABLED" != "N" ] && [ "$WATCHTOWER_ENABLED" != "n" ]; }; then |
|
||||||
message_arr+=("Watchtower: Enabled") |
|
||||||
else |
|
||||||
message_arr+=("Watchtower: Disabled") |
|
||||||
fi |
|
||||||
|
|
||||||
if [ "$ADVANCED_OPTIONS" = "y" ] ; then |
|
||||||
NUM_CORES=$(nproc || sysctl -n hw.ncpu || echo 1) |
|
||||||
echo "How many instances of NocoDB do you want to run (Maximum: ${NUM_CORES}) ? (default: 1): " |
|
||||||
NUM_INSTANCES=$(read_number_range 1 "$NUM_CORES") |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -z "$NUM_INSTANCES" ]; then |
|
||||||
NUM_INSTANCES=1 |
|
||||||
fi |
|
||||||
|
|
||||||
message_arr+=("Number of instances: $NUM_INSTANCES") |
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# *********************** INPUTS FROM USER END ******************************** |
|
||||||
|
|
||||||
|
|
||||||
# ****************************************************************************** |
|
||||||
# *************************** SETUP START ************************************* |
|
||||||
|
|
||||||
# Generate a strong random password for PostgreSQL |
|
||||||
STRONG_PASSWORD=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*()-_+=' | head -c 32) |
|
||||||
REDIS_PASSWORD=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 24) |
|
||||||
# Encode special characters in the password for JDBC URL usage |
|
||||||
ENCODED_PASSWORD=$(urlencode "$STRONG_PASSWORD") |
|
||||||
|
|
||||||
IMAGE="nocodb/nocodb:latest"; |
|
||||||
|
|
||||||
# Determine the Docker image to use based on the edition |
|
||||||
if [ -n "$EDITION" ] && { [ "$EDITION" = "EE" ] || [ "$EDITION" = "ee" ]; }; then |
|
||||||
IMAGE="nocodb/nocodb-ee:latest" |
|
||||||
DATABASE_URL="DATABASE_URL=postgres://postgres:${ENCODED_PASSWORD}@db:5432/nocodb" |
|
||||||
else |
|
||||||
# use NC_DB url until the issue with DATABASE_URL is resolved(encoding) |
|
||||||
DATABASE_URL="NC_DB=pg://db:5432?d=nocodb&user=postgres&password=${ENCODED_PASSWORD}" |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
message_arr+=("Docker image: $IMAGE") |
|
||||||
|
|
||||||
|
|
||||||
DEPENDS_ON="" |
|
||||||
|
|
||||||
# Add Redis service if enabled |
|
||||||
if [ -z "$REDIS_ENABLED" ] || { [ "$REDIS_ENABLED" != "N" ] && [ "$REDIS_ENABLED" != "n" ]; }; then |
|
||||||
DEPENDS_ON="- redis" |
|
||||||
fi |
|
||||||
|
|
||||||
|
|
||||||
# Write the Docker Compose file with the updated password |
|
||||||
cat <<EOF > docker-compose.yml |
|
||||||
services: |
|
||||||
nocodb: |
|
||||||
image: ${IMAGE} |
|
||||||
env_file: docker.env |
|
||||||
deploy: |
|
||||||
mode: replicated |
|
||||||
replicas: ${NUM_INSTANCES} |
|
||||||
depends_on: |
|
||||||
- db |
|
||||||
${DEPENDS_ON} |
|
||||||
restart: unless-stopped |
|
||||||
volumes: |
|
||||||
- ./nocodb:/usr/app/data |
|
||||||
labels: |
|
||||||
- "com.centurylinklabs.watchtower.enable=true" |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
db: |
|
||||||
image: postgres:16.1 |
|
||||||
env_file: docker.env |
|
||||||
volumes: |
|
||||||
- ./postgres:/var/lib/postgresql/data |
|
||||||
restart: unless-stopped |
|
||||||
healthcheck: |
|
||||||
interval: 10s |
|
||||||
retries: 10 |
|
||||||
test: "pg_isready -U \"\$\$POSTGRES_USER\" -d \"\$\$POSTGRES_DB\"" |
|
||||||
timeout: 2s |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
|
|
||||||
nginx: |
|
||||||
image: nginx:latest |
|
||||||
labels: |
|
||||||
com.nocodb.service: "nginx" |
|
||||||
volumes: |
|
||||||
- ./nginx:/etc/nginx/conf.d |
|
||||||
EOF |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
- webroot:/var/www/certbot |
|
||||||
- ./letsencrypt:/etc/letsencrypt |
|
||||||
- letsencrypt-lib:/var/lib/letsencrypt |
|
||||||
EOF |
|
||||||
fi |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
ports: |
|
||||||
- "80:80" |
|
||||||
- "443:443" |
|
||||||
depends_on: |
|
||||||
- nocodb |
|
||||||
restart: unless-stopped |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
EOF |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
certbot: |
|
||||||
image: certbot/certbot |
|
||||||
volumes: |
|
||||||
- ./letsencrypt:/etc/letsencrypt |
|
||||||
- letsencrypt-lib:/var/lib/letsencrypt |
|
||||||
- webroot:/var/www/certbot |
|
||||||
entrypoint: | |
|
||||||
/bin/sh -c ' |
|
||||||
apk add docker-cli || { echo "Failed to install Docker CLI"; exit 1; }; |
|
||||||
trap exit TERM; |
|
||||||
while :; do |
|
||||||
OUTPUT=\$\$(certbot renew 2>&1); |
|
||||||
echo "\$\$OUTPUT"; |
|
||||||
if echo "\$\$OUTPUT" | grep -q "No renewals were attempted"; then |
|
||||||
echo "No certificates were renewed."; |
|
||||||
else |
|
||||||
echo "Certificates renewed. Reloading nginx..."; |
|
||||||
sleep 5; |
|
||||||
CONTAINER_NAME=\$\$(docker ps --format "{{.Names}}" --filter "com.nocodb.service=nginx" | grep "nginx") || { echo "Failed to find nginx container"; exit 1; }; |
|
||||||
docker exec \$\$CONTAINER_NAME nginx -s reload || { echo "Failed to reload nginx"; exit 1; }; |
|
||||||
fi; |
|
||||||
sleep 12h & wait \$\${!}; |
|
||||||
done;' |
|
||||||
depends_on: |
|
||||||
- nginx |
|
||||||
restart: unless-stopped |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -z "$REDIS_ENABLED" ] || { [ "$REDIS_ENABLED" != "N" ] && [ "$REDIS_ENABLED" != "n" ]; }; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
redis: |
|
||||||
image: redis:latest |
|
||||||
restart: unless-stopped |
|
||||||
env_file: docker.env |
|
||||||
command: |
|
||||||
- /bin/sh |
|
||||||
- -c |
|
||||||
- redis-server --requirepass "\$\${REDIS_PASSWORD}" |
|
||||||
volumes: |
|
||||||
- redis:/data |
|
||||||
healthcheck: |
|
||||||
test: [ "CMD", "redis-cli", "-a", "\$\${REDIS_PASSWORD}", "--raw", "incr", "ping" ] |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
if [ -z "$WATCHTOWER_ENABLED" ] || { [ "$WATCHTOWER_ENABLED" != "N" ] && [ "$WATCHTOWER_ENABLED" != "n" ]; }; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
watchtower: |
|
||||||
image: containrrr/watchtower |
|
||||||
volumes: |
|
||||||
- /var/run/docker.sock:/var/run/docker.sock |
|
||||||
command: --schedule "0 2 * * 6" --cleanup |
|
||||||
restart: unless-stopped |
|
||||||
networks: |
|
||||||
- nocodb-network |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
volumes: |
|
||||||
letsencrypt-lib: |
|
||||||
webroot: |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
# add the cache volume |
|
||||||
if [ -z "$REDIS_ENABLED" ] || { [ "$REDIS_ENABLED" != "N" ] && [ "$REDIS_ENABLED" != "n" ]; }; then |
|
||||||
# check ssl enabled |
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
redis: |
|
||||||
EOF |
|
||||||
else |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
volumes: |
|
||||||
redis: |
|
||||||
EOF |
|
||||||
fi |
|
||||||
fi |
|
||||||
|
|
||||||
# Create the network |
|
||||||
cat <<EOF >> docker-compose.yml |
|
||||||
networks: |
|
||||||
nocodb-network: |
|
||||||
driver: bridge |
|
||||||
EOF |
|
||||||
|
|
||||||
# Write the docker.env file |
|
||||||
cat <<EOF > docker.env |
|
||||||
POSTGRES_DB=nocodb |
|
||||||
POSTGRES_USER=postgres |
|
||||||
POSTGRES_PASSWORD=${STRONG_PASSWORD} |
|
||||||
$DATABASE_URL |
|
||||||
NC_LICENSE_KEY=${LICENSE_KEY} |
|
||||||
EOF |
|
||||||
|
|
||||||
# add redis env if enabled |
|
||||||
if [ -z "$REDIS_ENABLED" ] || { [ "$REDIS_ENABLED" != "N" ] && [ "$REDIS_ENABLED" != "n" ]; }; then |
|
||||||
cat <<EOF >> docker.env |
|
||||||
REDIS_PASSWORD=${REDIS_PASSWORD} |
|
||||||
NC_REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
mkdir -p ./nginx |
|
||||||
|
|
||||||
# Create nginx config with the provided domain name |
|
||||||
cat > ./nginx/default.conf <<EOF |
|
||||||
server { |
|
||||||
listen 80; |
|
||||||
EOF |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat >> ./nginx/default.conf <<EOF |
|
||||||
server_name $DOMAIN_NAME; |
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
cat >> ./nginx/default.conf <<EOF |
|
||||||
location / { |
|
||||||
proxy_pass http://nocodb:8080; |
|
||||||
proxy_set_header Host \$host; |
|
||||||
proxy_set_header X-Real-IP \$remote_addr; |
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; |
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme; |
|
||||||
} |
|
||||||
EOF |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
cat >> ./nginx/default.conf <<EOF |
|
||||||
location /.well-known/acme-challenge/ { |
|
||||||
root /var/www/certbot; |
|
||||||
} |
|
||||||
EOF |
|
||||||
fi |
|
||||||
cat >> ./nginx/default.conf <<EOF |
|
||||||
} |
|
||||||
EOF |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
|
|
||||||
mkdir -p ./nginx-post-config |
|
||||||
|
|
||||||
# Create nginx config with the provided domain name |
|
||||||
cat > ./nginx-post-config/default.conf <<EOF |
|
||||||
upstream nocodb_backend { |
|
||||||
least_conn; |
|
||||||
server nocodb:8080; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
server { |
|
||||||
listen 80; |
|
||||||
server_name $DOMAIN_NAME; |
|
||||||
|
|
||||||
location / { |
|
||||||
return 301 https://\$host\$request_uri; |
|
||||||
} |
|
||||||
|
|
||||||
location /.well-known/acme-challenge/ { |
|
||||||
root /var/www/certbot; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
server { |
|
||||||
listen 443 ssl; |
|
||||||
server_name $DOMAIN_NAME; |
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/$DOMAIN_NAME/fullchain.pem; |
|
||||||
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem; |
|
||||||
|
|
||||||
location / { |
|
||||||
proxy_pass http://nocodb_backend; |
|
||||||
proxy_set_header Host \$host; |
|
||||||
proxy_set_header X-Real-IP \$remote_addr; |
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; |
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
EOF |
|
||||||
fi |
|
||||||
|
|
||||||
cat > ./update.sh <<EOF |
|
||||||
$DOCKER_COMMAND compose pull |
|
||||||
$DOCKER_COMMAND compose up -d --force-recreate |
|
||||||
$DOCKER_COMMAND image prune -a -f |
|
||||||
EOF |
|
||||||
|
|
||||||
message_arr+=("Update script: update.sh") |
|
||||||
|
|
||||||
$DOCKER_COMMAND compose pull |
|
||||||
$DOCKER_COMMAND compose up -d |
|
||||||
|
|
||||||
echo 'Waiting for Nginx to start...'; |
|
||||||
|
|
||||||
sleep 5 |
|
||||||
|
|
||||||
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
||||||
echo 'Starting Letsencrypt certificate request...'; |
|
||||||
|
|
||||||
$DOCKER_COMMAND compose exec certbot certbot certonly --webroot --webroot-path=/var/www/certbot -d "$DOMAIN_NAME" --email "contact@$DOMAIN_NAME" --agree-tos --no-eff-email && echo "Certificate request successful" || echo "Certificate request failed" |
|
||||||
# Initial Let's Encrypt certificate request |
|
||||||
|
|
||||||
# Update the nginx config to use the new certificates |
|
||||||
rm -rf ./nginx/default.conf |
|
||||||
mv ./nginx-post-config/default.conf ./nginx/ |
|
||||||
rm -r ./nginx-post-config |
|
||||||
|
|
||||||
echo "Restarting nginx to apply the new certificates" |
|
||||||
# Reload nginx to apply the new certificates |
|
||||||
$DOCKER_COMMAND compose exec nginx nginx -s reload |
|
||||||
|
|
||||||
message_arr+=("NocoDB is now available at https://$DOMAIN_NAME") |
|
||||||
|
|
||||||
elif [ -n "$DOMAIN_NAME" ]; then |
|
||||||
message_arr+=("NocoDB is now available at http://$DOMAIN_NAME") |
|
||||||
else |
|
||||||
message_arr+=("NocoDB is now available at http://localhost") |
|
||||||
fi |
|
||||||
|
|
||||||
print_box_message "${message_arr[@]}" |
|
||||||
|
|
||||||
# *************************** SETUP END ************************************* |
|
||||||
# **************************************************************************** |
|
||||||
|
|
||||||
echo "Do you want to start the management menu [Y/N] (default: Y): " |
|
||||||
read -r MANAGEMENT_MENU |
|
||||||
|
|
||||||
if [ -z "$MANAGEMENT_MENU" ] || { [ "$MANAGEMENT_MENU" != "N" ] && [ "$MANAGEMENT_MENU" != "n" ]; }; then |
|
||||||
management_menu |
|
||||||
fi |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 262 B |
After Width: | Height: | Size: 759 B |
After Width: | Height: | Size: 801 B |
After Width: | Height: | Size: 705 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 552 B |
After Width: | Height: | Size: 552 B |
After Width: | Height: | Size: 562 B |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 820 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 373 B |
After Width: | Height: | Size: 820 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 832 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 373 B |