Skip to main content

External Services

About 8 min

External services

Deployment of services that StormBPMN depends on: object storage, Redis, PlantUML, document conversion, and email. The basic checklist and load balancer are covered in the Production installation overview.

S3 storage for files

What is stored in S3:

  • Business process images - diagrams and charts
  • User avatars - profile pictures
  • Document templates - for report generation
  • Attachments - files attached to processes

What to choose if you don't have a corporate S3

StormBPMN works with any S3-compatible storage. Two simple options for self-host:

  • MinIO β€” a familiar option (see below). Note: in recent releases, the MinIO community console has been reduced to a simple object browser β€” bucket/policy management via the web interface has been removed.
  • SeaweedFS β€” a lightweight S3 storage in a single container with a built-in web interface (Filer). Recommended if you need a simple UI and minimal setup effort.

Recommended solution: MinIO

Info

If you used the script for a quick start, MinIO is already successfully deployed and connected to the system.

Installing MinIO

# Запуск MinIO Π² Docker
docker run -d \
  -p 9000:9000 \
  -p 9001:9001 \
  --name minio \
  -v /mnt/data:/data \
  -e "MINIO_ROOT_USER=stormbpmn-s3-user" \
  -e "MINIO_ROOT_PASSWORD=stormbpmn-s3-password" \
  quay.io/minio/minio server /data --console-address ":9001"

Creating the default bucket

curl -fLO https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/bin/
mc alias set minio http://localhost:9000 "stormbpmn-s3-user" "stormbpmn-s3-password"
mc mb minio/storm-uploads

Configuring environment variables

VariableDescriptionExample value
S3_ENDPOINTStorage URLhttp://192.168.0.4:9000
S3_ACCESS_KEYAccess keystormbpmn-s3-user
S3_SECRET_KEYSecret keystormbpmn-s3-password
S3_BUCKET_UPLOADSDefault bucketstorm-uploads
S3_BUCKET_USERSBucket for usersstorm-users
S3_BUCKET_IMPORTSBucket for importsstorm-imports
S3_SINGLE_USERS_BUCKETSingle bucket mode for userstrue
S3_EXTERNAL_ENDPOINTAddress at which the browser opens file links (optional)https://s3.company.com

S3_EXTERNAL_ENDPOINT

The Storm server accesses the storage via S3_ENDPOINT (usually an internal address), while users are issued temporary (presigned) links to files that their browser opens. If the internal address is not accessible from user computers, specify the external address of the same storage in S3_EXTERNAL_ENDPOINT. If the variable is not set, links are constructed using S3_ENDPOINT. The System Check verifies the operation of this address from the browser. After changing .env, restart the container.

When using another S3 storage compatible with AWS SDK v2, you may also need to:

  • Set the variable S3_REGION corresponding to your storage configuration
  • Set the variable S3_VIRTUAL_HOST=true for vHosted addressing type (default is false for Path-Style)

Single user bucket

  • For a fresh installation, we recommend using S3_SINGLE_USERS_BUCKET=true.
  • If you already have Storm installed and connected to an S3 storage where each user has their own bucket (of the form user123), you can migrate them to a single bucket (for example, storm-users), specify it in the variable S3_BUCKET_USERS and switch the operating mode to S3_SINGLE_USERS_BUCKET=true. In this case, the path to user files will look like s3://storm-users/user123/...

Verifying functionality

After configuration, when saving diagrams, their thumbnails should be displayed in the card view.

MinIO Documentation

Complete installation guide: MinIO Documentationopen in new window

Alternative: SeaweedFS (Simple S3 with Built-in UI)

SeaweedFSopen in new window is a lightweight S3-compatible storage solution. It runs as a single container, features a built-in web interface (Filer), and supports path-style addressing used by StormBPMN. It is a good choice if you do not have a corporate S3 implementation and MinIO does not meet your requirements.

Step 1. Access Credentials

S3 in SeaweedFS is open by default without a password β€” you must set access keys via configuration. Create the file s3-config.json:

{
  "identities": [
    {
      "name": "stormbpmn",
      "credentials": [
        { "accessKey": "stormbpmn-s3-user", "secretKey": "stormbpmn-s3-password" }
      ],
      "actions": ["Admin", "Read", "Write", "List", "Tagging"]
    }
  ]
}

Step 2. Container Startup

docker run -d \
  --name seaweedfs \
  --restart unless-stopped \
  -p 8333:8333 \
  -p 8888:8888 \
  -v /mnt/seaweedfs:/data \
  -v "$(pwd)/s3-config.json:/etc/seaweedfs/s3-config.json:ro" \
  chrislusf/seaweedfs server \
    -dir=/data \
    -s3 \
    -s3.port=8333 \
    -s3.config=/etc/seaweedfs/s3-config.json

The server command starts the master, volume, filer, and S3 gateway in a single process.

PortPurpose
8333S3 API (specified in S3_ENDPOINT)
8888Filer β€” web interface for browsing files

Step 3. Bucket Creation

docker exec -i seaweedfs weed shell <<< "s3.bucket.create -name storm-uploads"

Or using any S3 client with the same keys (e.g., AWS CLI):

aws --endpoint-url http://localhost:8333 s3 mb s3://storm-uploads

Step 4. StormBPMN Environment Variables

S3_ENDPOINT=http://<хост-seaweedfs>:8333
S3_ACCESS_KEY=stormbpmn-s3-user
S3_SECRET_KEY=stormbpmn-s3-password
S3_BUCKET_UPLOADS=storm-uploads
S3_SINGLE_USERS_BUCKET=true
# АдрСсация path-style Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ (S3_VIRTUAL_HOST=false) β€” ΠΌΠ΅Π½ΡΡ‚ΡŒ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ.

Step 5. Verification

  • Open the Filer web interface: http://<хост-seaweedfs>:8888 β€” buckets and files are visible there.
  • Save a diagram in StormBPMN β€” its thumbnail should appear in the card view, and the corresponding object should appear in the storm-uploads bucket (in Filer).

SeaweedFS Documentation

S3 API and its configuration: SeaweedFS β€” Amazon S3 APIopen in new window.



Redis: Collaborative Diagram Editing

Redis is used for the real-time collaborative diagram editing feature. It provides:

  • Pub/Sub - message delivery between application instances (cursors, XML changes, presence)
  • Session storage - information about current participants in collaborative editing

When is Redis required?

  • Single StormBPMN instance β€” Redis is not required. Data is stored in application memory (InMemory mode)
  • Multiple instances (multi-instance / HA) β€” Redis is mandatory for synchronization between nodes

Installation

# Запуск Redis Π² Docker
docker run -d \
  -p 6379:6379 \
  --name redis \
  redis:7-alpine

For production, it is recommended to set a password:

docker run -d \
  -p 6379:6379 \
  --name redis \
  redis:7-alpine \
  redis-server --requirepass your-secure-password

Configuring environment variables

VariableDescriptionExample valueRequired
REDIS_ENABLEDEnabling RedistrueFor multi-instance
REDIS_HOSTRedis host192.168.0.7When REDIS_ENABLED=true
REDIS_PORTRedis port6379When REDIS_ENABLED=true
REDIS_PASSWORDRedis passwordyour-passwordIf set on the server
REDIS_DATABASERedis database number0Optional (default 0)
REDIS_TIMEOUTConnection timeout1000msOptional

Functionality Check

After configuration, open one diagram in two browser tabs β€” you should see the avatars of other participants on the canvas and real-time synchronization of changes.

Configuring the Load Balancer for WebSocket

Collaborative editing uses WebSocket (STOMP over SockJS) via the path /ws. Ensure that the load balancer proxies WebSocket connections. A configuration example is provided in the section above.

Sticky Sessions

When using multiple nodes behind the load balancer, WebSocket connections must support sticky sessions (node affinity) β€” otherwise, the SockJS fallback may not work correctly.



PlantUML server (optional)

Provides UML diagram generation in the application interface.

Info

If you used the script for quick start, PlantUML is already successfully deployed and connected to the system.

Installation

# Запуск PlantUML сСрвСра
docker run -d \
  -p 8090:8080 \
  --name plantuml \
  plantuml/plantuml-server:jetty

Configuration

VariableDescriptionExample Value
PLANTUML_SERVERPlantUML server URLhttp://192.168.0.5:8090/


Document Conversion Service

Provides conversion of HTML to PDF and other document formats.

Info

If you used the script for a quick start, Gotenberg is already successfully deployed and connected to the system.

Installing Gotenberg

# Запуск Gotenberg
docker run -d \
  -p 3001:3000 \
  --name gotenberg \
  gotenberg/gotenberg:8

You can use our Gotenberg image

If external registries (Docker Hub) are prohibited in your organization, use the Gotenberg mirror in our private registry β€” this is the official image gotenberg/gotenberg:8, signed with the same Cosign signature as the main StormBPMN image, and available using the same credentials cr.selcloud.ru:

docker run -d \
  -p 3001:3000 \
  --name gotenberg \
  cr.selcloud.ru/stormbpmn-enterprise/gotenberg:8

The signature is verified in the same way as for the main image (see Changelog β†’ β€œImage Signature Verification (Cosign)”). Transferring the image to a corporate registry β€” follow the instructions in the Quick Start.

Configuration

VariableDescriptionExample Value
GOTENBERG_URLConversion service URLhttp://192.168.0.5:3001
GOTENBERG_WAIT_FOR_EXPRESSIONOptional. JavaScript expression that Gotenberg waits for on the page before printing to PDF. Do not change: the default value is suitable for Storm pageswindow.overlayReady != undefined && window.overlayReady

The default value is a public demo service

If GOTENBERG_URL is not set, https://demo.gotenberg.dev is used β€” a public demo service on the internet. Process models and user documents would be sent to a third-party service when exported to PDF, and it is generally inaccessible from a closed network. In production, deploy a dedicated Gotenberg container (see above) and ensure that GOTENBERG_URL is set. The System Check treats the demo address as an error.

Additional configuration for complex network setups

If load balancers or complex SSL configurations are used, you may need to specify the direct container address:

In the administrative interface:

  • gotenbergOverrideBaseUrl - direct address: http://corp.storm.internal

Gotenberg opens Storm pages itself, so this address must be accessible from the Gotenberg container. If the "System Check" reports that Gotenberg could not open the application page, specify the internal Storm address here.



Configuring Email Notifications

Choosing an Email Provider

OptionWhen to useConfiguration complexity
ListMonkYou need to customize email layouts and texts, and maintain a sending log⭐⭐
Simple SMTPStormbpmn's ready-made emails are sufficient, and sending is done via a corporate SMTP⭐

Templated emails in both options

In builds after October 7, 2026, all notifications (comments, approvals, invitations, access requests, simulations, password recovery, etc.) are sent as templated emails: a card with a logo, header, button, and a plain-text version of the email. For SMTP, the layout is embedded in the application and requires no external resources β€” the logo is embedded directly in the email. For ListMonk, the same templates are set up with a single click β€” see below.

You must specify this value in the administrative panel to ensure that correct URLs are generated in emails. This setting is required for any provider:

ParameterDescriptionExample
baseUrlBase URL for links in emailshttps://stormbpmn.company.com

Option 1: ListMonk (beautiful emails)

Installing ListMonk

# Π‘ΠΊΠ°Ρ‡ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ
 curl -LO https://github.com/knadh/listmonk/raw/master/docker-compose.yml

# Запуск (ΠΏΡ€ΠΈ нСобходимости ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΠΎΡ€Ρ‚Ρ‹ Π² docker-compose.yml)
docker compose up -d

Configuring ListMonk

  1. Open the admin panel: http://localhost:9000

  2. Create a super user and log in to the system

  3. Configure general settings (Settings β†’ General):

    • Specify the default email address for sending

    Default email configuration

  4. Configure SMTP (Settings β†’ SMTP):

    • Specify the corporate SMTP server parameters
    • Test the connection

    SMTP configuration

  5. Create an API user:

    • Users β†’ New β†’ Type: API
    • Role: Super Admin
    • Save the API token

    Creating an API user

Environment variables for StormBPMN

EMAIL_PROVIDER=listmonk
LISTMONK_BASE_URL=http://localhost:9000/api
LISTMONK_USERNAME=stormbpmn  # имя API ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ
LISTMONK_PASSWORD=api-token-here  # API Ρ‚ΠΎΠΊΠ΅Π½

Email templates

Quick path: "Configure basic templates in Listmonk" button

In builds after October 7, 2026, you do not need to create templates manually. Open Application Settings β†’ "πŸ“§ Email" tab in the admin panel and click "Configure basic templates in Listmonk". Stormbpmn:

  1. creates a transactional template in ListMonk for each notification type β€” with names like Storm BPMN Β· NEW_COMMENT, using the same layout as plain SMTP emails;
  2. writes the ID of each template to the corresponding setting (commentEmailTemplateId, etc. β€” see the table below).

You can edit the templates directly in ListMonk afterwards: change texts, colors, logos β€” Stormbpmn will still send emails using the IDs from the settings.

Re-clicking is safe:

  • a template that already exists in ListMonk with that name is not recreated or overwritten β€” your edits are preserved;
  • a setting that already contains the ID of a different template (you linked the trigger to your own) is not changed β€” such settings are listed in a warning after clicking;
  • empty settings (and the placeholder 0) are filled in.

Application permissions and address

The ListMonk user from LISTMONK_USERNAME needs permissions for templates (Super Admin, as in the step above). The logo in ListMonk emails is loaded from the address <baseUrl>/email/storm-logo.png β€” ensure that baseUrl is specified and accessible to recipients.

If ListMonk refuses (incorrect login, unavailable), the button displays the reason and a list of already configured triggers β€” re-clicking will complete the rest.

Manual configuration

If you manage your own templates, create them in ListMonk based on the topics in the table and record the ID of each template in the Stormbpmn admin panel.

Substitution syntax

Listmonk uses Go template syntax: variables are accessed via {{ .Tx.Data.имя }}, not {имя}. For example, {{ .Tx.Data.diagram_name }}.

Templates

Notification typeSetting in admin panelAvailable substitutions
New commentcommentEmailTemplateId{{ .Tx.Data.comment_author }}, {{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}, {{ .Tx.Data.html_text }}
Approval requestapprovalTemplateId{{ .Tx.Data.invite_author }}, {{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}
Password recoveryrestorePasswordTemplateId{{ .Tx.Data.restoreCode }}
Approval completedapprovalCompletedTemplateId{{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}
User activationuserActivationTemplateId{{ .Tx.Data.activation_token }}
Diagram invitationsecureUpdateTemlateId{{ .Tx.Data.invite_author }}, {{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}
Invitation + registrationinviteDiagramAndRegisterTemplateId{{ .Tx.Data.invite_author }}, {{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}, {{ .Tx.Data.register_url }}
Team invitationteamInviteTemplateId{{ .Tx.Data.invite_author }}, {{ .Tx.Data.team_name }}
Team invitation + registrationteamInviteAndRegisterTemplateId{{ .Tx.Data.invite_author }}, {{ .Tx.Data.team_name }}, {{ .Tx.Data.register_url }}
Diagram access requestaccessRequestTemplateId{{ .Tx.Data.requester_name }}, {{ .Tx.Data.diagram_name }}, {{ .Tx.Data.diagram_url }}, {{ .Tx.Data.request_message }}
Warm-up emails (Storm Master)retentionEmailTemplateId{{ .Tx.Data.subject }}, {{ .Tx.Data.body }} β€” the body is already ready HTML, output via {{ with .Tx.Data.body }}{{ Safe . }}{{ end }}. See "Warm-ups"

Typo in the key

The key secureUpdateTemlateId is specified with a typo intentionally β€” this is exactly how it is named in the system settings (without p in Temlate).

Specify the template ID in the Stormbpmn admin panel

Templates in the admin panel

Option 2: Simple SMTP

Environment Variables

ParameterDescriptionExample
EMAIL_PROVIDEREnable simple SMTPsmtp
SMTP_HOSTSMTP hostsmtp.company.com
SMTP_PORTSMTP port587
SMTP_USERNAMESMTP userstormbpmn@company.com
SMTP_PASSWORDSMTP passwordsecure-password
SMTP_FROMSender emailstormbpmn@company.com
SMTP_PROTOCOLSMTP/STARTTLS/SMTPS. STARTTLS is the defaultSTARTTLS
SMTP_USE_AUTHfalse β€” do not use authentication, even if SMTP_USERNAME is specified. Without SMTP_USERNAME, authentication is not used for any valuefalse

With simple SMTP, emails are already formatted (card, button, text version), and the logo is embedded in the email β€” nothing is loaded from the closed environment. You can verify sending using the "Send test email" button on the "πŸ“§ Email" tab of the admin panel: in case of an error, it displays the actual reason for the SMTP rejection.

Environment Variables

EMAIL_PROVIDER=smtp
SMTP_PROTOCOL=
SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_FROM=
SMTP_USE_AUTH=

Restart required

All SMTP settings are applied only after a restart of the application.

Testing Email Notifications

To verify email delivery, leave a comment with the following content:

@your.email@company.com test