Our Personal Data Server from scratch! tranquil.farm
oauth atproto pds rust postgresql objectstorage fun

fix: signal cli in containers

authored by lewis.moe and committed by tangled.org 18cdb612 2c8568b2

+45 -11
+13 -2
Dockerfile
··· 20 fi && \ 21 cp target/release/tranquil-pds /tmp/tranquil-pds 22 23 - FROM alpine:3.23 24 - RUN apk add --no-cache msmtp ca-certificates && ln -sf /usr/bin/msmtp /usr/sbin/sendmail 25 COPY --from=builder /tmp/tranquil-pds /usr/local/bin/tranquil-pds 26 COPY --from=frontend /app/dist /var/lib/tranquil-pds/frontend 27 COPY migrations /app/migrations 28 WORKDIR /app 29 ENV SERVER_HOST=0.0.0.0 30 ENV SERVER_PORT=3000 31 EXPOSE 3000
··· 20 fi && \ 21 cp target/release/tranquil-pds /tmp/tranquil-pds 22 23 + FROM alpine:3.23 AS signal-cli 24 + RUN apk add --no-cache curl tar 25 + ARG SIGNAL_CLI_VERSION=0.13.24 26 + RUN curl -fsSL "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-native.tar.gz" \ 27 + | tar xz -C /usr/local/bin 28 + 29 + FROM debian:trixie-slim 30 + RUN apt-get update && apt-get install -y --no-install-recommends msmtp ca-certificates \ 31 + && rm -rf /var/lib/apt/lists/* \ 32 + && ln -sf /usr/bin/msmtp /usr/sbin/sendmail 33 + COPY --from=signal-cli /usr/local/bin/signal-cli /usr/local/bin/signal-cli 34 + VOLUME /var/lib/signal-cli 35 COPY --from=builder /tmp/tranquil-pds /usr/local/bin/tranquil-pds 36 COPY --from=frontend /app/dist /var/lib/tranquil-pds/frontend 37 COPY migrations /app/migrations 38 WORKDIR /app 39 + ENV SIGNAL_CLI_CONFIG=/var/lib/signal-cli 40 ENV SERVER_HOST=0.0.0.0 41 ENV SERVER_PORT=3000 42 EXPOSE 3000
+32 -9
crates/tranquil-comms/src/sender.rs
··· 22 23 #[derive(Debug, thiserror::Error)] 24 pub enum SendError { 25 - #[error("Failed to spawn sendmail process: {0}")] 26 - ProcessSpawn(#[from] std::io::Error), 27 - #[error("Sendmail exited with non-zero status: {0}")] 28 - SendmailFailed(String), 29 #[error("Channel not configured: {0:?}")] 30 NotConfigured(CommsChannel), 31 #[error("External service error: {0}")] ··· 160 .stdin(Stdio::piped()) 161 .stdout(Stdio::piped()) 162 .stderr(Stdio::piped()) 163 - .spawn()?; 164 if let Some(mut stdin) = child.stdin.take() { 165 - stdin.write_all(email_content.as_bytes()).await?; 166 } 167 - let output = child.wait_with_output().await?; 168 if !output.status.success() { 169 let stderr = String::from_utf8_lossy(&output.stderr); 170 - return Err(SendError::SendmailFailed(stderr.to_string())); 171 } 172 Ok(()) 173 } ··· 656 retry_delay(attempt).await; 657 continue; 658 } 659 - return Err(SendError::ProcessSpawn(e)); 660 } 661 Err(_) => { 662 if attempt < MAX_RETRIES - 1 {
··· 22 23 #[derive(Debug, thiserror::Error)] 24 pub enum SendError { 25 + #[error("Failed to spawn {command}: {source}")] 26 + ProcessSpawn { 27 + command: String, 28 + source: std::io::Error, 29 + }, 30 + #[error("{command} exited with non-zero status: {detail}")] 31 + ProcessFailed { command: String, detail: String }, 32 #[error("Channel not configured: {0:?}")] 33 NotConfigured(CommsChannel), 34 #[error("External service error: {0}")] ··· 163 .stdin(Stdio::piped()) 164 .stdout(Stdio::piped()) 165 .stderr(Stdio::piped()) 166 + .spawn() 167 + .map_err(|e| SendError::ProcessSpawn { 168 + command: self.sendmail_path.clone(), 169 + source: e, 170 + })?; 171 if let Some(mut stdin) = child.stdin.take() { 172 + stdin.write_all(email_content.as_bytes()).await.map_err(|e| { 173 + SendError::ProcessSpawn { 174 + command: self.sendmail_path.clone(), 175 + source: e, 176 + } 177 + })?; 178 } 179 + let output = child.wait_with_output().await.map_err(|e| { 180 + SendError::ProcessSpawn { 181 + command: self.sendmail_path.clone(), 182 + source: e, 183 + } 184 + })?; 185 if !output.status.success() { 186 let stderr = String::from_utf8_lossy(&output.stderr); 187 + return Err(SendError::ProcessFailed { 188 + command: self.sendmail_path.clone(), 189 + detail: stderr.to_string(), 190 + }); 191 } 192 Ok(()) 193 } ··· 676 retry_delay(attempt).await; 677 continue; 678 } 679 + return Err(SendError::ProcessSpawn { 680 + command: self.signal_cli_path.clone(), 681 + source: e, 682 + }); 683 } 684 Err(_) => { 685 if attempt < MAX_RETRIES - 1 {