#!/bin/bash set -eu echo "=> Setting up mautrix-whatsapp bridge" # Create necessary directories mkdir -p /app/data mkdir -p /app/data/logs # For Cloudron, we run as the cloudron user UID=$(id -u cloudron) GID=$(id -g cloudron) # Set ownership early to avoid permission issues chown -R cloudron:cloudron /app/data # Configuration file paths CONFIG_PATH="/app/data/config.yaml" REGISTRATION_PATH="/app/data/registration.yaml" BACKUP_PATH="/app/data/config.yaml.bak" # Create example config from built-in template if [ ! -f "$CONFIG_PATH" ]; then echo "=> Generating example configuration" # Generate config as root first, then fix permissions /app/pkg/mautrix-whatsapp -g -c "$CONFIG_PATH" -r "$REGISTRATION_PATH" || { echo "=> Config generation failed, creating minimal config" # Generate secure random tokens AS_TOKEN=$(openssl rand -hex 32) HS_TOKEN=$(openssl rand -hex 32) cat > "$CONFIG_PATH" << EOF homeserver: address: https://matrix.example.com domain: example.com appservice: address: https://example.com hostname: 0.0.0.0 port: 29318 as_token: $AS_TOKEN hs_token: $HS_TOKEN database: type: postgres uri: postgres://user:pass@localhost/db bridge: username_template: whatsapp_{{.}} displayname_template: "{{if .BusinessName}}{{.BusinessName}}{{else}}{{.PushName}}{{end}} (WA)" logging: handlers: console: format: json file: filename: /app/data/mautrix-whatsapp.log level: info EOF cat > "$REGISTRATION_PATH" << EOF id: whatsapp url: https://example.com as_token: $AS_TOKEN hs_token: $HS_TOKEN rate_limited: false sender_localpart: whatsappbot namespaces: users: - exclusive: true regex: '@whatsapp_.*:.*' aliases: - exclusive: true regex: '#whatsapp_.*:.*' EOF } # Configure for Cloudron environment if [ -n "${CLOUDRON_POSTGRESQL_URL:-}" ]; then echo "=> Configuring PostgreSQL database" yq -i ".appservice.database.uri = \"$CLOUDRON_POSTGRESQL_URL\"" "$CONFIG_PATH" fi if [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then echo "=> Configuring homeserver and appservice settings" # For whatsapp.matrix.as.ci -> matrix.as.ci and domain as.ci BASE_DOMAIN=$(echo "$CLOUDRON_APP_DOMAIN" | cut -d. -f2-) # Update homeserver configuration yq -i ".homeserver.address = \"https://matrix.$BASE_DOMAIN\"" "$CONFIG_PATH" yq -i ".homeserver.domain = \"$BASE_DOMAIN\"" "$CONFIG_PATH" # Update appservice configuration yq -i ".appservice.address = \"https://$CLOUDRON_APP_DOMAIN\"" "$CONFIG_PATH" yq -i ".appservice.hostname = \"0.0.0.0\"" "$CONFIG_PATH" yq -i ".appservice.port = 29318" "$CONFIG_PATH" fi # Set log file path yq -i ".logging.handlers.file.filename = \"/app/data/mautrix-whatsapp.log\"" "$CONFIG_PATH" chown cloudron:cloudron "$CONFIG_PATH" "$REGISTRATION_PATH" echo "=> Initial configuration complete" echo "=> IMPORTANT: Please review $CONFIG_PATH and configure your Matrix homeserver settings" echo "=> You will need to:" echo " 1. Copy $REGISTRATION_PATH to your Matrix homeserver" echo " 2. Update your homeserver configuration to include the registration file" echo " 3. Restart your Matrix homeserver" echo " 4. Restart this bridge app" echo " 5. Authenticate with WhatsApp using QR code scanning" else echo "=> Using existing configuration" # Fix configuration in existing config if needed if [ -f "$CONFIG_PATH" ]; then # Fix logging configuration if grep -q "filename.*logs/" "$CONFIG_PATH" 2>/dev/null || ! grep -q "/app/data/" "$CONFIG_PATH" 2>/dev/null; then echo "=> Fixing logging configuration in existing config" # Ensure logging goes to the writable /app/data directory yq -i ".logging.handlers.file.filename = \"/app/data/mautrix-whatsapp.log\"" "$CONFIG_PATH" 2>/dev/null || true # Add console logging as well for debugging yq -i ".logging.handlers.console.format = \"json\"" "$CONFIG_PATH" 2>/dev/null || true yq -i ".logging.level = \"info\"" "$CONFIG_PATH" 2>/dev/null || true fi # Fix homeserver domain configuration and tokens if [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then BASE_DOMAIN=$(echo "$CLOUDRON_APP_DOMAIN" | cut -d. -f2-) CURRENT_DOMAIN=$(yq -r ".homeserver.domain // empty" "$CONFIG_PATH" 2>/dev/null) if [ "$CURRENT_DOMAIN" != "$BASE_DOMAIN" ] || [ -z "$CURRENT_DOMAIN" ]; then echo "=> Fixing homeserver domain configuration" yq -i ".homeserver.address = \"https://matrix.$BASE_DOMAIN\"" "$CONFIG_PATH" yq -i ".homeserver.domain = \"$BASE_DOMAIN\"" "$CONFIG_PATH" yq -i ".appservice.address = \"https://$CLOUDRON_APP_DOMAIN\"" "$CONFIG_PATH" fi # Update registration file with correct URL if [ -f "$REGISTRATION_PATH" ]; then yq -i ".url = \"https://$CLOUDRON_APP_DOMAIN\"" "$REGISTRATION_PATH" 2>/dev/null || true fi fi # Ensure tokens exist if [ -f "$CONFIG_PATH" ] && [ -f "$REGISTRATION_PATH" ]; then AS_TOKEN=$(yq -r ".as_token // empty" "$REGISTRATION_PATH" 2>/dev/null) HS_TOKEN=$(yq -r ".hs_token // empty" "$REGISTRATION_PATH" 2>/dev/null) # Generate tokens if missing if [ -z "$AS_TOKEN" ] || [ "$AS_TOKEN" = "generated_token" ]; then AS_TOKEN=$(openssl rand -hex 32) echo "=> Generating new as_token" yq -i ".as_token = \"$AS_TOKEN\"" "$REGISTRATION_PATH" 2>/dev/null || true yq -i ".appservice.as_token = \"$AS_TOKEN\"" "$CONFIG_PATH" 2>/dev/null || true fi if [ -z "$HS_TOKEN" ] || [ "$HS_TOKEN" = "generated_token" ]; then HS_TOKEN=$(openssl rand -hex 32) echo "=> Generating new hs_token" yq -i ".hs_token = \"$HS_TOKEN\"" "$REGISTRATION_PATH" 2>/dev/null || true yq -i ".appservice.hs_token = \"$HS_TOKEN\"" "$CONFIG_PATH" 2>/dev/null || true fi fi fi fi # Final permission fix before starting chown -R cloudron:cloudron /app/data # Configure TLS if certificates are available if [ -f "/run/tls/tls.crt" ] && [ -f "/run/tls/tls.key" ]; then echo "=> Configuring TLS certificates" yq -i ".appservice.tls_cert = \"/run/tls/tls.crt\"" "$CONFIG_PATH" yq -i ".appservice.tls_key = \"/run/tls/tls.key\"" "$CONFIG_PATH" fi # Start the bridge from the data directory to ensure relative paths work echo "=> Starting mautrix-whatsapp bridge" cd /app/data exec gosu cloudron:cloudron /app/pkg/mautrix-whatsapp -c "$CONFIG_PATH"