mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-06-25 09:23:16 +03:00
Add matrix-rustpush-bridge (iMessage)
Add the matrix-rustpush-bridge role, a Matrix <-> iMessage bridge built on the mautrix-go bridgev2 framework using RustPush (OpenBubbles backend). Unlike the existing mautrix-imessage/wsproxy bridge, it talks directly to Apple's push notification service, so it needs neither a running Mac nor a wsproxy on the homeserver. Each user supplies a hardware key extracted from a Mac through the bridge bot's login flow. The bridge uses its own bot username and puppet namespace (rustpushbot, rustpush_*) so it does not collide with the wsproxy iMessage bridge. This bridge is in early development and may have stability issues.
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
{#
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#}
|
||||
|
||||
# ── Stage 1: builder ─────────────────────────────────────────────────────────
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
cmake protobuf-compiler build-essential pkg-config \
|
||||
git curl ca-certificates \
|
||||
libolm-dev libclang-dev libssl-dev libunicorn-dev libheif-dev zlib1g-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Rust — install to default ~/.cargo so the Makefile's $(HOME)/.cargo/bin path resolves
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||
| sh -s -- -y --default-toolchain stable
|
||||
ENV PATH=/root/.cargo/bin:$PATH
|
||||
|
||||
# Go — arch-aware, fetches latest stable with fallback
|
||||
ARG TARGETARCH
|
||||
RUN set -e; \
|
||||
GOARCH="${TARGETARCH:-amd64}"; \
|
||||
GO_VERSION=$(curl -fsSL 'https://go.dev/dl/?mode=json' \
|
||||
| grep -o '"version":"go[0-9.]*"' | head -1 \
|
||||
| sed 's/"version":"//;s/"//'); \
|
||||
: "${GO_VERSION:=go1.25.0}"; \
|
||||
curl -fsSL "https://go.dev/dl/${GO_VERSION}.linux-${GOARCH}.tar.gz" \
|
||||
| tar -C /usr/local -xz
|
||||
ENV PATH=/usr/local/go/bin:$PATH \
|
||||
GOTOOLCHAIN=local
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# ── Rust build layers ─────────────────────────────────────────────────────────
|
||||
# Copy files that determine whether the clone+patch layer is valid.
|
||||
# Changing the SHA pin, Makefile, or open-absinthe overlay invalidates this layer.
|
||||
COPY third_party/rustpush-upstream.sha third_party/
|
||||
COPY rustpush/ rustpush/
|
||||
COPY Makefile .
|
||||
|
||||
# Clone upstream rustpush at the pinned SHA, apply all patches, overlay open-absinthe.
|
||||
RUN make ensure-rustpush-source
|
||||
|
||||
# Copy Rust crate sources. Changing these invalidates only the Rust build layer,
|
||||
# not the clone layer above.
|
||||
COPY pkg/rustpushgo/ pkg/rustpushgo/
|
||||
COPY nac-validation/ nac-validation/
|
||||
|
||||
# Build the Rust static library (~3 min; cached when Rust source is unchanged).
|
||||
# hardware-key enables the unicorn-based x86 NAC emulator required on Linux
|
||||
# (both amd64 and arm64 — unicorn supports cross-arch x86 emulation).
|
||||
RUN cd pkg/rustpushgo && \
|
||||
cargo build --release --features hardware-key && \
|
||||
cp target/release/librustpushgo.a /build/librustpushgo.a
|
||||
|
||||
# ── Go build layers ───────────────────────────────────────────────────────────
|
||||
# Download modules first so this layer is cached by go.mod/go.sum.
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# Copy Go source.
|
||||
COPY cmd/ cmd/
|
||||
COPY pkg/connector/ pkg/connector/
|
||||
COPY imessage/ imessage/
|
||||
COPY ipc/ ipc/
|
||||
|
||||
# Build the bridge binary.
|
||||
ARG BUILD_VERSION=dev
|
||||
ARG BUILD_COMMIT=unknown
|
||||
RUN BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) && \
|
||||
CGO_LDFLAGS="-L/build" \
|
||||
go build \
|
||||
-ldflags "-X main.Tag=${BUILD_VERSION} -X main.Commit=${BUILD_COMMIT} -X main.BuildTime=${BUILD_TIME}" \
|
||||
-o /build/matrix-rustpush \
|
||||
./cmd/matrix-rustpush/
|
||||
|
||||
# ── Stage 2: runtime ─────────────────────────────────────────────────────────
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Runtime shared libraries the bridge binary needs at startup.
|
||||
# libunicorn2 — unicorn-engine x86 NAC emulator (hardware-key feature)
|
||||
# libheif1 — HEIC/HEIF conversion (linked at compile time even when disabled)
|
||||
# libolm3 — Matrix OLM encryption (mautrix bridgev2 framework)
|
||||
# libssl3 — OpenSSL (rustpush openssl crate dynamic link)
|
||||
# ffmpeg — video transcoding
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libunicorn2 libheif1 libolm3 libssl3 ffmpeg \
|
||||
ca-certificates openssl curl \
|
||||
&& curl -fsSL 'https://www.apple.com/appleca/AppleIncRootCertificate.cer' \
|
||||
-o /tmp/AppleRootCA.cer \
|
||||
&& openssl x509 -inform DER -in /tmp/AppleRootCA.cer \
|
||||
-out /usr/local/share/ca-certificates/AppleRootCA.crt \
|
||||
&& update-ca-certificates \
|
||||
&& rm /tmp/AppleRootCA.cer \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /build/matrix-rustpush /usr/local/bin/matrix-rustpush
|
||||
|
||||
WORKDIR /data
|
||||
VOLUME /data
|
||||
EXPOSE 29332
|
||||
|
||||
ENTRYPOINT ["matrix-rustpush", "-c", "/data/config.yaml"]
|
||||
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,209 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
# Network-specific config options (iMessage via RustPush)
|
||||
network:
|
||||
# Displayname template for iMessage contacts.
|
||||
# Available variables:
|
||||
# .FirstName, .LastName, .Nickname
|
||||
# .Phone, .Email, .ID
|
||||
displayname_template: {{ matrix_rustpush_bridge_network_displayname_template | to_json }}
|
||||
|
||||
# How many days back to look for chats during initial sync.
|
||||
# Default is 365 (1 year). Set to 0 to use the default.
|
||||
initial_sync_days: {{ matrix_rustpush_bridge_initial_sync_days | to_json }}
|
||||
|
||||
# Set to false to disable CloudKit backfill globally
|
||||
cloudkit_backfill: {{ matrix_rustpush_bridge_cloudkit_backfill | to_json }}
|
||||
backfill_source: cloudkit
|
||||
|
||||
# Enable or disable video transcoding
|
||||
video_transcoding: {{ matrix_rustpush_bridge_video_transcoding | to_json }}
|
||||
|
||||
# Enable or disable HEIC conversion
|
||||
heic_conversion: {{ matrix_rustpush_bridge_heic_conversion | to_json }}
|
||||
heic_jpeg_quality: 95
|
||||
|
||||
# Set to true to disable Facetime support globally
|
||||
disable_facetime: {{ matrix_rustpush_bridge_disable_facetime | to_json }}
|
||||
|
||||
# Set to false to disable Statuskit support globally
|
||||
statuskit_notifications: {{ matrix_rustpush_bridge_statuskit_notifications | to_json }}
|
||||
statuskit_share_on_startup: {{ matrix_rustpush_bridge_statuskit_share_on_startup | to_json }}
|
||||
|
||||
# Config options that affect the central bridge module.
|
||||
bridge:
|
||||
# The prefix for commands. Only required in non-management rooms.
|
||||
command_prefix: {{ matrix_rustpush_bridge_bridge_command_prefix | to_json }}
|
||||
# Should the bridge create a space for each login containing the rooms that account is in?
|
||||
personal_filtering_spaces: true
|
||||
# Whether the bridge should set names and avatars explicitly for DM portals.
|
||||
private_chat_portal_meta: true
|
||||
# Should events be handled asynchronously within portal rooms?
|
||||
async_events: false
|
||||
# Should every user have their own portals rather than sharing them?
|
||||
split_portals: false
|
||||
# Should the bridge resend `m.bridge` events to all portals on startup?
|
||||
resend_bridge_info: false
|
||||
|
||||
# Should leaving Matrix rooms be bridged as leaving groups on the remote network?
|
||||
bridge_matrix_leave: false
|
||||
# Should room tags only be synced when creating the portal?
|
||||
tag_only_on_create: true
|
||||
# List of tags to allow bridging.
|
||||
only_bridge_tags: [m.favourite, m.lowpriority]
|
||||
# Should room mute status only be synced when creating the portal?
|
||||
mute_only_on_create: true
|
||||
|
||||
# What should be done to portal rooms when a user logs out or is logged out?
|
||||
cleanup_on_logout:
|
||||
enabled: false
|
||||
manual:
|
||||
private: nothing
|
||||
relayed: nothing
|
||||
shared_no_users: nothing
|
||||
shared_has_users: nothing
|
||||
bad_credentials:
|
||||
private: nothing
|
||||
relayed: nothing
|
||||
shared_no_users: nothing
|
||||
shared_has_users: nothing
|
||||
|
||||
# Settings for relay mode
|
||||
relay:
|
||||
enabled: false
|
||||
admin_only: true
|
||||
default_relays: []
|
||||
message_formats:
|
||||
m.text: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b>: {{ .Message }}{% endraw %}"
|
||||
m.notice: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b>: {{ .Message }}{% endraw %}"
|
||||
m.emote: "{% raw %}* <b>{{ .Sender.DisambiguatedName }}</b> {{ .Message }}{% endraw %}"
|
||||
m.file: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b> sent a file{{ if .Caption }}: {{ .Caption }}{{ end }}{% endraw %}"
|
||||
m.image: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b> sent an image{{ if .Caption }}: {{ .Caption }}{{ end }}{% endraw %}"
|
||||
m.audio: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b> sent an audio file{{ if .Caption }}: {{ .Caption }}{{ end }}{% endraw %}"
|
||||
m.video: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b> sent a video{{ if .Caption }}: {{ .Caption }}{{ end }}{% endraw %}"
|
||||
m.location: "{% raw %}<b>{{ .Sender.DisambiguatedName }}</b> sent a location{{ if .Caption }}: {{ .Caption }}{{ end }}{% endraw %}"
|
||||
displayname_format: "{% raw %}{{ .DisambiguatedName }}{% endraw %}"
|
||||
|
||||
# Permissions for using the bridge.
|
||||
permissions: {{ matrix_rustpush_bridge_bridge_permissions | to_json }}
|
||||
|
||||
# Config for the bridge's database.
|
||||
database:
|
||||
type: postgres
|
||||
uri: {{ matrix_rustpush_bridge_database_uri | to_json }}
|
||||
max_open_conns: 5
|
||||
max_idle_conns: 1
|
||||
max_conn_idle_time: null
|
||||
max_conn_lifetime: null
|
||||
|
||||
# Homeserver details.
|
||||
homeserver:
|
||||
address: {{ matrix_rustpush_bridge_homeserver_address | to_json }}
|
||||
domain: {{ matrix_rustpush_bridge_homeserver_domain | to_json }}
|
||||
software: standard
|
||||
status_endpoint:
|
||||
message_send_checkpoint_endpoint:
|
||||
async_media: {{ matrix_rustpush_bridge_homeserver_async_media | to_json }}
|
||||
websocket: false
|
||||
ping_interval_seconds: 0
|
||||
|
||||
# Application service host/registration related details.
|
||||
appservice:
|
||||
address: {{ matrix_rustpush_bridge_appservice_address | to_json }}
|
||||
public_address: {{ matrix_rustpush_bridge_appservice_public_address | to_json }}
|
||||
|
||||
hostname: 0.0.0.0
|
||||
port: 8081
|
||||
|
||||
id: rustpush-bridge
|
||||
bot:
|
||||
username: {{ matrix_rustpush_bridge_appservice_bot_username | to_json }}
|
||||
displayname: {{ matrix_rustpush_bridge_appservice_bot_displayname | to_json(ensure_ascii=False) }}
|
||||
avatar: {{ matrix_rustpush_bridge_appservice_bot_avatar | to_json }}
|
||||
|
||||
ephemeral_events: true
|
||||
async_transactions: false
|
||||
|
||||
as_token: {{ matrix_rustpush_bridge_appservice_token | to_json }}
|
||||
hs_token: {{ matrix_rustpush_bridge_homeserver_token | to_json }}
|
||||
|
||||
# Localpart template of MXIDs for remote users.
|
||||
username_template: {{ matrix_rustpush_bridge_appservice_username_template | to_json }}
|
||||
|
||||
# Config options that affect the Matrix connector of the bridge.
|
||||
matrix:
|
||||
message_status_events: false
|
||||
delivery_receipts: false
|
||||
message_error_notices: true
|
||||
sync_direct_chat_list: true
|
||||
federate_rooms: {{ matrix_rustpush_bridge_matrix_federate_rooms | to_json }}
|
||||
upload_file_threshold: 5242880
|
||||
|
||||
# Segment-compatible analytics endpoint for tracking some events.
|
||||
analytics:
|
||||
token: null
|
||||
url: https://api.segment.io/v1/track
|
||||
user_id: null
|
||||
|
||||
# Settings for provisioning API
|
||||
provisioning:
|
||||
prefix: /_matrix/provision
|
||||
shared_secret: {{ matrix_rustpush_bridge_provisioning_shared_secret | to_json }}
|
||||
allow_matrix_auth: true
|
||||
debug_endpoints: false
|
||||
|
||||
# Settings for backfilling messages.
|
||||
backfill:
|
||||
enabled: {{ matrix_rustpush_bridge_backfill_enabled | to_json }}
|
||||
max_initial_messages: {{ matrix_rustpush_bridge_backfill_max_initial_messages | to_json }}
|
||||
max_catchup_messages: {{ matrix_rustpush_bridge_backfill_max_catchup_messages | to_json }}
|
||||
unread_hours_threshold: 720
|
||||
threads:
|
||||
max_initial_messages: 50
|
||||
queue:
|
||||
enabled: false
|
||||
batch_size: 100
|
||||
batch_delay: 20
|
||||
max_batches: -1
|
||||
max_batches_override: {}
|
||||
|
||||
# Settings for enabling double puppeting
|
||||
double_puppet:
|
||||
servers: {}
|
||||
allow_discovery: false
|
||||
secrets: {{ matrix_rustpush_bridge_double_puppet_secrets | to_json }}
|
||||
|
||||
# End-to-bridge encryption support options.
|
||||
encryption:
|
||||
allow: {{ matrix_rustpush_bridge_bridge_encryption_allow | to_json }}
|
||||
default: {{ matrix_rustpush_bridge_bridge_encryption_default | to_json }}
|
||||
require: {{ matrix_rustpush_bridge_bridge_encryption_require | to_json }}
|
||||
appservice: {{ matrix_rustpush_bridge_bridge_encryption_appservice | to_json }}
|
||||
msc4190: {{ matrix_rustpush_bridge_msc4190_enabled | to_json }}
|
||||
self_sign: {{ matrix_rustpush_bridge_self_sign_enabled | to_json }}
|
||||
allow_key_sharing: {{ matrix_rustpush_bridge_bridge_encryption_key_sharing_allow | to_json }}
|
||||
pickle_key: {{ matrix_rustpush_bridge_bridge_encryption_pickle_key | to_json }}
|
||||
delete_keys:
|
||||
delete_outbound_on_ack: false
|
||||
dont_store_outbound: false
|
||||
ratchet_on_decrypt: false
|
||||
delete_fully_used_on_decrypt: false
|
||||
delete_prev_on_new_session: false
|
||||
delete_on_device_delete: false
|
||||
periodically_delete_expired: false
|
||||
delete_outdated_inbound: false
|
||||
verification_levels:
|
||||
receive: unverified
|
||||
send: unverified
|
||||
share: cross-signed-tofu
|
||||
rotation:
|
||||
enable_custom: false
|
||||
milliseconds: 604800000
|
||||
messages: 100
|
||||
disable_device_change_key_rotation: false
|
||||
|
||||
# Logging config.
|
||||
logging:
|
||||
min_level: {{ matrix_rustpush_bridge_logging_level | to_json }}
|
||||
writers:
|
||||
- type: stdout
|
||||
format: pretty-colored
|
||||
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
@@ -0,0 +1,53 @@
|
||||
{#
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#}
|
||||
|
||||
{% if matrix_rustpush_bridge_container_labels_traefik_enabled %}
|
||||
traefik.enable=true
|
||||
|
||||
{% if matrix_rustpush_bridge_container_labels_traefik_docker_network %}
|
||||
traefik.docker.network={{ matrix_rustpush_bridge_container_labels_traefik_docker_network }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.services.matrix-rustpush-bridge-metrics.loadbalancer.server.port=8000
|
||||
|
||||
{% if matrix_rustpush_bridge_container_labels_metrics_enabled %}
|
||||
############################################################
|
||||
# #
|
||||
# Metrics #
|
||||
# #
|
||||
############################################################
|
||||
|
||||
{% if matrix_rustpush_bridge_container_labels_metrics_middleware_basic_auth_enabled %}
|
||||
traefik.http.middlewares.matrix-rustpush-bridge-metrics-basic-auth.basicauth.users={{ matrix_rustpush_bridge_container_labels_metrics_middleware_basic_auth_users }}
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.middlewares=matrix-rustpush-bridge-metrics-basic-auth
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.rule={{ matrix_rustpush_bridge_container_labels_metrics_traefik_rule }}
|
||||
|
||||
{% if matrix_rustpush_bridge_container_labels_metrics_traefik_priority | int > 0 %}
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.priority={{ matrix_rustpush_bridge_container_labels_metrics_traefik_priority }}
|
||||
{% endif %}
|
||||
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.service=matrix-rustpush-bridge-metrics
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.entrypoints={{ matrix_rustpush_bridge_container_labels_metrics_traefik_entrypoints }}
|
||||
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.tls={{ matrix_rustpush_bridge_container_labels_metrics_traefik_tls | to_json }}
|
||||
{% if matrix_rustpush_bridge_container_labels_metrics_traefik_tls %}
|
||||
traefik.http.routers.matrix-rustpush-bridge-metrics.tls.certResolver={{ matrix_rustpush_bridge_container_labels_metrics_traefik_tls_certResolver }}
|
||||
{% endif %}
|
||||
|
||||
############################################################
|
||||
# #
|
||||
# /Metrics #
|
||||
# #
|
||||
############################################################
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
{{ matrix_rustpush_bridge_container_labels_additional_labels }}
|
||||
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#jinja2: lstrip_blocks: True
|
||||
[Unit]
|
||||
Description=Matrix RustPush bridge
|
||||
{% for service in matrix_rustpush_bridge_systemd_required_services_list %}
|
||||
Requires={{ service }}
|
||||
After={{ service }}
|
||||
{% endfor %}
|
||||
{% for service in matrix_rustpush_bridge_systemd_wanted_services_list %}
|
||||
Wants={{ service }}
|
||||
{% endfor %}
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}"
|
||||
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-rustpush-bridge 2>/dev/null || true'
|
||||
ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-rustpush-bridge 2>/dev/null || true'
|
||||
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
|
||||
--rm \
|
||||
--name=matrix-rustpush-bridge \
|
||||
--log-driver=none \
|
||||
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
|
||||
--cap-drop=ALL \
|
||||
--network={{ matrix_rustpush_bridge_container_network }} \
|
||||
--env HOME=/data \
|
||||
{% if matrix_rustpush_bridge_rust_log %} --env RUST_LOG={{ matrix_rustpush_bridge_rust_log }} \
|
||||
{% endif %} --mount type=bind,src={{ matrix_rustpush_bridge_config_path }},dst=/config \
|
||||
--mount type=bind,src={{ matrix_rustpush_bridge_data_path }},dst=/data \
|
||||
--label-file={{ matrix_rustpush_bridge_base_path }}/labels \
|
||||
--entrypoint /usr/local/bin/matrix-rustpush \
|
||||
{% for arg in matrix_rustpush_bridge_container_extra_arguments %}
|
||||
{{ arg }} \
|
||||
{% endfor %}
|
||||
{{ matrix_rustpush_bridge_container_image }} \
|
||||
-c /config/config.yaml -r /config/registration.yaml
|
||||
|
||||
{% for network in matrix_rustpush_bridge_container_additional_networks %}
|
||||
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-rustpush-bridge
|
||||
{% endfor %}
|
||||
|
||||
ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-rustpush-bridge
|
||||
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop -t {{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-rustpush-bridge 2>/dev/null || true'
|
||||
ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-rustpush-bridge 2>/dev/null || true'
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
SyslogIdentifier=matrix-rustpush-bridge
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
SPDX-FileCopyrightText: 2026 MDAD project contributors
|
||||
SPDX-FileCopyrightText: 2026 Jason LaGuidice
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
Reference in New Issue
Block a user