🌳
pt0/deployF/servicesF/vwRcloneAI.mts
4// single source of truth for the rclone image pin — bumpable via `updateimg` (scans this file)
5export const rcloneImg = 'rclone/rclone:1.75.0' // 260731
7// flat-file replica (attachments/sends/rsa_key) lives alongside the litestream db replica in the
8// same haS3 bucket, under a distinct prefix. additive copy only (no delete propagation) — orphaned
9// attachments are harmless (unreferenced by the db) and avoids any mass-delete risk.
10export const vwRclonePrefix = 'vaultwarden-files'
11const vwRcloneRemoteName = 'has3'
12const vwRcloneSyncIntervalSec = 900 // 15 min cadence
14// files to replicate: user attachments, sends, JWT signing keys. excludes db.sqlite3 (litestream),
15// icon_cache (regenerable), and litestream/upload scratch dirs.
16const vwRcloneIncludeA = ['/attachments/**', '/sends/**', '/rsa_key*']
18export const vwRcloneRemotePath = `${vwRcloneRemoteName}:${vwLitestreamBucket}/${vwRclonePrefix}`
20// rclone remote configured entirely via env (RCLONE_CONFIG_<name>_<KEY>) — no configmap needed.
21// creds baked into the config env (rclone's s3 backend needs RCLONE_CONFIG_HAS3_ACCESS_KEY_ID,
22// not the generic AWS_* that litestream reads).
23export const vwRcloneEnvH = ({cluster_name}: {cluster_name: string}): Record<string, string> => {
24 const {endpoint, accessKeyId, secretAccessKey} = getS3Cfg({bucket_name: vwLitestreamBucket, cluster_name})
25 return {
26 RCLONE_CONFIG_HAS3_TYPE: 's3',
27 RCLONE_CONFIG_HAS3_PROVIDER: 'Minio',
28 RCLONE_CONFIG_HAS3_ENDPOINT: endpoint,
29 RCLONE_CONFIG_HAS3_REGION: 'us-east-1',
30 RCLONE_CONFIG_HAS3_FORCE_PATH_STYLE: 'true',
31 RCLONE_CONFIG_HAS3_NO_CHECK_BUCKET: 'true',
32 RCLONE_CONFIG_HAS3_ACCESS_KEY_ID: accessKeyId,
33 RCLONE_CONFIG_HAS3_SECRET_ACCESS_KEY: secretAccessKey,
34 }
37// sidecar loop: copy /data flat files -> haS3 every 15 min (additive)
38export const vwRcloneCopyUpCmd = () => {
39 const includes = vwRcloneIncludeA.map(p => `--include '${p}'`).join(' ')
40 return `while true; do rclone copy /data ${vwRcloneRemotePath} ${includes} -v --contimeout 30s --timeout 300s || true; sleep ${vwRcloneSyncIntervalSec}; done`
43// restore: pull the flat-file replica back into /data (trailing slash -> rclone treats source as dir prefix)
44export const vwRcloneCopyDownCmd = () => `rclone copy ${vwRcloneRemotePath}/ /data -v --contimeout 30s --timeout 300s`