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