automated-setup/script/MANUAL_SETUP.md

1093 lines
32 KiB
Markdown

# Manual Setup Guide
This document contains detailed manual configuration instructions for LetsBe infrastructure components.
> **Note**: Most of these steps are handled automatically by the deployment scripts. This guide is for manual intervention, troubleshooting, and advanced configuration.
---
## Table of Contents
- [Docker Compose Updates](#updating-any-app-with-docker-compose)
- [DNS Configuration](#domain-dns-entries)
- [Required Subdomains](#required-subdomains-a-records)
- [Post-Installation Admin Setup](#after-installation)
- [Email Server Configuration](#e-mails-dns-settings-example)
- [Tool-Specific Setup](#tool-specific-setup)
- [Calcom](#calcom-setup-post-ansible)
- [Baserow](#baserow-setup)
- [Chatwoot](#chatwoot-setup)
- [MinIO](#minio)
- [Getmail6](#setting-up-getmail6)
- [Nextcloud](#upgrade-nextcloud-over-docker-exec)
- [Whiteboard](#whiteboard)
- [Typebot](#typebot-installation)
- [WordPress](#setting-up-wordpress-site-on-root-domain)
- [SSL Certificates](#finding-certificates-with-certbot)
- [Nginx Configuration Examples](#nginx-configuration-examples)
---
## Updating Any App With Docker Compose
```bash
docker compose down && docker compose pull && docker image prune -f && docker compose up -d
```
## Public Key
Before running the start.sh script ensure the file "id_ed25519.key" is in the same path as the README.md here or add / decrypt.
Always keep the file "id_ed25519.key" secure as you can access all server with all permissions with it.
## Domain DNS Entries
Preset subdomains can be adjusted before executing the start.sh script under "env_setup.sh" part: "# Start - Set subdomain per tool". Note that you cannot use the same domain name more than once, each tool must have its own subdomain name.
Each subdomain must then be added as an "A" DNS record in the domain settings, with the Server IP that you receive after purchasing a new server for the target customer.
You should create the "A" DNS entries before starting the "start.sh" script and then wait at least 15 minutes before you go on.
## Redash First Installation
Make sure to uncomment ports in docker-compose.
## Required Subdomains (A Records)
Set up these A records before running the installation script. All should point to your server's IP address.
### Core Subdomains
1. {root} - Main domain (e.g., client.com)
2. www - Standard www prefix
### Tools & Applications
3. activepieces - Workflow automation (automation.client.com)
4. baserow - Database management (database.client.com)
5. calcom - Appointment scheduling (bookings.client.com)
6. chatwoot - Customer support (support.client.com)
7. collabora - Document collaboration (collabora.client.com)
8. documenso - Document signing (documenso.client.com)
9. ghost - Content management/blogging (blog.client.com)
10. gitea - Code repository (code.client.com)
11. glitchtip - Error tracking (debug.client.com)
12. html - Static website hosting (html.client.com)
13. keycloak - Authentication service (auth.client.com)
14. librechat - AI chat service (chat.client.com)
15. listmonk - Email newsletter service (newsletters.client.com)
16. nextcloud - File storage/collaboration (cloud.client.com)
17. nocodb - Low-code database (crm.client.com)
18. odoo - Business management (erp.client.com)
19. penpot - Design platform (design.client.com)
20. portainer - Container management (containers.client.com)
21. poste - Email server (mail.client.com)
22. redash - Data visualization (data.client.com)
23. squidex - Headless CMS (contenthub.client.com)
24. stirlingpdf - PDF manipulation (pdf.client.com)
25. typebot - Conversational forms (botlab.client.com and bots.client.com)
26. umami - Analytics (analytics.client.com)
27. uptime-kuma - Monitoring (uptime.client.com)
28. whiteboard - Collaborative whiteboarding (whiteboard.client.com)
29. windmill - Workflow automation (flows.client.com)
30. wordpress - Website/blog (www.client.com or client.com)
### Infrastructure Subdomains
31. minio - Object storage admin interface (minio.client.com)
32. s3 - S3-compatible storage endpoint (s3.client.com)
33. n8n - Workflow automation alternative (n8n.client.com)
34. ci - Continuous integration (for Gitea/Drone) (ci.client.com)
35. marketing - Optional marketing site (marketing.client.com)
36. helpdesk - Help desk/documentation (helpdesk.client.com)
---
## After Installation
All tools must be prepared and the administrator account must be created/changed. This must be done immediately after installation:
`*` = No Embedding for External Apps
| Tool | Setup Required |
|------|----------------|
| baserow | Admin account must be created via the website |
| *calcom | Admin account must be created via the website |
| *chatwoot | Need to be changed (probably default: Username: "john@acme.inc", Password: "Password1!") |
| gitea | Admin account must be created via the website |
| glitchtip | Admin account must be created via the website under register new account |
| listmonk | Admin account details auto generated and can be found in initial_setup_backup.zip: stacks/listmonk/config.toml |
| *n8n | Admin account must be created via the website |
| nextcloud | Admin account details auto generated and can be found in initial_setup_backup.zip: stacks/nextcloud/docker-compose.yml under "app" & "environment" |
| nextcloud collabora | Admin account details auto generated and can be found in initial_setup_backup.zip: stacks/nextcloud/docker-compose.yml under "collabora" & "environment" |
| *odoo | Admin account must be created via the website |
| penpot | Admin account must be created via the website under register new account |
| *poste | Admin account must be created via the website |
| *squidex | Admin account must be created via the website under register new account |
| *umami | Need to be changed (default: Username: "admin", Password: "umami") |
| *uptime-kuma | Admin account must be created via the website |
| windmill | Need to be changed (default: E-Mail: "admin@windmill.dev", Password: "changeme") |
| *wordpress | Admin account must be created via the website |
**Additional Notes:**
- Add typebot subdomains: botlab & bots
- **Restart REDIS container for activepieces after installation!**
- **UNCOMMENT MINIO SSL/HPARAM LINES IN NGINX AFTER SETUP!!**
---
## Calcom Setup Post-Ansible
1. Go to env and generate a new calendso encryption using: `openssl rand -base64 24`
2. Add `NEXT_PUBLIC_API_V2_URL=https://bookings.{domain}`
---
## Docker-Compose and Nginx Config Location
- Docker compose: `/opt/letsbe/stacks/AppName`
- Nginx: `/etc/nginx/sites-available`
---
## E-Mails DNS Settings Example
```
A, mail.mydomain.com
MX, Name: @ Value: mail.mydomain.com (Priority: 10)
TXT, Name: _dmarc.mydomain.com Value: v=DMARC1; p=none; rua=mailto:administrator@mydomain.com
TXT, Name: @ Value: v=spf1 mx ~all
TXT = DKIM Name & Value: (generate for root domain in poste)
```
**IF DNS MANAGEMENT IS WIX:**
```
TXT, Name: domain.com Value: v=spf1 mx a:mail.qluxurymedia.com a:support.qluxurymedia.com ~all
```
**Email Ports:**
- IMAP without SSL (unencrypted): 143
- IMAP with SSL (encrypted): 993
- SSL/TLS Outgoing: 465
> **IMPORTANT**: You MUST request another certificate in the TLS settings for Poste in order for IMAP to work!
---
## For Containers
- `127.0.0.1` = local
- `0.0.0.0` = network wide
---
## Clients with Existing Email Inboxes
1. Run setup of server, ensure client inserts mail.domain.com A level record first (Only setup A level until after sync, then when you're ready to launch you do the rest), and that the SSL certificate is pulled and valid
2. Setup Poste mailserver
3. Ask client to change password on original mail server account (for their protection)
4. IMAP sync (Use internal container IP if hostnames are the same for the destination):
```bash
imapsync --host1 oldmailserver.com --user1 olduser --password1 oldpassword \
--host2 newmailserver.com --user2 newuser --password2 newpassword
```
5. Once synced, change existing DNS records and create new ones and delete existing conflicting ones - MX records are vital here, do NOT change them until the new server is ready for use
---
## Collabora URL Example for Nextcloud
```
https://admin:password@collabora.mydomain.com
```
---
## Tool-Specific Setup
### Whiteboard
> DO NOT install whiteboard before setting it up properly
If mimetypealiases not found:
```bash
docker exec -u 33 -it customer-nextcloud-app php /var/www/html/occ maintenance:mimetype:update-db
docker exec -u 33 -it customer-nextcloud-app php /var/www/html/occ maintenance:mimetype:update-js
```
**Setup Steps:**
1. Setup docker-compose and nginx if you haven't already made them standard
2. Generate JWT token: `openssl rand -base64 32`
3. Set that token for nextcloud and in the docker compose for the whiteboard:
```bash
docker exec -u 33 -it {CUSTOMER}-nextcloud-app php /var/www/html/occ config:app:set whiteboard jwt_secret_key --value="your-random-key"
```
4. Make NGINX config and link with:
```bash
sudo ln -s /etc/nginx/sites-available/whiteboard.conf /etc/nginx/sites-enabled/
```
5. Generate SSL
6. Restart nginx and reload docker compose
**Known Issues:**
If the integration_whiteboard app was previously installed there might be a leftover non-standard mimetype configured. In this case opening the whiteboard may fail and a file is downloaded instead. Make sure to remove any entry in config/mimetypealiases.json mentioning whiteboard and run:
```bash
docker exec -u 33 -it customer-nextcloud-app php /var/www/html/occ maintenance:mimetype:update-js -vvv
docker exec -u 33 -it customer-nextcloud-app php /var/www/html/occ maintenance:mimetype:update-db -vvv
```
---
### Finding Certificates with Certbot
```bash
sudo certbot certificates
```
**Example (portnimara):**
```bash
sudo certbot --nginx --expand -d portnimara.com -d www.portnimara.com \
-d analytics.portnimara.com \
-d automation.portnimara.com \
-d cloud.portnimara.com \
-d code.portnimara.com \
-d collabora.portnimara.com \
-d contenthub.portnimara.com \
-d crm.portnimara.com \
-d database.portnimara.com \
-d debug.portnimara.com \
-d design.portnimara.com \
-d flows.portnimara.com \
-d helpdesk.portnimara.com \
-d html.portnimara.com \
-d listmail.portnimara.com \
-d mail.portnimara.com \
-d marketing.portnimara.com \
-d schedule.portnimara.com \
-d support.portnimara.com \
-d uptime.portnimara.com \
-d whiteboard.portnimara.com
```
> **IMPORTANT**: DO NOT REQUEST CERTIFICATES BEFORE DOING THE LN COMMAND TO CONNECT SITES-AVAILABLE AND SITES-ENABLED
---
### Upgrade Nextcloud over Docker Exec
Find docker-compose files:
```bash
sudo find / -name "docker-compose.yml"
```
Docker composes are found in `/opt/letsbe/stacks/AppName`
```bash
sudo docker exec --user www-data exampleCustomer-nextcloud-app php occ upgrade
docker exec -u www-data -it exampleCustomer-nextcloud-app php occ db:add-missing-indices
# (CHANGE IMAGE IN DOCKER COMPOSE FILE)
docker-compose pull && docker-compose up -d
```
**Best Practice:**
```bash
sudo docker compose down && sudo docker compose pull && sudo docker compose up -d && sudo docker compose logs -f {customer}-nextcloud-app
```
If stuck in maintenance mode:
```bash
sudo docker exec --user www-data {customer}-nextcloud-app php occ maintenance:mode --off
```
Remove old images:
```bash
docker image prune -f
```
THEN - do the docker exec commands listed above (occ upgrade and add missing indices)
### Nextcloud Webhook Listeners
```bash
occ app:enable webhook_listeners
```
---
### Setting Up WordPress Site on Root Domain
Go to sites-available in the `/etc/nginx/sites-available` directory and edit the wordpress.conf:
```bash
sudo nano wordpress.conf
```
Add new server block to point to root domain:
```nginx
# Redirect HTTP to HTTPS for pitzone.io and www.pitzone.io
server {
listen 80;
server_name {domain}.{suffix} www.{domain}.{suffix};
# Redirect all HTTP requests to HTTPS
return 301 https://$host$request_uri;
}
# HTTPS configuration for pitzone.io with Proxy to Dockerized WordPress
server {
listen 443 ssl http2;
server_name {domain} www.{domain};
# SSL certificate paths from Let's Encrypt
ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Proxy requests to the Dockerized WordPress ({customer-wordpress} container)
location / {
proxy_pass http://{container_ip}:80; # Proxy to the Docker container's internal web server
# TO FIND: sudo docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' {customer}-wordpress
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Deny access to .htaccess files, if any
location ~ /\.ht {
deny all;
}
# ACME challenge for SSL certificate renewal
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
```
Then request certificates with certbot:
```bash
sudo certbot --nginx -d {domain} -d www.{domain}
```
**Nginx Errors:**
```bash
sudo tail -f /var/log/nginx/error.log
```
**Check for auto renewal of certificates:**
```bash
sudo certbot renew --dry-run
```
---
### Baserow Setup
1. Go back into docker-compose after initial setup and mailserver setup
2. Update email settings to enable automated emails
Example environment configuration:
```yaml
environment:
- BASEROW_PUBLIC_URL=https://database.qluxurymedia.com
- DATABASE_URL=postgresql://bzcdowdmi7:xKaDO81KzhRu7yZ4KWjO@baserow-db:5432/baserow
- EMAIL_SMTP=True
- EMAIL_SMTP_USE_TLS=True
- EMAIL_SMTP_HOST=mail.qluxurymedia.com
- EMAIL_SMTP_PORT=587
- FROM_EMAIL=system@qluxurymedia.com
- EMAIL_SMTP_USER=system@qluxurymedia.com
- EMAIL_SMTP_PASSWORD=
```
---
### Chatwoot Setup
> For all passwords, use only letters and numbers here
1. Setup the mail server and create a "support@[domain]" email address, also ensure minio is an A record
2. Change the .env file to include the password for the support email (you have to set this up when you setup the mail address). The .env file can be found in `/opt/letsbe/stacks/chatwoot`
3. Change the .env file to allow users to setup accounts (set to true), set mailer_inbound_email_domain to top level domain (letsbe.biz, for example)
4. Enter the container using:
```bash
docker exec -it [customername]-chatwoot-rails sh
```
5. Run each of these:
```bash
bundle exec rails db:setup
bundle exec rails db:migrate
```
6. Restart container (MUST BE DONE IN THE DIRECTORY OF THE DOCKER COMPOSE FILE):
```bash
docker-compose down && docker-compose up -d
```
7. Install and configure getmail6 and MinIO for S3 storage
#### Updating Chatwoot
```bash
docker compose down && docker compose pull && docker image prune -f && docker compose up -d
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
```
---
### MinIO
1. Edit docker compose for chatwoot to include MinIO (right above "networks" at the bottom), generate MinIO Root User & Root Password:
```yaml
minio:
image: quay.io/minio/minio:RELEASE.2024-10-29T16-01-48Z
container_name: {client}-minio
restart: always
volumes:
- {client}-minio-data:/data
environment:
- MINIO_ROOT_USER={minioadminUsername}
- MINIO_ROOT_PASSWORD={minioAdminPassword}
command: server /data --console-address ":9001"
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
networks:
matt-chatwoot:
ipv4_address: 172.20.1.6
createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 10;
mc alias set minio http://minio:9000 {MinIO Admin User} {MinIO Admin Password};
mc mb minio/typebot;
mc anonymous set public minio/typebot/public;
echo '{ \"Version\": \"2012-10-17\", \"Statement\": [{ \"Sid\": \"PublicRead\", \"Effect\": \"Allow\", \"Principal\": \"*\", \"Action\": [\"s3:GetBucketLocation\", \"s3:ListBucket\", \"s3:GetObject\"], \"Resource\": [\"arn:aws:s3:::typebot\", \"arn:aws:s3:::typebot/*\"], \"Condition\": {} }] }' > /tmp/policy.json
mc admin policy add minio public-read /tmp/policy.json;
mc admin policy set minio public-read user=minioadmin;
echo '{ \"CORSRules\": [{ \"AllowedHeaders\": [\"*\"], \"AllowedMethods\": [\"PUT\", \"POST\", \"GET\"], \"AllowedOrigins\": [\"*\"], \"ExposeHeaders\": [\"ETag\"] }] }' > /tmp/cors.json;
mc cors set minio/typebot /tmp/cors.json;
exit 0;
"
networks:
{chatwoot network name}:
```
And add to "Volumes" at the bottom:
```yaml
{client}-minio-data:
```
2. Edit .env file:
```bash
ENABLE_ACCOUNT_SIGNUP=true
SMTP_PASSWORD=
SMTP_PORT=587
MAILER_INBOUND_EMAIL_DOMAIN=[customer_domain] # letsbe.solutions
RAILS_INBOUND_EMAIL_PASSWORD=[SET] # set this password, you'll need it for getmail6
# Storage
ACTIVE_STORAGE_SERVICE=s3_compatible
STORAGE_BUCKET_NAME=chatwoot
STORAGE_ACCESS_KEY_ID=[minioRootUser]
STORAGE_SECRET_ACCESS_KEY=[minioRootPassword]
STORAGE_REGION=eu-central
STORAGE_ENDPOINT=https://minio.[domain.com]
STORAGE_FORCE_PATH_STYLE=true
# Amazon S3
S3_BUCKET_NAME=chatwoot
AWS_ACCESS_KEY_ID=[minioRootUser]
AWS_SECRET_ACCESS_KEY=[minioRootPassword]
AWS_REGION=eu-central
AWS_ENDPOINT=https://minio.[domain.com]
AWS_FORCE_PATH_STYLE=true
```
3. Go to `/etc/nginx/sites-available` and make a new minio.conf file (see Nginx Configuration Examples below)
4. Make s3.conf for the s3 subdomain (see Nginx Configuration Examples below)
5. **DO THIS AFTER YOU REQUEST THE CERTS:**
```bash
sudo ln -s /etc/nginx/sites-available/minio.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/s3.conf /etc/nginx/sites-enabled/
```
6. Request certificate, restart nginx:
```bash
certbot certificates
sudo certbot --expand -d analytics.qluxurymedia.com,automation.qluxurymedia.com,...,minio.qluxurymedia.com,s3.qluxurymedia.com
```
7. Chatwoot .env changes:
- Set `RAILS_INBOUND_EMAIL_SERVICE=relay`
- Add MinIO config
- Set `RAILS_INBOUND_EMAIL_PASSWORD` to something secure (to use in the configuration for getmail6)
- Change storage from "local" - add the MINIO configs
**Example .env:**
```bash
MAILER_SENDER_EMAIL=LetsBe <support@letsbe.solutions>
SMTP_DOMAIN=mail.letsbe.solutions
SMTP_ADDRESS=mail.letsbe.solutions
SMTP_PORT=465
SMTP_USERNAME=support@letsbe.solutions
SMTP_PASSWORD=3eA0GmDttFISUJ9qA0xb94YQz4N9tHObvDq5oBeX7BHg3OK42
SMTP_AUTHENTICATION=login
SMTP_ENABLE_STARTTLS_AUTO=true
SMTP_OPENSSL_VERIFY_MODE=none
SMTP_TLS=true
SMTP_SSL=
MAILER_INBOUND_EMAIL_DOMAIN=letsbe.solutions
RAILS_INBOUND_EMAIL_SERVICE=relay
RAILS_INBOUND_EMAIL_PASSWORD=hDZn9KAHlGFDxeyh1z3o67H3971oh4yfmWDTJR9DrTn9dozwu
ACTIVE_STORAGE_SERVICE=s3_compatible
STORAGE_BUCKET_NAME=chatwoot
STORAGE_ACCESS_KEY_ID=minioadmin
STORAGE_SECRET_ACCESS_KEY=MfHt6x7H9rbfORhkfy9O51OXjFxsC4QHJcobKbs14CMvXJ820
STORAGE_REGION=eu-central
STORAGE_ENDPOINT=https://s3.[domain].com
STORAGE_FORCE_PATH_STYLE=true
```
8. Access MinIO Interface and use the root user and password to login
9. Create a bucket called "chatwoot"
10. Check .env variables in the customer-chatwoot-rails container (OPTIONAL):
```bash
docker exec -it {customer}-chatwoot-rails sh
env | grep -E 'AWS|ACTIVE_STORAGE|STORAGE'
exit
```
---
### Setting up Getmail6
1. Install getmail6 on the server:
```bash
sudo apt-get update
sudo apt-get install -y python3-pip
cd /
git clone https://github.com/getmail6/getmail6.git
cd getmail6
sudo python3 setup.py install
getmail --version
```
2. Create a dedicated getmailuser user, and SWITCH TO THAT USER:
```bash
sudo adduser getmailuser
sudo su - getmailuser
```
3. Create necessary directories:
```bash
mkdir -p ~/.getmail
mkdir -p ~/bin
mkdir -p ~/logs
```
4. Make sure your RAILS_INBOUND_EMAIL_PASSWORD (Ingress Password) set in the chatwoot .env file is ready
5. Create the import email script (1 per account, ingress password remains the same):
```bash
nano ~/bin/import_mail_to_chatwoot.sh
```
Content:
```bash
#!/bin/bash
INGRESS_PASSWORD="{insert RAILS_INBOUND_EMAIL_PASSWORD here}"
URL='http://0.0.0.0:3011/rails/action_mailbox/relay/inbound_emails'
curl -sS -u "actionmailbox:{insert RAILS_INBOUND_EMAIL_PASSWORD here}" \
-A "Action Mailbox: curl relayer" \
-H "Content-Type: message/rfc822" \
--data-binary @- \
$URL
```
6. Make the script executable:
```bash
chmod +x ~/bin/import_mail_to_chatwoot.sh
```
7. Create the getmailrc config file (1 per email channel):
```bash
nano ~/.getmail/getmailrc
```
Content:
```ini
[retriever1]
type = MultidropIMAPSSLRetriever
server = mail.letsbe.solutions
username = support@letsbe.solutions
password = 3eA0GmDttFISUJ9qA0xb94YQz4N9tHObvDq5oBeX7BHg3OK42
mailboxes = ("INBOX",)
envelope_recipient = delivered-to:1
[retriever2] # Add if you have more mailboxes
type = MultidropIMAPSSLRetriever
server = mail.{domain}
username = help@{domain}
password = {Password}
mailboxes = ("INBOX",)
envelope_recipient = delivered-to:1
[destination]
type = MDA_external
path = /home/getmailuser/bin/import_mail_to_chatwoot.sh
[options]
verbose = 1
allow_root_commands = true
read_all = false
delete = false
delivered_to = false
received = false
message_log = ~/.getmail/getmail.log
message_log_syslog = false
message_log_verbose = true
```
8. Make config executable:
```bash
chmod +x ~/.getmail/getmailrc
```
9. Test Getmail manually:
```bash
getmail --rcfile ~/.getmail/getmailrc --verbose
```
10. Setup cron job:
```bash
crontab -e
```
Add at the bottom:
```
*/1 * * * * /usr/local/bin/getmail --rcfile /home/getmailuser/.getmail/* --quiet
```
11. Use "exit" to exit the getmailuser
12. Setup IMAP settings in Chatwoot App (in channel settings)
13. Do not forward emails to the address provided by Chatwoot in the channel setup
---
### Nextcloud Context Chat
See: https://docs.nextcloud.com/server/latest/admin_manual/ai/app_context_chat.html#ai-app-context-chat
---
### Apps Only for Tech Savvy People
1. gitea
2. Squidex
3. Windmill
---
### Typebot Installation
> Make sure to enact relevant changes in Nginx/Docker compose for s3 and Minio respectively
1. Create directory:
```bash
mkdir {client-typebot} in /opt/letsbe/stacks/
```
2. Create docker-compose.yml:
```yaml
version: '3.3'
volumes:
{client}-typebot-db-data:
services:
{client}-typebot-db:
image: postgres:16
restart: always
volumes:
- {client}-typebot-db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=typebot
- POSTGRES_PASSWORD=typebot
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
{chatwoot_network_name}:
ipv4_address: 172.20.1.7
typebot-builder:
image: baptistearno/typebot-builder:latest
restart: always
depends_on:
{client}-typebot-db:
condition: service_healthy
ports:
- '9080:3000'
extra_hosts:
- 'host.docker.internal:host-gateway'
env_file: /opt/letsbe/env/typebot.env
networks:
{chatwoot_network_name}:
ipv4_address: 172.20.1.8
typebot-viewer:
image: baptistearno/typebot-viewer:latest
depends_on:
{client}-typebot-db:
condition: service_healthy
restart: always
ports:
- '9081:3000'
env_file: /opt/letsbe/env/typebot.env
networks:
{chatwoot_network_name}:
ipv4_address: 172.20.1.9
networks:
{chatwoot_network_name}:
external: true
```
3. Create typebot.env in `/opt/letsbe/env/`:
Generate 64-bit key:
```bash
openssl rand -base64 24 | tr -d '\n' ; echo
```
Content:
```bash
ENCRYPTION_SECRET={key}
DATABASE_URL=postgresql://postgres:typebot@typebot-db:5432/typebot
NODE_OPTIONS=--no-node-snapshot
NEXTAUTH_URL=https://botlab.letsbe.solutions
NEXT_PUBLIC_VIEWER_URL=https://bots.letsbe.solutions
DEFAULT_WORKSPACE_PLAN=UNLIMITED
ADMIN_EMAIL=administrator@letsbe.solutions
# SMTP Configuration
SMTP_USERNAME=noreply@letsbe.biz
SMTP_PASSWORD=NF5joaQH2Q
SMTP_HOST=mail.letsbe.solutions
SMTP_PORT=465
SMTP_SECURE=true
NEXT_PUBLIC_SMTP_FROM="Typebot Notifications <noreply@letsbe.biz>"
SMTP_AUTH_DISABLED=false
# S3 Configuration for MinIO
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=A7wRC52q5BofIjnQFdOaM7aBScS6H7jY54u0aax4P1KCsceP5
S3_BUCKET=typebot
S3_PORT=
S3_ENDPOINT=s3.letsbe.solutions
S3_SSL=true
S3_REGION=eu-central
S3_PUBLIC_CUSTOM_DOMAIN=https://s3.letsbe.solutions
```
4. Create nginx configs for botlab and bots (see Nginx Configuration Examples below)
5. Requesting the certs:
```bash
# Link sites-available to sites-enabled first
sudo certbot --nginx -d botlab.{client}.{domain} -d bots.{client}.{domain}
sudo nginx -t
sudo systemctl reload nginx
```
---
## Nginx Configuration Examples
### Whiteboard Config
```nginx
server {
if ($host = whiteboard.letsbe.solutions) {
return 301 https://$host$request_uri;
}
client_max_body_size 64M;
listen 80;
server_name whiteboard.letsbe.solutions;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
server {
client_max_body_size 64M;
listen 443 ssl http2;
server_name whiteboard.letsbe.solutions;
ssl_certificate /etc/letsencrypt/live/whiteboard.letsbe.solutions/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/whiteboard.letsbe.solutions/privkey.pem;
location / {
proxy_pass http://0.0.0.0:4014;
proxy_http_version 1.1;
proxy_read_timeout 3600s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-Frontend-Host $host;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
```
### MinIO Config
```nginx
server {
if ($host = minio.letsbe.solutions) {
return 301 https://$host$request_uri;
}
client_max_body_size 64M;
listen 80;
server_name minio.letsbe.solutions;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
server {
listen 443 ssl http2;
server_name minio.letsbe.solutions;
location / {
proxy_pass http://0.0.0.0:9001;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded_Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
ssl_certificate /etc/letsencrypt/live/support.letsbe.solutions/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/support.letsbe.solutions/privkey.pem;
}
```
### S3 Config
```nginx
server {
if ($host = s3.qluxurymedia.com) {
return 301 https://$host$request_uri;
}
client_max_body_size 0;
listen 80;
server_name s3.qluxurymedia.com;
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
server {
client_max_body_size 0;
listen 443 ssl http2;
server_name s3.qluxurymedia.com;
ssl_certificate /etc/letsencrypt/live/analytics.qluxurymedia.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.qluxurymedia.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header Access-Control-Allow-Origin;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' '*' always;
add_header 'Access-Control-Expose-Headers' 'Origin, Content-Type, Content-MD5, Content-Disposition, ETag' always;
if ($request_method = 'OPTIONS') {
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
```
### Typebot Botlab Config
```nginx
server {
if ($host = botlab.{client}.{domain}) {
return 301 https://$host$request_uri;
}
client_max_body_size 64M;
listen 80;
server_name botlab.{client}.{domain};
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
server {
client_max_body_size 64M;
large_client_header_buffers 4 16k;
listen 443 ssl http2;
server_name botlab.{client}.{domain};
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://172.20.1.8:3000;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
### Typebot Bots Config
```nginx
server {
if ($host = bots.{client}.{domain}) {
return 301 https://$host$request_uri;
}
client_max_body_size 64M;
listen 80;
server_name bots.{client}.{domain};
location / {
return 301 https://$host$request_uri;
}
location ^~ /.well-known/acme-challenge/ {
alias /var/www/html/.well-known/acme-challenge/;
default_type "text/plain";
allow all;
}
}
server {
client_max_body_size 64M;
large_client_header_buffers 4 16k;
listen 443 ssl http2;
server_name bots.{client}.{domain};
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://172.20.1.9:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```
---
## Nginx Tips
Always do the link of the nginx files before requesting certs, but comment out any ssl locations.
```bash
# Link sites-available to sites-enabled
sudo ln -s /etc/nginx/sites-available/{config}.conf /etc/nginx/sites-enabled/
# Test nginx configuration
sudo nginx -t
# Reload nginx
sudo systemctl reload nginx
```
---
## ToDo
- Fix backups.sh