# Blog ImageGen
Source: https://docs.trymondo.com/ai/blog-image-gen
This is the introduction to the proposal experience at proposals.trymondo.com
# Custom Image Generation for Blog Feature Images
Mondo is going to be using custom image generation models that are highly tuned for style, quality, composure, speed, storage, and web-ready compression to spruce up ugly feature images on blogs.
This image used a combination of Stable Diffusion and ChatGPT to generate a blog feature image for a post about AI. The image was generated using a custom model fine-tuned for the specific style and quality requirements of Mondo's blog.
## Goal
The goal is to enhance the visual appeal of blog feature images by leveraging advanced image generation techniques. This will ensure that the images are not only aesthetically pleasing but also optimized for web performance.
## Approach
1. **On-Prem GPUs**: Utilize on-premises GPUs to handle the computationally intensive tasks of training and running custom image generation models. This approach ensures full control over the hardware and data, while also reducing dependency on cloud services.
2. **Open Source and Free Tools**: Leverage open-source and free tools to build and fine-tune the image generation models. This includes:
* Frameworks like PyTorch or TensorFlow for model development.
* Pre-trained models from repositories like Hugging Face or Stability AI as a starting point.
* Tools for image optimization and compression, such as ImageMagick or TinyPNG.
3. **Custom Tuning**: Fine-tune the models to prioritize:
* **Style**: Ensure the generated images align with the desired aesthetic.
* **Quality**: Maintain high resolution and clarity.
* **Composure**: Generate images with balanced composition and focus.
* **Speed**: Optimize the models for fast inference times.
* **Storage**: Minimize file sizes without compromising quality.
* **Web-Ready Compression**: Ensure the images are optimized for fast loading on the web.
By combining these strategies, Mondo will be able to generate high-quality, visually appealing, and web-optimized feature images for blogs efficiently and cost-effectively.
# Ozzie AI
Source: https://docs.trymondo.com/ai/client-llm
This is the introduction to the proposal experience at proposals.trymondo.com
# Mondo's Client LLM: Revolutionizing Business Insights
Mondo is building its own Client LLM (Large Language Model) to empower small businesses with instant access to comprehensive insights. This cutting-edge solution will consolidate all client-related data, including past creative assets, posts, invoices, ad analytics, and more, into a single, intelligent system.
By leveraging this technology, small businesses can gain ultimate business insights without incurring the exorbitant costs typically associated with such advanced tools. The Client LLM will streamline decision-making, enhance operational efficiency, and provide actionable recommendations tailored to each business's unique needs.
Eventually, all these capabilities will be seamlessly integrated into a client-facing application called the **Mondo App**, delivering unparalleled value and accessibility to small businesses everywhere.
# null
Source: https://docs.trymondo.com/mops/apps/calcom
## Overview
Cal.com is a scheduling and appointment management system integrated into the Mondo MOPS ecosystem. It provides a robust solution for managing appointments, scheduling meetings, and coordinating availability across team members. In the MOPS platform, Cal.com serves as the central scheduling infrastructure, accessible via its own subdomain.
Cal.com was formerly known as Calendly and provides similar functionality with
additional features for self-hosting and customization.
## Architecture
Cal.com in the MOPS stack consists of:
* **Cal.com Application Container**: The main application serving the web interface
* **PostgreSQL Database**: Stores all scheduling data, accounts, and configuration
* **Traefik Integration**: Handles routing and TLS termination
## Deployment Configuration
### Docker Compose Setup
```yaml theme={null}
services:
database:
container_name: calcom-db
image: postgres:17.4
restart: unless-stopped
volumes:
- ./db:/var/lib/postgresql/data/
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
env_file: .env
networks:
- calcom-net
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER}']
interval: 5s
timeout: 5s
retries: 5
calcom:
image: calcom/cal.com:v5.0.19
container_name: calcom-app
restart: unless-stopped
volumes:
- ./data:/app/data
networks:
- traefik-net
- calcom-net
ports:
- 3000:3000
env_file: .env
environment:
# Database Configuration
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@calcom-db:5432/${POSTGRES_DB}?sslmode=disable
- DATABASE_DIRECT_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@calcom-db:5432/${POSTGRES_DB}?sslmode=disable
# Google Calendar Integration
- GOOGLE_API_CREDENTIALS=${GOOGLE_API_CREDENTIALS}
# SAML Configuration
- SAML_DATABASE_URL=${SAML_DATABASE_URL}
- SAML_ADMINS=${SAML_ADMINS}
# Security and Auth
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- CALENDSO_ENCRYPTION_KEY=${CALENDSO_ENCRYPTION_KEY}
- NEXTAUTH_URL=https://cal.trymondo.com
# Application URLs
- NEXT_PUBLIC_WEBAPP_URL=https://cal.trymondo.com
- NEXT_PUBLIC_APP_URL=https://cal.trymondo.com
- NEXT_PUBLIC_API_V2_URL=https://cal.trymondo.com/api/v2
- WEBAPP_URL=https://cal.trymondo.com
- APP_URL=https://cal.trymondo.com
# Hostname Configuration
- ALLOWED_HOSTNAMES="cal.trymondo.com,trymondo.com,localhost:3000"
# Email Configuration
- EMAIL_FROM=info@trymondo.com
- MAIL_FROM=info@trymondo.com
# SMTP Configuration
- SMTP_HOST=smtp.mailersend.net
- SMTP_PORT=587
- SMTP_USERNAME=${SMTP_USERNAME}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_SECURE=false
- SMTP_AUTH_TYPE=LOGIN
- SMTP_IGNORE_TLS=false
# Nodemailer Configuration
- EMAIL_SERVER_HOST=${SMTP_HOST}
- EMAIL_SERVER_PORT=587
- EMAIL_SERVER_USER=${EMAIL_SERVER_USER}
- EMAIL_SERVER_PASSWORD=${EMAIL_SERVER_PASSWORD}
# Force SMTP over sendmail
- EMAIL_TRANSPORT=smtp
- SENDMAIL_DISABLED=true
- MAILER_PROVIDER=smtp
# Debug
- DEBUG=email:*,nodemailer:*,prisma:*
- EMAIL_DEBUG=true
- NODE_TLS_REJECT_UNAUTHORIZED=0
# Application Settings
- NEXT_PUBLIC_LICENSE_CONSENT=true
- CALCOM_TELEMETRY_DISABLED=1
- NEXT_PUBLIC_IS_E2E=0
- NEXT_PUBLIC_IS_PREMIUM=true
- NEXT_PUBLIC_TEAM_IMPERSONATION=false
- NEXT_DISABLE_IMPERSONATION_PAGE=true
depends_on:
- database
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.cal.rule=Host(`cal.trymondo.com`)'
- 'traefik.http.routers.cal.entrypoints=websecure'
- 'traefik.http.routers.cal.tls=true'
- 'traefik.http.routers.cal.tls.certresolver=production'
- 'traefik.http.services.cal.loadbalancer.server.scheme=http'
- 'traefik.http.services.cal.loadbalancer.server.port=3000'
- 'traefik.http.routers.cal.middlewares=cors@file,secureHeaders@file'
networks:
traefik-net:
external: true
calcom-net:
external: true
```
## Configuration
### Environment Variables
Create a `.env` file in the Cal.com directory with the following variables:
```
# Database Configuration
POSTGRES_USER=your_db_username
POSTGRES_PASSWORD=your_db_password
POSTGRES_DB=calcom
# Security Keys
NEXTAUTH_SECRET=your_random_secret_string
CALENDSO_ENCRYPTION_KEY=your_32_character_key
# Google Calendar (Optional)
GOOGLE_API_CREDENTIALS={"web":{"client_id":"your_client_id","project_id":"your_project_id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"your_client_secret","redirect_uris":["https://cal.trymondo.com/api/auth/callback/google"],"javascript_origins":["https://cal.trymondo.com"]}}
# SAML Configuration (Optional)
SAML_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@calcom-db:5432/${POSTGRES_DB}?sslmode=disable
SAML_ADMINS=admin@your-domain.com
# SMTP Configuration
SMTP_USERNAME=your_smtp_username
SMTP_PASSWORD=your_smtp_password
EMAIL_SERVER_USER=your_email_username
EMAIL_SERVER_PASSWORD=your_email_password
```
Store these credentials securely. The `.env` file contains sensitive
information that should not be committed to version control.
### Key Configuration Options
| Setting | Description | Example |
| --------------------------- | --------------------------------------- | ------------------------------- |
| `ALLOWED_HOSTNAMES` | Comma-separated list of valid hostnames | `cal.trymondo.com,trymondo.com` |
| `NEXTAUTH_URL` | URL for authentication | `https://cal.trymondo.com` |
| `NEXT_PUBLIC_WEBAPP_URL` | Public-facing URL | `https://cal.trymondo.com` |
| `SMTP_*` | Email configuration | Settings for your SMTP provider |
| `CALCOM_TELEMETRY_DISABLED` | Disable usage tracking | `1` |
| `EMAIL_DEBUG` | Enable email debugging | `true` for troubleshooting |
## Installation and Setup
### Prerequisites
* Docker and Docker Compose installed
* External `traefik-net` network created
* Domain with DNS pointing to your server
* SMTP credentials for email notifications
### Deployment Steps
1. **Create Required Networks**:
```bash theme={null}
docker network create calcom-net
# Ensure traefik-net exists
docker network ls | grep traefik-net || docker network create traefik-net
```
2. **Prepare Directory Structure**:
```bash theme={null}
mkdir -p /opt/apps/calcom/{db,data}
cd /opt/apps/calcom
```
3. **Create Configuration Files**:
```bash theme={null}
# Create docker-compose.yml using the configuration above
nano docker-compose.yml
# Create .env file with required variables
nano .env
```
4. **Deploy the Stack**:
```bash theme={null}
docker compose up -d
```
5. **Monitor Initial Startup**:
```bash theme={null}
docker compose logs -f
```
### First-Time Setup
Once deployed, complete the setup:
1. Visit `https://cal.trymondo.com`
2. Create the admin account
3. Configure organization settings
4. Set up event types and availability
## Integration with Other MOPS Services
### Authentication
Cal.com can be integrated with Auth0 or other authentication providers:
1. Configure the OAuth provider in your authentication service
2. Add the appropriate callback URLs
3. Update the Cal.com environment variables with the OAuth credentials
### API Integration
Cal.com exposes an API that can be used by other MOPS services:
```bash theme={null}
# Example API endpoint
https://cal.trymondo.com/api/v2/
```
## Maintenance
### Backup and Restore
Cal.com data is stored in two locations:
1. **PostgreSQL Database**: Use Backrest to back up the database volume
2. **Application Data**: The `./data` volume contains uploads and other files
Regular backups should include both components:
```bash theme={null}
# Example backup using docker commands
docker exec calcom-db pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > calcom_backup_$(date +%Y%m%d).sql
# Example restore
cat calcom_backup_20250415.sql | docker exec -i calcom-db psql -U ${POSTGRES_USER} ${POSTGRES_DB}
```
### Updates
To update Cal.com:
1. Update the image tag in docker-compose.yml
2. Pull the new image:
```bash theme={null}
docker compose pull
```
3. Apply the update:
```bash theme={null}
docker compose up -d
```
Always create a backup before updating to prevent data loss.
## Troubleshooting
### Common Issues
| Issue | Solution |
| -------------------------- | -------------------------------------------------------- |
| Database connection errors | Check PostgreSQL container health and connection string |
| Email not sending | Verify SMTP settings and check logs with `DEBUG=email:*` |
| White screen after update | Check application logs for JavaScript errors |
| Authentication issues | Verify `NEXTAUTH_URL` and `NEXTAUTH_SECRET` settings |
### Checking Logs
```bash theme={null}
# View application logs
docker logs calcom-app
# View database logs
docker logs calcom-db
# Follow logs in real-time
docker logs -f calcom-app
```
### Health Checks
```bash theme={null}
# Check database health
docker exec calcom-db pg_isready -U ${POSTGRES_USER}
# Check application health
curl -kI https://cal.trymondo.com
```
## Performance Tuning
### Resource Allocation
Cal.com performs well with moderate resources:
* Database: 1 CPU, 1GB RAM
* Application: 1-2 CPU, 2GB RAM
For high-traffic instances, consider adding resource constraints to docker-compose.yml:
```yaml theme={null}
services:
database:
deploy:
resources:
limits:
memory: 1G
cpus: '1'
calcom:
deploy:
resources:
limits:
memory: 2G
cpus: '2'
```
## Security Considerations
1. **Database Access**: Limit access to the PostgreSQL database
2. **SMTP Credentials**: Regularly rotate email credentials
3. **API Security**: Monitor API usage and restrict access as needed
4. **Traefik Configuration**: Ensure proper security headers are applied (already configured)
## References
* [Cal.com Documentation](https://cal.com/docs)
* [Cal.com GitHub Repository](https://github.com/calcom/cal.com)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
***
This documentation provides a comprehensive guide to deploying, configuring, and maintaining Cal.com within the Mondo MOPS ecosystem. For specific customization needs or advanced features, refer to the official Cal.com documentation.
# null
Source: https://docs.trymondo.com/mops/apps/espocrm
## Overview
This guide covers the deployment and configuration of EspoCRM using Docker Compose behind Traefik reverse proxy. EspoCRM serves as Mondo's customer relationship management solution, accessible at `crm.trymondo.com`.
## Architecture
EspoCRM is deployed as a multi-container application with the following components:
* **MariaDB**: Database server storing EspoCRM data
* **EspoCRM**: Main application container
* **EspoCRM Daemon**: Background process container
* **EspoCRM WebSocket**: Real-time communications container
All services use the external `traefik-net` network for routing through Traefik.
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External `traefik-net` network
* DNS configured for `crm.trymondo.com`
## Deployment
### Directory Structure
```
environments/prod/espocrm/
├── docker-compose.yml # Main configuration file
├── .env # Environment variables (not in repo)
```
### Environment Variables
Create a `.env` file with the following variables:
```
MYSQL_ROOT_PASSWORD=your_secure_password
MYSQL_DATABASE=espocrm
MYSQL_USER=espocrm_user
MYSQL_PASSWORD=your_secure_password
ESPO_ADMIN_USERNAME=admin
ESPO_ADMIN_PASSWORD=your_secure_password
ESPO_SITE_URL=https://crm.trymondo.com
```
Never commit the `.env` file to version control. Store passwords securely in
your password manager.
### Docker Compose Configuration
The deployment uses a shared image reference and multiple service definitions:
```yaml theme={null}
x-espocrm-image: &espocrm-image
image: espocrm/espocrm:9.0.8
services:
mariadb:
image: mariadb:11.7.2
container_name: espocrm-db
restart: unless-stopped
init: true
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mariadb-data:/var/lib/mysql
healthcheck:
test:
[
'CMD-SHELL',
'mariadb-admin ping -h 127.0.0.1 -u root -p$${MYSQL_ROOT_PASSWORD}',
]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
networks:
- espocrm-net
espocrm:
<<: *espocrm-image
container_name: espocrm
restart: unless-stopped
init: true
depends_on:
mariadb:
condition: service_healthy
environment:
ESPOCRM_DATABASE_DRIVER: mysql
ESPOCRM_DATABASE_HOST: mariadb
ESPOCRM_DATABASE_USER: ${MYSQL_USER}
ESPOCRM_DATABASE_PASSWORD: ${MYSQL_PASSWORD}
ESPOCRM_DATABASE_NAME: ${MYSQL_DATABASE}
ESPOCRM_ADMIN_USERNAME: ${ESPO_ADMIN_USERNAME}
ESPOCRM_ADMIN_PASSWORD: ${ESPO_ADMIN_PASSWORD}
ESPOCRM_SITE_URL: ${ESPO_SITE_URL}
volumes:
- html-data:/var/www/html
healthcheck:
test: ['CMD-SHELL', 'curl -sf http://localhost || exit 1']
interval: 10s
timeout: 5s
retries: 5
networks:
- traefik-net
- espocrm-net
labels:
- traefik.enable=true
- traefik.http.routers.espocrm.rule=Host(`crm.trymondo.com`)
- traefik.http.routers.espocrm.entrypoints=web,websecure
- traefik.http.routers.espocrm.tls=true
- traefik.http.routers.espocrm.tls.certresolver=production
- traefik.http.services.espocrm.loadbalancer.server.port=80
- traefik.http.routers.espocrm.middlewares=secureHeaders@file
espocrm-daemon:
<<: *espocrm-image
container_name: espocrm-daemon
restart: unless-stopped
init: true
entrypoint: docker-daemon.sh
depends_on:
- espocrm
volumes:
- html-data:/var/www/html
networks:
- espocrm-net
espocrm-websocket:
<<: *espocrm-image
container_name: espocrm-websocket
restart: unless-stopped
init: true
entrypoint: docker-websocket.sh
depends_on:
- espocrm
environment:
ESPOCRM_CONFIG_USE_WEB_SOCKET: 'true'
ESPOCRM_CONFIG_WEB_SOCKET_URL: 'wss://crm.trymondo.com/ws'
ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: 'tcp://*:7777'
ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: 'tcp://espocrm-websocket:7777'
volumes:
- html-data:/var/www/html
networks:
- traefik-net
- espocrm-net
labels:
- traefik.enable=true
- traefik.http.routers.espocrm-ws.rule=Host(`crm.trymondo.com`) && PathPrefix(`/ws`)
- traefik.http.routers.espocrm-ws.entrypoints=web,websecure
- traefik.http.routers.espocrm-ws.tls=true
- traefik.http.routers.espocrm-ws.tls.certresolver=production
- traefik.http.services.espocrm-ws.loadbalancer.server.port=80
volumes:
mariadb-data:
html-data:
networks:
traefik-net:
external: true
espocrm-net:
external: true
```
## Deployment Commands
Deploy the stack with:
```bash theme={null}
cd /opt/apps/espocrm
docker compose up -d
```
Verify all components are running:
```bash theme={null}
docker compose ps
```
## Configuration Highlights
### Traefik Integration
EspoCRM is configured with the following Traefik routing:
* Main application at `crm.trymondo.com`
* WebSocket endpoint at `crm.trymondo.com/ws`
* TLS certificate managed by Traefik's `production` resolver
* Security headers applied through Traefik middleware
### WebSocket Configuration
Real-time communication is enabled through ZeroMQ and WebSockets:
* WebSocket URL: `wss://crm.trymondo.com/ws`
* Internal ZeroMQ communication between containers
* Separate Traefik router rule for WebSocket traffic
### Volume Management
The deployment uses Docker named volumes:
* `mariadb-data`: Persistent storage for the database
* `html-data`: Shared volume for EspoCRM application data across all containers
## Maintenance
### Backup Strategy
EspoCRM data should be backed up regularly using Restic/Backrest:
```bash theme={null}
# Backup database
docker compose exec mariadb mysqldump -u root -p${MYSQL_ROOT_PASSWORD} ${MYSQL_DATABASE} > backup_$(date +%Y%m%d).sql
# Include volumes in Backrest paths
# /var/lib/docker/volumes/espocrm_mariadb-data
# /var/lib/docker/volumes/espocrm_html-data
```
### Updates
To update EspoCRM:
1. Update the image version tag in `docker-compose.yml`
2. Pull the new image:
```bash theme={null}
docker compose pull
```
3. Deploy the updated stack:
```bash theme={null}
docker compose up -d
```
4. Check logs for any migration issues:
```bash theme={null}
docker compose logs -f
```
## Troubleshooting
### Database Connection Issues
If EspoCRM can't connect to the database:
1. Check MariaDB container status:
```bash theme={null}
docker compose ps mariadb
```
2. Verify network connectivity:
```bash theme={null}
docker compose exec espocrm ping mariadb
```
3. Check database credentials:
```bash theme={null}
docker compose exec mariadb mysql -u ${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SHOW DATABASES;"
```
### WebSocket Issues
If real-time updates aren't working:
1. Check WebSocket container is running:
```bash theme={null}
docker compose ps espocrm-websocket
```
2. Verify WebSocket URL configuration matches the Traefik route.
3. Test WebSocket connectivity from browser developer tools.
### Traefik Routing Problems
If the site is unreachable:
1. Check Traefik logs:
```bash theme={null}
docker logs traefik
```
2. Verify DNS resolution for `crm.trymondo.com`
3. Confirm Traefik network is correctly attached to all containers.
## Resources
* [Official EspoCRM Docker Documentation](https://docs.espocrm.com/administration/docker/)
* [MariaDB Documentation](https://mariadb.com/kb/en/documentation/)
* [Traefik v2 Documentation](https://doc.traefik.io/traefik/v2.0/)
## Next Steps
* Set up monitoring and alerting for EspoCRM services with Prometheus/Grafana
* Implement automated backups of volumes and database dumps
* Configure SMTP for email notifications
* Explore EspoCRM API integrations with other Mondo services
# null
Source: https://docs.trymondo.com/mops/apps/filepizza
## Overview
FilePizza is a browser-based, peer-to-peer file sharing service deployed as part of the Mondo Open Platform Service (MOPS). It allows users to share files directly between browsers using WebRTC technology, without storing files on a central server.
## Service Details
| Component | Value |
| --------- | -------------------------------------------------------- |
| URL | [https://pizza.trymondo.com](https://pizza.trymondo.com) |
| Image | kern/filepizza:latest |
| Container | filepizza |
| Port | 3000 (internal) |
| Network | traefik-net (external) |
## Architecture
FilePizza consists of a single container connected to the Traefik network:
```
[Client Browsers] <-- WebRTC P2P --> [Client Browsers]
↑ ↑
| |
+-----------→ [FilePizza] ←---------+
↑
|
[Traefik]
```
FilePizza acts as a WebRTC signaling server to establish direct peer connections, but the file data transfers directly between browsers.
## Deployment Configuration
### Docker Compose File
```yaml theme={null}
services:
redis:
image: redis:7.4.2
container_name: redis
restart: unless-stopped
ports:
- 127.0.0.1:6379:6379
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 30s
timeout: 10s
retries: 5
networks:
- filepizza-net
volumes:
- filepizza-redis-data:/data
# coturn:
# image: coturn/coturn:4.6.3
# container_name: coturn
# restart: unless-stopped
# ports:
# - 3478:3478
# - 3478:3478/udp
# - 5349:5349
# - 5349:5349/udp
# - 60000-60128:60000-60128/udp
# environment:
# - DETECT_EXTERNAL_IP=yes
# - DETECT_RELAY_IP=yes
# command: -n --log-file=stdout --redis-userdb="ip=redis connect_timeout=30" --min-port=60000 --max-port=60128
# networks:
# - traefik-net
# - filepizza-net
# labels:
# - traefik.enable=true
# - traefik.http.routers.coturn.rule=Host(`coturn.trymondo.com`)
# - traefik.http.routers.coturn.entrypoints=websecure
# - traefik.http.routers.coturn.tls=true
# - traefik.http.routers.coturn.tls.certresolver=production
# - traefik.http.services.coturn.loadbalancer.server.port=3478
filepizza:
image: kern/filepizza:7e8650f
container_name: filepizza
restart: unless-stopped
environment:
- PORT=80
- REDIS_URL=redis://redis:6379
- COTURN_ENABLED=false
networks:
- traefik-net
- filepizza-net
depends_on:
- redis
labels:
- traefik.enable=true
- traefik.http.routers.filepizza.rule=Host(`pizza.trymondo.com`)
- traefik.http.routers.filepizza.entrypoints=websecure
- traefik.http.routers.filepizza.tls=true
- traefik.http.routers.filepizza.tls.certresolver=production
- traefik.http.services.filepizza.loadbalancer.server.port=80
networks:
traefik-net:
external: true
filepizza-net:
external: true
volumes:
filepizza-redis-data:
```
## Deployment Instructions
1. Create the deployment directory:
```bash theme={null}
mkdir -p /opt/apps/filepizza
```
2. Create the `docker-compose.yml` file with the content shown above:
```bash theme={null}
nano /opt/apps/filepizza/docker-compose.yml
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/filepizza
docker compose up -d
```
4. Verify the service is running:
```bash theme={null}
docker compose ps
```
## Traefik Integration
FilePizza is configured with the following Traefik settings:
* **Host Rule**: `pizza.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 3000
## Usage
1. Access the service at `https://pizza.trymondo.com`
2. File senders can:
* Select a file to share
* Receive a unique URL to share with recipients
3. File recipients:
* Open the shared URL
* Download the file directly from the sender's browser
## Important Notes
FilePizza requires WebRTC support in browsers. Some corporate firewalls or
restrictive networks might block WebRTC connections.
FilePizza is a stateless application. No persistent volumes are needed as
files are never stored on the server.
## Resource Usage
FilePizza is a lightweight application with minimal resource requirements:
* **Memory**: Typically less than 100MB
* **CPU**: Minimal usage during idle periods, moderate during connection establishment
## Maintenance
### Updates
To update FilePizza to the latest version:
```bash theme={null}
cd /opt/apps/filepizza
docker compose pull
docker compose up -d
```
### Troubleshooting
If the service is inaccessible:
1. Check container status:
```bash theme={null}
docker compose ps
```
2. View container logs:
```bash theme={null}
docker compose logs
```
3. Verify Traefik routing:
```bash theme={null}
curl -I -H "Host: pizza.trymondo.com" https://pizza.trymondo.com
```
## Security Considerations
* FilePizza doesn't store files, reducing data exposure risks
* All communications go through HTTPS via Traefik
* WebRTC connections are encrypted by default
* Consider adding Traefik middleware for additional security:
```yaml theme={null}
- traefik.http.routers.filepizza.middlewares=secureHeaders@file
```
## Additional Resources
* [FilePizza GitHub Repository](https://github.com/kern/filepizza)
* [WebRTC Documentation](https://webrtc.org/)
# Dashboard
Source: https://docs.trymondo.com/mops/apps/homer
dash.trymondo.com is the first place to go to see an overview of all the services on the MOPS platform.
## Overview
**Homer** is a simple, static dashboard that allows you to organize your server applications and bookmarks into a clean, modern interface. This document covers the deployment and configuration of Homer using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| -------------- | ------------------------------------------------------ |
| URL | [https://dash.trymondo.com](https://dash.trymondo.com) |
| Image | b4bz/homer:v25.04.1 |
| Container Name | homer |
| Port | 8080 (internal) |
| Network | traefik-net (external) |
| Volume | ./assets (configuration and customization) |
## Architecture
Homer is deployed as a single container that serves a static dashboard:
```
┌─────────────┐
HTTPS Request │ Traefik │
─────────────────▶│ │
└──────┬──────┘
│
▼
┌─────────────┐
│ Homer │
│ Dashboard │
└──────┬──────┘
│
▼
┌─────────────┐
│ ./assets │
│ Volume │
└─────────────┘
```
* **Traefik**: Provides HTTPS termination and routing
* **Homer Container**: Serves the static dashboard
* **Assets Volume**: Contains configuration and customization files
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External `traefik-net` network
* DNS configured for `dash.trymondo.com`
## Deployment Configuration
### Directory Structure
```
/opt/apps/homer/
├── docker-compose.yml # Main configuration file
├── docker-compose.override.yml # (Optional) Resource limits
└── assets/ # Homer configuration files
├── config.yml # Dashboard configuration
├── icons/ # Custom icons
└── logos/ # Custom logos
```
### Docker Compose File
```yaml theme={null}
services:
homer:
image: b4bz/homer:v25.04.1
container_name: homer
volumes:
- ./assets:/www/assets
environment:
- INIT_ASSETS=1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.homer.rule=Host(`dash.trymondo.com`)'
- 'traefik.http.routers.homer.entrypoints=websecure'
- 'traefik.http.routers.homer.tls=true'
- 'traefik.http.routers.homer.tls.certresolver=production'
- 'traefik.http.services.homer.loadbalancer.server.port=8080'
- 'traefik.http.routers.homer.middlewares=secureHeaders@file'
- 'diun.enable=true'
networks:
- traefik-net
restart: unless-stopped
networks:
traefik-net:
external: true
```
### Resource Limits (Optional)
For improved stability, you can add resource constraints using a `docker-compose.override.yml` file:
```yaml theme={null}
services:
homer:
deploy:
resources:
limits:
memory: 128M
cpus: '0.2'
```
## Deployment Instructions
1. Create the deployment directory:
```bash theme={null}
mkdir -p /opt/apps/homer/assets
```
2. Create the `docker-compose.yml` file:
```bash theme={null}
nano /opt/apps/homer/docker-compose.yml
```
3. Create the optional resource limits file:
```bash theme={null}
nano /opt/apps/homer/docker-compose.override.yml
```
4. Deploy the service:
```bash theme={null}
cd /opt/apps/homer
docker compose up -d
```
5. Verify the service is running:
```bash theme={null}
docker compose ps
```
## Configuration
### Basic `config.yml` Setup
After deploying Homer, you'll need to configure your dashboard. When the `INIT_ASSETS=1` environment variable is set, Homer will create a default configuration on first launch.
Edit the configuration file:
```bash theme={null}
nano /opt/apps/homer/assets/config.yml
```
Here's a basic example configuration:
```yaml theme={null}
---
title: 'Mondo Dashboard'
subtitle: 'Self-hosted services'
logo: 'logo.png'
# Optional theme customization
theme: default
colors:
light:
primary: '#3367d6'
dark:
primary: '#3367d6'
# Optional message
message:
style: 'is-info'
title: 'Welcome to the Mondo MOPS Dashboard!'
content: 'This dashboard provides quick access to all Mondo services.'
# Services displayed on the dashboard
services:
- name: 'DevOps'
icon: 'fas fa-code-branch'
items:
- name: 'Traefik'
logo: 'assets/tools/traefik.png'
subtitle: 'Reverse Proxy'
tag: 'infrastructure'
url: 'https://traefik.trymondo.com'
- name: 'Portainer'
logo: 'assets/tools/portainer.png'
subtitle: 'Container Management'
tag: 'infrastructure'
url: 'https://portainer.trymondo.com'
- name: 'Gitea'
logo: 'assets/tools/gitea.png'
subtitle: 'Git Server'
tag: 'tools'
url: 'https://git.trymondo.com'
- name: 'Applications'
icon: 'fas fa-cloud'
items:
- name: 'Outline Wiki'
logo: 'assets/tools/outline.png'
subtitle: 'Knowledge Base'
tag: 'app'
url: 'https://wiki.trymondo.com'
- name: 'Mautic'
logo: 'assets/tools/mautic.png'
subtitle: 'Marketing Automation'
tag: 'app'
url: 'https://outreach.trymondo.com'
- name: 'N8N'
logo: 'assets/tools/n8n.png'
subtitle: 'Workflow Automation'
tag: 'app'
url: 'https://automations.trymondo.com'
```
### Custom Icons and Logos
You can add custom icons and logos to your dashboard:
1. Create directories for your assets:
```bash theme={null}
mkdir -p /opt/apps/homer/assets/icons
mkdir -p /opt/apps/homer/assets/logos
mkdir -p /opt/apps/homer/assets/tools
```
2. Add your custom images to these directories
3. Reference them in your `config.yml` file
### Theme Customization
Homer supports multiple themes. To change the theme, update the `theme` property in `config.yml`:
```yaml theme={null}
# Available themes: default, sui, slate, minimal
theme: minimal
# Custom colors
colors:
light:
primary: '#34495e'
background: '#f5f5f5'
dark:
primary: '#3498db'
background: '#222222'
```
## Traefik Integration
Homer is configured with the following Traefik settings:
* **Host Rule**: `dash.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 8080
* **Middleware**: secureHeaders for enhanced security
## Update Monitoring
Homer is configured with Diun monitoring to automatically detect image updates:
```yaml theme={null}
labels:
- 'diun.enable=true'
```
When a new version of the Homer image is available, Diun will send a notification.
## Maintenance
### Backup Strategy
Back up Homer's configuration regularly:
```bash theme={null}
# Backup the assets directory
tar -czf homer-assets-backup-$(date +%Y%m%d).tar.gz -C /opt/apps/homer assets
```
### Updates
To update Homer:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
cd /opt/apps/homer
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
## Troubleshooting
### Dashboard Not Loading
If the dashboard is not loading:
1. Check if the container is running:
```bash theme={null}
docker compose ps
```
2. Verify the assets volume is correctly mounted:
```bash theme={null}
docker compose exec homer ls -la /www/assets
```
3. Check for errors in the logs:
```bash theme={null}
docker compose logs
```
### Configuration Issues
If the dashboard does not reflect your configuration changes:
1. Verify the syntax of your `config.yml`:
```bash theme={null}
cd /opt/apps/homer/assets
yamllint config.yml
```
2. Restart the container to reload the configuration:
```bash theme={null}
docker compose restart
```
3. Check file permissions:
```bash theme={null}
chmod -R 755 /opt/apps/homer/assets
```
## Advanced Customization
### Adding Message of the Day
You can add a message of the day to your dashboard:
```yaml theme={null}
message:
style: 'is-warning' # Options: is-info, is-success, is-warning, is-danger
title: 'System Maintenance'
content: 'Scheduled maintenance on Friday from 2-4 PM MST.'
```
### Grouping Services
You can organize your services into groups:
```yaml theme={null}
services:
- name: 'Infrastructure'
icon: 'fas fa-server'
items:
# Infrastructure services...
- name: 'Marketing'
icon: 'fas fa-bullhorn'
items:
# Marketing services...
- name: 'Development'
icon: 'fas fa-code'
items:
# Development services...
```
### Custom CSS
You can add custom CSS by creating a `custom.css` file:
```bash theme={null}
nano /opt/apps/homer/assets/custom.css
```
Then reference it in your `config.yml`:
```yaml theme={null}
stylesheet: 'assets/custom.css'
```
## Additional Resources
* [Official Homer Documentation](https://github.com/bastienwirtz/homer)
* [Homer Demo Page](https://homer-demo.netlify.app/)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
## Integration Examples
### Adding Mondo Services
Here's an example of how to add all Mondo services to your Homer dashboard:
```yaml theme={null}
services:
- name: 'Infrastructure'
icon: 'fas fa-server'
items:
- name: 'Traefik'
url: 'https://traefik.trymondo.com'
- name: 'Portainer'
url: 'https://portainer.trymondo.com'
- name: 'Backrest'
url: 'https://backrest.trymondo.com'
- name: 'Marketing Tools'
icon: 'fas fa-bullhorn'
items:
- name: 'Mautic'
url: 'https://outreach.trymondo.com'
- name: 'N8N'
url: 'https://automations.trymondo.com'
- name: 'EspoCRM'
url: 'https://crm.trymondo.com'
- name: 'Development'
icon: 'fas fa-code'
items:
- name: 'Gitea'
url: 'https://git.trymondo.com'
- name: 'Woodpecker CI'
url: 'https://ci.trymondo.com'
- name: 'Collaboration'
icon: 'fas fa-users'
items:
- name: 'Outline Wiki'
url: 'https://wiki.trymondo.com'
- name: 'Cal.com'
url: 'https://cal.trymondo.com'
- name: 'FilePizza'
url: 'https://pizza.trymondo.com'
```
# null
Source: https://docs.trymondo.com/mops/apps/mautic
## Overview
Mautic is an open-source marketing automation platform deployed as part of the Mondo Open Platform Service (MOPS). This documentation covers the deployment, configuration, and management of Mautic using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| ---------- | -------------------------------------------------------------- |
| URL | [https://outreach.trymondo.com](https://outreach.trymondo.com) |
| Image | mautic/mautic:5.2.4-apache |
| Containers | mautic\_web, mautic\_cron, mautic\_worker, mautic\_db |
| Database | MySQL 8.0 |
| Networks | traefik-net, mautic-net |
## Architecture
Mautic is deployed as a multi-container application with the following components:
```
┌─────────────┐
│ Traefik │
└──────┬──────┘
│ HTTPS
▼
┌─────────────┐ ┌──────────────┐
│ Mautic Cron │◄────▶│ Mautic Web │
└─────────────┘ └──────┬───────┘
▲ │
│ ▼
│ ┌──────────────┐
└─────────────┤ MySQL DB │
└──────────────┘
▲
┌─────────────┐ │
│Mautic Worker│◄────────────┘
└─────────────┘
```
* **Mautic Web**: Main application container serving the UI and API
* **Mautic Cron**: Runs scheduled tasks for email campaigns, etc.
* **Mautic Worker**: Processes queue jobs like email sending
* **MySQL Database**: Stores all Mautic data
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External networks: `traefik-net` and `mautic-net`
* DNS configured for `outreach.trymondo.com`
## Deployment Configuration
### Directory Structure
```
/opt/apps/mautic/
├── docker-compose.yml # Main configuration file
├── docker-compose.override.yml # Resource limits
├── .mautic.env # Mautic configuration
├── .env # Database credentials
├── mautic/
│ ├── config/ # Configuration files
│ ├── logs/ # Log files
│ └── media/ # Uploads
└── cron/ # Cron job configuration
```
### Environment Variables
Create a `.env` file with the following variables:
```
MYSQL_ROOT_PASSWORD=secure_root_password
MYSQL_DATABASE=mautic
MYSQL_USER=mautic_user
MYSQL_PASSWORD=secure_user_password
MAUTIC_PORT=8001
DOCKER_MAUTIC_LOAD_TEST_DATA=false
DOCKER_MAUTIC_RUN_MIGRATIONS=true
```
Create a `.mautic.env` file with additional Mautic-specific configurations (not shown in the provided files).
### Docker Compose Configuration
```yaml theme={null}
x-mautic-volumes: &mautic-volumes
- ./mautic/config:/var/www/html/config:z
- ./mautic/logs:/var/www/html/var/logs:z
- ./mautic/media/files:/var/www/html/docroot/media/files:z
- ./mautic/media/images:/var/www/html/docroot/media/images:z
- ./cron:/opt/mautic/cron:z
- mautic-docroot:/var/www/html/docroot:z
services:
db:
image: mysql:8.0
container_name: mautic_db
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- mysql-data:/var/lib/mysql
healthcheck:
test: mysqladmin --user=$$MYSQL_USER --password=$$MYSQL_PASSWORD ping
start_period: 5s
interval: 5s
timeout: 5s
retries: 10
networks:
- mautic-net
restart: unless-stopped
mautic_web:
image: mautic/mautic:5.2.4-apache
links:
- db:mysql
ports:
- ${MAUTIC_PORT:-8001}:80
volumes: *mautic-volumes
container_name: mautic_web
environment:
- DOCKER_MAUTIC_LOAD_TEST_DATA=${DOCKER_MAUTIC_LOAD_TEST_DATA}
- DOCKER_MAUTIC_RUN_MIGRATIONS=${DOCKER_MAUTIC_RUN_MIGRATIONS}
env_file:
- .mautic.env
healthcheck:
test: curl http://localhost
start_period: 5s
interval: 5s
timeout: 5s
retries: 100
depends_on:
db:
condition: service_healthy
networks:
- traefik-net
- mautic-net
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.mautic.rule=Host(`outreach.trymondo.com`)'
- 'traefik.http.routers.mautic.entrypoints=websecure'
- 'traefik.http.routers.mautic.tls=true'
- 'traefik.http.routers.mautic.tls.certresolver=production'
- 'traefik.http.services.mautic.loadbalancer.server.scheme=http'
- 'traefik.http.services.mautic.loadbalancer.server.port=80'
- 'traefik.http.routers.mautic.middlewares=cors@file,secureHeaders@file'
restart: unless-stopped
mautic_cron:
image: mautic/mautic:5.2.4-apache
links:
- db:mysql
volumes: *mautic-volumes
container_name: mautic_cron
environment:
- DOCKER_MAUTIC_ROLE=mautic_cron
env_file:
- .mautic.env
depends_on:
mautic_web:
condition: service_healthy
networks:
- mautic-net
restart: unless-stopped
mautic_worker:
image: mautic/mautic:5.2.4-apache
links:
- db:mysql
volumes: *mautic-volumes
container_name: mautic_worker
environment:
- DOCKER_MAUTIC_ROLE=mautic_worker
env_file:
- .mautic.env
depends_on:
mautic_web:
condition: service_healthy
networks:
- mautic-net
restart: unless-stopped
volumes:
mysql-data:
mautic-docroot:
networks:
traefik-net:
external: true
mautic-net:
external: true
```
### Resource Limits (Optional)
For improved stability, add resource constraints using a `docker-compose.override.yml` file:
```yaml theme={null}
services:
db:
deploy:
resources:
limits:
memory: 512M
cpus: '0.2'
mautic_web:
deploy:
resources:
limits:
memory: 384M
cpus: '0.5'
mautic_cron:
deploy:
resources:
limits:
memory: 320M
cpus: '0.2'
mautic_worker:
deploy:
resources:
limits:
memory: 512M
cpus: '0.3'
```
## Network Configuration
Before deployment, ensure the required networks exist:
```bash theme={null}
# Create external networks if they don't exist
docker network create mautic-net
docker network create traefik-net
```
## Deployment Instructions
1. Create the deployment directory structure:
```bash theme={null}
mkdir -p /opt/apps/mautic/{mautic/{config,logs,media/{files,images}},cron}
```
2. Create the configuration files:
```bash theme={null}
touch /opt/apps/mautic/.env
touch /opt/apps/mautic/.mautic.env
nano /opt/apps/mautic/docker-compose.yml
nano /opt/apps/mautic/docker-compose.override.yml
```
3. Add appropriate content to the `.env` and `.mautic.env` files
4. Deploy the service:
```bash theme={null}
cd /opt/apps/mautic
docker compose up -d
```
5. Verify the services are running:
```bash theme={null}
docker compose ps
```
## Traefik Integration
Mautic is configured with the following Traefik settings:
* **Host Rule**: `outreach.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 80
* **Middlewares**: CORS and secure headers
## Webflow Integration
Mautic can be integrated with Webflow forms using JavaScript tracking. Add the following code to your Webflow site:
```javascript theme={null}
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('leadForm');
const emailField = document.getElementById('Email-7');
const firstNameField = document.getElementById('First-Name');
const lastNameField = document.getElementById('Last-Name');
form.addEventListener('submit', function (event) {
const email = emailField.value;
const firstName = firstNameField.value;
const lastName = lastNameField.value;
// Identify contact in Mautic
mt('send', 'pageview', {
email: email,
firstname: firstName,
lastname: lastName,
});
// Let the form submit normally
setTimeout(function () {
form.submit();
}, 300); // short delay to ensure tracking call completes
});
});
```
## Maintenance
### Backup Strategy
Back up Mautic regularly:
```bash theme={null}
# Stop the services
docker compose stop
# Backup the database
docker compose exec db mysqldump -u root -p${MYSQL_ROOT_PASSWORD} ${MYSQL_DATABASE} > mautic_backup_$(date +%Y%m%d).sql
# Backup volumes
tar -czf mautic_data_backup_$(date +%Y%m%d).tar.gz -C /opt/apps/mautic mautic
# Restart the services
docker compose start
```
### Updates
To update Mautic:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
cd /opt/apps/mautic
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
Always back up your data before updating Mautic to a new version.
## Troubleshooting
### Database Connection Issues
If Mautic can't connect to the database:
1. Verify MySQL container is running:
```bash theme={null}
docker compose ps db
```
2. Check database logs:
```bash theme={null}
docker compose logs db
```
3. Verify credentials in `.env` file match what Mautic is using
### Email Configuration Problems
If emails are not being sent:
1. Check worker logs:
```bash theme={null}
docker compose logs mautic_worker
```
2. Verify SMTP settings in Mautic's configuration
3. Ensure the worker container has proper network access to the SMTP server
### Web Interface Not Accessible
If you can't access the Mautic interface:
1. Check container health:
```bash theme={null}
docker compose ps
```
2. Verify Traefik routing:
```bash theme={null}
docker compose logs mautic_web | grep -i "traefik"
```
3. Check for any error logs:
```bash theme={null}
docker compose logs mautic_web
```
## Performance Optimization
For improved performance:
1. **Increase Memory Limits**: Adjust values in `docker-compose.override.yml` if needed
2. **Database Tuning**: Consider adding MySQL configuration for better performance
3. **Caching**: Enable Redis if needed for larger installations
## Additional Resources
* [Official Mautic Documentation](https://docs.mautic.org/)
* [Mautic Docker Image Documentation](https://github.com/mautic/docker-mautic)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
* [MySQL Documentation](https://dev.mysql.com/doc/)
## Integration Examples
### Mautic Forms
Example of embedding a Mautic form on a website:
```html theme={null}
```
# null
Source: https://docs.trymondo.com/mops/apps/n8n
## Overview
n8n is a powerful workflow automation platform that allows you to connect various services and applications to create automated workflows. This document covers the deployment and configuration of n8n using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| ------------ | -------------------------------------------------------------------- |
| URL | [https://automations.trymondo.com](https://automations.trymondo.com) |
| Image | n8nio/n8n:1.88.0 |
| Container | n8n |
| Database | PostgreSQL 17.4 |
| Networks | traefik-net, n8n-net |
| Data Storage | ./data directory |
## Architecture
n8n is deployed as a multi-container application with the following components:
```
┌─────────────┐
│ Traefik │
└──────┬──────┘
│ HTTPS
▼
┌──────────────┐
│ n8n │
└──────┬───────┘
│
▼
┌──────────────┐
│ PostgreSQL │
└──────────────┘
```
* **n8n**: Main application container serving the workflow editor and execution engine
* **PostgreSQL**: Database for storing workflows, credentials, and execution data
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External networks: `traefik-net` and `n8n-net`
* DNS configured for `automations.trymondo.com`
* SMTP credentials for email notifications
## Deployment Configuration
### Environment Variables
Create a `.env` file with the following variables:
```
# n8n Host Configuration
N8N_HOST=automations.trymondo.com
# Database Configuration
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8n_user
DB_POSTGRESDB_PASSWORD=secure_password_here
# SMTP Configuration
N8N_SMTP_USER=your_smtp_username
N8N_SMTP_PASS=your_smtp_password
# Security Configuration
N8N_BASIC_AUTH_USER=admin_username
N8N_BASIC_AUTH_PASSWORD=secure_admin_password
N8N_ENCRYPTION_KEY=random_32_character_string
```
Generate a secure, random string for N8N\_ENCRYPTION\_KEY. This is used to
encrypt credentials and sensitive data.
You can generate a secure random string with: `bash openssl rand -hex 16 `
### Docker Compose File
```yaml theme={null}
services:
n8n:
image: n8nio/n8n:1.88.0
container_name: n8n
restart: unless-stopped
environment:
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=http
- N8N_EDITOR_BASE_URL=https://${N8N_HOST}
- WEBHOOK_URL=https://${N8N_HOST}
- N8N_PATH=/
- N8N_LISTEN_ADDRESS=0.0.0.0
- N8N_PERSONALIZATION_ENABLED=true
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=db
- DB_POSTGRESDB_DATABASE=${DB_POSTGRESDB_DATABASE}
- DB_POSTGRESDB_USER=${DB_POSTGRESDB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_POSTGRESDB_PASSWORD}
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_SCHEMA=public
- DB_POSTGRESDB_SSL_ENABLED=false
- N8N_EMAIL_MODE=smtp
- N8N_SMTP_HOST=smtp.mailersend.net
- N8N_SMTP_PORT=587
- N8N_SMTP_USER=${N8N_SMTP_USER}
- N8N_SMTP_PASS=${N8N_SMTP_PASS}
- N8N_SMTP_SENDER=info@trymondo.com
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
- N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_TRUST_PROXY=true
- N8N_USE_X_FORWARDED_HOST=true
- N8N_RUNNERS_ENABLED=true
- EXECUTIONS_MODE=regular
- EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
- EXECUTIONS_DATA_SAVE_ON_ERROR=all
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=336
- N8N_LOG_LEVEL=info
- N8N_LOG_OUTPUT=console
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- NODE_ENV=production
- TZ=America/Denver
volumes:
- ./data:/home/node/.n8n
depends_on:
- db
networks:
- traefik-net
- n8n-net
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.n8n.rule=Host(`automations.trymondo.com`)'
- 'traefik.http.routers.n8n.entrypoints=websecure'
- 'traefik.http.routers.n8n.tls.certresolver=production'
- 'traefik.http.services.n8n.loadbalancer.server.port=5678'
- 'traefik.http.services.n8n.loadbalancer.server.scheme=http'
- 'traefik.http.routers.traefik.middlewares=rateLimit@file,secureHeaders@file'
- 'traefik.docker.network=traefik-net'
db:
image: postgres:17.4
container_name: n8n-db
restart: unless-stopped
environment:
- POSTGRES_DB=${DB_POSTGRESDB_DATABASE}
- POSTGRES_USER=${DB_POSTGRESDB_USER}
- POSTGRES_PASSWORD=${DB_POSTGRESDB_PASSWORD}
volumes:
- ./db:/var/lib/postgresql/data
networks:
- n8n-net
networks:
traefik-net:
external: true
n8n-net:
external: true
```
## Network Configuration
Before deployment, ensure the required networks exist:
```bash theme={null}
# Create external networks if they don't exist
docker network create n8n-net
docker network create traefik-net
```
## Deployment Instructions
1. Create the deployment directory structure:
```bash theme={null}
mkdir -p /opt/apps/n8n/{data,db}
```
2. Create the configuration files:
```bash theme={null}
nano /opt/apps/n8n/.env
nano /opt/apps/n8n/docker-compose.yml
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/n8n
docker compose up -d
```
4. Verify the services are running:
```bash theme={null}
docker compose ps
```
5. Access n8n at `https://automations.trymondo.com` and log in with the credentials specified in the `.env` file.
## Traefik Integration
n8n is configured with the following Traefik settings:
* **Host Rule**: `automations.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 5678
* **Middlewares**: Rate limiting and secure headers
## Configuration Highlights
### Security Configuration
n8n is configured with several security features:
* **Basic Authentication**: Requires username/password to access the UI
* **Encryption Key**: All sensitive data is encrypted at rest
* **HTTPS**: All traffic is encrypted via Traefik
* **Rate Limiting**: Prevents brute force attacks
### Workflow Execution Settings
The n8n instance is configured with the following execution settings:
* **Regular Execution Mode**: Workflows run in the main process
* **Data Retention**: Error execution data is saved, successful executions are not
* **Data Pruning**: Old execution data is automatically removed after 336 hours (14 days)
* **Runners Enabled**: Allows distributed workflow execution
### Email Notifications
Email is configured using SMTP with the following settings:
* **SMTP Host**: smtp.mailersend.net
* **SMTP Port**: 587
* **Sender**: [info@trymondo.com](mailto:info@trymondo.com)
## Maintenance
### Backup Strategy
Back up n8n regularly using the following commands:
```bash theme={null}
# Stop the services
cd /opt/apps/n8n
docker compose stop
# Backup the database
docker compose exec db pg_dump -U ${DB_POSTGRESDB_USER} ${DB_POSTGRESDB_DATABASE} > n8n_backup_$(date +%Y%m%d).sql
# Backup n8n data
tar -czf n8n_data_backup_$(date +%Y%m%d).tar.gz -C /opt/apps/n8n data
# Restart the services
docker compose start
```
### Updates
To update n8n:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
cd /opt/apps/n8n
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
Always back up your data before updating n8n to a new version.
## Troubleshooting
### Database Connection Issues
If n8n can't connect to the database:
1. Verify PostgreSQL container is running:
```bash theme={null}
docker compose ps db
```
2. Check database logs:
```bash theme={null}
docker compose logs db
```
3. Verify credentials in `.env` file match what n8n is using
### Webhook Issues
If webhooks are not working correctly:
1. Verify the webhook URL configuration:
```bash theme={null}
docker compose exec n8n node -e "console.log(process.env.WEBHOOK_URL)"
```
2. Check that the URL is accessible from the internet
3. Verify Traefik is properly routing requests
### Authentication Problems
If you're having trouble logging in:
1. Check the basic auth settings:
```bash theme={null}
docker compose exec n8n node -e "console.log(process.env.N8N_BASIC_AUTH_ACTIVE)"
```
2. Reset the admin password by updating the `.env` file and restarting the container
## Example Workflows
### Webflow Form to Mautic Integration
This workflow captures form submissions from Webflow and adds contacts to Mautic:
1. Create a webhook node as the trigger
2. Copy the webhook URL to your Webflow form's action URL
3. Add a Mautic node to create/update contacts
4. Configure the mapping between Webflow form fields and Mautic contact fields
### Daily Database Backup Notification
This workflow creates and notifies about database backups:
1. Set up a Cron node to trigger daily at a specific time
2. Add an Execute Command node to run pg\_dump
3. Add a Send Email node to notify about successful backups
4. Add error handling to notify about failures
## Security Considerations
* **Credential Storage**: All API credentials are encrypted using the N8N\_ENCRYPTION\_KEY
* **Basic Authentication**: The UI is protected with username/password
* **HTTPS**: All traffic is encrypted via Traefik
* **Database Security**: The PostgreSQL database is not exposed outside the Docker network
* **Execution Data**: Only error execution data is saved to reduce sensitive data exposure
## Additional Resources
* [Official n8n Documentation](https://docs.n8n.io/)
* [n8n Docker Image Documentation](https://github.com/n8n-io/n8n/blob/master/docker/images/n8n/README.md)
* [n8n Community Forums](https://community.n8n.io/)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
## Integration with Other Mondo Services
n8n can be integrated with other Mondo services:
* **Mautic**: Use the Mautic nodes to manage contacts and campaigns
* **EspoCRM**: Use HTTP Request nodes or custom nodes to interact with the CRM API
* **Gitea**: Use Webhook triggers for repository events
* **Traefik**: Ensure proper routing and HTTPS termination
# null
Source: https://docs.trymondo.com/mops/apps/outline
## Overview
Outline is a modern team knowledge base and wiki platform deployed as part of the Mondo Open Platform Service (MOPS). This document covers the deployment and configuration of Outline using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| --------- | ------------------------------------------------------ |
| URL | [https://wiki.trymondo.com](https://wiki.trymondo.com) |
| Image | outlinewiki/outline:0.82.0 |
| Database | PostgreSQL 17.4 |
| Cache | Redis 7.4.2 |
| Networks | traefik-net, outline-net |
## Architecture
Outline is deployed as a multi-container application with the following components:
```
┌─────────────┐
│ Traefik │
└──────┬──────┘
│ HTTPS
▼
┌─────────────┐ ┌──────────────┐
│ Redis │◄────▶│ Outline │
└─────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ PostgreSQL │
└──────────────┘
```
* **Outline**: Main application container serving the wiki interface and API
* **PostgreSQL**: Database for storing wiki content, users, and metadata
* **Redis**: In-memory cache for improved performance
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External networks: `traefik-net` and `outline-net`
* DNS configured for `wiki.trymondo.com`
* Auth0 or other compatible OIDC provider
* SMTP credentials for email notifications
## Deployment Configuration
### Environment Variables
Create a `.env` file with the following variables:
```
# Security
OUTLINE_SECRET_KEY=random_32_character_string
OUTLINE_UTILS_SECRET=another_random_32_character_string
# Authentication
OIDC_CLIENT_ID=your_oidc_client_id
OIDC_CLIENT_SECRET=your_oidc_client_secret
AUTH0_DOMAIN=your_auth0_domain
# Email
SMTP_HOST=smtp.mailersend.net
SMTP_USER=your_smtp_username
SMTP_PASS=your_smtp_password
SMTP_FROM_EMAIL=info@trymondo.com
```
Generate secure, random strings for OUTLINE\_SECRET\_KEY and
OUTLINE\_UTILS\_SECRET. These are used to encrypt sensitive data and sign
sessions.
You can generate secure random strings with: `bash openssl rand -hex 16 `
### Docker Compose File
````yaml theme={null}
openssl rand -hex 16
```
### Docker Compose File
```yaml
services:
outline:
image: outlinewiki/outline:0.82.0
container_name: outline
depends_on:
- postgres
- redis
environment:
- NODE_ENV=production
- URL=https://wiki.trymondo.com
- SECRET_KEY=${OUTLINE_SECRET_KEY}
- UTILS_SECRET=${OUTLINE_UTILS_SECRET}
- DATABASE_URL=postgres://outline:outline@postgres:5432/outline
- REDIS_URL=redis://redis:6379
- FILE_STORAGE=local
- FILE_STORAGE_LOCAL_ROOT_DIR=/opt/outline/storage
- FILE_STORAGE_UPLOAD_MAX_SIZE=26214400
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=587
- SMTP_USERNAME=${SMTP_USER}
- SMTP_PASSWORD=${SMTP_PASS}
- SMTP_FROM_EMAIL=${SMTP_FROM_EMAIL}
- PGSSLMODE=disable
- DATABASE_CONNECTION_POOL_MIN=2
- DATABASE_CONNECTION_POOL_MAX=10
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
- OIDC_AUTH_URI=https://${AUTH0_DOMAIN}/authorize
- OIDC_TOKEN_URI=https://${AUTH0_DOMAIN}/oauth/token
- OIDC_USERINFO_URI=https://${AUTH0_DOMAIN}/userinfo
- OIDC_DISPLAY_NAME=Auth0
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.outline.rule=Host(`wiki.trymondo.com`)'
- 'traefik.http.routers.outline.entrypoints=websecure'
- 'traefik.http.routers.outline.tls=true'
- 'traefik.http.routers.outline.tls.certresolver=production'
- 'traefik.http.services.outline.loadbalancer.server.port=3000'
- 'traefik.http.routers.outline.middlewares=secureHeaders@file'
networks:
- traefik-net
- outline-net
restart: unless-stopped
user: '1001:1001'
volumes:
- ./data/uploads:/opt/outline/storage/uploads
- ./data/logs:/opt/outline/logs
postgres:
image: postgres:17.4
container_name: outline_postgres
restart: unless-stopped
environment:
- POSTGRES_USER=outline
- POSTGRES_PASSWORD=outline
- POSTGRES_DB=outline
volumes:
- ./data/db:/var/lib/postgresql/data
networks:
- outline-net
redis:
image: redis:7.4.2
container_name: outline_redis
restart: unless-stopped
networks:
- outline-net
networks:
traefik-net:
external: true
outline-net:
````
## Network Configuration
Before deployment, ensure the required networks exist:
```bash theme={null}
# Create external networks if they don't exist
docker network create outline-net
docker network create traefik-net
```
## Deployment Instructions
1. Create the deployment directory structure:
```bash theme={null}
mkdir -p /opt/apps/outline/data/{uploads,logs,db}
```
2. Create the configuration files:
```bash theme={null}
nano /opt/apps/outline/.env
nano /opt/apps/outline/docker-compose.yml
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/outline
docker compose up -d
```
4. Verify the services are running:
```bash theme={null}
docker compose ps
```
5. Access Outline at `https://wiki.trymondo.com` and sign in using your Auth0 credentials.
## Auth0 Configuration
Before deploying Outline, you need to configure Auth0:
1. Create a new application in Auth0
2. Set the application type to "Regular Web Application"
3. Configure the following URLs:
* Allowed Callback URLs: `https://wiki.trymondo.com/auth/oidc.callback`
* Allowed Logout URLs: `https://wiki.trymondo.com`
4. Note the Client ID and Client Secret for the `.env` file
## Traefik Integration
Outline is configured with the following Traefik settings:
* **Host Rule**: `wiki.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 3000
* **Middleware**: secureHeaders for enhanced security
## Configuration Highlights
### File Storage
Outline is configured to use local file storage with the following settings:
* **Storage Directory**: `/opt/outline/storage`
* **Maximum Upload Size**: 25MB (26,214,400 bytes)
* **Storage Path**: Mounted to `./data/uploads` on the host
### Database Connection Pool
PostgreSQL connection pooling is configured for optimal performance:
* **Minimum Connections**: 2
* **Maximum Connections**: 10
## Maintenance
### Backup Strategy
Back up Outline regularly using the following steps:
```bash theme={null}
# Stop the containers
cd /opt/apps/outline
docker compose stop
# Backup the database
docker compose exec postgres pg_dump -U outline -d outline > outline_backup_$(date +%Y%m%d).sql
# Backup uploaded files
tar -czf outline_uploads_$(date +%Y%m%d).tar.gz -C /opt/apps/outline/data uploads
# Restart the containers
docker compose start
```
!!! note
Consider scheduling regular backups using cron and storing them offsite.
### Updates
To update Outline:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
cd /opt/apps/outline
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
Always back up your data before updating Outline to a new version.
## Troubleshooting
### Auth0 Connection Issues
If you can't sign in with Auth0:
1. Verify Auth0 configuration:
* Check the callback URL in Auth0
* Verify Client ID and Secret in `.env`
2. Check Outline logs for auth errors:
```bash theme={null}
docker compose logs outline | grep -i "auth"
```
### Database Connection Problems
If Outline can't connect to the database:
1. Verify PostgreSQL container is running:
```bash theme={null}
docker compose ps postgres
```
2. Check database logs:
```bash theme={null}
docker compose logs postgres
```
3. Test database connection:
```bash theme={null}
docker compose exec postgres psql -U outline -c "SELECT 1;"
```
### File Upload Issues
If file uploads aren't working:
1. Check permissions on the upload directory:
```bash theme={null}
ls -la /opt/apps/outline/data/uploads
```
2. Verify the user ID matches what's in the `docker-compose.yml` file:
```bash theme={null}
id -u outline
```
3. Check for storage-related errors in logs:
```bash theme={null}
docker compose logs outline | grep -i "storage"
```
## User Management
### Adding Users
Outline uses Auth0 for authentication, so users are managed through Auth0:
1. Users must be able to sign in through Auth0
2. On first login, users will be created in Outline
3. Admin users can promote others to admin through the Outline UI
### Setting Up Teams
To organize users into teams:
1. Sign in as an admin
2. Go to Settings > Teams
3. Create new teams and invite members by email
## Document Structure
Outline uses a hierarchical document structure:
* **Collections**: Top-level containers for related documents
* **Documents**: Individual wiki pages within collections
* **Sections**: Hierarchical organization within documents
## Integration Examples
### Slack Integration
To integrate Outline with Slack:
1. Go to Settings > Integrations
2. Click on Slack and follow the configuration steps
3. Users will be able to share and search Outline documents directly from Slack
### API Usage
Outline provides a REST API for integration with other systems:
1. Generate an API token in Settings > API Tokens
2. Use the token to authenticate API requests:
```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_TOKEN" https://wiki.trymondo.com/api/documents
```
## Additional Resources
* [Official Outline Documentation](https://docs.getoutline.com/)
* [Outline GitHub Repository](https://github.com/outline/outline)
* [Auth0 Documentation](https://auth0.com/docs/)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
## Best Practices
* Enable regular backups of database and uploads
* Monitor disk space usage on the uploads directory
* Update Outline regularly for security patches
* Use document templates for consistent content
* Organize collections by team or project area
# Changelog
Source: https://docs.trymondo.com/mops/changelog
This project is still in heavy development, but we will post updates here.
### March 2024
This is the initial update. MOPS is live in alpha stage at dash.trymondo.com
# null
Source: https://docs.trymondo.com/mops/devops/diun
## Overview
Diun (Docker Image Update Notifier) is a service that automatically monitors Docker container images and sends notifications when updates are detected. This document covers the deployment and configuration of Diun using Docker Compose.
## Service Details
| Component | Value |
| -------------------- | -------------------------- |
| Image | crazymax/diun:4.29.0 |
| Container Name | diun |
| Volume | diun-data |
| Watch Schedule | Every hour (0 \* \* \* \*) |
| Notification Channel | Discord |
| Time Zone | America/Denver |
## Architecture
Diun operates as a standalone container with the following connections:
```
┌─────────────┐
│ Discord │
└─────────────┘
▲
│ Notifications
│
┌─────────────┐ ┌─────────────┐
│ Diun │───▶│Docker Socket│
└─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│Persistent DB│
└─────────────┘
```
* **Docker Socket**: Diun monitors running containers via the Docker socket
* **Persistent Data**: State is maintained across restarts using a Docker volume
* **Notifications**: Updates are sent to Discord via webhooks
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Discord server with webhook permissions (for notifications)
* Running containers with the `diun.enable=true` label
## Environment Variables
Create a `.env` file with the following variable:
```
DIUN_DISCORD_WEBHOOK=https://discord.com/api/webhooks/your-webhook-url
```
Never commit the `.env` file to version control. Store your webhook URL
securely in a password manager.
## Deployment Configuration
### Docker Compose File
```yaml theme={null}
services:
diun:
image: crazymax/diun:4.29.0
container_name: diun
command: serve
volumes:
- 'diun-data:/data'
- '/var/run/docker.sock:/var/run/docker.sock'
environment:
- 'TZ=America/Denver'
- 'LOG_LEVEL=info'
- 'LOG_JSON=false'
- 'DIUN_WATCH_WORKERS=20'
- 'DIUN_WATCH_SCHEDULE=0 * * * *'
- 'DIUN_WATCH_JITTER=30s'
- 'DIUN_PROVIDERS_DOCKER=true'
- 'DIUN_NOTIF_DISCORD_WEBHOOKURL=${DIUN_DISCORD_WEBHOOK}'
- 'DIUN_NOTIF_DISCORD_MENTIONS=@here'
restart: always
volumes:
diun-data:
```
## Deployment Instructions
1. Create the deployment directory:
```bash theme={null}
mkdir -p /opt/apps/diun
```
2. Create the `docker-compose.yml` and `.env` files:
```bash theme={null}
nano /opt/apps/diun/docker-compose.yml
nano /opt/apps/diun/.env
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/diun
docker compose up -d
```
4. Verify the service is running:
```bash theme={null}
docker compose ps
docker compose logs
```
## Configuration Highlights
### Watch Settings
Diun is configured with the following watch parameters:
* **Schedule**: Every hour (`0 * * * *` cron expression)
* **Workers**: 20 concurrent image checks
* **Jitter**: 30-second random delay to avoid API rate limits
### Notification Setup
Notifications are configured to:
* Send to Discord via webhook
* Mention `@here` for visibility
* Include detailed image update information
## Enabling Monitoring for Containers
To monitor a container for updates, add the following label to its configuration:
```yaml theme={null}
labels:
- 'diun.enable=true'
```
### Advanced Container Monitoring
You can add additional labels to customize monitoring:
```yaml theme={null}
labels:
- 'diun.enable=true' # Enable monitoring
- 'diun.watch_repo=true' # Watch all tags of this image
- 'diun.max_tags=5' # Limit number of tags to watch
- 'diun.include_tags=^1\\..*,^2\\..*$' # Only include specific tag patterns
- 'diun.exclude_tags=.*-alpha.*' # Exclude specific tag patterns
```
## Example: Monitoring Multiple Services
Here's an example of enabling Diun monitoring for several containers:
```yaml theme={null}
# Gitea configuration
services:
server:
image: gitea/gitea:1.23.7-rootless
labels:
- 'diun.enable=true'
db:
image: postgres:17.4
labels:
- 'diun.enable=true'
```
## Maintenance
### Backup Strategy
Back up Diun's data regularly:
```bash theme={null}
# Option 1: Use Restic/Backrest for the volume
# Include /var/lib/docker/volumes/diun_diun-data in your backup paths
# Option 2: Manual backup
docker compose stop
tar -czf diun-backup-$(date +%Y%m%d).tar.gz -C /var/lib/docker/volumes/diun_diun-data .
docker compose start
```
### Updates
To update Diun:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
## Troubleshooting
### No Notifications
If you're not receiving notifications:
1. Verify Discord webhook URL is correct:
```bash theme={null}
docker compose logs diun | grep -i "discord"
```
2. Check if Diun is running on schedule:
```bash theme={null}
docker compose logs diun | grep -i "cron"
```
3. Test the webhook manually:
```bash theme={null}
curl -X POST -H "Content-Type: application/json" \
-d '{"content": "Testing webhook"}' \
$DIUN_DISCORD_WEBHOOK
```
### No Images Being Monitored
If no images are being monitored:
1. Verify Docker socket access:
```bash theme={null}
docker compose exec diun ls -la /var/run/docker.sock
```
2. Check container discovery logs:
```bash theme={null}
docker compose logs diun | grep -i "docker provider"
```
3. Ensure containers have the proper `diun.enable=true` label
## Image Update Triggers
Diun identifies image updates by:
1. **Tag Changes**: When an image with a specific tag is updated
2. **New Tags**: When configured to watch repositories for new tags
3. **Manifest Changes**: When the image digest changes, even if the tag remains the same
## Manual Update Check
To trigger an immediate update check:
```bash theme={null}
docker compose exec diun diun run
```
## Security Considerations
* **Docker Socket**: Diun has access to the Docker socket, granting it significant privileges
* **Discord Webhook**: Keep your webhook URL confidential to prevent unauthorized notifications
* **Image Policies**: Consider using `diun.include_tags` to only monitor production tags
## Additional Resources
* [Official Diun Documentation](https://crazymax.dev/diun/)
* [Diun GitHub Repository](https://github.com/crazy-max/diun)
* [Cron Expression Format](https://en.wikipedia.org/wiki/Cron#CRON_expression)
## Integration Examples
### Complete Stack Example
Add Diun labels to your existing infrastructure:
```yaml theme={null}
# Example Traefik integration
services:
traefik:
image: traefik:v3.3.5
labels:
- 'diun.enable=true'
- 'diun.include_tags=^v3\\..*$'
postgres:
image: postgres:17
labels:
- 'diun.enable=true'
- 'diun.watch_repo=false' # Only watch the specific tag
```
# null
Source: https://docs.trymondo.com/mops/devops/gitea
## Overview
Gitea is a lightweight, self-hosted Git service that provides repository management, issue tracking, and CI/CD integration through Woodpecker CI. This document covers the deployment and configuration of Gitea using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| ---------- | ---------------------------------------------------- |
| URL | [https://git.trymondo.com](https://git.trymondo.com) |
| Main Image | gitea/gitea:1.23.7-rootless |
| Database | PostgreSQL 17.4 |
| Containers | gitea, gitea-db |
| SSH Port | 2222 (via Traefik) |
| Networks | gitea-net, traefik-net |
| Time Zone | America/Denver |
## Architecture
The deployment consists of:
1. **Gitea Server**: The main application container running the Git service
2. **PostgreSQL Database**: Persistent storage for all Gitea data
3. **Traefik Integration**: Handles routing, SSL termination, and SSH proxying
```
┌─────────────┐
│ Traefik │
└─────────────┘
↑ ↑
HTTP/HTTPS ┌─┘ └─┐ SSH
│ │
┌──────────────┐ ┌─────────────┐
│ Gitea Server │◄───┤ Gitea SSH │
└──────────────┘ └─────────────┘
▲
│
┌──────────────┐
│ PostgreSQL │
└──────────────┘
```
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External networks: `gitea-net` and `traefik-net`
* SSH entrypoint configured in Traefik
* DNS configured for `git.trymondo.com`
## Deployment Configuration
### Environment Variables
Create a `.env` file with the following variables:
```
GITEA_DB_PASSWORD=secure_password_here
POSTGRES_PASSWORD=secure_password_here
```
Never commit the `.env` file to version control. Store passwords securely in a
password manager.
### Docker Compose File
```yaml theme={null}
services:
server:
image: gitea/gitea:1.23.7-rootless
container_name: gitea
restart: unless-stopped
volumes:
- gitea-data:/var/lib/gitea
- gitea-config:/etc/gitea
environment:
- TZ=America/Denver
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${GITEA_DB_PASSWORD}
depends_on:
- db
networks:
- gitea-net
- traefik-net
labels:
- traefik.enable=true
- traefik.http.routers.gitea.rule=Host(`git.trymondo.com`)
- traefik.http.routers.gitea.entrypoints=websecure
- traefik.http.routers.gitea.tls.certresolver=production
- traefik.http.services.gitea.loadbalancer.server.port=3000
- traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)
- traefik.tcp.routers.gitea-ssh.entrypoints=ssh
- traefik.tcp.routers.gitea-ssh.service=gitea-ssh
- traefik.tcp.services.gitea-ssh.loadbalancer.server.port=2222
- 'diun.enable=true'
db:
image: postgres:17.4
container_name: gitea-db
restart: unless-stopped
environment:
- TZ=America/Denver
- POSTGRES_DB=gitea
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- gitea-db-data:/var/lib/postgresql/data
networks:
- gitea-net
labels:
- 'diun.enable=true'
volumes:
gitea-data:
gitea-config:
gitea-db-data:
networks:
gitea-net:
external: true
traefik-net:
external: true
```
## Network Configuration
Before deployment, ensure the required networks exist:
```bash theme={null}
# Create external networks if they don't exist
docker network create gitea-net
docker network create traefik-net
```
## Deployment Instructions
1. Create the deployment directory:
```bash theme={null}
mkdir -p /opt/apps/gitea
```
2. Create the `docker-compose.yml` and `.env` files:
```bash theme={null}
nano /opt/apps/gitea/docker-compose.yml
nano /opt/apps/gitea/.env
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/gitea
docker compose up -d
```
4. Verify the service is running:
```bash theme={null}
docker compose ps
```
## Traefik Integration Details
### HTTP Routing
Gitea's web interface is available through HTTPS:
* **Host Rule**: `git.trymondo.com`
* **Entrypoint**: websecure (HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 3000
### SSH Routing
Git SSH operations are handled through Traefik's TCP router:
* **Rule**: HostSNI(`*`) - accepts all hostnames for SSH
* **Entrypoint**: ssh (TCP port typically 2222)
* **Service**: gitea-ssh
* **Backend Port**: 2222
Users will need to configure their Git client to use port 2222 for SSH
operations: `git clone ssh://git@git.trymondo.com:2222/username/repo.git`
## Initial Configuration
After deploying Gitea, complete the setup through the web interface:
1. Access `https://git.trymondo.com` in your browser
2. You'll be redirected to the installation page
3. Configure the following settings:
### Database Settings
* **Database Type**: PostgreSQL (pre-configured)
* **Host**: db:5432 (pre-configured)
* **Username**: gitea (pre-configured)
* **Password**: \[value from .env file] (pre-configured)
* **Database Name**: gitea (pre-configured)
### Application General Settings
* **Site Title**: GitMondo (recommended)
* **Repository Root Path**: /var/lib/gitea/repositories (default)
* **Git LFS Root Path**: /var/lib/gitea/lfs (default)
* **Run As Username**: git (default)
* **SSH Server Domain**: git.trymondo.com
* **SSH Server Port**: 2222
* **Gitea HTTP Listen Port**: 3000 (default)
* **Gitea Base URL**: [https://git.trymondo.com/](https://git.trymondo.com/)
* **Log Path**: /var/lib/gitea/log (default)
### Email Settings (Optional)
* **SMTP Host**: smtp.mailersend.net
* **SMTP Port**: 587
* **From Email**: [info@trymondo.com](mailto:info@trymondo.com)
* **SMTP Username**: \[your SMTP username]
* **SMTP Password**: \[your SMTP password]
### Administrator Account
* Create an initial administrator account with secure credentials
## Maintenance
### Backup Strategy
Back up Gitea regularly using the following steps:
1. Stop the Gitea container (keep the database running):
```bash theme={null}
docker compose stop server
```
2. Back up volumes:
```bash theme={null}
# Use Restic or another backup tool to back up these volumes:
# - gitea-data
# - gitea-config
# - gitea-db-data
```
3. Restart Gitea:
```bash theme={null}
docker compose start server
```
Consider using Backrest to automate regular backups of Gitea's volumes.
### Updates
To update Gitea:
1. Update the image tag in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs -f server
```
## Troubleshooting
### Database Connection Issues
If Gitea can't connect to the database:
1. Verify PostgreSQL container is running:
```bash theme={null}
docker compose ps db
```
2. Check database logs:
```bash theme={null}
docker compose logs db
```
3. Test database connection:
```bash theme={null}
docker compose exec db psql -U gitea -d gitea -c "SELECT 1;"
```
### SSH Connection Problems
If Git SSH operations fail:
1. Verify Traefik is properly routing SSH traffic:
```bash theme={null}
# Check if port 2222 is open
telnet git.trymondo.com 2222
```
2. Check Gitea's SSH settings:
```bash theme={null}
# View SSH configuration
docker compose exec server cat /etc/gitea/app.ini | grep SSH
```
3. Verify user's SSH configuration:
```bash theme={null}
# Example ~/.ssh/config entry for users
Host git.trymondo.com
Port 2222
User git
```
## Monitoring
Gitea and its database have Diun labels for container update monitoring:
```yaml theme={null}
labels:
- 'diun.enable=true'
```
## Additional Resources
* [Official Gitea Documentation](https://docs.gitea.com/)
* [Gitea Container Documentation](https://docs.gitea.com/installation/install-with-docker)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
* [Traefik TCP Routing Documentation](https://doc.traefik.io/traefik/routing/services/#configuring-tcp-services)
## Integration with CI/CD
For CI/CD integration with Woodpecker CI, see the DevOps Stack documentation.
# null
Source: https://docs.trymondo.com/mops/devops/woodpecker
## Overview
Woodpecker CI is a lightweight, cloud-native continuous integration and deployment system built on Docker. This document covers the deployment and configuration of Woodpecker CI using Docker Compose with Traefik as a reverse proxy.
## Service Details
| Component | Value |
| -------------- | -------------------------------------------------- |
| URL | [https://ci.trymondo.com](https://ci.trymondo.com) |
| Server Image | woodpeckerci/woodpecker-server:v3.5.2 |
| Agent Image | woodpeckerci/woodpecker-agent:v3.5.2 |
| Database | PostgreSQL 17 |
| Services | woodpecker-server, woodpecker-agent, woodpecker-db |
| Networks | woodpecker-net, traefik-net |
| Authentication | GitHub OAuth |
## Architecture
The deployment consists of three main components:
1. **Woodpecker Server**: The core service that manages the UI, API, and orchestrates CI jobs
2. **Woodpecker Agent**: Executes CI jobs in containers
3. **PostgreSQL Database**: Stores all Woodpecker CI data
```
┌─────────────┐
│ Traefik │
└─────────────┘
↑
│ HTTP/HTTPS
↓
┌─────────────────────┐
│ Woodpecker Server │
└─────────────────────┘
↑ ↑
gRPC (9000) │ │ Database
↓ ↓
┌───────────────┐ ┌────────────┐
│ Woodpecker │ │ PostgreSQL │
│ Agent │ │ │
└───────────────┘ └────────────┘
↑
│
┌──────────────┐
│ Docker API │
└──────────────┘
```
## Prerequisites
* Docker Engine (24.0+)
* Docker Compose v2
* Traefik reverse proxy configured and running
* External networks: `woodpecker-net` and `traefik-net`
* GitHub OAuth application
* DNS configured for `ci.trymondo.com`
## Configuration Preparation
### GitHub OAuth Setup
1. Create a GitHub OAuth application at [https://github.com/settings/applications/new](https://github.com/settings/applications/new)
2. Set the callback URL to `https://ci.trymondo.com/login`
3. Note the Client ID and Client Secret for your `.env` file
### Environment Variables
Create a `.env` file with the following variables:
```env theme={null}
# Woodpecker Configuration
WOODPECKER_HOST=https://ci.trymondo.com
WOODPECKER_OPEN=true
WOODPECKER_GITHUB_CLIENT=your_github_client_id
WOODPECKER_GITHUB_SECRET=your_github_client_secret
WOODPECKER_AGENT_SECRET=generate_a_secure_random_string
WOODPECKER_ADMIN=github_username
# Database Configuration
POSTGRES_PASSWORD=secure_postgres_password
```
Generate a secure, random string for WOODPECKER\_AGENT\_SECRET. This is used to authenticate agents with the server.
You can generate a secure random string with:
```bash theme={null}
openssl rand -hex 32
```
## Deployment Configuration
### Docker Compose File
```yaml theme={null}
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:v3.5.2
container_name: woodpecker-server
restart: unless-stopped
expose:
- '8000'
- '9000'
volumes:
- woodpecker-server-data:/var/lib/woodpecker
environment:
- WOODPECKER_OPEN=${WOODPECKER_OPEN:-true}
- WOODPECKER_HOST=${WOODPECKER_HOST?Variable WOODPECKER_HOST is not set}
- WOODPECKER_GITHUB=true
- WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT?Variable WOODPECKER_GITHUB_CLIENT is not set}
- WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET?Variable WOODPECKER_GITHUB_SECRET is not set}
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET?Variable WOODPECKER_AGENT_SECRET is not set}
- WOODPECKER_DATABASE_DRIVER=postgres
- WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${POSTGRES_PASSWORD?Variable POSTGRES_PASSWORD is not set}@woodpecker-db:5432/woodpecker?sslmode=disable
- WOODPECKER_GITHUB_URL=https://github.com
- WOODPECKER_ADMIN=${WOODPECKER_ADMIN?Variable WOODPECKER_ADMIN is not set}
networks:
- woodpecker-net
- traefik-net
labels:
- traefik.enable=true
- traefik.docker.network=traefik-net
- traefik.http.services.woodpecker.loadbalancer.server.port=8000
- traefik.http.routers.woodpecker-secure.rule=Host(`ci.trymondo.com`)
- traefik.http.routers.woodpecker-secure.entrypoints=websecure
- traefik.http.routers.woodpecker-secure.service=woodpecker
- traefik.http.routers.woodpecker-secure.tls=true
- traefik.http.routers.woodpecker-secure.tls.certresolver=production
- traefik.http.middlewares.woodpecker-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.woodpecker-redirect.redirectscheme.permanent=true
- traefik.http.routers.woodpecker-http.rule=Host(`ci.trymondo.com`)
- traefik.http.routers.woodpecker-http.entrypoints=web
- traefik.http.routers.woodpecker-http.service=woodpecker
- traefik.http.routers.woodpecker-http.middlewares=woodpecker-redirect@docker
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:v3.5.2
container_name: woodpecker-agent
restart: unless-stopped
depends_on:
- woodpecker-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock:rw
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_GRPC_SECURE=false
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET?Variable WOODPECKER_AGENT_SECRET is not set}
networks:
- woodpecker-net
woodpecker-db:
image: postgres:17
container_name: woodpecker-db
restart: unless-stopped
environment:
- POSTGRES_USER=woodpecker
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=woodpecker
volumes:
- woodpecker-db-data:/var/lib/postgresql/data
networks:
- woodpecker-net
volumes:
woodpecker-server-data:
woodpecker-db-data:
networks:
woodpecker-net:
external: true
traefik-net:
external: true
```
## Network Configuration
Before deployment, ensure the required networks exist:
```bash theme={null}
docker network create woodpecker-net
docker network create traefik-net
```
## Deployment Instructions
1. Create the deployment directory:
```bash theme={null}
mkdir -p /opt/apps/woodpecker
```
2. Create the `docker-compose.yml` and `.env` files:
```bash theme={null}
nano /opt/apps/woodpecker/docker-compose.yml
nano /opt/apps/woodpecker/.env
```
3. Deploy the service:
```bash theme={null}
cd /opt/apps/woodpecker
docker compose up -d
```
4. Verify all services are running:
```bash theme={null}
docker compose ps
```
## Traefik Integration Details
The Woodpecker server is configured with the following Traefik settings:
* **Host Rule**: `ci.trymondo.com`
* **Entrypoints**: websecure (HTTPS on port 443), web (HTTP on port 80 with redirect to HTTPS)
* **TLS**: Enabled with production certificate resolver
* **Backend Port**: 8000 (Woodpecker Web UI)
* **Middleware**: HTTP to HTTPS redirect for enhanced security
## Pipeline Configuration
### Basic .woodpecker.yml Example
Create a `.woodpecker.yml` file in the root of your GitHub repository:
```yaml theme={null}
pipeline:
build:
image: node:20
commands:
- npm install
- npm run build
- npm test
docker:
image: plugins/docker
settings:
registry: registry.example.com
repo: registry.example.com/myapp
tags: latest
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
branch: main
```
### Secrets Management
To add secrets to your Woodpecker CI projects:
1. Navigate to your repository in the Woodpecker UI
2. Go to **Settings** > **Secrets**
3. Add required secrets (e.g., `docker_username`, `docker_password`)
## Scaling and Performance
### Additional Agents
To scale out CI capacity, you can add more agents:
```yaml theme={null}
woodpecker-agent-2:
image: woodpeckerci/woodpecker-agent:v3.5.2
container_name: woodpecker-agent-2
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:rw
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_GRPC_SECURE=false
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
networks:
- woodpecker-net
```
### Resource Constraints
For improved stability, consider adding resource constraints:
```yaml theme={null}
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
```
## Maintenance
### Backup Strategy
Back up Woodpecker CI regularly:
1. Database backup:
```bash theme={null}
docker compose exec woodpecker-db pg_dump -U woodpecker woodpecker > woodpecker_backup_$(date +%Y%m%d).sql
```
2. Volume backup using Restic/Backrest:
* `woodpecker-server-data` (contains server state)
* `woodpecker-db-data` (contains database files)
### Updates
To update Woodpecker CI:
1. Update the image tags in `docker-compose.yml`
2. Apply the update:
```bash theme={null}
docker compose pull
docker compose up -d
```
3. Check logs for any issues:
```bash theme={null}
docker compose logs
```
## Troubleshooting
### Server Startup Issues
If the server fails to start:
1. Check environment variables:
```bash theme={null}
docker compose logs woodpecker-server | grep "required key"
```
2. Verify database connection:
```bash theme={null}
docker compose logs woodpecker-server | grep "database"
```
### Agent Connection Problems
If agents can't connect to the server:
1. Check agent logs:
```bash theme={null}
docker compose logs woodpecker-agent
```
2. Verify agent secret is consistent between server and agent
3. Check network connectivity between containers:
```bash theme={null}
docker compose exec woodpecker-agent ping woodpecker-server
```
### GitHub Integration Issues
If GitHub integration is not working:
1. Verify OAuth callback URL is correctly set to `https://ci.trymondo.com/login`
2. Check GitHub client ID and secret in environment variables
3. Examine server logs for OAuth-related errors:
```bash theme={null}
docker compose logs woodpecker-server | grep -i "github"
```
## Security Considerations
* **Agent Secret**: Use a strong, randomly generated secret for agent authentication
* **Admin Access**: Limit admin access to specific GitHub usernames
* **Docker Socket**: The agent has access to the Docker socket, which grants significant privileges
* **HTTPS**: Enforce HTTPS-only access through Traefik
* **Network Isolation**: Use separate networks for communication between services
## Additional Resources
* [Official Woodpecker CI Documentation](https://woodpecker-ci.org/docs/)
* [Woodpecker CI GitHub Repository](https://github.com/woodpecker-ci/woodpecker)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)
## Pipeline Examples
### Node.js Application
```yaml theme={null}
pipeline:
test:
image: node:20
commands:
- npm install
- npm test
```
### Docker Build and Push
```yaml theme={null}
pipeline:
build:
image: plugins/docker
settings:
registry: docker.io
repo: myuser/myapp
tags: latest
username:
from_secret: docker_username
password:
from_secret: docker_password
```
### Multi-stage Pipeline with Approval
```yaml theme={null}
pipeline:
test:
image: golang:1.21
commands:
- go test ./...
build:
image: golang:1.21
commands:
- go build -o myapp
deploy:
image: plugins/ssh
settings:
host: production.example.com
user: deploy
key:
from_secret: ssh_key
script:
- ./deploy.sh
when:
status: success
branch: main
approval:
approved_by:
- admin_user
```
# Overview
Source: https://docs.trymondo.com/mops/infrastructure
This document defines how to work with MOPS infrastructure across environments (dev, staging, prod) using Docker, Portainer, and Git. It ensures Jordan and Joe operate with the same brain and adhere to expert standards.
## Folder Structure
```
MOPS/
├── environments/
│ ├── dev/
│ │ ├── n8n/
│ │ │ ├── .env
│ │ │ └── docker-compose.yml
│ │ └── traefik/
│ ├── staging/
│ │ ├── n8n/
│ │ └── traefik/
│ └── prod/
│ ├── n8n/
│ └── traefik/
├── shared/ # Reserved for shared future config fragments
└── README.md
```
***
## Stack Naming (Portainer)
* Format: `[env]-[service]-stack`
* Examples:
* `dev-n8n-stack`
* `prod-n8n-stack`
* `staging-traefik-stack`
All container, volume, and network names follow the same prefixing rule.
***
## Environments
### `dev/`
* Used for experiments, rapid iteration, test credentials only.
* Safe to break.
* Only accessible to internal team.
### `staging/`
* Used for internal QA.
* Should mirror `prod` config and infrastructure 1:1 as closely as possible.
* Uses *real integration endpoints* (e.g., SMTP, OAuth), but **not production data**.
### `prod/`
* Production-only.
* Zero downtime expectation.
* Code and config **`must flow from staging`**, not directly from `dev`.
***
## Workflow Summary
1. **`Develop in dev/`**
* Work with live containers locally or via Portainer Stack.
* Debug, test new features, iterate quickly.
2. **`Promote to staging/`**
* Use `rsync` or `git` to copy the working config.
* Replace test `.env` values with real sandbox/QA credentials.
* Run end-to-end test flows.
3. **`Promote to prod/`**
* Only after staging passes.
* Tag commit (`v1.2.0-prod`), deploy via CI/CD or Portainer Git Stack.
* Document changes and review logs post-deploy.
***
## Secrets Management
### Current State
`.env` files are stored in Git — this is **not secure**.
### Immediate Fix
* Move `.env` values to Portainer **Secrets** (per environment).
* Reference them in `docker-compose.yml` like this:
```yaml theme={null}
env_file:
- /run/secrets/n8n_api_key
```
### Near-Future Upgrade Path
* Use [dotenv-vault](https://www.dotenv.org/) or \[SOPS + Git-crypt] for OSS secret encryption.
* Alternative: GitHub Actions + \[secrets manager] for automated secure injection.
***
## CI/CD Plan
### Goals
* Push to `environments/prod/**` requires PR approval and triggers deploy to `prod`
* Push to `environments¸/staging/**` triggers deploy to `staging`
### Tool: GitHub Actions
```yaml theme={null}
on:
push:
paths:
- 'environments/staging/**'
branches:
- main
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Staging
run: |
ssh user@server 'cd /docker && docker compose -f environments/staging/n8n/docker-compose.yml up -d'
```
Add manual approval + backup steps for `prod`.
***
## Backup & Rollback Plan
### For PostgreSQL (n8n, mautic):
* Use `pg_dump` and `pg_restore`.
* Set up nightly cron-based backup containers.
### For Volumes:
* Use \[bind mounts] to make data externally accessible.
* Snapshot `/var/lib/docker/volumes` regularly using rsync or Btrfs/ZFS snapshots.
***
## Best Practices
* Never deploy to `prod` directly.
* Never store `.env` with secrets in Git.
* Always test in `staging` before production.
* Always prefix stacks/networks/containers with `[env]-[service]`.
* Always document new services in their `README.md`.
* Avoid floating Docker image tags in `prod` (e.g., use `n8nio/n8n:1.27.1` not `:latest`).
***
## Future Improvements
* Central secrets manager
* Automated rollback script
* Infra diagram / dependency map
* Multi-server orchestration (Docker Swarm or K8s)
* Terraform/Ansible for provisioning VPSes
***
> Questions? Ping Jordan or Joe. Otherwise: build, test, promote. Stay sharp.
> git config --global pull.rebase true
# Introduction
Source: https://docs.trymondo.com/mops/introduction
Welcome to the official documentation for **Mondo** – your open platform for modern, privacy-respecting software.
To report a bug, visit \[[https://tally.so/r/w8E7Qx](https://tally.so/r/w8E7Qx)]
## 🔍 What You'll Find Here
* **Getting Started** – Learn how to install, configure, and deploy Mondo.
* **Features** – Explore what makes Mondo powerful and modular.
* **Developer Guide** – Dive into APIs, integrations, and advanced workflows.
* **FAQ & Troubleshooting** – Common questions, tips, and fixes.
***
## 📦 Quick Start
```bash theme={null}
git clone https://github.com/mondosolutions/MOPS.git
cd MOPS
docker compose up -d
```
Open your browser at [http://localhost:8000](http://localhost:8000) to explore the docs locally.
***
## 📚 Project Overview
Mondo is a modular open platform that helps teams build and scale self-hosted infrastructure with:
* ⚡️ Rapid deployment via Docker & Traefik
* 🔐 Privacy-first approach with no data sent to third parties
* 🧩 Easily extensible with open standards
* 💬 Active community support
***
## 💬 Join the Conversation
* [GitHub Discussions](https://github.com/mondosolutions/MOPS/discussions)
* [Submit an Issue](https://github.com/mondosolutions/MOPS/issues)
***
## 👏 Contributing
We welcome contributions! Check out our [contribution guide](contributing.md) to get started.
***
Get your docs set up locally for easy development
Preview your changes before you push to make sure they're perfect
Build interactive features and designs to guide your users
Check out our showcase of our favorite documentation
# null
Source: https://docs.trymondo.com/mops/project-overview
# Mondo MOPS (Mondo Open Platform Service)
**A privacy-first, self-hosted open platform for modern marketing teams and agencies.**
## What This Repo Contains
This repository contains the full deployment framework for the MOPS platform, including:
* **Core Marketing Services**: Mautic (email marketing), n8n (workflow automation), EspoCRM (customer relationship management), Outline (knowledge base), Cal.com (scheduling)
* **Infrastructure Configuration**: Traefik (reverse proxy), Docker Compose files, environment configurations
* **Monitoring & Management**: Loki/Grafana (logging), Backrest/Restic (backups), Portainer (container management)
* **Authentication & Security**: Authentik (identity provider), secure headers configuration
MOPS follows a modular architecture allowing teams to deploy only the services they need while maintaining a consistent management interface.
## Why Use Mondo MOPS?
* **100% Self-Hosted, Privacy-Respecting**: Complete control over your marketing data and infrastructure
* **Pre-Integrated Tools**: Carefully selected and configured marketing tools that work together seamlessly
* **Enterprise-Grade Infrastructure**: Built with Docker, Traefik, and modern DevOps practices for reliability
* **Consistent Environments**: Standardized development, staging, and production environments
* **Open Source Foundation**: Built on trusted open source technologies with active communities
## Getting Started
### Basic Requirements
* Cloud- or Self-Hosted VPS running Ubuntu 24.04 LTS
* Docker 24+ and Docker Compose
* Domain name with DNS control for subdomain routing
* 2GB+ RAM (4GB+ recommended for full stack)
* At least 20GB storage space
### Quick Start
1. Clone this repository
2. Configure your environment variables
3. Run the deployment script
For complete installation and deployment instructions, see the [Setup Documentation](./docs/setup/README.md).
## Repository Structure
```
MOPS/
├── docs/ # Documentation
├── environments/ # Environment-specific configurations
│ ├── dev/ # Development environment
│ ├── staging/ # Staging environment
│ └── prod/ # Production environment
│ ├── traefik/ # Reverse proxy configuration
│ ├── n8n/ # Workflow automation
│ ├── mautic/ # Email marketing platform
│ ├── espocrm/ # CRM platform
│ ├── outline/ # Knowledge base
│ └── ... # Other services
├── shared/ # Shared configurations and utilities
└── .github/
└── workflows/ # CI/CD pipelines
```
## Services
| Service | Description | URL |
| --------- | ---------------------- | ------------------------ |
| Traefik | Reverse Proxy & TLS | traefik.trymondo.com |
| Mautic | Email Marketing | outreach.trymondo.com |
| n8n | Automation Workflows | automations.trymondo.com |
| EspoCRM | CRM Platform | crm.trymondo.com |
| Outline | Knowledge Base | wiki.trymondo.com |
| Portainer | Container Management | portainer.trymondo.com |
| Grafana | Observability | grafana.trymondo.com |
| Cal.com | Appointment Scheduling | cal.trymondo.com |
| Homer | Service Dashboard | dash.trymondo.com |
| FilePizza | File Sharing | pizza.trymondo.com |
## Development
!!! note
MOPS follows standardized naming conventions across environments. See [Naming Conventions](./docs/naming-conventions.md) for details.
For development guidelines, contribution workflows, and technical specifications, refer to the [Developer Documentation](./docs/development/README.md).
## License
Mondo MOPS is licensed under the MIT License. See [LICENSE](./LICENSE) for details.
***
Developed and maintained by \[
# null
Source: https://docs.trymondo.com/mops/troubleshooting
This page helps you diagnose and resolve common problems with MOPS services. If your issue isn't listed, please reach out to our support team.
## Table of Contents
* [Service Down](#service-down)
* [Deployment Failures](#deployment-failures)
* [Configuration Errors](#configuration-errors)
* [Authentication Issues](#authentication-issues)
* [Contact Support](#contact-support)
***
## Service Down
* Service is not responding
* 5xx errors in logs
* Health checks failing
**Steps to Diagnose:**
1. Check service status with:
```sh theme={null}
systemctl status mops-service
```
2. Review recent logs:
```sh theme={null}
journalctl -u mops-service --since "10 minutes ago"
```
3. Ensure dependencies (database, network) are operational.
***
## Deployment Failures
* Incorrect environment variables
* Build errors
* Insufficient permissions
**Steps to Diagnose:**
1. Review deployment logs for errors.
2. Verify all required environment variables are set.
3. Check permissions for deployment user.
***
## Configuration Errors
* Service starts but behaves unexpectedly
* Error messages about missing config
**Steps to Diagnose:**
1. Validate your configuration file syntax.
2. Ensure all required fields are present.
3. Restart the service after changes.
***
## Authentication Issues
* Users cannot log in
* 401/403 errors
**Steps to Diagnose:**
1. Confirm authentication service is running.
2. Check user credentials and permissions.
3. Review authentication logs for errors.
***
## Contact Support
If you can't resolve your issue, please [contact support](mailto:techsupport@trymondo.com) with:
* A description of the problem
* Steps you've tried
* Relevant logs or screenshots
***
Continually add new troubleshooting topics below as new issues are discovered!
# Connect X API
Source: https://docs.trymondo.com/posts/connecting-x
A step-by-step guide to help you set up your X API credentials in Mondo Posts.
# Setting Up Your X API Credentials in Mondo Posts
Follow these simple steps to set up your X API credentials in Mondo Posts. This guide is designed for non-technical users, so no prior technical knowledge is required.
## Step 1: Log in to Your X Account
1. Open your web browser and go to the X Developer Portal: [https://developer.x.com](https://developer.x.com).
2. Log in using your X account credentials.
## Step 2: Create a New App
1. Once logged in, navigate to the **Apps** section.
2. Click on the **Create App** button.
3. Fill in the required details for your app (e.g., name, description, and website URL).
4. Save your app by clicking **Create** or **Save**.
## Step 3: Locate Your API Credentials
1. After creating your app, go to the **Keys and Tokens** section of your app.
2. Copy the following credentials:
* **API Key**
* **API Secret Key**
* **Access Token**
* **Access Token Secret**
## Step 4: Open Mondo Posts
1. Log in to your Mondo Posts account at [https://posts.trymondo.com](https://posts.trymondo.com).
2. Navigate to the **Settings** section.
## Step 5: Enter Your X API Credentials
1. In the **Settings** section, find the **API Integrations** or **X Integration** option.
2. Paste the credentials you copied earlier into the corresponding fields:
* API Key
* API Secret Key
* Access Token
* Access Token Secret
3. Click **Save** or **Connect** to finalize the setup.
## Step 6: Test the Connection
1. Go back to the Mondo Posts dashboard.
2. Create a test post and try publishing it to X.
3. If the post is successfully published, your setup is complete!
Congratulations! You’ve successfully set up your X API credentials in Mondo Posts. If you encounter any issues, refer to the Mondo Posts support team for assistance.
# Introduction
Source: https://docs.trymondo.com/posts/introduction
What is Mondo Posts, and why should you use it?
Welcome to Mondo Posts, a powerful and intuitive platform designed to simplify your content creation and management process. Whether you're a seasoned writer or just starting out, Mondo Posts provides the tools you need to create, organize, and share your content effortlessly.
## Why Choose Mondo Posts?
Mondo Posts is built with flexibility and ease of use in mind. It empowers you to focus on what matters most—your content—while handling the technical complexities behind the scenes. Here’s why you should consider using Mondo Posts:
* **Streamlined Workflow**: Create and manage posts with a user-friendly interface that saves you time and effort.
* **Customizable**: Tailor the platform to fit your unique needs and preferences.
* **Scalable**: Whether you're managing a personal blog or a large-scale publication, Mondo Posts grows with you.
* **Seamless Integration**: Easily integrate with other tools and platforms to enhance your content strategy.
## Getting Started
Setting up Mondo Posts is quick and straightforward. These docs will guide you through every step of the process, from installation to advanced customization. Here's how to begin:
1. **Installation**: Follow the setup instructions to get Mondo Posts up and running on your system.
2. **Configuration**: Customize your settings to align with your goals and workflow.
3. **Create Your First Post**: Dive in and start creating content using the intuitive editor.
4. **Explore Advanced Features**: Learn about additional tools and integrations to maximize your productivity.
Dive into the documentation to unlock the full potential of Mondo Posts and take your content creation to the next level. Let’s get started!
# User Management
Source: https://docs.trymondo.com/posts/user-management
Best practices for managing clients in Mondo Posts.
Managing clients effectively involves organizing and overseeing their accounts, content, and interactions. Start by creating individual profiles for each client to keep their information separate and secure. Use scheduling tools to plan and publish content tailored to their needs. Monitor performance metrics to track engagement and adjust strategies as needed. Regular communication and reporting ensure transparency and help maintain strong client relationships.
# Workspaces
Source: https://docs.trymondo.com/posts/workspaces
How the workspaces work in Mondo Posts and how to get started.
# Frontend
Source: https://docs.trymondo.com/proposals/frontend
The weird journey on how the frontend came to be.
## Design
The entire point of building our own proposal software was not to escape the endless fees and revenue sharing that most tools force you into, but to also improve the experience. Mondo's proposals were designed around a few basic concepts:
1. Quickly explain the way Mondo does business.
2. Allow for **clients to choose** what services to proceed with
3. See a very clear and concise pricing breakdown of **one-time and recurring charges.**
4. Clear and concise **timeline estimations**
5. Allow for instant **signatures.**
6. Allow for **payment**
All of the above, **in one page experience**, making for a great start to a relationship of ease and simplicity at the core of the Mondo experience.
While this is nice and all, we needed to also tie this into utilizing AI to auto-generate proposals by supplemening real-time data that was highly precise to current trends, tools, and analysis. So we had to build in ProposalGen AI.
## Automatic Proposal Generator (supplemented by humans)
As Mondo has scaled over the years, the need to build processes around the proposal generation process was a major thorn in our side. This is due to the lack of overall strategic knowledge and know-how of incoming staff to grasp how proposals needed to be priced and pitched. In marketing, we are not always just selling a package of services that are predictable. Most agencies attempt to solve this to skirt around having to solve the proposal problem, but the industry moves to fast to keep services bundled in this manner. In our experience this leads to stagnant, ineffective service offerings that are really only artificially there to benefit the agencies processes and hiring.
**The client shouldn't be the victim of this**
So what is our solution?
Leverage AI with a sliding scale of pricing we have set as a median to each business size and industry. Traditionally, this would be tons of work for a human to work out. By combining the automation and hyper-accurate results of ai, analysis of the client, their industry, their budget, their geo... a human alone would almost never get a proposal to be this accurate. So this works out great; a proposal that benefits both parties, the speed and near elimination of the need to hash over service offerings before even showing it to a potential client, and it **scales**.
After many iterations of planning, and resisting the urge to just sign up for the latest paid "solution", we decided that there would always need to be a human touch. Of course. So we introduced a section at the top of all our proposals where a Mondo strategist would provide a video recording of a walkthrough of the proposal to clearly explain what is needed and to engage the customer in iterating on the proposal if necessary. This engagement with the client makes them feel like they are more in-charge than that of the normal agency experience. **This is what we were after.**
So here is the flow:
1. Intake form requires many metrics to be gathered on the business through the human sales funnel at Mondo.
2. This data is then split into a marketing analytics agent that goes into very deep research of the businesses' online presence. Content, SEO, website aesthetics, followers, domain authority, etc.
3. Contact and business data is sent to a data enrichment service to gather as much information on the business as possible. Sometimes validating and sometimes not the accuracy of the data given to the salesperson at Mondo. Which helps us be realistic with the client.
4. Data from both is parsed into a problem solving agent that considers all solutions for the business and matches it to a service set at Mondo and possibly even services that Mondo doesn't offer. This is all provided to the client.
5. This is then combined again and parsed into a prompt for pricing. This agent has access to our master pricing list to ensure consideration of our absolute bottom-dollar sale and where the industry norms are. (This allows us freedom to discount services in hopes to persuade the company to invest more into their growth long term)
6. At last, we combine all of this data into a page generating AI that generates static pages and displays them on proposals.trymondo.com
7. Before showing the client the proposal goes through Discord channels to be approved/disapproved. Upon approval, it request a video link to inject into the top of the proposal.
8. Upon decline, it goes back to the pricing engine that iterates upon the changes requested on the proposal and loops this approval process until complete.
In the end, the client drastically benefits from the extra research on their business, gives them the best price possible, and Mondo hopefully gets a lifelong customer. Kaboom! Win win.
# HTML Generator
Source: https://docs.trymondo.com/proposals/htmlgenerator
This agent takes the proposal and generates an HTML file thaty is hosted on proposals.trymondo.com
# Introduction
Source: https://docs.trymondo.com/proposals/introduction
This is the introduction to the proposal experience at proposals.trymondo.com
# Building a proposal experience like no other.
A modern, visually striking landing page for customers to review, select, and purchase proposals, including contract signature and Stripe checkout.
## Features
* **View and select proposal options** (with prices)
* **Dynamic total calculation** (one-time and subscription charges separated)
* **All options pre-selected** on page load for user convenience
* **Sticky totals section**: Totals remain visible and become sticky at the bottom on scroll
* **Interactive process timeline**: Visual guide from Pick Options → Sign Agreement → Pay → Success 🚀
* **Estimated Timelines panel**: Shows how long each selected service will take (placeholders, ready for Supabase data)
* **Digital contract signature**: User must sign before payment
* **Confetti celebration**: Confetti flies across the screen when the contract is signed
* **Captivating payment button**: Green, full-width, animated, and only enabled after signature (with lawyer tooltip if not signed)
* **Stripe Checkout integration**
* **Supabase for data storage**
* **Fully responsive UI**: Optimized for mobile and desktop
* **Dark/light mode**
* **Modern gradients and alternating black/white sections**
## Tech Stack
* Next.js (React)
* Tailwind CSS
* Supabase
* Stripe
* canvas-confetti (for signature celebration)
## Getting Started
1. `npm install`
2. Set up `.env.local` with Supabase and Stripe keys
3. `npm run dev`
### Logo Customization
* Replace `/public/mondo-white.svg` with your own logo (SVG/PNG/JPG) and update the `
` in `pages/index.js` if needed.
### Confetti Effect
* The confetti animation on contract signature uses [`canvas-confetti`](https://www.npmjs.com/package/canvas-confetti). This is installed automatically with `npm install`.
## Deployment
Ready for Ubuntu 24.04 VPS. See deployment instructions in this README after setup.
## Usage Guidance
* **Select/deselect services**: All are checked by default; uncheck what you don't need.
* **Estimated timelines**: Shown for each selected service.
* **Sign the contract**: Enter your name and sign to unlock payment.
* **Proceed to payment**: Button becomes active after signing. If not signed, a tooltip explains why.
* **Celebrate!**: Confetti will fly when you sign the contract.
# Marketing Analysis Agent
Source: https://docs.trymondo.com/proposals/marketingagent
A description of the Gumloop flows are all intertwined to make the system work.
\#The following is the promport for the AI agent that will analyze the form data and provide a structured output for the marketing proposal.
```markdown theme={null}
You are a senior marketing strategist AI responsible for analyzing client information submitted via a sales intake form. Your task is to provide a clear, actionable brief on **only the marketing services that will directly benefit this business**, while aligning recommendations to their stated goals, challenges, and industry context.
Your output will be used by another AI agent to generate a proposal, so consistency, clarity, and accuracy are critical.
---
#### Context
You will be passed structured form data that includes:
- Business details (name, industry, size, region, etc.)
- Marketing goals (lead generation, social growth, etc.)
- Challenges (competition, growth limitations, niche issues)
- Service preferences (ads, website, SEO, etc.)
- Specific requests (quote formats, human ideas, transcript uploads)
- Optional competitor data
- Additional comments from sales reps
---
**