nowCRM - your open source CRM with multichannel outreach capabilities and efficient data management at scale.
Contact Details & Communication History

Journeys - Automated Marketing Workflows

Composer - Multi-Channel Outreach

Dynamic Variables in Email Campaigns

nowCRM is the central customer relationship management platform developed by nowtec solutions AG.
It connects several microservices (Strapi, Composer, Journeys, and DAL) into one modular solution.
Licensed under the GNU Affero General Public License v3.0.
Attribution required β see NOTICE.
nowCRM relies on the following core services:
| Service | Description |
|---|---|
| Strapi 5 | Headless CMS used as the universal data backend, authentication layer, and admin panel. |
| Composer | Handles content generation, channel dispatch, and AWS SES event ingestion. |
| Journeys | Manages automated multi-step marketing journeys. |
| DAL (Data Access Layer) | Orchestrates heavy asynchronous or bulk operations. |
| nowCRM (Frontend) | The Next.js 15 web interface connecting users to all backend services. |
Before starting local development, ensure you have:
- Node.js, 20+
- pnpm
- Docker + Docker Compose
git clone https://github.com/nowtec/nowCRM.git
cd nowCRM- Option A: One step Docker setup with
make up - Option B: Local step by step setup with
make devand per service commands
This is the quickest way to get a complete environment running.
-
Make sure Docker and Docker Compose are running on your machine.
-
From the project root, run:
make up
-
You will be prompted to enter your customer domain For example:
Enter your customer domain (e.g. nowtec.solutions): -
After you confirm the domain, the full setup will run automatically inside Docker All required services will be started and wired together.
If you prefer to run everything locally outside of Docker, you can bring up the environment step by step.
From the project root, run:
make devThis command prepares the local development environment (dependencies, configs, etc.) for all services.
For DAL, Composer and Journeys, go into each service root folder and run:
pnpm build
pnpm startExamples:
cd dal
pnpm build
pnpm startcd composer
pnpm build
pnpm startcd journeys
pnpm build
pnpm startFrom the nowcrm (frontend) root folder:
pnpm devThe frontend will start in development mode and connect to the locally running backend services.
Before deploying to production, ensure you have:
- Docker and Docker Compose installed on your production server
- A customer domain configured with DNS pointing to your server
- All required secrets and credentials (SMTP, S3, database, etc.)
- Access to the nowCRM container images from GitHub Container Registry
git clone https://github.com/nowtec/nowCRM.git
cd nowCRMThe production compose file uses an external network that must be created first:
docker network create my_netCopy the sample environment file and configure it with your production values:
cp .env.sample .envImportant: Edit .env and fill in all required values. Critical variables include:
CUSTOMER_DOMAIN- Your production domain (e.g.,example.com)STRAPI_DATABASE_*- PostgreSQL database credentialsSTRAPI_ADMIN_JWT_SECRET,STRAPI_API_TOKEN_SALT,STRAPI_APP_KEYS- Generate secure random valuesCRM_AUTH_SECRET- Generate a secure random value for NextAuthCRM_TOTP_ENCRYPTION_KEY- 32-digit key for 2FA encryptionS3_*- S3-compatible storage credentials for file uploadsSTRAPI_AWS_*- AWS S3 credentials for Strapi media storageCOMPOSER_OPENAI_API_KEY,COMPOSER_ANTHROPIC_KEY- AI service API keysCOMPOSER_SMTP_*,DAL_SMTP_*- SMTP credentials for email sendingSSL_EMAIL- Email address for Let's Encrypt SSL certificate generation
Ensure the following files are present:
docker-compose.prod.yaml- Production compose configurationcaddy/Caddyfile- Caddy reverse proxy configurationrabbitmq/rabbitmq_delayed_message_exchange-4.1.0.ez- RabbitMQ plugin
Pull the latest production images from GitHub Container Registry:
docker pull ghcr.io/nowtec/nowcrm/strapi:latest
docker pull ghcr.io/nowtec/nowcrm/nowcrm:latest
docker pull ghcr.io/nowtec/nowcrm/journeys:latest
docker pull ghcr.io/nowtec/nowcrm/composer:latest
docker pull ghcr.io/nowtec/nowcrm/dal:latestOr specify a version with the VERSION environment variable:
c```bash VERSION=v0.4.7 docker compose -f docker-compose.prod.yaml pull
### 6. Start Production Services
Start all services in detached mode:
```bash
docker compose -f docker-compose.prod.yaml up -d
Check that all services are running:
docker compose -f docker-compose.prod.yaml psVerify service logs:
docker compose -f docker-compose.prod.yaml logs -fOnce running, your services will be accessible at:
- CRM:
https://crm.{CUSTOMER_DOMAIN} - Strapi Admin:
https://admin.{CUSTOMER_DOMAIN} - Strapi API:
https://api.{CUSTOMER_DOMAIN} - Journeys:
https://journeys.{CUSTOMER_DOMAIN} - Composer:
https://composer.{CUSTOMER_DOMAIN} - DAL:
https://dal.{CUSTOMER_DOMAIN} - RabbitMQ Management:
https://rabbitmq.{CUSTOMER_DOMAIN}
- Create Strapi Admin User: Access
https://admin.{CUSTOMER_DOMAIN}and create the initial admin user - Configure Channels: Set up email, SMS, and other channels in the CRM admin panel
- Verify Health Checks: Run through the Installation Verification Protocol
- Configure Backups: Set up automated backups for PostgreSQL and Redis volumes
View logs:
docker compose -f docker-compose.prod.yaml logs -f [service_name]Restart a service:
docker compose -f docker-compose.prod.yaml restart [service_name]Stop all services:
docker compose -f docker-compose.prod.yaml downUpdate to a new version:
VERSION=v0.4.8 docker compose -f docker-compose.prod.yaml pull
docker compose -f docker-compose.prod.yaml up -dServices fail to start:
- Check that the
my_netnetwork exists:docker network ls - Verify all environment variables are set in
.env - Check service logs:
docker compose -f docker-compose.prod.yaml logs
SSL certificate issues:
- Ensure
SSL_EMAILis set correctly in.env - Check Caddy logs:
docker compose -f docker-compose.prod.yaml logs caddy - Verify DNS is properly configured for your domain
Database connection issues:
- Verify PostgreSQL container is healthy:
docker compose -f docker-compose.prod.yaml ps postgres - Check database credentials in
.env - Review PostgreSQL logs:
docker compose -f docker-compose.prod.yaml logs postgres
DAL uses BullMQ queues backed by Redis.
| Queue | Purpose |
|---|---|
masssendQueue |
Defines bulk mailings with throttle intervals and target lists. |
sendQueue |
Dispatches individual messages respecting rate limits and retries. |
masssendQueuecreates jobs for each recipient with delay =index Γ throttleMs.sendQueueprocesses each contact job, sending messages and applying exponential backoff on failure.
Observability:
- New Relic, or Prometheus + Graphana
| Route | Description |
|---|---|
/createReference |
Generates the base message composition. |
/createAdditionalResult |
Adds additional channel-specific content. |
/createComposition |
Builds complete multi-channel compositions. |
All variables are prefixed with COMPOSER_.
Example .env (shortened):
COMPOSER_PORT=3020
COMPOSER_REDIS_HOST=localhost
COMPOSER_STRAPI_API_URL=http://localhost:1337/api/
COMPOSER_OPENAI_API_KEY="sk-..."
COMPOSER_SMTP_HOST="email-smtp.eu-central-1.amazonaws.com"SES β SNS β Webhook β Composer endpoint
https://COMPOSER.customerdomain.com/webhook/ses-event-to-strapi
Manual Configuration Steps:
- Set up SNS Topic in AWS SNS Console to receive SES events
- Create SNS Subscription with HTTPS endpoint pointing to your Composer service
- Configure SES Configuration Set to publish events to your SNS topic
- Set the configuration set in AWS SES Console to use your SNS topic
Required Environment Variables:
COMPOSER_CRM_REDIRECT_HEALTH_CHECK- URL for health check redirectsCUSTOMER_DOMAIN- Your customer domain for webhook URL generationCOMPOSER_STRAPI_API_TOKEN- Strapi API token for event processing
Purpose: Central content hub and backend API for all apps.
- Content types for CRM data
- API endpoints for entities
- Admin panel for managing users, lists, and compositions
- Custom plugins for reporting and forms
cd strapi-app
pnpm developProduction mode:
pnpm build
pnpm startPostgreSQL service configured in docker-compose.yaml with:
command: -c 'max_connections=500'
shm_size: 256mbDatabase pool (config/database.js):
pool: { min: 10, max: 500, acquireTimeoutMillis: 60000 }Before pushing:
pnpm lint:fix
pnpm build- Always use environment variable prefixes (
COMPOSER_,DAL_,STRAPI_, etc.) - Avoid hardcoding API URLs; read from
.env - Monitor Redis queues actively during development
- Keep your
.npmrcconfigured for private package registry access
This guide provides a comprehensive summary of the installation verification protocol, channel configuration, and environment configuration for the nowCRM platform.
The Installation Verification Protocol outlines a step-by-step process to ensure proper deployment and functionality of the nowCRM platform and its associated services.
- Customer domain information
- Administrative credentials
- Test data (CSV files for imports)
- Confirm Strapi is running and accessible
- Check Strapi admin panel is responding
- Create Strapi admin user if necessary
- Create dedicated user for nowCRM with admin rights
- Verify user exists and has proper permissions
- Verify public token has appropriate access rights
- Test token functionality
Verify tokens have proper access for:
- DAL (Data Access Layer)
- Journeys service
- Composer service
- Verify nowCRM platform is accessible
- Confirm Admin user created in step 1.2 user can login, and with a wrong password it CAN NOT
- Verify forget and reset password functionality
- Document any access issues
Verify the following domains are accessible:
-
dal(-demo).CUSTOMERDOMAIN -
journeys(-demo).CUSTOMERDOMAIN -
composer(-demo).CUSTOMERDOMAIN
For each service, verify:
- Check service logs for:
- DAL service - no crashes or critical errors
- Journeys service - no crashes or critical errors
- Composer service - no crashes or critical errors
- Create a contact with organization
- Edit the contact information
- Delete a contact
- Filter verification: Find the contact using search/filter functionality
- Verify unsubscribe link works correctly
- Test unsubscribe process end-to-end
- Default channel: Generate and send email composition
- Other channels: Test only if specific configurations are required
- Verify delivery and formatting
Production environment:
- Import CSV with a few test lines
- Verify import success
Demo environment:
- Import CSV with 100k records
- Monitor performance and completion
Actions Import:
- Repeat import process for actions
- Filter verification: Find imported actions using search/filter functionality
- Verify events are properly recorded
- Confirm event streaming is functional
- Check stats collection from Composer service
- Validate analytics data accuracy
- Create a new form
- Configure form sharing/distribution
- Test form accessibility
- Fill out the form completely
- Submit form data
- Results verification: Confirm form results are processed and stored correctly
- Verify Terms of Use page is accessible
- Confirm content is properly displayed
- Test acceptance functionality if applicable
- Access admin settings panel
- Verify all configuration options are available
- Test critical settings functionality
- Confirm permissions are working correctly
- Create a simple journey workflow
- Configure journey triggers and actions
- Verify journey configuration is saved
- Run the created journey
- Monitor Journeys service for proper execution
- Verify Composer service handles journey actions correctly
- Check for any errors or failures in the workflow
Complete E2E Test:
- Create a journey triggered by form completion
- Submit the form
- Verify the journey executes automatically
- Confirm all services work together seamlessly
The Composer module in nowCRM supports multi-channel messaging, including Email, SMS, WhatsApp, LinkedIn, Twitter(X), Telegram, and WordPress. Each channel requires specific configuration in the CRM Admin Panel and, in some cases, external setup.
-
Navigate to the Admin Panel: Go to the CRM Admin Panel and select the Channels section.
-
Select the Channel: Click on the channel you wish to configure (e.g., Email, WhatsApp, SMS, Telegram, Twitter(X), WordPress, LinkedIn, Unipile).
-
Enter Required Credentials: Fill in the required fields such as API keys, tokens, client IDs, secrets, or other authentication details as prompted.
-
Authorize Access (if required): For channels that require OAuth or similar authorization (e.g., LinkedIn), follow the provided link to authorize the CRM application to access your account.
-
Save Credentials: After entering all necessary information, click Save Credentials.
-
Validate Connection: Click the Run Health Check button for each channel. The status will update to show if the connection is active or if there are issues.
- Navigate to Channels > Email in the Admin Panel
- Click Save Credentials
- Click Run Health Check to verify the connection
- Set up a WhatsApp Business Account and register for Meta for Developers
- Go to the Meta App Dashboard and create or select your app
- Under WhatsApp > API Setup, generate a WhatsApp Access Token and retrieve your WhatsApp Business Account ID
- In the CRM Admin Panel, go to Channels > WhatsApp
- Enter the WhatsApp Access Token and Business Account ID
- Click Save Credentials
- Click Run Health Check to verify the connection
- Sign in to the AWS Management Console
- Go to the IAM Console and create or use an IAM user with SNS permissions
- Generate an Access Key ID and Secret Access Key
- Identify your SNS region (e.g., eu-central-1, us-east-1)
- In the CRM Admin Panel, go to Channels > SMS
- Enter the Access Key ID, Secret Access Key, and select the SNS region
- Click Save Credentials
- Click Run Health Check to verify the connection
- Open Telegram and search for @BotFather
- Use
/newbotto create a new bot and follow the instructions to get your Bot API Token - Add your bot to the desired group or channel as an administrator
- To get the Channel ID, use userinfobot or send a message to your bot and use the Telegram API to retrieve the chat ID
- In the CRM Admin Panel, go to Channels > Telegram
- Enter the Bot API Token and Channel ID
- Click Save Credentials
- Click Run Health Check to verify the connection
- Register your application in the Twitter Developer Portal
- Create a Project and an App to obtain your API Key, API Secret Key, Bearer Token, and Access Tokens
- In the CRM Admin Panel, go to Channels > Twitter(X)
- Enter the required credentials
- Click Save Credentials
- Click Run Health Check to verify the connection
- Ensure your WordPress site has the WordPress REST API enabled (default for WordPress 4.7+)
- (Optional) Install a plugin for authentication, such as Application Passwords or JWT Authentication
- Generate an Application Password or JWT Token for your WordPress user
- In the CRM Admin Panel, go to Channels > WordPress
- Enter the WordPress Site URL, Username, and Application Password or JWT Token
- Click Save Credentials
- Click Run Health Check to verify the connection
- Register your application in the LinkedIn Developer Portal
- Retrieve the Client ID and Client Secret from your LinkedIn app settings
- Obtain your Organization URN from your LinkedIn organization page
- In the CRM Admin Panel, go to Channels > LinkedIn
- Enter the Client ID, Client Secret, and Organization URN
- Click the Authorize LinkedIn Access link and complete the authorization flow
- Click Save Credentials
- If prompted, use Refresh Access Token
- Click Run Health Check to verify the connection
- Register for a Unipile developer account at Unipile Developer Portal (if available)
- Obtain your Unipile API Key and any other required credentials from your Unipile dashboard
- In the CRM Admin Panel, go to Channels > Unipile
- Enter the API Key and any other required information
- Click Save Credentials
- Click Run Health Check to verify the connection
Environment configuration is managed through .env files for each service. These files contain critical settings for database connections, API endpoints, authentication, and service-specific configurations.
The main .env file contains backend configurations, secrets, and deployment settings.
- Configure database connections, API endpoints, and service-specific settings for each service
- Ensure proper authentication tokens and credentials are set for inter-service communication
# Environment Configuration
NODE_ENV="development" # Options: 'development', 'production', 'test'
DAL_PORT="6001" # The port your server will listen on
DAL_HOST="localhost" # Hostname for the server
DAL_CORS_ORIGIN="http://localhost:3000" # Allowed CORS origin, adjust as necessary
DAL_COMMON_RATE_LIMIT_MAX_REQUESTS="100" # Max number of requests per window per IP
DAL_MINUTE_TO_LAUNCH="5"
DAL_STRAPI_API_URL="http://localhost:1337/api/"
DAL_STRAPI_API_TOKEN=""
DAL_CHECK_TIME="1440" # This variable helps journeys to understand when to close processed journey job and open new 1 for checking default is 1 day
DAL_JOB_FAIL_LIFE_TIME_DAYS="1"
DAL_JOB_COMPLETED_LIFE_TIME_DAYS="1"
DAL_REDIS_PORT="6379"
DAL_REDIS_HOST="localhost"
DAL_BASIC_AUTH_USERNAME=""
DAL_BASIC_AUTH_PASSWORD=""
DAL_WORKER_COUNT="4"
DAL_JOB_CONCURRENCY="1"
DAL_DATABASE_CLIENT="postgresql"
DAL_DATABASE_HOST="localhost"
DAL_DATABASE_PORT=5433
DAL_DATABASE_NAME=""
DAL_DATABASE_USERNAME=""
DAL_DATABASE_PASSWORD=""
DAL_DATABASE_RDS=false
DAL_DATABASE_SSL_SELF=false
DAL_SMTP_HOST="localhost"
DAL_SMTP_PORT="587"
DAL_SMTP_USER="username"
DAL_SMTP_PASS="password"
DAL_SMTP_FROM=""
# Basic Auth (optional)
DAL_BASIC_AUTH_USERNAME="admin"
DAL_BASIC_AUTH_PASSWORD="admin"
# Shared URLs
STRAPI_URL="http://localhost:1337/api/"
COMPOSER_URL="http://localhost:3020/"
RABBITMQ_URL="amqp://guest:guest@localhost:5672"
NODE_ENV='development' # Options: 'development', 'production', 'test'
CRM_BASE_URL="http://localhost:3000"
CRM_STRAPI_API_URL="http://localhost:1337/api/"
CRM_STRAPI_API_TOKEN=""
DAL_URL='http://localhost:6001/api/'
COMPOSER_URL="http://localhost:3020/"
# API URLs
STRAPI_URL="http://localhost:1337/api/"
JOURNEYS_URL="http://localhost:3010/"
# Authentication
CRM_STRAPI_API_TOKEN=""
CRM_TOTP_ENCRYPTION_KEY=""
AUTH_SECRET=""
AUTH_URL="http://localhost:3000/api/auth"
AUTH_TRUST_HOST=false # for development use false in cause of http
# Configuration
NT_STACK_VERSION=""
TEST_RUN=false
# S3 Configuration (optional)
S3_ACCESS_KEY=""
S3_SECRET_KEY=""
S3_ENDPOINT=""
S3_BUCKET=""
S3_PUBLIC_URL_BASE=""
# Environment Configuration
NODE_ENV="development" # Options: 'development', 'production', 'test'
COMPOSER_PORT="3020" # The port your server will listen on
COMPOSER_HOST="localhost" # Hostname for the server
COMPOSER_CORS_ORIGIN="http://localhost:3000" # Allowed CORS origin, adjust as necessary
COMPOSER_COMMON_RATE_LIMIT_MAX_REQUESTS="100" # Max number of requests per window per IP
COMPOSER_CRM_REDIRECT_HEALTH_CHECK="http://localhost:3000/crm/admin-panel/channels"
# API Configuration
COMPOSER_STRAPI_API_TOKEN=""
STRAPI_URL="http://localhost:1337/api/"
COMPOSER_URL="http://localhost:3020/"
# Redis Configuration
COMPOSER_REDIS_PORT="6379"
COMPOSER_REDIS_HOST="localhost"
# AI Service Configuration
COMPOSER_OPENAI_API_KEY=""
COMPOSER_ANTHROPIC_KEY=""
# SMTP Configuration
COMPOSER_SMTP_HOST=""
COMPOSER_SMTP_PORT="18000"
COMPOSER_SMTP_USER=""
COMPOSER_SMTP_PASS=""
# Domain Configuration
CUSTOMER_DOMAIN=""
COMPOSER_CUSTOMER_IDENTITY=""
# Message Queue
RABBITMQ_URL="amqp://guest:guest@localhost:5672"
# Environment Configuration
NODE_ENV="development" # Options: 'development', 'production', 'test'
JOURNEYS_PORT="3010" # The port your server will listen on
JOURNEYS_HOST="localhost" # Hostname for the server
JOURNEYS_CORS_ORIGIN="http://localhost:3000" # Allowed CORS origin, adjust as necessary
JOURNEYS_COMMON_RATE_LIMIT_MAX_REQUESTS="100" # Max number of requests per window per IP
JOURNEYS_MINUTE_TO_LAUNCH="5"
# API Configuration
JOURNEYS_STRAPI_API_TOKEN=""
STRAPI_URL="http://localhost:1337/api/"
COMPOSER_URL="http://localhost:3020/"
# Job Configuration
JOURNEYS_CHECK_TIME="1440" # This variable helps journeys to understand when to close processed journey job and open new 1 for checking default is 1 day
JOURNEYS_JOB_FAIL_LIFE_TIME_DAYS="1"
JOURNEYS_JOB_COMPLETED_LIFE_TIME_DAYS="1"
# Redis Configuration
JOURNEYS_REDIS_PORT="6379"
JOURNEYS_REDIS_HOST="localhost"
JOURNEYS_REDIS_MAX_RETRIES="3"
JOURNEYS_REDIS_RETRY_DELAY_MS="1000"
JOURNEYS_REDIS_CONNECT_TIMEOUT="10000"
JOURNEYS_REDIS_COMMAND_TIMEOUT="5000"
JOURNEYS_REDIS_LAZY_CONNECT="0"
# Redis Cleanup
REDIS_CLEANUP_CRON="0 2 * * *" # Daily at 2 AM
# Strapi Pagination
STRAPI_PAGINATION_MAX_PAGES="100"
STRAPI_PAGINATION_MAX_RECORDS="10000"
# Circuit Breaker Configuration
CIRCUIT_BREAKER_FAILURE_THRESHOLD="5"
CIRCUIT_BREAKER_RESET_TIMEOUT_MS="60000"
CIRCUIT_BREAKER_HALF_OPEN_MAX_CALLS="3"
# RabbitMQ Configuration
RABBITMQ_URL="amqp://guest:guest@localhost:5672"
RABBITMQ_PREFETCH_COUNT="10"
RABBITMQ_RECONNECT_DELAY_MS="5000"
RABBITMQ_MAX_RECONNECT_ATTEMPTS="10"
RABBITMQ_CONSUMER_CONCURRENCY="5"
RABBITMQ_MAX_RETRIES="3"
RABBITMQ_RETRY_INITIAL_DELAY_MS="1000"
RABBITMQ_RETRY_MAX_DELAY_MS="30000"
-
Security: Never share real credentials in documentation or screenshots. All credentials should be securely managed (e.g., in 1Password).
-
Environment Separation: Use different configurations for development, testing, and production environments.
-
Variable Naming: Use descriptive variable names with service prefixes to avoid conflicts (e.g.,
CRM_,DAL_,BEXIO_). -
Secrets Management: Store sensitive information securely in variables or other secret management systems.
-
Documentation: Include a
.env.samplefile for each service, documenting every variable.
This configuration guide provides a comprehensive overview of the installation verification protocol, channel configuration, and environment configuration for the nowCRM platform. Following these guidelines ensures proper deployment, functionality, and security of the system.
For technical support during installation:
- Technical Team: nowtec solutions AG Engineering [email protected]
Β© 2025 nowtec solutions AG
Licensed under the GNU Affero General Public License v3.0
IMPORTANT: This software is licensed under AGPL-3.0, which means:
- β You can use, modify, and distribute this software freely
- β You can use it commercially
β οΈ You MUST provide the source code of any modificationsβ οΈ You MUST disclose your modifications under AGPL-3.0β οΈ You MUST provide source code access to all users if you run it as a network service (SaaS, web application, etc.)β οΈ You MUST retain all copyright and attribution notices
Attribution notice (see NOTICE) must be preserved in all forks, derivative works, and any network-accessible deployments.
If you modify nowCRM and make it available to users over a network (including as a web service, SaaS, or API), you are required to make the complete source code of your modified version available to those users under AGPL-3.0. This is the key difference from standard GPL licenses.
For commercial licensing options that may provide different terms, please contact:
- Website: https://www.nowtec.solutions
- Email: [email protected]
We welcome contributions! By contributing to nowCRM, you agree that your contributions will be licensed under AGPL-3.0.
Please ensure:
- All new files include the appropriate AGPL-3.0 header
- You have the right to contribute the code
- Your code follows the project's coding standards
- You've tested your changes thoroughly
For questions, issues, or support:
- GitHub Issues: https://github.com/nowtec/nowCRM/issues
- Documentation: https://github.com/nowtec/nowCRM




