diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..51fb21d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +## 1.0.0 - 2026-01-15 + +- Initial Cloudron package release +- Based on mautrix-signal v0.2512.0 +- PostgreSQL database support +- Automatic configuration for Cloudron environment +- End-to-bridge encryption support +- Cleanup on logout functionality +- Health check endpoint diff --git a/CloudronManifest.json b/CloudronManifest.json new file mode 100644 index 0000000..763cb06 --- /dev/null +++ b/CloudronManifest.json @@ -0,0 +1,32 @@ +{ + "version": "1.0.0", + "upstreamVersion": "0.2512.0", + "id": "dev.maunium.signal.cloudronapp", + "title": "Matrix Signal Bridge", + "author": "Tulir Asokan ", + "description": "file://DESCRIPTION.md", + "tagline": "Bridge between Matrix and Signal", + "healthCheckPath": "/health", + "httpPort": 29328, + "icon": "logo.png", + "addons": { + "localstorage": {}, + "postgresql": {}, + "tls": {} + }, + "manifestVersion": 2, + "website": "https://docs.mau.fi/bridges/go/signal/index.html", + "contactEmail": "support@cloudron.io", + "tags": [ + "matrix", + "signal", + "chat", + "bridge", + "communication" + ], + "minBoxVersion": "7.1.0", + "postInstallMessage": "Mautrix-Signal bridge is installed!\n\nPlease note you will need to:\n1. Configure your homeserver by setting up the registration\n2. Configure the bridge in the data directory\n3. Link your Signal account using QR code or phone number\n\nVisit https://docs.mau.fi/bridges/go/signal/index.html for detailed instructions.", + "changelog": "file://CHANGELOG.md", + "documentationUrl": "https://docs.mau.fi/bridges/go/signal/index.html", + "forumUrl": "https://matrix.to/#/#signal:maunium.net" +} diff --git a/DESCRIPTION.md b/DESCRIPTION.md new file mode 100644 index 0000000..679ade5 --- /dev/null +++ b/DESCRIPTION.md @@ -0,0 +1,24 @@ +# Matrix Signal Bridge + +A Matrix-Signal puppeting bridge that allows you to use Signal Messenger through Matrix. + +## Features + +- **Two-way messaging**: Send and receive messages between Matrix and Signal +- **Media support**: Share images, videos, documents, and other files +- **Group chats**: Bridge Signal groups to Matrix rooms +- **Reactions**: React to messages across platforms +- **Read receipts**: Sync read status between Matrix and Signal +- **Typing indicators**: See when someone is typing +- **End-to-bridge encryption**: Optional encryption for messages between Matrix and the bridge + +## Setup + +After installation: + +1. Copy the registration file from `/app/data/registration.yaml` to your Matrix homeserver +2. Add the registration to your homeserver configuration and restart it +3. Start a chat with `@signalbot:yourdomain.com` in Matrix +4. Follow the authentication instructions to link your Signal account + +For detailed setup instructions, visit the [official documentation](https://docs.mau.fi/bridges/go/signal/index.html). diff --git a/Dockerfile.cloudron b/Dockerfile.cloudron new file mode 100644 index 0000000..51e05f5 --- /dev/null +++ b/Dockerfile.cloudron @@ -0,0 +1,44 @@ +FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c6637eaf4a41ec4e596c + +# Install dependencies +RUN apt-get update && apt-get install -y \ + curl \ + ca-certificates \ + netcat-openbsd \ + bash \ + jq \ + yq \ + git \ + build-essential \ + libolm-dev \ + gosu \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Go +ENV GO_VERSION=1.24.0 +RUN curl -LO https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz \ + && rm go${GO_VERSION}.linux-amd64.tar.gz +ENV PATH="/usr/local/go/bin:$PATH" + +# Create app directories +RUN mkdir -p /app/code /app/pkg /app/data +WORKDIR /app/code + +# Download and build mautrix-signal +RUN git clone --branch v0.2512.0 https://github.com/mautrix/signal.git . \ + && go build -o /app/pkg/mautrix-signal ./cmd/mautrix-signal + +# Copy startup script +COPY start.sh /app/pkg/ + +# Set volumes and environment +VOLUME /app/data +ENV UID=1337 GID=1337 + +# Add health check endpoint - check if the appservice port is responding +HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \ + CMD nc -z localhost 29328 || exit 1 + +CMD ["/app/pkg/start.sh"] diff --git a/README.md b/README.md index e6e318c..295fb80 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,95 @@ -# mautrix-signal-cloudron +# Mautrix-Signal Bridge for Cloudron +This is a Cloudron package for the [mautrix-signal](https://github.com/mautrix/signal) Matrix bridge. + +## Features + +- Bridge between Matrix and Signal Messenger +- Two-way messaging with media support +- Group chat support +- End-to-bridge encryption +- Automatic Cloudron integration + +## Building + +Build the package using the Cloudron build service: + +```bash +cloudron build --set-build-service builder.docker.due.ren \ + --build-service-token e3265de06b1d0e7bb38400539012a8433a74c2c96a17955e \ + --set-repository andreasdueren/mautrix-signal \ + --tag 1.0.0 +``` + +## Installing + +Install on your Cloudron: + +```bash +cloudron install --location signal.matrix.due.ren \ + --image andreasdueren/mautrix-signal:1.0.0 +``` + +## Setup + +After installation: + +1. Access the app data directory to get the registration file: + ```bash + cloudron exec --app signal.matrix.due.ren + cat /app/data/registration.yaml + ``` + +2. Copy the registration file content to your Matrix homeserver's configuration directory + +3. Add the registration to your homeserver configuration (e.g., in Synapse's `homeserver.yaml`): + ```yaml + app_service_config_files: + - /path/to/signal-registration.yaml + ``` + +4. Restart your Matrix homeserver + +5. Start a chat with `@signalbot:due.ren` in your Matrix client + +6. Follow the authentication instructions to link your Signal account + +## Viewing Logs + +To view the application logs: + +```bash +cloudron logs --app signal.matrix.due.ren -f +``` + +## Configuration + +The bridge configuration is located at `/app/data/config.yaml` inside the app. You can edit it by: + +```bash +cloudron exec --app signal.matrix.due.ren +nano /app/data/config.yaml +``` + +After making changes, restart the app from the Cloudron dashboard. + +## Troubleshooting + +### Bridge not connecting to homeserver + +Check that: +- The registration file is correctly configured in your homeserver +- The homeserver has been restarted after adding the registration +- The app is running (check logs) + +### Authentication issues + +Make sure you're messaging `@signalbot:due.ren` (replace `due.ren` with your actual base domain). + +## Documentation + +For more information, visit the [official mautrix-signal documentation](https://docs.mau.fi/bridges/go/signal/index.html). + +## License + +This Cloudron package is licensed under the same terms as mautrix-signal (AGPL-3.0). diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..d92688e Binary files /dev/null and b/logo.png differ diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..8eeb726 --- /dev/null +++ b/start.sh @@ -0,0 +1,255 @@ +#!/bin/bash + +set -eu + +echo "=> Setting up mautrix-signal 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" + +# Try to generate config from built-in template +if [ ! -f "$CONFIG_PATH" ]; then + echo "=> Attempting to generate configuration using mautrix-signal" + # Run as cloudron user to avoid permission issues and change to data directory + cd /app/data + gosu cloudron:cloudron /app/pkg/mautrix-signal -e -c "$CONFIG_PATH" + + # Configure basic settings first before generating registration + if [ -f "$CONFIG_PATH" ]; then + echo "=> Applying basic Cloudron configuration to generated config" + + # Configure for Cloudron environment + if [ -n "${CLOUDRON_POSTGRESQL_URL:-}" ]; then + echo "=> Configuring PostgreSQL database: $CLOUDRON_POSTGRESQL_URL" + # Add SSL mode disable to Cloudron PostgreSQL URL if not already present + if [[ "$CLOUDRON_POSTGRESQL_URL" == *"sslmode="* ]]; then + DB_URL="$CLOUDRON_POSTGRESQL_URL" + else + DB_URL="$CLOUDRON_POSTGRESQL_URL?sslmode=disable" + fi + yq -i -y '.database.uri = "'"$DB_URL"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure database" + fi + + if [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then + echo "=> Configuring homeserver and appservice settings for domain: $CLOUDRON_APP_DOMAIN" + # Extract base domain (e.g., signal.matrix.due.ren -> due.ren) + BASE_DOMAIN=$(echo "$CLOUDRON_APP_DOMAIN" | rev | cut -d. -f1-2 | rev) + echo "=> Base domain extracted: $BASE_DOMAIN" + + # Update homeserver configuration + yq -i -y '.homeserver.address = "https://matrix.'"$BASE_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure homeserver address" + yq -i -y '.homeserver.domain = "'"$BASE_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure homeserver domain" + + # Update appservice configuration + yq -i -y '.appservice.address = "https://'"$CLOUDRON_APP_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure appservice address" + yq -i -y '.appservice.public_address = "https://'"$CLOUDRON_APP_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure appservice public_address" + yq -i -y '.appservice.hostname = "0.0.0.0"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure appservice hostname" + yq -i -y '.appservice.port = 29328' "$CONFIG_PATH" || echo "=> ERROR: Could not configure appservice port" + yq -i -y '.appservice.bot_username = "signalbot"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure appservice bot_username" + + # Configure permissions for base domain users + yq -i -y '.bridge.permissions."'"$BASE_DOMAIN"'" = "user"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure permissions" + + # Configure cleanup on logout to delete everything + yq -i -y '.bridge.cleanup_on_logout.enabled = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup enabled" + yq -i -y '.bridge.cleanup_on_logout.manual.private = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup manual private" + yq -i -y '.bridge.cleanup_on_logout.manual.relayed = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup manual relayed" + yq -i -y '.bridge.cleanup_on_logout.manual.shared_no_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup manual shared_no_users" + yq -i -y '.bridge.cleanup_on_logout.manual.shared_has_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup manual shared_has_users" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.private = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup bad_credentials private" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.relayed = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup bad_credentials relayed" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.shared_no_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup bad_credentials shared_no_users" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.shared_has_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure cleanup bad_credentials shared_has_users" + + # Configure end-to-bridge encryption with best practices + yq -i -y '.encryption.allow = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption allow" + yq -i -y '.encryption.default = false' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption default" + yq -i -y '.encryption.require = false' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption require" + yq -i -y '.encryption.appservice = false' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption appservice" + yq -i -y '.encryption.plaintext_mentions = false' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption plaintext_mentions" + yq -i -y '.encryption.delete_keys.delete_outbound_on_ack = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption delete_outbound_on_ack" + yq -i -y '.encryption.delete_keys.dont_store_outbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption dont_store_outbound" + yq -i -y '.encryption.delete_keys.ratchet_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption ratchet_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_fully_used_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption delete_fully_used_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_prev_on_new_session = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption delete_prev_on_new_session" + yq -i -y '.encryption.delete_keys.delete_on_device_delete = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption delete_on_device_delete" + yq -i -y '.encryption.delete_keys.periodically_delete_expired = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption periodically_delete_expired" + yq -i -y '.encryption.delete_keys.delete_outdated_inbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption delete_outdated_inbound" + yq -i -y '.encryption.verification_levels.receive = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption verification receive" + yq -i -y '.encryption.verification_levels.send = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption verification send" + yq -i -y '.encryption.verification_levels.share = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not configure encryption verification share" + fi + + # Now generate registration with proper config + echo "=> Generating registration file" + gosu cloudron:cloudron /app/pkg/mautrix-signal -g -c "$CONFIG_PATH" -r "$REGISTRATION_PATH" + + # Fix registration file regex patterns to use base domain instead of homeserver domain + if [ -f "$REGISTRATION_PATH" ] && [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then + echo "=> Fixing registration file regex patterns for domain: $BASE_DOMAIN" + # Fix user regex patterns to use base domain instead of matrix subdomain + yq -i -y '.namespaces.users[0].regex = "^@signalbot:'"$BASE_DOMAIN"'$"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix signalbot regex" + yq -i -y '.namespaces.users[1].regex = "^@signal_.+:'"$BASE_DOMAIN"'$"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix signal_.+ regex" + yq -i -y '.sender_localpart = "signalbot"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix sender_localpart" + fi + + chown cloudron:cloudron "$CONFIG_PATH" "$REGISTRATION_PATH" 2>/dev/null || true + echo "=> Configuration applied successfully" + fi + + if [ ! -f "$CONFIG_PATH" ]; then + echo "=> ERROR: Config generation failed and no config file was created" + echo "=> Will try to start without config to see error messages" + fi +else + echo "=> Using existing configuration" + # Fix configuration in existing config if needed + if [ -f "$CONFIG_PATH" ]; then + echo "=> Config file exists, applying fixes..." + # Always fix configuration on every start to ensure proper settings + echo "=> Applying configuration fixes" + + # Fix database configuration if needed + if [ -n "${CLOUDRON_POSTGRESQL_URL:-}" ]; then + # Add SSL mode disable to Cloudron PostgreSQL URL if not already present + if [[ "$CLOUDRON_POSTGRESQL_URL" == *"sslmode="* ]]; then + DB_URL="$CLOUDRON_POSTGRESQL_URL" + else + DB_URL="$CLOUDRON_POSTGRESQL_URL?sslmode=disable" + fi + CURRENT_DB_URI=$(yq -r '.database.uri' "$CONFIG_PATH" 2>/dev/null || echo "") + if [ "$CURRENT_DB_URI" != "$DB_URL" ]; then + echo "=> Updating database configuration" + yq -i -y '.database.uri = "'"$DB_URL"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not update database" + fi + fi + + # Fix homeserver configuration if needed + if [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then + # Extract base domain (e.g., signal.matrix.due.ren -> due.ren) + BASE_DOMAIN=$(echo "$CLOUDRON_APP_DOMAIN" | rev | cut -d. -f1-2 | rev) + CURRENT_DOMAIN=$(yq -r '.homeserver.domain' "$CONFIG_PATH" 2>/dev/null || echo "") + if [ "$CURRENT_DOMAIN" != "$BASE_DOMAIN" ]; then + echo "=> Updating homeserver configuration" + echo "=> Setting homeserver.address to: https://matrix.$BASE_DOMAIN" + echo "=> Setting homeserver.domain to: $BASE_DOMAIN" + echo "=> Setting appservice.address to: https://$CLOUDRON_APP_DOMAIN" + yq -i -y '.homeserver.address = "https://matrix.'"$BASE_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not update homeserver address" + yq -i -y '.homeserver.domain = "'"$BASE_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not update homeserver domain" + yq -i -y '.appservice.address = "https://'"$CLOUDRON_APP_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not update appservice address" + yq -i -y '.appservice.public_address = "https://'"$CLOUDRON_APP_DOMAIN"'"' "$CONFIG_PATH" || echo "=> ERROR: Could not update appservice public_address" + yq -i -y '.appservice.hostname = "0.0.0.0"' "$CONFIG_PATH" || echo "=> ERROR: Could not update appservice hostname" + yq -i -y '.appservice.port = 29328' "$CONFIG_PATH" || echo "=> ERROR: Could not update appservice port" + yq -i -y '.appservice.bot_username = "signalbot"' "$CONFIG_PATH" || echo "=> ERROR: Could not update appservice bot_username" + + # Configure permissions for base domain users + yq -i -y '.bridge.permissions."'"$BASE_DOMAIN"'" = "user"' "$CONFIG_PATH" || echo "=> ERROR: Could not update permissions" + + # Configure cleanup on logout to delete everything + yq -i -y '.bridge.cleanup_on_logout.enabled = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup enabled" + yq -i -y '.bridge.cleanup_on_logout.manual.private = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup manual private" + yq -i -y '.bridge.cleanup_on_logout.manual.relayed = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup manual relayed" + yq -i -y '.bridge.cleanup_on_logout.manual.shared_no_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup manual shared_no_users" + yq -i -y '.bridge.cleanup_on_logout.manual.shared_has_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup manual shared_has_users" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.private = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup bad_credentials private" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.relayed = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup bad_credentials relayed" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.shared_no_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup bad_credentials shared_no_users" + yq -i -y '.bridge.cleanup_on_logout.bad_credentials.shared_has_users = "delete"' "$CONFIG_PATH" || echo "=> ERROR: Could not update cleanup bad_credentials shared_has_users" + + # Configure end-to-bridge encryption with best practices + yq -i -y '.encryption.allow = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption allow" + yq -i -y '.encryption.default = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption default" + yq -i -y '.encryption.require = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption require" + yq -i -y '.encryption.appservice = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption appservice" + yq -i -y '.encryption.plaintext_mentions = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption plaintext_mentions" + yq -i -y '.encryption.delete_keys.delete_outbound_on_ack = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_outbound_on_ack" + yq -i -y '.encryption.delete_keys.dont_store_outbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption dont_store_outbound" + yq -i -y '.encryption.delete_keys.ratchet_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption ratchet_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_fully_used_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_fully_used_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_prev_on_new_session = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_prev_on_new_session" + yq -i -y '.encryption.delete_keys.delete_on_device_delete = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_on_device_delete" + yq -i -y '.encryption.delete_keys.periodically_delete_expired = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption periodically_delete_expired" + yq -i -y '.encryption.delete_keys.delete_outdated_inbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_outdated_inbound" + yq -i -y '.encryption.verification_levels.receive = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification receive" + yq -i -y '.encryption.verification_levels.send = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification send" + yq -i -y '.encryption.verification_levels.share = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification share" + + # Verify the changes were applied + echo "=> Verifying configuration changes:" + echo "=> Current homeserver.address: $(yq -r '.homeserver.address' "$CONFIG_PATH")" + echo "=> Current homeserver.domain: $(yq -r '.homeserver.domain' "$CONFIG_PATH")" + fi + fi + + # Fix logging configuration + yq -i -y '.logging.writers[1].filename = "/app/data/mautrix-signal.log"' "$CONFIG_PATH" 2>/dev/null || true + + # Always apply encryption settings (regardless of domain changes) + echo "=> Applying encryption configuration" + yq -i -y '.encryption.allow = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption allow" + yq -i -y '.encryption.default = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption default" + yq -i -y '.encryption.require = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption require" + yq -i -y '.encryption.appservice = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption appservice" + yq -i -y '.encryption.plaintext_mentions = false' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption plaintext_mentions" + yq -i -y '.encryption.delete_keys.delete_outbound_on_ack = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_outbound_on_ack" + yq -i -y '.encryption.delete_keys.dont_store_outbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption dont_store_outbound" + yq -i -y '.encryption.delete_keys.ratchet_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption ratchet_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_fully_used_on_decrypt = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_fully_used_on_decrypt" + yq -i -y '.encryption.delete_keys.delete_prev_on_new_session = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_prev_on_new_session" + yq -i -y '.encryption.delete_keys.delete_on_device_delete = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_on_device_delete" + yq -i -y '.encryption.delete_keys.periodically_delete_expired = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption periodically_delete_expired" + yq -i -y '.encryption.delete_keys.delete_outdated_inbound = true' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption delete_outdated_inbound" + yq -i -y '.encryption.verification_levels.receive = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification receive" + yq -i -y '.encryption.verification_levels.send = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification send" + yq -i -y '.encryption.verification_levels.share = "cross-signed-tofu"' "$CONFIG_PATH" || echo "=> ERROR: Could not update encryption verification share" + + # Update registration file with correct URL and fix regex patterns + if [ -f "$REGISTRATION_PATH" ] && [ -n "${CLOUDRON_APP_DOMAIN:-}" ]; then + yq -i -y '.url = "https://'"$CLOUDRON_APP_DOMAIN"'"' "$REGISTRATION_PATH" 2>/dev/null || true + # Fix user regex patterns to use base domain instead of matrix subdomain + yq -i -y '.namespaces.users[0].regex = "^@signalbot:'"$BASE_DOMAIN"'$"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix signalbot regex" + yq -i -y '.namespaces.users[1].regex = "^@signal_.+:'"$BASE_DOMAIN"'$"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix signal_.+ regex" + yq -i -y '.sender_localpart = "signalbot"' "$REGISTRATION_PATH" || echo "=> ERROR: Could not fix sender_localpart" + fi + + # Let the bridge handle token generation automatically - remove any placeholder tokens + if [ -f "$REGISTRATION_PATH" ]; then + echo "=> Registration file generated, letting bridge handle token management" + fi + fi + echo "=> Configuration fixes completed" +fi + +# Final permission fix before starting +echo "=> Setting final permissions..." +chown -R cloudron:cloudron /app/data +echo "=> Permissions set" + +# Configure TLS if certificates are available +if [ -f "/run/tls/tls.crt" ] && [ -f "/run/tls/tls.key" ]; then + echo "=> Configuring TLS certificates" + yq -i -y '.appservice.tls_cert = "/run/tls/tls.crt"' "$CONFIG_PATH" + yq -i -y '.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-signal bridge" +echo "=> Config path: $CONFIG_PATH" +echo "=> Registration path: $REGISTRATION_PATH" +echo "=> Working directory: $(pwd)" +cd /app/data +echo "=> About to exec bridge binary..." +exec gosu cloudron:cloudron /app/pkg/mautrix-signal -c "$CONFIG_PATH"