π‘οΈ Securityο
πΊοΈ Overviewο
All core CogStack-NiFi services β including NiFi, Elasticsearch/OpenSearch, Kibana/OpenSearch Dashboards, JupyterHub, NGINX and Gitea β are now deployed with HTTPS enabled by default.
Each component is provisioned with its own X.509 certificates issued by the shared root CA generated via the create_root_ca_cert.sh script.
This ensures full end-to-end encryption across the stack for essential operations, including service-to-service communication and user-facing endpoints.
Security is achieved through:
A unified root Certificate Authority (CA),
Per-service certificate generation and signing scripts,
Environment variable management for secrets and credentials, and
Optional reverse-proxy enforcement via NGINX.
β οΈ Important: Always generate unique certificates and credentials for each deployment.
The repository provides sample certificates for demonstration only.
π§© Components secured with HTTPSο
Service |
HTTPS/TLS Enabled |
Certificate Location |
Script(s) Used |
|---|---|---|---|
NiFi |
β |
|
|
Elasticsearch / OpenSearch |
β |
|
|
Kibana / OpenSearch Dashboards |
β |
|
|
JupyterHub |
β |
|
|
Gitea |
β |
|
|
NGINX |
β |
|
|
π Folder structureο
The security/ directory centralizes all certificate, credential, and role management for CogStack-NiFi.
Below is the high-level structure with explanations for each sub-folder.
security/
βββ certificates/ # All generated certificates and keystores
β βββ elastic/ # Elasticsearch / OpenSearch + Kibana certs
β βββ nifi/ # Apache NiFi certificates (generated via NiFi Toolkit)
β βββ root/ # Root CA files and truststores
β
βββ env/ # Environment variable definitions for certs and users
β βββ certificates_*.env # Variables controlling certificate generation
β βββ users_*.env # Default credentials for each service
β
βββ es_roles/ # Role and role mapping definitions for ES / OpenSearch
β βββ elasticsearch/ # Native Elasticsearch roles
β βββ opensearch/ # OpenSearch Security Plugin configs
β
βββ scripts/ # Shell utilities for creating certs and credentials
β βββ create_root_ca_cert.sh # Generates the shared root CA (trust anchor)
β βββ create_es_native_certs.sh # Elasticsearch node and client certs
β βββ create_es_native_credentials.sh # Runs post-deployment to create default Elasticsearch system users and tokens
β βββ create_opensearch_node_cert.sh # Generates certificates and JKS stores for each OpenSearch node
β βββ create_opensearch_admin_certs.sh # Creates admin + client certificates for OpenSearch Dashboards (Kibana equivalent)
β βββ create_opensearch_internal_passwords.sh # Generates bcrypt password hashes for OpenSearch internal_users.yml
β βββ create_opensearch_users.sh # Creates OpenSearch internal users and role mappings (manual execution post-startup)
β βββ nifi_toolkit_security.sh # Generates NiFi HTTPS certs using NiFi Toolkit (for NiFi < 2.0, no longer used for certs as of 2.0+)
β βββ nifi_init_create_user_auth.sh # Bootstraps a temporary NiFi container to create a single-user authentication file
β βββ nifi_create_single_user_auth.sh # Helper script executed inside the container to generate NiFi single-user credentials
β βββ es_native_cert_generator.sh # Helper called by create_es_native_certs.sh to assemble ES cert bundles
β βββ create_keystore.sh # Builds Java KeyStores (JKS) from PEM or PKCS#12 certificates
β
βββ templates/ # OpenSSL / X.509 configuration templates
βββ ssl-extensions-x509.cnf # SAN extensions used across certificate scripts
ποΈ Certificates and Root CAο
This section describes the full structure of the security/certificates/ directory and explains how certificates are generated, organized, and used across CogStack-NiFi services.
All certificates originate from the Root Certificate Authority (CA), generated via create_root_ca_cert.sh.
This Root CA signs all service certificates (NiFi, OpenSearch, Kibana, JupyterHub, Gitea, etc.), ensuring consistent trust across the stack, with the exception of ElasticSearch (Native), we use Elasticβs built-in cert generation scripts for it instead.
π Certificate directory structureο
security/
βββ certificates/
βββ elastic/ # Certificates for Elasticsearch / OpenSearch clusters
β βββ elasticsearch/ # Native Elasticsearch certificates
β β βββ elastic-stack-ca.* # CA for Elasticsearch (self-signed or derived from root)
β β βββ elasticsearch/ # Node certificates for Elasticsearch instances
β β β βββ elasticsearch-1,2,3/ and *-dev/ variants
β β β β βββ *.crt, *.key, *.p12 # Node certs for each instance
β β β β βββ http-elasticsearch-*.csr/key # HTTP service certs for HTTPS APIs
β β β β βββ sample-elasticsearch.yml # Example ES configuration
β β β β βββ README.txt # Node-level info
β β βββ elasticsearch-ssl-http.zip # Bundled certs for HTTP layer
β β βββ es_native_certs_bundle*.zip # Bundled native ES certs
β β βββ instances.yml # Defines node names and hostnames
β β βββ kibana/ # Certificates for Kibana dashboard
β β βββ sample-kibana.yml
β β βββ README.txt
β β
β βββ opensearch/ # OpenSearch and OpenSearch Dashboard certs
β βββ admin.*, es_kibana_client.*, root-ca.* # Admin + dashboard + CA certs
β βββ elasticsearch/ # Node certs for OpenSearch nodes
β β βββ elasticsearch-{1,2,3}/ # Per-node certs, keystore/truststore
β β β βββ *.crt, *.key, *.p12, *.csr
β β β βββ elasticsearch-*-keystore.jks # Keystores for OpenSearch nodes
β β β βββ elasticsearch-*-truststore.key # Truststores
β β β βββ http-elasticsearch-*.csr/key # HTTP layer certs
β βββ es_kibana_client.{pem,key,p12,csr} # Kibana client certs
β βββ elastic-stack-ca.* # OpenSearch cluster CA
β βββ root-ca.* # Root CA reference for OpenSearch
β
βββ nifi/ # NiFi HTTPS and toolkit certificates
β βββ nifi.{crt,key,p12,pem,csr} # Primary NiFi node certificates
β βββ nifi-keystore.jks # Java keystore for NiFi server
β βββ nifi-truststore.jks # Truststore for verifying other services
β
βββ root/ # Root Certificate Authority (CA)
βββ root-ca.key, root-ca.pem # Private key and public cert
βββ root-ca.p12, root-ca.keystore.jks # PKCS#12 and Java Keystore formats
βββ root-ca-truststore.jks # Truststore for client-side verification
βββ root-ca.csr, root-ca.srl # Certificate signing request and serial
βοΈ Environment configurationο
All certificate-generation scripts source variables from .env files under security/env/:
File |
Description |
|---|---|
|
Global Root CA options (CN, expiry, key size). |
|
Node names, SAN hostnames, version control for ES/OS. |
|
NiFi keystore/truststore names and passwords. |
|
Default credentials used by generation scripts. |
π openssl-x509.confο
Set up a reusable certificate config to define SANs and subject. This is used globally for all services except ES native. Feel free to add custom DNS Note that the settings here impact services that rely on Distinguished Names (DN) attributes for authentication.
# =========================================================================================
# π OpenSSL X.509 v3 Extensions Configuration
# For: Root CA and Node/Client Certificates
# =========================================================================================
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectAltName=DNS:nifi,DNS:elasticsearch-1,DNS:elasticsearch-2,DNS:elasticsearch-3,DNS:cogstack,DNS:*.cogstack
[v3_leaf]
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
[alt_names]
DNS.1 = nifi
DNS.2 = nifi-nginx
DNS.3 = elasticsearch-1
DNS.4 = elasticsearch-2
DNS.5 = elasticsearch-3
DNS.6 = ocr-service
DNS.7 = ocr-service-text-only
DNS.8 = medcat-trainer-nginx
DNS.9 = medcat-trainer-ui
DNS.10 = nlp-medcat-service-production
DNS.11 = nlp-medcat-service-production-deid
DNS.12 = cogstack-kibana
DNS.13 = cogstack-cohort
DNS.14 = cogstack-elasticsearch-1
DNS.15 = cogstack-elasticsearch-2
DNS.16 = cogstack-elasticsearch-3
DNS.17 = cogstack-nifi
DNS.18 = cogstack-nifi-nginx
DNS.19 = cogstack-auth-service
DNS.20 = cogstack
DNS.21 = *.cogstack
DNS.22 = localhost
IP.1 = 127.0.0.1
email.1 = admin@cogstack.net
[req]
default_bits = 4096
string_mask = utf8only
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = v3_leaf
default_md = sha256
[req_distinguished_name]
CN = cogstack
C = UK
ST = London
L = UK
O = cogstack
OU = cogstack
CN = cogstack
π‘ Tip:
Always reload environment variables before running any script:cd ../deploy source export_env_vars.sh cd ../securityor manually if you just want to test out one file:
source file.env
π οΈ Generation workflowο
Generate Root CA
cd security/scripts bash create_root_ca_cert.sh
Generate service certificates
# Elasticsearch bash create_es_native_certs.sh # OpenSearch bash create_opensearch_node_cert.sh elasticsearch-1 elasticsearch-2 elasticsearch-3 # Kibana / Dashboards bash create_opensearch_client_admin_certs.sh # NiFi bash nifi_toolkit_security.sh (not needed as of version 2.0+, use only for NiFi versions < 2.0) make sure to change $NIFI_TOOLKIT_VERSION env var in `../deploy/nifi.env`.
(Optional) Create custom JKS keystores
bash create_keystore.sh mycert.pem mystore.jks mypassword
Re-export environment variables and restart services
cd ../deploy source export_env_vars.sh make start-<SERVICE_NAME>
π§ Best practicesο
Do not commit private keys (
*.key,*.p12,*.jks) to version control.Back up the Root CA files securely β theyβre your trust anchor.
Rotate certificates regularly (every 2 years) or whenever hostnames change.
Use unique CN/SANs per environment (
dev,staging,prod).Verify certificate chains before deployment (e.g):
openssl verify -CAfile security/certificates/root/root-ca.pem security/certificates/elastic/opensearch/elasticsearch/elasticsearch-1/elasticsearch-1.crt
ποΈ Security for CogStack provided other servicesο
General services TLS configurationο
All services in cogstack that are not listed in deploy/services.ymland use TLS will be described on this page. For services that are still part of the stack but in dervices/<SERVICE_NAME> (again, service not also present in deploy/services.yml) the TLS setup is handled differently, and the setup is described in each serviceβs README.md. Generally, most should just use the root-ca certs from security/certificates/root/.
Gitea TLS Configurationο
This section describes how Gitea is secured using the shared Root Certificate Authority (CA) generated by create_root_ca_cert.sh.
Unlike other services (such as NiFi or Elastic), Gitea does not require its own dedicated certificate pair or an NGINX reverse proxy. It operates directly with the Root CA to provide HTTPS encryption and mutual trust within the CogStack-NiFi stack.
π Certificate sourceο
All certificates used by Gitea originate from:
security/certificates/root/
File |
Purpose |
|---|---|
|
Public CA certificate used by Gitea for HTTPS trust |
|
Root CA private key (used only when generating new certificates) |
|
Optional PKCS#12 keystore (not required by Gitea) |
π§ Notesο
The Root CA (
root-ca.pem) is shared across all CogStack services for internal TLS trust.You do not need to create a new
gitea.crtorgitea.key; the Root CA cert/key pair is sufficient.Ensure
root-ca.keyremains private and is not committed to version control.The same CA also secures NiFi, ElasticSearch, OpenSearch, Kibana, and JupyterHub.
β Verificationο
To confirm Gitea is serving HTTPS correctly:
curl -vk --cacert ./security/certificates/root/root-ca.pem https://gitea.local:2222/
You should see a valid TLS handshake and an HTTP 200 response.
π NiFi TLS & Admin Access Setup (with NGINX)ο
This guide documents how to configure TLS and certificate-based admin access for Apache NiFi behind NGINX. For background on how certificates are generated, see Certificates and Root CA.
π Folder Structureο
security/certificates
βββ elastic
βββ nifi
β βββ nifi-keystore.jks
β βββ nifi-truststore.jks
β βββ nifi.crt
β βββ nifi.csr
β βββ nifi.key
β βββ nifi.p12
β βββ nifi.pem
βββ root
βββ root-ca-keystore.jks
βββ root-ca-truststore.jks
βββ root-ca.crt
βββ root-ca.csr
βββ root-ca.key
βββ root-ca.p12
βββ root-ca.pem
βββ root-ca.srl
For securing Apache NiFi endpoints with certificates, see the official documentation.
Before starting the NiFi container:
(optional if already done) run
create_root_ca_cert.shto generate root CA certs used across services.set
nifi.sensitive.props.keyto a stable value (minimum 12 characters).
Example (nifi/conf/nifi.properties):
nifi.security.keystorePasswd=example-keystore-password
nifi.security.keyPasswd=example-key-password
nifi.security.truststore=./conf/truststore.jks
nifi.security.truststoreType=jks
nifi.security.truststorePasswd=example-truststore-password
Setting up access via user account (single user credentials)ο
Default:
username: admin
password: cogstackNiFi
login-identity-providers.xmlinnifi/conf/stores the account settings.to generate credentials inside the container:
/opt/nifi/nifi-current/bin/nifi.sh set-single-user-credentials USERNAME PASSWORD
alternatively:
set credentials in
security/env/users_nifi.envstop NiFi (
docker stop cogstack-nifi)run
bash security/scripts/nifi_init_create_user_auth.sh
nifi-nginxο
NGINX provides secure reverse-proxy access to NiFi at:
Reference: services/nginx/config/nginx.conf.template.
π nifi.properties proxy settingsο
nifi.web.proxy.host=localhost:8443,nginx.local:8443
nifi.web.proxy.context.path=/nifi
nifi.security.identity.mapping.pattern.dn=^.*?CN=(.*?)(,|$)
π NGINX reverse proxy example (NiFi)ο
server {
listen 8443 ssl;
server_name nginx.local;
ssl_certificate /certificates/nifi/nifi.pem;
ssl_certificate_key /certificates/nifi/nifi.key;
ssl_client_certificate /certificates/root/root-ca.pem;
ssl_trusted_certificate /certificates/root/root-ca.pem;
location / {
proxy_set_header Host nifi;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-ProxyHost $host;
proxy_set_header X-ProxyPort 8443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-ProxyScheme $scheme;
proxy_pass https://nifi;
}
location /nifi {
proxy_set_header Host nifi;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-ProxyHost $host;
proxy_set_header X-ProxyPort 8443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-ProxyScheme $scheme;
proxy_pass https://nifi;
}
location ^~ /nifi-api/ {
proxy_set_header Host nifi;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-ProxyHost $host;
proxy_set_header X-ProxyPort 8443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-ProxyScheme $scheme;
proxy_pass https://nifi/nifi-api/;
}
}
β Final checklistο
[x] Certificate CN matches the NiFi admin identity
[x] NGINX uses the expected certificates and root CA
[x]
nifi.web.proxy.*settings match exposed URL and context[x] Clear cookies if browser UI shows
Anonymous
π§ͺ Test connectivityο
curl -vk --cert ./nifi.pem --key ./nifi.key https://localhost:8443/nifi-api/flow/about
π Troubleshootingο
Verify
Initial Admin Identityinauthorizers.xmlmatches the certificate identity.Recreate
authorizations.xmlif permissions are stuck.Restart NiFi after configuration updates.
Maintained by: admin@cogstack.org
π Elasticsearch / OpenSearch Securityο
This section describes how to secure both Elasticsearch (native) and OpenSearch clusters used in the CogStack-NiFi stack, including certificate setup, user management, and role configuration.
All related certificates are stored in security/certificates/elastic/, and are generated from the shared Root CA created via create_root_ca_cert.sh.
π Overviewο
Both Elasticsearch and OpenSearch deployments require:
TLS certificates for all nodes and HTTPS endpoints,
secure credentials for built-in and custom users,
properly configured roles and role mappings.
Certificates and credentials are generated using the scripts provided in security/scripts/ and are controlled through the .env files under security/env/.
π Environment files usedο
All scripts reference the following environment configuration files:
File |
Purpose |
|---|---|
|
Hostnames, instance names, and certificate parameters for ES / OpenSearch nodes |
|
Root CA configuration |
|
Internal user credentials |
Reload them before running any security-related script:
cd ../deploy
source export_env_vars.sh
cd ../security
βοΈ Version variableο
Set the ES/OS version in deploy/elasticsearch.env before launching containers:
ELASTICSEARCH_VERSION=opensearch
# or
ELASTICSEARCH_VERSION=elasticsearch
This ensures the correct certificate directory (elasticsearch or opensearch) is mounted into containers.
π§© Common certificate layoutο
Certificate naming and folder structure are consistent across both ES and OpenSearch:
security/certificates/elastic/
βββ elasticsearch/
β βββ elastic-stack-ca.crt.pem
β βββ elastic-stack-ca.key.pem
β βββ elasticsearch/
β β βββ elasticsearch-{1,2,3}/
β β β βββ http-elasticsearch-*.crt
β β β βββ http-elasticsearch-*.key
β β β βββ http-elasticsearch-*.p12
β β β βββ elasticsearch-*.crt
β β β βββ elasticsearch-*.key
β β β βββ elasticsearch-*.p12
β βββ kibana/
β βββ sample-kibana.yml
β βββ README.txt
βββ opensearch/
βββ admin.*, es_kibana_client.*, root-ca.*
βββ elasticsearch/{1,2,3}/...
Each version has its own generation scripts, but they all depend on the same .env configuration and naming patterns.
ποΈ Generating certificatesο
Elasticsearch (native)ο
To generate certificates for Elasticsearch:
bash ./create_es_native_certs.sh
This script creates all required node and HTTP certificates under:
security/certificates/elastic/elasticsearch/elasticsearch-{1,2,3}/
The script uses variables such as:
ES_INSTANCE_NAME_*β Node names (matchELASTICSEARCH_NODE_*_NAMEin/deploy/elasticsearch.env)ES_INSTANCE_ALTERNATIVE_*_NAMEβ Alternative hostnamesES_HOSTNAMESβ List of all node hostnamesES_CLIENT_SUBJ_ALT_NAMES/ES_NODE_SUBJ_ALT_NAMESβ Additional domain aliases for SAN fields
Make sure the environment variables are set correctly before running the script.
OpenSearchο
For OpenSearch nodes:
bash ./create_opensearch_node_cert.sh elasticsearch-1 elasticsearch-2 elasticsearch-3
Then generate the admin and client certificates:
bash ./create_opensearch_client_admin_certs.sh
This produces:
File |
Purpose |
|---|---|
|
Admin dashboard certificate |
|
Client certificate for Kibana/OpenDashboard |
|
Node keystores/truststores for HTTPS and inter-node encryption |
The resulting certificates are placed in:
security/certificates/elastic/opensearch/
π Kibana / OpenDashboard certificatesο
Platform |
Required Certificates |
Source Folder |
|---|---|---|
Kibana |
|
|
OpenDashboard (OpenSearch) |
|
|
All certificate references in services/kibana/config/kibana_opensearch.yml or services.yml must point to these locations.
π Users and rolesο
OpenSearchο
Edit
security/es_roles/opensearch/internal_users.ymlto define users.Optionally generate password hashes:
bash ./create_opensearch_internal_passwords.shApply changes by recreating containers:
docker compose down -v docker compose up -d
Use
create_opensearch_users.shto populate roles and user mappings.
OpenSearch includes default roles (admin, kibanaserver, readall, snapshotrestore, etc.) β always change their passwords after first run.
Elasticsearch (native)ο
Run after containers start:
bash ./create_es_native_credentials.sh
This script creates system users, roles, and a service account token for Kibana.
You can modify credentials in security/env/elasticsearch_users.env.
New roles created:
ingestβ for NiFi and pipeline ingestion (cogstack_*,nifi_*indices)cogstack_accessβ read-only access tocogstack_*andnifi_*
New users:
nifiβingestcogstack_userβcogstack_access
β οΈ Notesο
The
security/certificates/folder is also mounted inside NiFi so NiFi processors can access ES/OS securely without restarting.For OpenSearch role details, see the OpenSearch Security Plugin documentation.
For Elasticsearch, refer to the official Elastic Security docs.
β Verificationο
To verify HTTPS access and trust:
curl -vk --cacert ./root-ca.pem https://elasticsearch-1:9200
To check inter-node encryption (inside a container):
openssl s_client -connect elasticsearch-1:9300 -CAfile ./root-ca.pem