README.md (5013 bytes)
1 # sbm-sync 2 3 sbm-sync keeps your [sbm](https://github.com/equwal/sbm) bookmark file the 4 same on each of your devices: bm on your computers, the sbm app for Android 5 and the sbm add-on for Firefox and Chrome. 6 7  8 9 The demo (80 seconds, also as [MP4](demo/sbm-demo.mp4)): bm adds a bookmark 10 in a terminal. The add-on in the browser shows it, and adds the page that it 11 shows. After `bm-sync`, bm has that bookmark too. All through 12 sbm.subread.space. 13 14 It is one small Go program. It keeps its data in plain files: no database. 15 The only dependency is `golang.org/x/crypto` for bcrypt. 16 17 The clients use **https://sbm.subread.space** unless you set another 18 server. That server is free for 30 days, then $3 a month or $30 a year. 19 Run your own server free of charge. 20 21 ## How sync works 22 23 A device sends its whole bookmark file and the name of the version that it 24 got last time. The server merges the changes of the device into its own 25 copy, keeps the result and sends it back. The device writes the result to 26 its file and keeps the new version name. 27 28 The merge compares whole lines: 29 30 - A line that the device removed since its last version goes. 31 - A line that the device added comes in, at the end of the file, where bm 32 adds bookmarks. When the server has another line for the same bookmark 33 (the same URL, as bm compares URLs), the line of the device takes its 34 place. So an edit on a device wins. 35 - Lines that other devices added stay. 36 37 When the server does not know the last version of a device (for its first 38 sync), nothing is removed: the result is the union of both files. 39 40 ## Protocol 41 42 Plain HTTP, for any client with curl. 43 44 POST /api/login form fields email, password 45 200: a token, as text 46 POST /api/sync?base=V Authorization: Bearer <token> 47 body: the bookmark file 48 200: the merged file; header Sbm-Version: <new V> 49 POST /api/logout Authorization: Bearer <token> 50 51 Errors come as text: 401 (sign in again), 402 (the subscription or the 52 trial has ended), 413 (the file is larger than 4 MB), 429 (too many sign-in 53 attempts). 54 55 curl -d email=me@example.org --data-urlencode password=... https://sbm.subread.space/api/login 56 curl -H "Authorization: Bearer $token" --data-binary @bookmarks \ 57 "https://sbm.subread.space/api/sync?base=$version" 58 59 ## Run your own server 60 61 go build 62 SBM_URL=https://sbm.example.org ./sbm-sync 63 64 Then put it behind a web server that does TLS. `contrib/` has a systemd unit 65 and an nginx site. With Go installed elsewhere: 66 67 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build 68 69 Settings, all through the environment: 70 71 SBM_URL public address of the server (default http://localhost:8750) 72 SBM_ADDR address to listen on (default 127.0.0.1:8750) 73 SBM_DATA data directory (default ./data) 74 SBM_CONTACT email address on the privacy page (optional) 75 SBM_TRIAL_DAYS days of sync before payment, with billing on (default 30) 76 SBM_BILLING_START date when billing starts, as 2026-10-01: accounts 77 from before it get the full trial from that date 78 79 Accounts need no email check. To reset a password, the operator deletes the 80 account in `accounts.json` (with the server stopped), and the user signs up 81 again. The bookmark files stay on the devices. 82 83 ## Billing 84 85 Billing is off unless `STRIPE_SECRET_KEY` is set. Without billing, sync 86 is free for all accounts. To turn it on: 87 88 1. In Stripe, make a product with two recurring prices, for example $3 a 89 month and $30 a year. 90 2. Add a webhook endpoint `https://<your server>/stripe` for the events 91 `checkout.session.completed`, `customer.subscription.created`, 92 `customer.subscription.updated` and `customer.subscription.deleted`. 93 3. Turn on the customer portal in the Stripe settings, so that customers 94 can cancel and change their card. 95 4. Set these variables, then restart the server: 96 97 STRIPE_SECRET_KEY sk_test_... or sk_live_... 98 STRIPE_WEBHOOK_SECRET whsec_... of the endpoint 99 STRIPE_PRICE_MONTH price_... of the monthly price 100 STRIPE_PRICE_YEAR price_... of the yearly price 101 102 Keep the keys out of git: put them in the environment file of the service. 103 104 ## Data 105 106 data/accounts.json accounts: email, bcrypt hash, token hashes, 107 Stripe customer and subscription state 108 data/files/<account>/<sha256> the last 50 versions of each bookmark file 109 data/files/<account>/HEAD name of the current version 110 111 To back up, copy the directory. 112 113 ## Test 114 115 go vet ./... && go test ./... 116 117 The merge has property tests (with [rapid](https://github.com/flyingmutant/rapid)). 118 119 ## License 120 121 AGPL-3.0. If you run a changed version for other people, give them its 122 source code. 123 124 If sbm is useful to you, you can support it on [Ko-fi](https://ko-fi.com/truex).