DevOps Guide

This guide is tailored to DevOps engineers that are responsible for Corteza instance deploys and it’s maintenance on a system level; such as configuring the environment and setting up email notifications.

Architecture overview

Mayor component or services in Corteza:
  • Frontend applications (WebApps),

  • Corteza server,

  • Corteza Corredor server.

Auxiliary services:
  • Log storage,

  • error tracking,

  • email sending,

  • object storage,

  • database.

Frontend applications:
  • Corteza Auth handles all flows related to user authentication; such as sign-up, login, and password recovery,

  • Corteza Admin handles main administration aspects of your Corteza instance; such as configuring settings, defining roles, and managing general permissions,

  • Corteza Low Code is a low-code development platform and allows creation of record-absed business applications,

  • Corteza Messaging collaboration platform that allows teams to collaborate more efficiently and communicate safely with other organizations or customers,

  • Corteza One is a unified workspace to access and run third-party web and Corteza applications. Centralized access management from a single console enables administrative control over who can see or access applications.

Corteza architectural overview
Figure 1. An abstract overview of the entire Corteza and how different components are connected.

System requirements

Supported clients

Corteza doesn’t support older browsers as we wish to develop a modern platform on modern technologies.

If you wish to do so, you may build your own Docker containers with custom build procedures.

Table 1. Corteza supports the following clients:
Client Version

Chrome

v78+

Firefox

v68+

Safari

v12+

Edge

v44+

iOS

iPhone 5s devices and later with iOS 12+

Android

Android 7+

Server Operating System

Any Docker-compatible operating system is supported.

We recommend a Linux-based operating system; preferably Ubuntu LTS.

Docker

The minimum Docker Engine version is 1.12.x

HTTP server

You should place the API and the web applications behind a firewall or an HTTP reverse proxy. The reverse proxy is responsible for traffic forwarding to Corteza services and SSL termination.

Most of the popular HTTP servers support this.

The documentation provides configurations guides for Nginx Reverse Proxy and the LetsEncrypt nginx-proxy companion.

You don’t need to use Nginx; you can use the HTTP server you are most familiar with.

Use provided examples for Nginx as a reference on how to configure it.

Database

We recommend the Percona Server for MySQL 8.x, either native on the host or provided via Docker.

Hardware

Number of Users

Processor

Memory

1 - 500

1 vCPU/cores

2 GB RAM

500 - 1000

2 vCPU/cores

4 GB RAM

1000 - 2000

4 vCPU/cores

8 GB RAM

2000 - 5000

8 vCPU/cores

16 GB RAM

5000+

16 vCPU/cores

32 GB RAM

Storage

Table 2. Estimated storage per user per month:
Volume Description Recommended Storage

Low volume

Messaging: sending text messages and links (without file upload); Low Code: creating plain-text records (without file upload).

5 MB/user/month

Medium volume

Messaging: sending text messages, links and occasionally sending documents and images; Low Code: attaching documents to records.

25 MB/user/month

High volume

Messaging: uploading large files daily; Low Code: attaching a high number of documents to records daily.

100 MB/user/month

Annual storage calculation:
  • Base storage (operating system and core components) of 10 GB,

  • recommended storage per user per month based on the matrix above (multiplied by 12 to get the yearly amount),

  • average number of users in a year,

  • apply a safety factor; we recommend at least 2.0.

The formula:
total = (nr. of users * recommended storage * 12 * safety factor) + base storage
Example calculation for 30 medium usage users:
Recommended storage = (30 * 25 MB * 12 * 2) + 10 GB = 28 GB / year

Network

Depending on your configuration, Corteza may need some access to outside services.

If you intend to use any email communication; such as sending confirmation emails, password reset emails, or sending emails from automation scripts; you must configure your SMTP servers to be accessible.

If you enable OAuth2 or OIDC sign-up, or you are accessing external services via automation scripts, you should allow HTTP traffic.

Domain and hostname

The most common setup involves two domains — API and web app:
  • Hostname for Web application,

  • hostname for API server.

If you already own a domain, you can add two or more hosts and use them to access your Corteza instance.

HTTPS/SSL Certificates

Corteza supports any SSL certificate from all certificate authorities (CA). You can use any existing or new SSL certificate from any commercial SSL certificate provider or self-signed.

We use Let’s Encrypt.

If you aren’t using any other HTTP server, we highly recommend you use Nginx Reverse Proxy and LetsEncrypt companion container for nginx-prox.

Its an automated and the simplest way to secure Corteza or any other web application you host.

Docker Compose

If you are not planning on using Docker you can skip this section entirely.

Environment setup

If your system already has Docker (we recommend at least version 18.0) and Docker Compose installed, you can safely skip this.

You can checkout your Docker version by entering docker -v in your CLI.

If you don’t have Docker installed, or the version is below the recommended version, download and install a Docker community edition for desktop or server or cloud that fits your environment.

docker-compose file

The docker-compose.yaml file describes the different services, networks and storage configurations, used to configure your Docker containers. Refer to the Docker Compose documentation for a complete reference.

Some useful Docker Compose commands

Stop and remove containers along with their volumes without confirmation

docker-compose rm --force --stop -v

View container logs

docker-compose logs --follow --tail 20
# You can additionally filter by service; for example:
docker-compose logs --follow --tail 20 server

Executing with Docker Compose (when service is started)

docker-compose exec <service name> help

Executing with docker (when a container is running)

docker exec -it <container name> help

Running with Docker Compose (when service is not started)

docker run -it --rm <container name> help

Executing with Docker (when container is not running)

docker run -it --rm [docker run options] <container name> help

Running and executing with Docker Compose should be easier and simpler because all required options and settings for the container are packed in the docker-compose.yaml file.

Server configuration

Core Corteza services are configured via the environment (.env) file. It allows a quick deploy to another platform, along with fine-tuning the system’s behaviour and enabled features.

The .env file is at the root of the application. In the context of Docker Compose, it is next to the docker-compose.yaml file.

The .env file affects three levels:
  1. Implicit Docker Compose configuration,

  2. variable substitution in Docker configuration,

  3. service configuration.

When you are using Docker Compose, you must explicitly reference the environment file for each service in the docker-compose.yaml file (env_file: [.env]).

You can use variables defined in the .env inside your docker-compose.yaml file; for example ${VERSION}.

Base configuration

These variables control the base Corteza configurations, such as the port and the database DSN.

Type Default value Description

DB_DSN

string

corteza:corteza@tcp(db:3306)/corteza?collation=utf8mb4_general_ci

Database connection string <username>:<password>@(<host>:<port>)/<dbname>?collation=utf8mb4_general_ci

DB_MAX_TRIES

int

100

Maximum number of connection retries.

DB_CONN_ERR_DELAY

duration

5 seconds

Duration between database connection retries.

DB_CONN_TIMEOUT

duration

1 minute

After how long we should give up on connecting with the database.

GRPC_SERVER_NETWORK

string

tcp

Network to use for gRPC.

GRPC_SERVER_ADDR

string

:50051

Where do we listen for gRPC connections.

GRPC_CLIENT_BACKOFF_DELAY

duration

1 minute

Maximum delay for backoff on connection.

HTTP_ADDR

string

:80

IP and port for the HTTP server.

HTTP_METRICS

boolean

false

Enable (prometheus) metrics.

HTTP_METRICS_NAME

string

corteza

Name for metrics endpoint.

HTTP_METRICS_USERNAME

string

metrics

Username for the metrics endpoint.

HTTP_METRICS_PASSWORD

string

(random)

Password for the metrics endpoint.

HTTP_CLIENT_TIMEOUT

boolean

30 seconds

Default timeout for clients.

MONITOR_INTERVAL

duration

5 minutes

Output (log) interval for monitoring.

STORAGE_PATH

string

var/store

Where do we store uploaded files

Security

These variables control security aspects of Corteza, such as the JWT token secret and the token lifetime.

Type Default value Description

AUTH_JWT_SECRET

string

(random)

Secret used for signing JWT tokens.

Make sure to provide a secret. If you don’t, a random value is assigned — this causes all of the tokens to become invalid after a server restart.

AUTH_JWT_EXPIRY

duration

1 month

Expiration time for the auth JWT tokens.

HTTP_CLIENT_TSL_INSECURE

boolean

false

Allow insecure (invalid, expired TSL/SSL certificates) connections.

We strongly recommend keeping this value set to false except for local development or demos.

Provisioning

Provisioning allows you to configure a Corteza instance when deployed. It occurs automatically after the Corteza server starts.

We recommend you to keep provisioning enabled as it simplifies version updates by updating the database and updating settings.

If you’re doing local development or some debugging, you can disable this.

Type Default value Description

PROVISION_ALWAYS

boolean

true

Controls if the provisioning should run when the server starts.

UPGRADE_ALWAYS

boolean

true

Controls if the upgradable systems should be upgraded when the server starts.

Provision authentication settings

Key Type Default value Description

PROVISION_SETTINGS_AUTH_EXTERNAL_ENABLED

auth.external.enabled

boolean

true

Is OAuth2 enabled or disabled.

PROVISION_SETTINGS_AUTH_EXTERNAL_REDIRECT_URL

auth.external.redirect-url

string

searches env-variables (DOMAIN, LETSENCRYPT_HOST, VIRTUAL_HOST, HOSTNAME, HOST) and uses additional info (monolith, api-base-url) to calculate the value.

PROVISION_SETTINGS_AUTH_EXTERNAL_SESSION_STORE_SECRET

auth.external.session-store-secret

string

random 64 char string

generated 64 char long string if missing.

Is session cookie "secure" flag used (if yes, cookie can only be access over HTTPS).

PROVISION_SETTINGS_AUTH_EXTERNAL_SESSION_STORE_SECURE

auth.external.session-store-secure

boolean

false

If HTTPS is used for external auth redirection url, value is set to true.

PROVISION_SETTINGS_AUTH_FRONTEND_URL_BASE

auth.frontend.url.base

string

Where the frontend SPA is located. Serves as base for generating other auth.frontend.url…​ variables.

PROVISION_SETTINGS_AUTH_FRONTEND_URL_PASSWORD_RESET

auth.frontend.url.password-reset

string

Where the frontend SPA is located, the password reset form.

PROVISION_SETTINGS_AUTH_FRONTEND_URL_EMAIL_CONFIRMATION

auth.frontend.url.email-confirmation

string

Where the frontend SPA is located, password email confirmation page. auth.frontend.url.base is used as base URL

PROVISION_SETTINGS_AUTH_FRONTEND_URL_REDIRECT

auth.frontend.url.redirect

string

Where the frontend SPA is located. User will be redirected here on successful external authentication. Auto discovery uses auth.frontend.url.base as base URL.

PROVISION_SETTINGS_AUTH_EMAIL_FROM_ADDRESS

auth.mail.from-address

string

to-be-configured@example.tld

Email address used for sending auth emails (password reset, email confirmation).

Name used for sending auth emails (password reset, email confirmation).

PROVISION_SETTINGS_AUTH_EMAIL_FROM_NAME

auth.mail.from-name

string

Corteza Team (to-be-configured)

The email from parameter.

PROVISION_SETTINGS_AUTH_INTERNAL_ENABLED

auth.internal.signup

boolean

true

Controls if users are allowed to use internal authentication features, such as login, sign-up, and password reset.

PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_ENABLED

auth.internal.signup.enabled

boolean

true

Controls if users are allowed to ue internal authentication sign-up.

PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_EMAIL_CONFIRMATION_REQUIRED

auth.internal.signup-email-confirmation-required

boolean

false

Controls if users are required to confirm the email? Enabled on auto-discovery if server has email capabilities (SMTP_HOST variable is set).

PROVISION_SETTINGS_AUTH_INTERNAL_PASSWORD_RESET_ENABLED

auth.internal.password-reset.enabled

boolean

false

Controls if suers are allowed to use password reset for accounts created via internal sign-up.

Provision OIDC providers

Type Default value Description

PROVISION_OIDC_PROVIDER

string

Registers available providers from a list of space delimited provided pairs (<name> <provider-url> or <name> <provider-url> <name-2> <provider-url-2>).

The provider is auto-discovered only if it does not exist (match by name).

Also, make sure that your redirect URL (auth.external.redirect-url) is properly configured.

PROVISION_SETTINGS_AUTH_EXTERNAL_REDIRECT_URL

string

Sets value for auth.external.redirect-url setting.

Provision other external provider

Type Default value Description

PROVISION_SETTINGS_AUTH_EXTERNAL_GITHUB

string

Github’s app credentials: <key> <secret>.

PROVISION_SETTINGS_AUTH_EXTERNAL_FACEBOOK

string

Facebook’s app credentials: <key> <secret>.

PROVISION_SETTINGS_AUTH_EXTERNAL_GOOGLE

string

Google’s app credentials: <key> <secret>.

PROVISION_SETTINGS_AUTH_EXTERNAL_LINKEDIN

string

LinkedIn’s app credentials: <key> <secret>.

PROVISION_SETTINGS_AUTH_EXTERNAL_OIDC

string

OIDC provider settings <name> <issuer> <key> <secret>.

SMTP

Type Default value Description

SMTP_HOST

string

localhost:25

The SMTP server hostname.

SMTP_PORT

int

The SMTP post.

SMTP_USER

string

The SMTP username.

SMTP_PASS

string

The SMTP password.

SMTP_FROM

string

The from email parameter.

Corredor

Type Default value Description

CORREDOR_ENABLED

boolean

true

Enable/disable Corredor integration.

CORREDOR_ADDR

string

corredor:80

Hostname and port of the Corredor gRPC server.

CORREDOR_MAX_BACKOFF_DELAY

duration

1 minute

Max delay for backoff on connection.

CORREDOR_MAX_RECEIVE_MESSAGE_SIZE

int

16MB

CORREDOR_DEFAULT_EXEC_TIMEOUT

time

1 minute

CORREDOR_LIST_TIMEOUT

duration

2 second

CORREDOR_LIST_REFRESH

duration

2 second

CORREDOR_RUN_AS_ENABLED

bool

false

CORREDOR_CLIENT_CERTIFICATES_ENABLED

bool

false

CORREDOR_CLIENT_CERTIFICATES_PATH

string

/certs/corredor/client

CORREDOR_CLIENT_CERTIFICATES_CA

string

ca.crt

CORREDOR_CLIENT_CERTIFICATES_PUBLIC

string

public.crt

CORREDOR_CLIENT_CERTIFICATES_PRIVATE

string

private.key

CORREDOR_CLIENT_CERTIFICATES_SERVER_NAME

string

""

MinIO

The MinIO integration allows you to replace local storage with cloud storage. When configured, STORAGE_PATH is not needed.

Type Default value Description

MINIO_ENDPOINT

string

MINIO_SECURE

boolean

true

MINIO_ACCESS_KEY

string

MINIO_SECRET_KEY

string

MINIO_SSEC_KEY

string

MINIO_BUCKET

string

MINIO_STRICT

boolean

false

Debugging

These parameters help in the development and testing process. When you are deploying to production, these should be disabled to improve performance and reduce storage usage.

You should configure external services such as Sentry or ELK to keep track of logs and error reports.

Sentry

Type Default value Description

SENTRY_DSN

string

Set to enable Sentry client.

SENTRY_DEBUG

boolean

false

Print out debugging information.

SENTRY_ATTACH_STACKTRACE

boolean

false

Attach stacktraces.

SENTRY_SAMPLE_RATE

float32

Sample rate for event submission (0.0 - 1.0, defaults to 1.0).

SENTRY_MAX_BREADCRUMBS

int

Maximum number of breadcrumbs.

SENTRY_SERVERNAME

string

Set reported Server name.

SENTRY_RELEASE

string

(current version)

Set reported Release.

SENTRY_DIST

string

Set reported distribution.

SENTRY_ENVIRONMENT

string

Set reported environment.

Logging

Type Default value Description

DB_LOGGER

boolean

false

Log SQL queries.

CORREDOR_LOG_ENABLED

boolean

false

Log communication with Corredor.

HTTP_REPORT_PANIC

boolean

true

Report HTTP panic to Sentry.

HTTP_LOG_REQUEST

boolean

false

Log HTTP requests.

HTTP_LOG_RESPONSE

boolean

false

Log HTTP responses.

HTTP_ENABLE_VERSION_ROUTE

boolean

false

Enable /version route.

HTTP_ENABLE_DEBUG_ROUTE

boolean

false

Enable /debug route.

GRPC_CLIENT_LOG

boolean

false

Log gRPC communication.

Delaying API execution

You can configure these options to defer API execution until another external (HTTP) service is up and running.

Delaying API execution can come in handy in complex setups where execution order is important.

Type Default value Description

WAIT_FOR

duration

0

Delays API startup for the amount of time specified (10s, 2m…​).

This delay happens before service (WAIT_FOR_SERVICES) probing.

WAIT_FOR_STATUS_PAGE

boolean

true

Show temporary status web page.

WAIT_FOR_SERVICES

string

Space delimited list of hosts and/or URLs to probe. Host format: host or host:443 (port will default to 80).

Services are probed in parallel.

WAIT_FOR_SERVICES_TIMEOUT

duration

1m

Max time for each service probe.

WAIT_FOR_SERVICES_PROBE_TIMEOUT

duration

30s

Timeout for each service probe.

WAIT_FOR_SERVICES_PROBE_INTERVAL

duration

5s

Interval between service probes.

Corredor server configuration

You can place all configurations into a single .env file.

Corteza Corredor server is configured via the environment (.env) file. It allows a quick deploy to another platform, along with fine-tuning the behaviour and enabled features.

The .env file is at the root of the application. In the context of Docker Compose, it is next to the docker-compose.yaml file.

You can use variables defined in the .env inside your docker-compose.yaml file; for example ${VERSION}.

Base configuration

These variables control the base Corredor server configurations, such as extension search paths, and certificate locations.

Type Default value Description

CORREDOR_ADDR

string

corredor:80

This setting is used by both, Corredor and API Server.

For Corredor server: where is server listening on

For API server: where can Corredor server be accessed.

Used by Corredor and API server.

CORREDOR_ENABLED

bool

false

This is a setting for API server, will Corredor be used for server automation?

Used by Corredor and API server.

CORREDOR_MAX_BACKOFF_DELAY

duration

1m

Connection timeout (from API server to Corredor)

Used by API server.

CORREDOR_EXEC_CSERVERS_API_BASEURL_TEMPLATE

string

https://api.{host}/{service}

Location of the Corteza server API. {host} is replaced with value from env variables (in this order: CORREDOR_EXEC_CSERVERS_API_HOST, DOMAIN, HOSTNAME, HOST), {service} is replaced dynamically inside Corredor with compose, system or messaging.

Used by Corredor server.

CORREDOR_EXEC_CSERVERS_API_HOST

string

Hostname used for template

Used by Corredor server.

CORREDOR_LOG_ENABLED

boolean

corredor

This setting is used by both, Corredor and API Server.

For Corredor service: where is service listening on (gRPC)

For API server: where can Corredor service be accessed.

Used by Corredor and API server.

CORREDOR_LOG_LEVEL

string

info

Defaults to trace when CORREDOR_DEBUG is true, defines amount of log information outputed.

Used by Corredor and API server.

CORREDOR_LOG_PRETTY

boolean

false

Are events logged in one-line JSON or formatted to ease development?

Used by Corredor.

CORREDOR_DEBUG

boolean

false

Corredor will log even more information.

Used by Corredor.

CORREDOR_EXT_DEPENDENCIES_AUTO_UPDATE

boolean

true

Corredor will auto update script dependencies found in package.json files

Used by Corredor.

CORREDOR_EXT_SERVER_SCRIPTS_ENABLED

boolean

true

Server scripts are enabled

Used by Corredor.

CORREDOR_EXT_SERVER_SCRIPTS_WATCH

boolean

true

Corredor will reload server-scripts on change

Used by Corredor.

CORREDOR_EXT_CLIENT_SCRIPTS_ENABLED

boolean

true

Client scripts are enabled

Used by Corredor.

CORREDOR_EXT_CLIENT_SCRIPTS_WATCH

boolean

true

Corredor will reload client-scripts on change

Used by Corredor.

Corteza CLI

Corteza command-line interface tool allows you to quickly interact with different parts of the system — from changing the settings to assigning roles to users.

Depending on built flavour, you can use a different entry:
  • Microservice build produce corteza-server-system, corteza-server-messaging and corteza-server-compose,

  • monolith build produces corteza-server binary with system, messaging, compose sub-commands.

Base commands

Start the HTTP Server with REST API

Usage:
  corteza-server serve-api [flags]

Flags:
  -h, --help   help for serve-api

Provision commands

Base command

Usage:
  corteza-server provision [command]

Available Commands:
  configuration    Create permissions & resources
  migrate-database Run database migration scripts

Flags:
  -h, --help   help for provision

Use "corteza-server provision [command] --help" for more information about a command.

Create permissions and resources

Usage:
  corteza-server provision configuration [flags]

Flags:
  -h, --help   help for configuration

Run database migration scripts

Usage:
  corteza-server provision migrate-database [flags]

Flags:
  -h, --help   help for migrate-database

System commands

External authentication

Usage:
  corteza-server system auth [command]

Available Commands:
  auto-discovery     Auto discovers new OIDC client
  jwt                Generates new JWT for a user
  test-notifications Sends samples of all authentication notification to the recipient

Flags:
  -h, --help   help for auth

Use "corteza-server system auth [command] --help" for more information about a command.

Auto discovers new OIDC client

Usage:
  corteza-server system auth auto-discovery [name] [url] [flags]

Flags:
      --enable            Enable this provider and external auth
  -h, --help              help for auto-discovery
      --skip-validation   Skip validation

Sends samples of all authentication notification to the recipient

Usage:
  corteza-server system auth test-notifications [recipient] [flags]

Flags:
  -h, --help   help for test-notifications

Generates new JWT for a user

Usage:
  corteza-server system auth jwt [email-or-id] [flags]

Flags:
  -h, --help   help for jwt

Export system resources

Usage:
  corteza-server system export [flags]

Flags:
  -h, --help          help for export
  -p, --permissions   Export system permissions
  -s, --settings      Export settings

Import system resources

Usage:
  corteza-server system import [flags]

Flags:
  -h, --help   help for import

Manage roles

Usage:
  corteza-server system roles [command]

Available Commands:
  useradd     Add user to role

Flags:
  -h, --help   help for roles

Use "corteza-server system roles [command] --help" for more information about a command.

Add user to role

Usage:
  corteza-server system roles useradd [role-ID-or-name-or-handle] [user-ID-or-email] [flags]

Flags:
  -h, --help   help for useradd

Manage settings

Usage:
  corteza-server system settings [command]

Available Commands:
  delete      Set value (raw JSON) for a specific key (or by prefix)
  export      Import settings as JSON to stdout or file
  get         Get value (raw JSON) for a specific key
  import      Import settings as JSON from stdin or file
  list        List all
  set         Set value (raw JSON) for a specific key

Flags:
  -h, --help   help for settings

Use "corteza-server system settings [command] --help" for more information about a command.

Remove settings for specific keys

Usage:
  corteza-server system settings delete [keys, ...] [flags]

Flags:
  -h, --help            help for delete
      --prefix string   Filter settings by prefix

Export settings as JSON to stdout or a file

Usage:
  corteza-server system settings export [file] [flags]

Flags:
  -h, --help   help for export

Get value for a specific key

The value is provided as a raw JSON.

Usage:
  corteza-server system settings get [key to get, ...] [flags]

Flags:
  -h, --help   help for get

Import settings as JSON from stdin or a file

Usage:
  corteza-server system settings import [file] [flags]

Flags:
  -h, --help   help for import

List all settings

Usage:
  corteza-server system settings list [flags]

Flags:
  -h, --help            help for list
      --prefix string   Filter settings by prefix

Set value for a specific key

The value is provided as a raw JSON.

Usage:
  corteza-server system settings set [key to set] [value] [flags]

Flags:
  -h, --help   help for set

Sink

Usage:
  corteza-server system sink [command]

Available Commands:
  signature   Creates signature for sink HTTP endpoint

Flags:
  -h, --help   help for sink

Use "corteza-server system sink [command] --help" for more information about a command.

Create sink signature

Usage:
  corteza-server system sink signature [flags]

Flags:
      --content-type string   Content type (optional)
      --expires string        Date of expiration (YYYY-MM-DD, optional)
  -h, --help                  help for signature
      --max-body-size int     Max allowed body size
      --method string         HTTP method that will be used (optional)
      --origin string         Origin of the request (arbitrary string, optional)
      --path string           Full sink request path (do not include /sink prefix, add / for just root)
      --signature-in-path     Include signature in a path instead of query string

Manage system users

Usage:
  corteza-server system users [command]

Available Commands:
  add         Add new user
  list        List users
  password    Change password for user

Flags:
  -h, --help   help for users

Use "corteza-server system users [command] --help" for more information about a command.

Add a new system user

Usage:
  corteza-server system users add [email] [flags]

Flags:
  -h, --help          help for add
      --no-password   Create user without password

List system users

Usage:
  corteza-server system users list [flags]

Flags:
  -h, --help   help for list

Change password for a system user

Usage:
  corteza-server system users password [email] [flags]

Flags:
  -h, --help   help for password

Low Code commands

Export Low Code resources

Usage:
  corteza-server compose export [flags]

Flags:
  -h, --help               help for export
      --namespace string   Export namespace resources (by ID or string)
  -p, --permissions        Export system permissions
  -s, --settings           Export settings

Arguments:
  modules                  Export modules
  pages                    Export pages
  charts                   Export charts
  permissions              Export permissions

Import Low Code resources

Usage:
  corteza-server compose import [flags]

Flags:
  -h, --help               help for import
      --namespace string   Import into namespace (by ID or string)

Messaging commands

Export Messaging resources

Usage:
  corteza-server messaging export [flags]

Flags:
  -h, --help          help for export
  -p, --permissions   Export system permissions
  -s, --settings      Export settings

Import Messaging resources

Usage:
  corteza-server messaging import [flags]

Flags:
  -h, --help   help for import

Basic setup for a local demo

The section covers configuration files that are only suitable for a demo on a local environment. All services are on the same network, ports are bound to the host’s network, etc.

This is not an optimal setup for a production environment. See Nginx proxy and production setup guides for a production deploy.

Configurations

Some of the configuration lines in the provided docker-compose file are written in a single line for brevity and simpler enabling/disabling (commenting-out).

Some operating systems do not like files that start with a dot, so make sure .env file is properly named.

.env
########################################################################################################################
# docker-compose supports environment variable interpolation/substitution in compose configuraiton file
# (more info: https://docs.docker.com/compose/environment-variables)

########################################################################################################################
# General settings
VERSION=2020.9

########################################################################################################################
# Ports where these services will be accessible
# In case of an "address already in use" change these ports to a higher number

# Web applications
# http://localhost:8080
LOCAL_DEMO_SPA_PORT=18080

# API Server
# http://localhost:8081
LOCAL_DEMO_API_PORT=18081

# Corredor gRPC server, nothing to see here,
# just for internal traffic between API server and corredor
LOCAL_DEMO_CRD_PORT=18082


########################################################################################################################
# Database connection

DB_DSN=dbuser:dbpass@tcp(db:3306)/dbname?collation=utf8mb4_general_ci

########################################################################################################################
# Authentication

# Secret to use for JWT token
# Make sure you change it (>30 random characters) if
# you expose your deployment to outside traffic

AUTH_JWT_SECRET=this-is-only-for-demo-purpose--make-sure-you-change-it-for-production

########################################################################################################################
# SMTP (mail sending) settings

# Disable email confirmation for sign-up protocol to allow more seamless setup without the need
# for SMTP Server
PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_EMAIL_CONFIRMATION_REQUIRED=false

# Point this to your local or external SMTP server
#SMTP_HOST=smtp-server.example.tld:587
#SMTP_USER=postmaster@smtp-server.example.tld
#SMTP_PASS=this-is-your-smtp-password
#SMTP_FROM="Demo" <info@your-demo.example.tld>
docker-compose.yaml
version: '3.5'

services:
  webapp:
    image: cortezaproject/corteza-webapp:${VERSION}
    restart: on-failure
    depends_on: [ server ]
    # Binds internal port 80 to port LOCAL_DEMO_SPA_PORT on localhost
    ports: [ "127.0.0.1:${LOCAL_DEMO_SPA_PORT}:80" ]
    environment:
      # Monolith API settings informs webapp autoconfiguration script that we're running
      # a monolith API server.
      MONOLITH_API: "true"
      # Configure web application with API location
      API_BASEURL:  "127.0.0.1:${LOCAL_DEMO_API_PORT}"

  server:
    image: cortezaproject/corteza-server-monolith:${VERSION}
    restart: on-failure
    depends_on: [ db, corredor ]
    # Binds internal port 80 to port LOCAL_DEMO_API_PORT on localhost
    ports: [ "127.0.0.1:${LOCAL_DEMO_API_PORT}:80" ]
    env_file: [ .env ]
    environment:
      # Using name of the service, will connect to server API over internal docker network
      CORREDOR_ADDR: "corredor:80"

  corredor:
    image: cortezaproject/corteza-server-corredor:${VERSION}
    restart: on-failure
    # Binds internal port 80 to port LOCAL_DEMO_CRD_PORT on localhost
    ports: [ "127.0.0.1:${LOCAL_DEMO_CRD_PORT}:80" ]
    env_file: [ .env ]
    environment:
      # CORREDOR_EXEC_CSERVERS_API_HOST host will replace {host} in 'https://api.{host}/{service}' template
      # You can change the template with CORREDOR_EXEC_CSERVERS_API_BASEURL_TEMPLATE
      # (best if you can set this variable inside .env)
      #
      # Using name of the service, will connect to server API over internal docker network
      CORREDOR_EXEC_CSERVERS_API_HOST: "server"

  db:
    # MySQL Database
    # See https://hub.docker.com/r/percona/percona-server for details
    image: percona:8.0
    restart: on-failure
    environment:
      # To be picked up by percona image when creating the database
      # Must match with DB_DSN settings inside .env
      #
      # Warning: these are values that are only used on 1st start
      #          if you want to change it later, you need to do that
      #          manually inside db container
      MYSQL_DATABASE: dbname
      MYSQL_USER:     dbuser
      MYSQL_PASSWORD: dbpass
      MYSQL_RANDOM_ROOT_PASSWORD: random # docker-compose logs db |grep "GENERATED ROOT PASSWORD"
    healthcheck: { test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"], timeout: 20s, retries: 10 }

Create an empty directory with the .env and docker-compose.yaml files. You can adjust the provided example configuration files as you see fit.

Make sure to change the AUTH_JWT_SECRET value to something else.

Run the services

docker-compose up -d

Run this command in the same directory as your docker-compose.yaml file. It will start all of the services based on the configurations provided in the configuration files.

You can check if everything is running correctly, by executing the docker-compose ps command. The output should be similar to this one:

      Name                    Command                   State                      Ports
-------------------------------------------------------------------------------------------------------
basic_corredor_1   /corredor/node_modules/.bi ...   Up (healthy)     127.0.0.1:18082->80/tcp
basic_db_1         /docker-entrypoint.sh mysqld     Up (healthy)     3306/tcp, 33060/tcp
basic_server_1     bin/server serve-api             Up (healthy)     127.0.0.1:18081->80/tcp
basic_webapp_1     /entrypoint.sh                   Up (healthy)     127.0.0.1:18080->80/tcp

You can see 4 services up and running. Two of them are accessible on localhost (ports 8080 and 8081).

If you changed the ports in your .env file, the ports will be different.

Finishing the setup

  1. Direct your browser to http://localhost:8080. If you used other ports in your configurations, use those. On your first visit, you should be redirected to the authentication page (/auth),

  2. create your account through the sign-up form.

The first user gets automatically promoted to an administrator. You can add additional users by using the sign-up form or by adding them in the administration panel.

Nginx proxy

This is not needed when working on local instances. Following the setup local demo section is enough to get a local instance up and running.

We advise against merging/mixing Corteza and nginx-proxy in the same directory.

It can be done but requires some experience with Docker Compose.

The following instructions assume that you don’t have anything similar setup on your current environment. If you are using other means of providing traffic forwarding or SSL certificate handling, proceed with caution.

Containers must be on the same network as nginx-proxy (in the examples we’re using network named proxy).

Nginx Proxy (docker image jwilder/nginx-proxy) is an auto-configurable reverse-proxy that routes traffic from your public IP to Docker containers on the host.

LetsEncrypt Nginx Proxy Companion (docker image jrcs/letsencrypt-nginx-proxy-companion) automates the process of creating, renewing and using Let’s Encrypt certificates for your Docker containers.

What does this do?
  1. Both images listen for docker events to detect when containers start or stop,

  2. Nginx Proxy generates and reloads the configuration, and starts forwarding HTTP traffic to that container based on the VIRTUAL_HOST,

  3. LetsEncrypt companion starts the certificate creation process, reconfigures Nginx Proxy and enables redirection from HTTP to HTTPS based on the LETSENCRYPT_HOST.

What are the benefits?
  1. Containers (like Corteza server, and fronted application) that are exposed publicly no longer have to publish their ports on public IP,

  2. complicated firewall configurations and network forwarding rules are no longer required.

Configurations

docker-compose.yaml
version: '3.5'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    restart: always
    networks:
      - proxy
    ports:
      - "80:80"
      - "443:443"
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    volumes:
      - ./certs:/etc/nginx/certs
      - ./htpasswd:/etc/nginx/htpasswd
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - ./custom.conf:/etc/nginx/conf.d/custom.conf:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nginx-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-letsencrypt
    restart: always
    depends_on:
      - nginx-proxy
    volumes:
      - ./certs:/etc/nginx/certs
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro

# Create network if it does not exist
networks: { proxy: { name: proxy } }
custom.conf
# Make sure we can upload at least 200Mb files
client_max_body_size    200M;

# Add other custom configs.

#

custom.conf must be placed next to docker-compose.yaml.

Run the services

docker-compose up -d

You can check if everything is running correctly by executing the docker-compose ps command. The output should be similar to this one:

      Name                     Command               State                    Ports
-----------------------------------------------------------------------------------------------------
nginx-letsencrypt   /bin/bash /app/entrypoint. ...   Up
nginx-proxy         /app/docker-entrypoint.sh  ...   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

Production setup

You can use similar steps when deploying a staging or a demo environment.

This setup depends on you running the Nginx proxy service.

Make sure your nginx-proxy service is up and running before running Corteza. In other cases, you might get an error like:

ERROR: Network proxy declared as external, but could not be found. Please create the network manually using `docker network create proxy` and try again.

If nginx-proxy refuses to start, inspect your configuration files and compare them with ones provided in the Nginx proxy section.

DNS

This demo uses 2 example domains; your-demo.example.tld and api.your-demo.example.tld.

You need to configure your DNS by adding two hosts and point them to the IP address (A record) or the hostname (CNAME record) of the server you’re using for running Corteza.

Configurations

Some of the configuration options in the docker-compose are in-lined for brevity and easier enabling/disabling (commenting-out).

Some operating systems do not like files that start with a dot, so make sure .env file is properly named.

.env
########################################################################################################################
# docker-compose supports environment variable interpolation/substitution in compose configuraiton file
# (more info: https://docs.docker.com/compose/environment-variables)

########################################################################################################################
# General settings
DOMAIN=your-demo.example.tld
VERSION=2020.9

########################################################################################################################
# Database connection

DB_DSN=dbuser:dbpass@tcp(db:3306)/dbname?collation=utf8mb4_general_ci

########################################################################################################################
# Authentication

# Secret to use for JWT token
# Make sure you change it (>30 random characters) if
# you expose your deployment to outside traffic
AUTH_JWT_SECRET=this-is-only-for-demo-purpose--make-sure-you-change-it-for-production

########################################################################################################################
# SMTP (mail sending) settings

# Disable email confirmation for sign-up protocol to allow more seamless setup without the need
# for SMTP Server
#PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_EMAIL_CONFIRMATION_REQUIRED=false

# Point this to your local or external SMTP server
SMTP_HOST=smtp-server.example.tld:587
SMTP_USER=postmaster@smtp-server.example.tld
SMTP_PASS=this-is-your-smtp-password
SMTP_FROM="Demo" <info@your-demo.example.tld>


########################################################################################################################
# Corredor service settings

# Corredor address is used in Corredor service for grpc server configuration
# and inside Server for configuring corredor gRPC client with location for corredor server
# If these two values are different in your environment for
CORREDOR_ADDR=corredor:80
docker-compose.yaml
version: '3.5'

services:
  webapp:
    image: cortezaproject/corteza-webapp:${VERSION}
    restart: on-failure
    depends_on: [ server ]
    networks: [ proxy ]
    environment:
      # VIRTUAL_HOST helps NginX proxy route trafic for specific virtual host to
      # this container
      VIRTUAL_HOST:     ${DOMAIN}
      # This is needed only if you are using NginX Lets-Encrypt companion
      # (see docs.cortezaproject.org for details)
      LETSENCRYPT_HOST: ${DOMAIN}
      # Monolith API settings informs webapp autoconfiguration script that we're running
      # a monolith API server.
      MONOLITH_API: "true"

  server:
    image: cortezaproject/corteza-server-monolith:${VERSION}
    restart: on-failure
    env_file: [ .env ]
    depends_on: [ db, corredor ]
    networks: [ proxy, internal ]
    # Uncomment to use local fs for data persistence
    # volumes: [ "./data/server:/data" ]
    environment:
      # VIRTUAL_HOST helps NginX proxy route traffic for specific virtual host to
      # this container
      # This value is also picked up by initial boot auto-configuration procedure
      # If this is changed, make sure you change settings accordingly
      VIRTUAL_HOST: api.${DOMAIN}
      # This is needed only if you are using NginX Lets-Encrypt companion
      # (see docs.cortezaproject.org for details)
      LETSENCRYPT_HOST: api.${DOMAIN}

  corredor:
    image: cortezaproject/corteza-server-corredor:${VERSION}
    networks: [ internal ]
    restart: on-failure
    env_file: [ .env ]
    environment:
      # API host will replace {host} in 'https://api.{host}/{service}' template
      # You can change the template with CORREDOR_EXEC_CSERVERS_API_BASEURL_TEMPLATE
      # (best if you can set this variable inside .env)
      CORREDOR_EXEC_CSERVERS_API_HOST: api.${DOMAIN}


  db:
    # MySQL Database
    # See https://hub.docker.com/r/percona/percona-server for details
    image: percona:8.0
    restart: on-failure
    # Uncomment to use local fs for data persistence
    # volumes: [ "./data/db:/var/lib/mysql" ]
    environment:
      # To be picked up by percona image when creating the database
      # Must match with DB_DSN settings inside .env
      #
      # Warning: these are values that are only used on 1st start
      #          if you want to change it later, you need to do that
      #          manually inside db container
      MYSQL_DATABASE: dbname
      MYSQL_USER:     dbuser
      MYSQL_PASSWORD: dbpass
      MYSQL_RANDOM_ROOT_PASSWORD: random # docker-compose logs db |grep "GENERATED ROOT PASSWORD"
    healthcheck: { test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"], timeout: 20s, retries: 10 }
    networks: [ internal ]



networks:
  internal: {}
  proxy: { external: true }

Create an empty directory with the .env and docker-compose.yaml files. You can adjust the provided example configuration files as you see fit.

Make sure to change the AUTH_JWT_SECRET value to something else.

Run the services

docker-compose up -d

Run this command in the same directory as your docker-compose.yaml file. It will start all of the services based on the configurations provided in the configuration files.

You can check if everything is running correctly by executing the docker-compose ps command. The output should be similar to this one:

        Name                       Command                  State              Ports
-------------------------------------------------------------------------------------------
production_corredor_1   docker-entrypoint.sh node  ...   Up (healthy)   80/tcp
production_db_1         /docker-entrypoint.sh mysqld     Up             3306/tcp, 33060/tcp
production_server_1     /bin/corteza-server serve-api    Up (healthy)   80/tcp
production_webapp_1     /entrypoint.sh                   Up (healthy)   80/tcp

You can see four services up and running.

Your services should soon be available on the configured domains in a matter of minutes.

Finishing the setup

  1. Direct your browser to http://your-demo.example.tld. On your first visit, Corteza redirects you to the authentication page (/auth),

  2. create your account through the sign-up form.

The first user gets automatically promoted to an administrator. You can add additional users by using the sign-up form or by adding them in the administration panel.

Relaying inbound emails to Corteza with Postfix

Corteza allows you to detect and react to incoming emails via automation scripts. You can implement automatic responses, create records based on the email content, and forward the email to a Messaging channel.

All further sections assume that the system is configured by following these instructions. If you’ve used anything else, such as MailGun, the examples might not work correctly.

This section doesn’t cover any script development related topics, such as detecting sink routes. Refer to the integrator guide for more information regarding script development.

Flow outline:
  1. Postfix; or similar; forwards the email to the sink API endpoint,

  2. Corteza sink service extracts header and body data from received email,

  3. onReceive triggers are filtered for a match (you can configure your triggers to only respond to specific conditions),

  4. automation scripts are executed.

Corteza setup

For a sink route to work, you must generate a sink signature.

Consider your sink signatures as passwords that allow access to some parts of the system. Make sure they are kept safe and sound.

We recommend constraining sink signatures as much as possible to help with system security. For example, if we only care about POST requests, let the signature only allow POST requests.

Run docker-compose exec server system sink signature -h for all available options:

    --content-type string   Content type (optional)
    --expires string        Date of expiration (YYYY-MM-DD, optional)
-h, --help                  help for signature
    --max-body-size int     Max allowed body size
    --method string         HTTP method that will be used (optional)
    --origin string         Origin of the request (arbitrary string, optional)
    --path string           Full sink request path (do not include /sink prefix, add / for just root)
    --signature-in-path     Include signature in a path instead of query string

For example:

docker-compose exec server system sink signature --content-type email

Should output something in the lines of:

/system/sink?__sign=187...3D
Sink request constraints:
 - signature should be part of query-string
 - body size is not limited
 - expecting content type to be "email"

Make sure to specify a --content-type email.

Take note of the above __sign=…​ parameter; we will need it later.

Postfix setup

Edit /etc/postfix/main.cf:
virtual_alias_maps = pcre:/etc/postfix/virtual_alias

Make sure to change the domain in the below snippet.

Add virtual alias to /etc/postfix/virtual_alias:
# Catch-all for corteza.domain.tld and redirect it to corteza_sink mailbox
#     vv change this vv
/.+@corteza\.domain\.tld$/ corteza_sink
Update virtual-alias map/db file, and restart postfix
postmap /etc/postfix/virtual_alias
postfix reload

Make sure to change the domain and the sink signature to match your parameters.

Add entry to /etc/aliases
corteza_sink: "| curl --data-binary @- 'https://api.your-corteza-instance.tld/system/sink?content-type=email&expires=&method=POST&origin=postfix&__sign=187...3D'"

The above will forward any email for a specific mailbox to a curl command, which then pushes that raw email to the sink endpoint on the Corteza API.

Update aliases
newaliases

Testing Postfix changes

We recommend using a different machine — one that is not running postfix.

You can verify if everything works correctly by either sending an email to the configured address or with a simple CLI command:

# Make sure to change `test@corteza.domain.tld`.
echo "hello corteza"|mail -s 'hello' test@corteza.domain.tld

This should produce a new entry in your mail log (usually /var/log/mail.log) for the test email, along with a log that looks something in the lines of:

postfix/smtpd[23155]: connect from some-host.tld[xxx.xxx.xxx.xxx]
postfix/smtpd[23155]: 277AF5C1B78: client=some-host.tld[xxx.xxx.xxx.xxx]
postfix/cleanup[23159]: 277AF5C1B78: message-id=<b808218e-ce41-6cbf-cb4f-be2b4cf8f776@crust.tech>
postfix/qmgr[14490]: 277AF5C1B78: from=<sender@some-host.tld>, size=1476, nrcpt=1 (queue active)
postfix/smtpd[23155]: disconnect from some-host.tld[xxx.xxx.xxx.xxx] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
postfix/local[23160]: 277AF5C1B78: to=<corteza_sink@my-server>, orig_to=<demo@corteza.domain.tld>, relay=local, delay=0.67, delays=0.03/0.01/0/0.62, dsn=2.0.0, status=sent (delivered to command:  curl --data-binary @- 'https://api.your-corteza-instance.tld/system/sink?content-type=email&expires=&method=POST&origin=postfix&__sign=187...3D')
postfix/qmgr[14490]: 277AF5C1B78: removed

If nothing happens when you send an email, there could be a firewall issue and blocked ports.

Testing Corteza

To test if your sink signature and automaton script are setup correctly, you can use the following command:

echo "
From: <sender@cortezaproject.org>
To: <test@corteza.domain.tld>
Subject: hello
Message-ID: <1234@local.machine.example>

Ola Corteza!
" | curl -i --data-binary @- "https://api.your-corteza-instance.tld/system/sink?content-type=email&expires=&method=POST&origin=postfix&__sign=187...3D"

If this command does not return a 200 OK response, it means that something is misconfigured. Refer to system logs to see exactly where the issue lies.

Backup and restore

We recommend updating your database and uploaded files regularly. It is also highly recommended to do a database backup before you upgrade to a newer Corteza version.

You can define a cron job that backups your data to some external storage.

Backup the database

We recommend the use of mysqldump tool. It’s builtin to the db container (percona:8.0 image).

If you want to use a different tool to create your backup, you will need to connect to the container or publish MySQL ports.

By default, mysqldump locks the tables when you run the export. Table locks might cause issues when running in production, so do keep this in mind.

Do not try to copy raw database files to perform a backup. It might lead to corrupted data.

Database dump command:
# This will dump the entire database and place it in the dump.sql file.
docker-compose exec -T \
    --env MYSQL_PWD=your-password db \
    mysqldump your-db-name --add-drop-database -u your-username > dump.sql

You can backup your data without shutting down Corteza server.

Restore the database

Database restore command:
# This will restore the database based on the dump.sql file
docker-compose exec -T \
    --env MYSQL_PWD=your-password db \
    mysql your-db-name -u your-username < dump.sql

We recommend that Corteza server is shut-down until the restore procedure finishes.

Backup uploaded files

Without object storage service like Min.io, uploaded files are stored directly on the filesystem. Corteza server is storing data to the /data directory (if not configured differently with *_STORAGE_PATH environmental variables).

You can use any one of the standard file management tools to make a backup copy of the files.

Compressing files with tar command:
# This will compress all your uploaded files into the backup.tar.bz2 archive
tar -cjf backup.tar.bz2 data/server/

Restore uploaded files

Uncompromising files from the archive with tar command:
# This will restore your backup.tar.bz2 archive
tar -xjf foo.tar.bz2