Removed SMTP_NO_MX_LOOKUPS and SMTP_ALLOWED_TLS_VERSIONS settings
that were added during troubleshooting. Using only basic SMTP
configuration that works for other services (mattermost, tandoor).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
For implicit SSL on port 465, we need SMTP_SSL: true and should
NOT set SMTP_TLS (which is for STARTTLS on port 587).
Added SMTP_NO_MX_LOOKUPS to skip MX record lookups.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Reverted to use ${EMAIL_SMTP_PORT} from .env (port 465) since
this configuration works for other services.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Port 465 with implicit SSL is not working. Switching to port 587
with STARTTLS (SMTP_TLS: always) which is more compatible with
Swoosh SMTP adapter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added SMTP_NO_MX_LOOKUPS, SMTP_TLS_VERIFY_HOST, and
SMTP_TLS_VERIFY_CERT settings to fix SSL connection issues
with IONOS SMTP on port 465.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Environment variables are strings. Use 'never' not ':never' so
the Elixir code can convert it to an atom properly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
SMTP_TLS must be an Elixir atom (:never, :always, or :if_available).
Using :never for implicit SSL on port 465.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
IONOS SMTP on port 465 uses implicit SSL, not STARTTLS.
Set SMTP_TLS: false and SMTP_SSL: true.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Port 465 requires implicit TLS, not SSL. Changed SMTP_SSL to SMTP_TLS
with value 'always' and added SMTP_AUTH: always.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add EMAIL_FROM to arty.yml environment defaults
- Configure asciinema to use EMAIL_FROM for MAIL_FROM_ADDRESS
- Set SMTP_SSL to true for IONOS SMTP on port 465
- Set SIGN_UP_DISABLED default to false (will enable after admin creation)
- Follow netdata compose.yaml pattern for Traefik labels
- Add proper HTTP to HTTPS redirect middlewares
- Configure compression and security headers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed API key reference from ${ANTHROPIC_API_KEY} to
os.environ/ANTHROPIC_API_KEY to match LiteLLM's documented syntax.
The os.environ/ prefix tells LiteLLM to use os.getenv() to retrieve
the environment variable at runtime, which is the correct way to
reference environment variables in LiteLLM config files.
Reference: https://docs.litellm.ai/docs/proxy/deploy🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed custom Dockerfile and SFTP function integration in favor of
the simpler REST API approach (webui-export.py).
Changes:
- Restored webui service to use official Open WebUI image
- Removed custom Dockerfile.webui (paramiko build)
- Removed ai/functions/save_to_disk.py SFTP function
- Removed SSH key and functions volume mounts
The REST API export script (webui-export.py) is a simpler and more
flexible solution that doesn't require Docker modifications.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Python script to extract and save code blocks from Open WebUI
chat conversations to local disk using the REST API.
Features:
- Export code blocks from specific chats or all chats
- Automatic language detection and proper file extensions
- Organizes files by chat title with metadata
- No Docker modifications needed
- Remote access support via SSH tunnel or public URL
Usage:
python3 ai/webui-export.py --all --output-dir ./exports
python3 ai/webui-export.py --chat-id <id> --output-dir ./code
This replaces the complex SFTP integration with a simple API-based
approach that's easier to maintain and use.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added custom Open WebUI function for SSH/SFTP file operations:
**New Function: save_to_disk.py**
- save_file(): Write generated code to local filesystem via SFTP
- read_file(): Read files from local disk
- list_files(): List directory contents
- Configurable via Valves (host, port, username, paths)
**Custom Dockerfile (Dockerfile.webui)**
- Based on ghcr.io/open-webui/open-webui:main
- Installs paramiko library for SSH/SFTP support
- Creates .ssh directory for key storage
**Configuration Updates**
- Mount SSH private key from host (/root/.ssh/id_rsa)
- Mount functions directory for custom tools
- Build custom image with SFTP capabilities
**Usage in Open WebUI**
Claude can now use these tools to:
- Generate code and save it directly to your local disk
- Read existing files for context
- List project directories
- Create new files in any project
Default base path: /home/valknar/Projects
Authentication: SSH key-based (passwordless)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added LiteLLM as an OpenAI-compatible proxy for Anthropic's API to
enable Claude models in Open WebUI.
**New Service: litellm**
- Image: ghcr.io/berriai/litellm:main-latest
- Internal proxy on port 4000
- Converts Anthropic API to OpenAI-compatible format
- Health check with 30s intervals
- Not exposed via Traefik (internal only)
**LiteLLM Configuration (litellm-config.yaml)**
- Claude Sonnet 4 (claude-sonnet-4-20250514)
- Claude Sonnet 4.5 (claude-sonnet-4-5-20250929)
- Claude 3.5 Sonnet (claude-3-5-sonnet-20241022)
- Claude 3 Opus (claude-3-opus-20240229)
- Claude 3 Haiku (claude-3-haiku-20240307)
**Open WebUI Configuration Updates**
- Changed OPENAI_API_BASE_URLS to point to LiteLLM proxy
- URL: http://litellm:4000/v1
- Added litellm as dependency for webui service
- Dummy API key for proxy authentication
**Why LiteLLM?**
Anthropic's API uses different endpoint structure and authentication
headers compared to OpenAI. LiteLLM acts as a translation layer,
allowing Open WebUI to use Claude models through its OpenAI-compatible
interface.
**Available Models in Open WebUI**
- claude-sonnet-4 (latest Claude Sonnet 4)
- claude-sonnet-4.5 (Claude Sonnet 4.5)
- claude-3-5-sonnet
- claude-3-opus
- claude-3-haiku
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated README.md with AI intelligence system:
**Core Systems Table**:
- Added AI system entry with ai.pivoine.art access point
**Infrastructure Section**:
- Added AI Intelligence Core with PostgreSQL 16 + pgvector
- Listed Open WebUI, Crawl4AI, and document embeddings
**Navigation Commands**:
- New AI Operations section with usage instructions
- How to configure Claude API in Open WebUI
- Steps: create account, add API connection, select model, upload docs
- Internal services documentation (Crawl4AI, PostgreSQL)
- n8n workflow integration examples
**Ship Architecture**:
- Added AI Intelligence category with 3 services
- PostgreSQL+pgvector for vector database
- Open WebUI for Claude interface
- Crawl4AI for web scraping (internal)
**Storage Volumes**:
- ai_postgres_data: AI vector database
- ai_webui_data: Open WebUI application data
- ai_crawl4ai_data: Web scraping cache
**Backup Protocol**:
- Updated backup window to 2-10 AM
- Updated count from 11 to 16 backup plans
All AI services accessible at https://ai.pivoine.art with Claude
integration, RAG support, and web search capabilities.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed service name from 'postgres' to 'ai_postgres' to avoid naming
conflict with the core PostgreSQL service in Docker Compose include.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created complete AI infrastructure stack at ai.pivoine.art:
**New Services:**
- **Open WebUI** (ai.pivoine.art)
- ChatGPT-like interface for AI models
- Multi-user chat with authentication
- RAG (Retrieval-Augmented Generation) support
- Document upload and processing
- Claude API integration via Anthropic
- **PostgreSQL with pgvector** (dedicated AI database)
- Vector similarity search for RAG
- Separate from production databases
- Stores embeddings and documents
- **Crawl4AI** (internal API service)
- Web scraping optimized for LLMs
- Converts websites to clean Markdown
- Called by n8n workflows
- No public exposure (internal only)
**Configuration:**
- Added 18 AI environment variables to arty.yml
- Configured email notifications via IONOS SMTP
- OpenAI API compatibility for Claude integration
- Traefik SSL termination and compression
**Backup:**
- Added 3 AI volumes to Restic backup
- Daily backup at 3 AM
- Retention: 7 daily, 4 weekly, 6 monthly, 2 yearly
**Integration:**
- Shares falcon_network with existing services
- Ready for n8n workflow automation
- Mattermost notifications support
- Watchtower auto-updates enabled
Ready for Phase 2: GPU server integration with Ollama, Whisper, and
Stable Diffusion when IONOS A10 server is provisioned.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed PostgreSQL image from postgres:16-alpine to
pgvector/pgvector:pg16-alpine to enable vector similarity search
capabilities for AI/RAG applications.
This is required for Open WebUI's RAG functionality to store and
query document embeddings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Tandoor's internal Nginx listens on port 80, not 8080. This was causing
502 Bad Gateway errors because Traefik was trying to connect to the wrong port.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed VPN backup configuration since the VPN service is not currently
included in the compose.yaml and the vpn_etc_wireguard volume doesn't exist.
Kept Netdata backup as those volumes exist and the service is running.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Tandoor Recipes as a comprehensive recipe management solution:
**Tandoor Stack** (tandoor.pivoine.art):
- Modern recipe manager with smart scaling and collaboration
- PostgreSQL backend for recipe persistence
- Email notifications via IONOS SMTP
- Static and media file storage in dedicated volumes
- User signups disabled (admin-only access)
**Features:**
- Smart recipe scaling (auto-adjust ingredients for servings)
- Spaces for collaboration (family/roommate recipe sharing)
- Meal planning and shopping lists
- Recipe import from URLs
- Mobile app support (Kitshn app)
- Nutritional information and pricing
**Infrastructure updates:**
- Added tandoor database to PostgreSQL init script
- Added environment variables to arty.yml
- Updated compose.yaml include list
- Added Tandoor volumes (staticfiles, mediafiles) to Restic backup
- Configured email notifications for invitations and notifications
**Tech stack:**
- Django/Python backend
- Vue.js frontend
- PostgreSQL database (shared core instance)
- Gunicorn WSGI server
Tandoor provides superior UX compared to Mealie with better recipe
scaling, collaboration features, and mobile app experience.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to reflect current infrastructure:
**Added:**
- Mattermost team collaboration platform
- Team chat, file sharing, integrations
- Email notifications via IONOS SMTP
- Incoming webhooks for infrastructure alerts
- PostgreSQL backend
- Netdata real-time monitoring
- System and service monitoring
- PostgreSQL and Docker monitoring
- Restic backup repository monitoring
- Email and Mattermost alerts
- HTTP Basic Auth protection
**Removed:**
- Gotify notification server (replaced by Mattermost)
**Updated:**
- Database initialization: Added mattermost database
- Backup configuration: Added Mattermost volumes
- Environment variables: Added MATTERMOST_WEBHOOK_URL and WATCHTOWER_NOTIFICATION_URL
- Volume management: Added Mattermost, Joplin, and Jellyfin volumes
- Service list in compose include pattern
All documentation now reflects the current state of the infrastructure
with Mattermost as the central notification and collaboration hub.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Mattermost volumes to backup configuration:
- mattermost_config: Server configuration and settings
- mattermost_data: User data, posts, files, and attachments
- mattermost_plugins: Installed plugins
These volumes contain critical Mattermost data and should be
backed up regularly to ensure team chat history and configurations
can be restored if needed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed Gotify completely from infrastructure, replaced by Mattermost:
- Removed gotify/compose.yaml stack
- Removed Gotify environment variables from arty.yml
- Removed Gotify from compose.yaml include list
- Removed Gotify volume backup from Restic configuration
Gotify has been fully replaced by Mattermost for:
- Infrastructure notifications (Netdata, Watchtower, Restic)
- n8n workflow notifications
- Team collaboration and chat
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added MATTERMOST_WEBHOOK_URL environment variable to n8n:
- Available as environment variable in workflow expressions
- Can be used in HTTP Request nodes to send notifications
- Enables easy integration with Mattermost from any workflow
Usage in n8n workflows:
- Use {{ $env.MATTERMOST_WEBHOOK_URL }} in expressions
- Send POST requests with JSON payload to notify Mattermost
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Mattermost webhook notifications for infrastructure services:
- **Netdata**: Health monitoring alerts sent to Mattermost
- Configured via MATTERMOST_WEBHOOK_URL environment variable
- All alert roles route to Mattermost notifications channel
- **Restic/Backrest**: Backup status notifications
- Webhook URL passed as environment variable
- Backrest web UI can be configured to use the webhook
- **Watchtower**: Container update notifications
- Uses Shoutrrr mattermost:// URL format
- Sends notifications when containers are updated
Configuration:
- Webhook URL stored securely in .env file
- All services reference ${MATTERMOST_WEBHOOK_URL} variable
- Watchtower uses specialized Shoutrrr format URL
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Mattermost stack to the docker-compose infrastructure:
- **Mattermost stack** (mattermost.pivoine.art):
- Team collaboration and chat platform
- PostgreSQL backend for message persistence
- Email notifications via IONOS SMTP
- Support for channels, direct messages, and integrations
- Mobile and desktop app support
- Full Traefik integration with SSL termination
Infrastructure updates:
- Updated PostgreSQL init script to create mattermost database
- Added environment variables to arty.yml for Mattermost configuration
- Updated compose.yaml include list
- Configured email settings for notifications and invitations
This will replace Gotify as the primary notification and messaging platform.
All services integrated with Traefik for SSL termination and include
Watchtower auto-update labels.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Netdata container is Debian-based, not Alpine. Updated package
manager from apk to apt-get for installing msmtp packages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created custom Dockerfile for Netdata container that includes msmtp
and msmtp-mta packages for sending email notifications.
Changes:
- Added netdata/Dockerfile extending netdata/netdata:latest
- Installed msmtp, msmtp-mta, and ca-certificates via apk
- Set proper permissions (600) for msmtprc config file
- Updated compose.yaml to build from custom Dockerfile
This enables Netdata to send health alarm notifications via email
using the IONOS SMTP configuration in msmtprc.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive email configuration to enable notifications for
password resets, user invitations, system alerts, and backup failures.
**Services configured:**
- **Vaultwarden** (vault/compose.yaml):
- SMTP settings for password resets, 2FA, emergency access emails
- Uses IONOS SMTP with force_tls security
- Sender: hi@pivoine.art
- **Linkwarden** (links/compose.yaml):
- Email server configuration for user invitations
- Password reset functionality via email
- Uses smtp:// connection string format
- **n8n** (n8n/compose.yaml):
- SMTP mode enabled for workflow notifications
- User invitation emails
- Password reset support
- SSL-secured connection
- **Netdata** (netdata/compose.yaml, health_alarm_notify.conf, msmtprc):
- Health alarm notifications via email
- MSMTP configuration for sending alerts
- Notifications sent to valknar@pivoine.art
- Alerts for system issues, resource exhaustion, service failures
**Common SMTP settings** (from .env):
- Provider: IONOS (smtp.ionos.de:465)
- From address: hi@pivoine.art
- Transport: SMTP with TLS/SSL
- Admin email: valknar@pivoine.art
**Backrest notifications:**
- Configured via web UI at restic.pivoine.art
- Supports webhooks to Gotify for push notifications
- Email notifications can be added through UI settings
All services now have proper email notification capabilities for
improved monitoring, user management, and security features.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed from mounting entire go.d directory to mounting specific
config files (postgres.conf, filecheck.conf) to avoid conflicts
with Netdata's initialization script which needs to write to the
go.d directory during startup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added HTTP Basic Authentication to secure the Netdata monitoring dashboard:
- Added basicauth middleware using shared AUTH_USERS credentials
- Protects sensitive infrastructure metrics from unauthorized access
- Uses same credentials as Scrapy and other protected services
- Maintains SSL/TLS encryption via Traefik
Security improvements:
- Dashboard now requires username/password
- Prevents public access to server metrics
- Infrastructure monitoring data protected
- Follows security best practices from Netdata documentation
Access requires credentials stored in AUTH_USERS environment variable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Netdata real-time monitoring system at netdata.pivoine.art:
- Real-time infrastructure and container monitoring
- Auto-discovers all Docker containers
- Tracks CPU, memory, disk, network usage per service
- Low overhead monitoring (~1-3% CPU)
- Self-hosted with web dashboard on port 19999
Configuration:
- Created netdata/compose.yaml with full Traefik integration
- Added to main compose.yaml include list
- Added environment variables to arty.yml
- Mounted Docker socket for container metrics
- Mounted system directories for host metrics (/proc, /sys, /var/log)
- Three persistent volumes: config, lib, cache
- Required capabilities: SYS_PTRACE, SYS_ADMIN for system monitoring
- Watchtower enabled for automatic updates
Benefits for infrastructure:
- Monitor 20+ running services in real-time
- Track PostgreSQL, Redis, Traefik performance
- Watch backup processes (Backrest/Restic)
- Monitor Jellyfin transcoding load
- Alert on resource issues before they become critical
- Historical data for capacity planning
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Excalidraw collaborative drawing tool to the Kit toolkit at draw.kit.pivoine.art:
- Virtual whiteboard for sketching hand-drawn diagrams
- Infinite canvas with collaborative features
- Image: excalidraw/excalidraw:latest
- Exposed on port 80 via Traefik with SSL
Configuration:
- Added draw service to kit/compose.yaml
- Added KIT_DRAW_IMAGE and KIT_DRAW_TRAEFIK_HOST to arty.yml
- Health check disabled to prevent false negatives
- Follows same pattern as other Kit tools
- Watchtower enabled for automatic updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>