diff --git a/.gitignore b/.gitignore index e15bae5..4b0e10c 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,6 @@ Temporary Items .apdisk .tools +build +.cache .idea/ diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index b124f60..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,38 +0,0 @@ -pipeline { - agent { label 'linux-docker-small' } - options { - buildDiscarder(logRotator(numToKeepStr:'25')) - disableConcurrentBuilds() - timestamps() - } - triggers { - /* - Restrict nightly builds to master branch - Note: The BRANCH_NAME will only work with a multi-branch job using the github-branch-source - */ - cron(BRANCH_NAME == "master" ? "H H(4-6) * * *" : "") - } - environment { PATH="${tool 'docker-latest'}/bin:$PATH" } - stages { - stage('Build Images') { - steps { - sh 'make image' - } - } - stage('Deploy Images') { - when { - allOf { - expression { env.CHANGE_ID == null } - expression { env.BRANCH_NAME == "master" } - } - } - environment { - DOCKER_LOGIN = credentials('dockerhub-codicebot') - } - steps { - sh 'docker login -u $DOCKER_LOGIN_USR -p $DOCKER_LOGIN_PSW' - sh 'make push' - } - } - } -} diff --git a/Makefile b/Makefile index b9f5c43..0b427b4 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,53 @@ -# Set the base name for the image -IMAGE_NAME:=codice/ddf-base - -GIT_SHA:=$(shell git rev-parse HEAD) -MASTER_SHA:=$(shell git show-ref -s refs/heads/master) -ifneq (${MASTER_SHA}, ${GIT_SHA}) - IMAGE_VERSION=${GIT_SHA} +PROJECT_NAME ?= ddf-entrypoint +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +project_home := $(patsubst %/,%,$(dir $(mkfile_path))) +version_file := Version.txt +CACHE_DIR := .cache +BINARY_CACHE := $(CACHE_DIR)/bin +TOOLS_DIR := .tools +ifeq (, $(shell which podman)) + CONTAINER := docker container else - IMAGE_VERSION=latest + CONTAINER := podman container endif -# Compute Build Tag -BUILD_TAG=$(IMAGE_NAME):$(IMAGE_VERSION) + +BATS = $(CONTAINER) run --rm -it --entrypoint=bash -v ./$<:/opt/entrypoint.tar.gz -v ./$@:/tests --workdir /tests docker.io/bats/bats -c "apk add --no-cache bash && mkdir /opt/entrypoint && tar xzf /opt/entrypoint.tar.gz -C /opt/entrypoint && bats *.bats" + +ARGBASH := $(TOOLS_DIR)/argbash/bin/argbash + +BUILD_DIR := build +BUILD_PACKAGES_DIR := $(BUILD_DIR)/packages +ARGBASH_PREP_DIR := $(BUILD_DIR)/argbash-templates +BUILD_PREP_DIR := $(BUILD_DIR)/prep +VERSION := $(shell cat $(version_file)) +PACKAGE_NAME := $(PROJECT_NAME)-$(VERSION) +ARCHIVE_PREP_DIR := $(BUILD_PREP_DIR)/$(PACKAGE_NAME) +ARCHIVE_NAME := $(PACKAGE_NAME).tar.gz +ARCHIVE_OUTPUT := $(BUILD_PACKAGES_DIR)/$(ARCHIVE_NAME) +INSTALL_OUTPUT := $(BUILD_PREP_DIR)/$(PACKAGE_NAME) + +PROPS_VERSION := 0.2.0 +JQ_VERSION := 1.5 +ARGBASH_VERSION := 2.7.1 +ENVSUBST_VERSION := 1.1.0 +PROPS_DOWNLOAD_URL := https://github.com/oconnormi/props/releases/download/v$(PROPS_VERSION)/props_linux_amd64 +JQ_DOWNLOAD_URL := https://github.com/stedolan/jq/releases/download/jq-$(JQ_VERSION)/jq-linux64 +ARGBASH_DOWNLOAD_URL := https://github.com/matejak/argbash/archive/$(ARGBASH_VERSION).tar.gz +ENVSUBST_DOWNLOAD_URL := https://github.com/a8m/envsubst/releases/download/v$(ENVSUBST_VERSION)/envsubst-Linux-x86_64 + +environment_sources := $(wildcard environment/*.env) +environment_targets := $(patsubst environment/%.env, $(ARCHIVE_PREP_DIR)/environment/%.env, $(environment_sources)) +current_environment_source = $(patsubst $(ARCHIVE_PREP_DIR)/environment/%.env, environment/%.env, $@) +library_sources := $(wildcard library/*.sh) +library_targets := $(patsubst library/%.sh, $(ARCHIVE_PREP_DIR)/library/%.sh, $(library_sources)) +current_library_source = $(patsubst $(ARCHIVE_PREP_DIR)/library/%.sh, library/%.sh, $@) +argbash_sources := $(wildcard argbash-templates/*.m4) +argbash_targets := $(patsubst argbash-templates/%.m4, $(ARCHIVE_PREP_DIR)/bin/%, $(argbash_sources)) +current_argbash_source = $(patsubst $(ARCHIVE_PREP_DIR)/bin/%, argbash-templates/%.m4, $@) +files_sources := $(shell find files -maxdepth 1 -mindepth 1 -type d) +files_targets := $(patsubst files/%, $(ARCHIVE_PREP_DIR)/%, $(files_sources)) +current_file_source = $(patsubst $(ARCHIVE_PREP_DIR)/%, files/%, $@) + .DEFAULT_GOAL := help @@ -17,13 +55,141 @@ BUILD_TAG=$(IMAGE_NAME):$(IMAGE_VERSION) help: ## Display help. @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) -.PHONY: image -image: ## Build the docker image - @echo "Building $(BUILD_TAG)" - @docker build --pull -t $(BUILD_TAG) . +.PHONY: clean +clean: ## Cleans up build artifacts + @rm -rf $(BUILD_DIR) + +.PHONY: clean_cache +clean_cache: ## Cleans up download cache + @rm -rf $(CACHE_DIR) + +.PHONY: build +build: package test ## Build and test the entrypoint + +.PHONY: package +package: dependencies prepare $(ARCHIVE_OUTPUT) ## Package the project output into an archive + +.PHONY: test +test: argbash-templates/tests tests ## Run Tests + +.PHONY: argbash-templates/tests +argbash-templates/tests: $(ARCHIVE_OUTPUT) ## Test Argbash Templates + $(BATS) + +.PHONY: tests +tests: $(ARCHIVE_OUTPUT) ## Run Integration Tests + $(BATS) + +.PHONY: prepare +prepare: tools $(ARCHIVE_PREP_DIR) $(environment_targets) $(library_targets) $(argbash_targets) $(ARCHIVE_PREP_DIR)/bin/jq $(ARCHIVE_PREP_DIR)/bin/props $(files_targets) ## Prepares for packaging + +.PHONY: dependencies +dependencies: $(BINARY_CACHE)/props $(BINARY_CACHE)/jq + +.PHONY: tools +tools: $(TOOLS_DIR)/argbash ## Downloads and prepares any tools used by the build + +$(CACHE_DIR): + @mkdir -p $@ + +$(BINARY_CACHE): $(CACHE_DIR) + @mkdir -p $@ + +$(BINARY_CACHE)/props: $(BINARY_CACHE) + @wget -N -O $@ $(PROPS_DOWNLOAD_URL) + @touch $@ + @chmod 755 $@ + +$(BINARY_CACHE)/jq: $(BINARY_CACHE) + @wget -N -O $@ $(JQ_DOWNLOAD_URL) + @touch $@ + @chmod 755 $@ + +$(BINARY_CACHE)/envsubst: $(BINARY_CACHE) + @wget -N -O $@ $(ENVSUBST_DOWNLOAD_URL) + @touch $@ + @chmod 755 $@ + +$(TOOLS_DIR): + @mkdir -p $@ + +$(TOOLS_DIR)/argbash: $(CACHE_DIR)/argbash.tar.gz $(TOOLS_DIR) + @mkdir -p $@ + @tar xzf $< -C $@ --strip-components=1 + +$(CACHE_DIR)/argbash.tar.gz: $(CACHE_DIR) + @wget -N -O $@ $(ARGBASH_DOWNLOAD_URL) + @touch $@ + +$(BUILD_DIR): + @mkdir -p $@ + +$(BUILD_PREP_DIR): $(BUILD_DIR) + @mkdir -p $@ + +$(BUILD_PACKAGES_DIR): $(BUILD_DIR) + @mkdir -p $@ + +$(ARCHIVE_PREP_DIR): $(BUILD_PREP_DIR) + @mkdir -p $@ + +# Begin Processing sources +# Environment Files +$(ARCHIVE_PREP_DIR)/environment: $(BUILD_PREP_DIR)/$(PACKAGE_NAME) + @mkdir -p $@ + +$(environment_targets): %.env: $(ARCHIVE_PREP_DIR)/environment + @echo "Copying env file: $(current_environment_source) to: $@" + @cp $(current_environment_source) $@ + @chmod 755 $@ + +# Library Scripts +$(ARCHIVE_PREP_DIR)/library: $(ARCHIVE_PREP_DIR) + @mkdir -p $@ + +$(library_targets): %.sh: $(ARCHIVE_PREP_DIR)/library + @echo "Copying library file: $(current_library_source) to: $@" + @cp $(current_library_source) $@ + @chmod 755 $@ + +# Argbash Scripts +$(ARCHIVE_PREP_DIR)/bin: $(ARCHIVE_PREP_DIR) + @mkdir -p $@ + +$(ARGBASH_PREP_DIR): $(BUILD_DIR) + @mkdir -p $@ + +$(argbash_targets): %: $(ARCHIVE_PREP_DIR)/bin $(TOOLS_DIR)/argbash + @echo "Building Argbash Template $(current_argbash_source) as $@" + @$(ARGBASH) $(current_argbash_source) -o $@ + @touch $@ + +$(ARCHIVE_PREP_DIR)/bin/jq: $(BINARY_CACHE)/jq $(ARCHIVE_PREP_DIR)/bin + @echo "Copying jq from $< to $@" + @cp $< $@ + @chmod 755 $@ + @touch $@ + +$(files_targets): %: $(ARCHIVE_PREP_DIR) + @cp -R $(current_file_source) $@ + +$(ARCHIVE_PREP_DIR)/bin/props: $(BINARY_CACHE)/props $(ARCHIVE_PREP_DIR)/bin + @echo "Copying props from $< to $@" + @cp $< $@ + @chmod 755 $@ + @touch $@ + +$(ARCHIVE_PREP_DIR)/bin/envsubst: $(BINARY_CACHE)/envsubst $(ARCHIVE_PREP_DIR)/bin + @echo "Copying envsubst from $< to $@" + @cp $< $@ + @chmod 755 $@ + touch $@ -.PHONY: push -push: image ## Push the docker image - @echo "Pushing $(BUILD_TAG)" - @docker push $(BUILD_TAG) +$(ARCHIVE_PREP_DIR)/entrypoint.sh: $(ARCHIVE_PREP_DIR) + @cp entrypoint.sh $@ + @touch $@ + @chmod 755 $@ +$(ARCHIVE_OUTPUT): $(ARCHIVE_PREP_DIR) $(BUILD_PACKAGES_DIR) $(ARCHIVE_PREP_DIR)/bin/props $(ARCHIVE_PREP_DIR)/bin/jq $(ARCHIVE_PREP_DIR)/bin/envsubst $(ARCHIVE_PREP_DIR)/entrypoint.sh $(argbash_targets) $(library_targets) $(environment_targets) $(files_targets) + @echo "Packaging Entrypoint Distribution $@ from $<" + @tar czf $@ -C $< . diff --git a/README.md b/README.adoc similarity index 60% rename from README.md rename to README.adoc index 758e243..b5aad3b 100644 --- a/README.md +++ b/README.adoc @@ -1,54 +1,75 @@ -# DDF Base +ifdef::env-github[] +:tip-caption: :bulb: +:note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:warning-caption: :warning: +endif::[] -Base level docker image containing all dependencies for DDF as well as a common set of steps for running a DDF based distribution +:toc: +:toc-placement!: -## Notice on Versions + += DDF Base + +Entrypoint scripts for booting and configuring ddf based distributions. Intended to be packaged in container and vm images. + +toc::[] + +[IMPORTANT] +==== +This repository no longer produces a docker image. +A versioned tarball is produced instead, and should be pulled into any image that needs to make use of the entrypoint functionality. +To this end the entrypoint has been refactored to make it more portable. +==== + +== Notice on Versions This repo has been re-organized to have a single version of the entrypoint scripts going forward. the previous state of the repository can be found on the `legacy` branch. -## Usage Requirements +== Usage Requirements -This image is meant to be the basis for any ddf based image. +These scripts are meant to be used as the entrypoint for any for any ddf based image. It packages the dependencies and an entrypoint script for use with any ddf based application -Any downstream containers must provide environment variables for: +There are some minimal requirements for using this entrypoint script within an image. + +=== Environment Variables * APP_NAME - Name of application, used for branding by the entrypoint * APP_HOME - Home Directory for application installation (should have a bin directory as a child) * APP_LOG - Location of the application log file -```Dockerfile -FROM codice/ddf-base +=== Packages -ENV APP_NAME= -ENV APP_HOME= -ENV APP_LOG= -... -# Install application -``` -## Features +* curl +* openssl + +== Features * Oracle JDK8 - * [jq](https://stedolan.github.io/jq/) for processing json + * https://stedolan.github.io/jq/[jq] for processing json * curl - * [props](https://github.com/oconnormi/props) tool for modifying properties files + * https://github.com/oconnormi/props[props] tool for modifying properties files * Common entry point for DDF based distributions * Automated certificate generation * Automated initial setup and configuration * Can request certs from a remote cfssl based CA via `CA_REMOTE_URL=https://:` -## Extending +== Extending -All the steps performed by the scripts in this image are broken down into two categories, `pre-start` and `post-start`. +All the steps performed by these scripts are broken down into two categories, `pre-start` and `post-start`. Pre-start steps are all performed prior to the ddf instance being started, while post-start steps are all performed after the ddf instance is started. Both of these sets of steps can be extended easily using the following methods. -### Customizing Readiness Check +=== Customizing Readiness Check -There are a few protections in place in this image to help get timings right when performing installations. The default approach checks if all bundles are started before considering the system "ready" +There are a few protections in place in these scripts to help get timings right when performing installations. The default approach checks if all bundles are started before considering the system "ready" By default there are a few bundles that are excluded from this check. These defaults can be overriden via the `READINESS_EXCLUSIONS` environment variable -The default exclusions are: `Apache Karaf :: Features :: Extension, Hosts|DDF :: Platform :: OSGi :: Conditions, Hosts|Apache Karaf :: Shell :: Console, Hosts|DDF :: Platform :: PaxWeb :: Jetty Config, Hosts` +The default exclusions are: +`Apache Karaf :: Features :: Extension, Hosts|DDF :: Platform :: OSGi :: Conditions, Hosts|Apache Karaf :: Shell :: Console, Hosts|DDF :: Platform :: PaxWeb :: Jetty Config, Hosts` + Exclusions must be a string that is separated by `|` characters for each entry Downstream images that need a custom set of exclusions should override via their `Dockerfile`: @@ -59,78 +80,94 @@ ENV READINESS_EXCLUSIONS="some bundle name|another bundle name|yet another bundl ``` Additionally for distributions that make use of the fabric8 health/readiness endpoint the experimental health checks can be used instead of the older approach by setting `EXPERIMENTAL_READINESS_CHECKS_ENABLED=true` -*Note:* This requires that the `fabric8-karaf-checks` feature is installed as part of the distribution's boot features -### Pre-Start Extensions +[NOTE] +==== +This requires that the `fabric8-karaf-checks` feature is installed as part of the distribution's boot features +==== + +=== Pre-Start Extensions For simple extension, add a script: `$ENTRYPOINT_HOME/pre_start_custom.sh` For more complex extension, any number of executable files can be added to `$ENTRYPOINT_HOME/pre/` -### Post-Start Extensions +=== Post-Start Extensions For simple extension, add a script: `$ENTRYPOINT_HOME/post_start_custom.sh` For more complex extension, any number of executable files can be added to `$ENTRYPOINT_HOME/post/` -### Basic Configuration +=== Basic Configuration -#### System Hostname +==== System Hostname To set the external hostname used by DDF based systems, provide a value to `EXTERNAL_HOSTNAME=`. This will be the hostname that all external requests to the system should use. To set the internal hostname used by DDF based systems, provide a value to `INTERNAL_HOSTNAME=` -#### Internal System Ports +==== Internal System Ports -*Note:* Setting these options changes the ports that are actually bound by the server. In most cases this should not be necessary. +[NOTE] +==== +Setting these options changes the ports that are actually bound by the server. In most cases this should not be necessary. +==== To set the internal HTTPS Port provide a value for `INTERNAL_HTTPS_PORT=` To set the internal HTTP Port provide a value for `INTERNAL_HTTP_PORT=` -#### External System Ports +==== External System Ports -*Note:* Setting these options affect the url that the server expects external requests to use. +[NOTE] +==== +Setting these options affect the url that the server expects external requests to use. +==== To set the external HTTPS Port provide a value for `EXTERNAL_HTTPS_PORT=` To set the external HTTP Port provide a value for `EXTERNAL_HTTP_PORT=` -#### Internal Service Context +==== Internal Service Context Change the root context for all services Set `INTERNAL_CONTEXT=` -#### External Service Context +==== External Service Context Change the context for services when running behind a proxy/load balancer Set `EXTERNAL_CONTEXT=` -#### Site Name +==== Site Name To set the site name for the system provide a value to `SITE_NAME=`. This defaults to the external hostname of the system when omitted. -#### External Solr +==== External Solr To configure a solr backend, provide a value to `SOLR_URL=`. By default this will use the internal solr server To configure a solr cloud backend, provide a value to `SOLR_ZK_HOSTS=,,,...` -#### External LDAP -To configure the ldap client, provide a value to `LDAP_HOST=`. *NOTE:* Currently this is for testing purposes only, as it does not provide a means for configuring the protocol, port, username, or password used by the ldap client. +==== External LDAP + +To configure the ldap client, provide a value to `LDAP_HOST=`. -#### Java Memory +[NOTE] +==== +Currently this is for testing purposes only, as it does not provide a means for configuring the protocol, port, username, or password used by the ldap client. +==== + +==== Java Memory To set the amount of memory allocated to the system set `JAVA_MAX_MEM` -#### Advanced Configuration +==== Advanced Configuration Copy (or mount) any necessary configuration files into `APP_HOME/etc/` Additionally any files mounted or copied to `$ENTRYPOINT_HOME/pre_config` will be copied under `APP_HOME` before the system is started -### Managing Apps and Features +=== Managing Apps and Features There are several methods for installing and uninstalling apps and features at startup. @@ -143,18 +180,18 @@ To uninstall features, provide a list of features to `UNINSTALL_FEATURES=;;...` -### Configuring HTTPS +=== Configuring HTTPS Custom keystores can easily be mounted to `APP_HOME/etc/keystores/serverKeystore.jks` and `APP_HOME/etc/keystores/serverTruststore.jks` -#### Auto-generated demo certs +==== Auto-generated demo certs If custom keystores are not used the startup process will generate certificates on the fly. By default the local ddf demo CA (bundled within the ddf distribution) will be used to generate a certificate for the value of `INTERNAL_HOSTNAME`, or if not provided the value of `hostname -f` will be used. Additionally Subject Alternative Names will be added to the certificate for `DNS:$INTERNAL_HOSTNAME(if unset will use `hostname -f`),$EXTERNAL_HOSTNAME,DNS:localhost,IP:127.0.0.1`. To add additional SAN values use the `CSR_SAN=:,...` environment variable. -#### Import Existing Certificates +==== Import Existing Certificates Certificates can be imported at runtime by passing the certificate chain in the `SSL_CERT` environment variable. The chain must be in the format: @@ -170,43 +207,76 @@ Certificates can be imported at runtime by passing the certificate chain in the -----END CERTIFICATE----- ``` -*Warning:* This should not be used in a production environment as it is insecure. Anyone with access to the docker daemon will be able to retrieve this from the environment. - -#### Remote CA Support +==== Remote CA Support -Certificates can also be requested from a remote [cffsl](https://github.com/cloudflare/cfssl) based CA at startup by using the `REMOTE_CA_URL=https://:`. By default this will request a certificate from the remote CA that looks identical to the ones generated from the local CA. The remote CA mode provides additional configuration options for customizing the values used in the certificate. +Certificates can also be requested from a remote https://github.com/cloudflare/cfssl[cfssl] based CA at startup by using the `REMOTE_CA_URL=https://:`. By default this will request a certificate from the remote CA that looks identical to the ones generated from the local CA. The remote CA mode provides additional configuration options for customizing the values used in the certificate. -##### CSR Customization +===== CSR Customization Only applicable when using `CA_REMOTE_URL` -| Variable | Description | Default | -|:-------------------------:|:----------------------------------------------------------------:|:------------------------------:| -| `CSR_KEY_ALGORITHM` | Sets the key algorithm for the generated Certificate | `rsa` | -| `CSR_KEY_SIZE` | Sets the key size for the generated Certificate | `2048` | -| `CSR_SAN` | Sets the SAN value for the generated Certificate | `DNS:,DNS:localhost` | -| `CSR_COUNTRY` | Sets the Country value for the generated Certificate | `US` | -| `CSR_LOCALITY` | Sets the Locality value for the generated Certificate | `Hursley` | -| `CSR_ORGANIZATION` | Sets the Organization value for the generated Certificate | `DDF` | -| `CSR_ORGANIZATIONAL_UNIT` | Sets the Organizational Unit value for the generated Certificate | `Dev` | -| `CSR_STATE` | Sets the State value for the generated Certificate | `AZ` | -| `CSR_PROFILE` | Sets the type of certificate requested from the CA | `server` | +[cols=3*^,options="header"] +|=== + +|Variable +|Description +|Default + +a|`CSR_KEY_ALGORITHM` +|Sets the key algorithm for the generated Certificate +a|`rsa` + +a|`CSR_KEY_SIZE` +|Sets the key size for the generated Certificate +a|`2048` + +a|`CSR_SAN` +|Sets the SAN value for the generated Certificate +a|`DNS:,DNS:localhost` -### Seeding Data +a|`CSR_COUNTRY` +|Sets the Country value for the generated Certificate +a|`US` + +a|`CSR_LOCALITY` +|Sets the Locality value for the generated Certificate +a|`Hursley` + +a|`CSR_ORGANIZATION` +|Sets the Organization value for the generated Certificate +a|`DDF` + +a|`CSR_ORGANIZATIONAL_UNIT` +|Sets the Organizational Unit value for the generated Certificate +a|`Dev` + +a|`CSR_STATE` +|Sets the State value for the generated Certificate +a|`AZ` + +a|`CSR_PROFILE` +|Sets the type of certificate requested from the CA +a|`server` + +|=== + +=== Seeding Data It is possible to automatically seed the system with data using multiple methods. Both catalog metadata and content can be preloaded from local and remote sources. This is mostly useful for testing and demonstration purposes. -#### Seeding Catalog Metadata +==== Seeding Catalog Metadata To ingest data automatically after the system is running, the `INGEST_DATA` environment variable can be used. It can take a comma separated list of locations to retrieve archives of metadata from: `https://foo.bar/baz.zip,http://fake.com/foo.tar.gz` Supported archive types are: + - `zip` - `tar` - `tar.gz` - `tgz` Supported protocols are: + - `http://` - `https://` - `file://` @@ -216,18 +286,20 @@ Optionally a transformer for each set of data can be specified by adding `|||[||]` (`[]` denote optional parameters) -#### Source Types +==== Source Types -By default the only source type that is supported is `csw_federated`. Additional template files can be added similar to (csw_federated.config)[https://github.com/oconnormi/docker-ddf-base/blob/master/2.14/linux/entrypoint/files/templates/sources/csw_federated.config] and placed in `${ENTRYPOINT_HOME}/templates/sources` +By default the only source type that is supported is `csw_federated`. Additional template files can be added similar to https://github.com/oconnormi/docker-ddf-base/blob/master/2.14/linux/entrypoint/files/templates/sources/csw_federated.config[csw_federated.config] and placed in `${ENTRYPOINT_HOME}/templates/sources` -### Catalog Fanout Mode +=== Catalog Fanout Mode To switch the behavior of the catalog to use fanout mode provide `CATALOG_FANOUT_MODE=true` as an environment variable -#### Extending +==== Extending -By default the base image only supports `CSW` type registries. +By default these scripts only support `CSW` type registries. To support other registry types add a template to `$ENTRYPOINT_HOME/templates/registry/`. Templates should be named: `.template` -### Troubleshooting +=== Troubleshooting Sometimes during the startup process the system can take a while to fully initialize. This can be due to memory/cpu constraints. On underpowered systems it might be necessary to instruct the entrypoint script to wait longer and attempt more retries to connect to the system during the boot process. This can be accomplished by setting the `KARAF_CLIENT_DELAY=