Created
January 23, 2025 02:10
-
-
Save gcr/dee9a4b18f52fa2ad949d50b66fea213 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| * Programatically setting up SyncThing via the bulit-in CLI command: A worked example | |
| I have two virtual machines, =syncOne= and =syncTwo=, and I want to make a shared folder on them. I want to *only use the CLI*. Maybe these are remote machines, maybe I need to automate this, or maybe I don't have a web browser handy. | |
| ** TL;DR | |
| Install syncthing and run it in the background. Gather each machine's IDs by running: | |
| #+begin_src shell | |
| syncthing cli show system | jq -r .myID | |
| #+end_src | |
| Syncthing will generate device IDs, but it will not generate random folder IDs. Pick a cryptographically secure folder ID by hashing some random bytes: | |
| #+begin_src shell | |
| dd if=/dev/random count=1024 | sha1sum | |
| #+end_src | |
| Then, on each machine, run: | |
| #+begin_src shell | |
| # Introduce this device to the other device | |
| syncthing cli config devices add --device-id $OTHER_DEVICE_ID | |
| # Register the folder (syncthing will create | |
| # it if it does not exist. If it does exist, | |
| # syncthing will add a `.stfolder` | |
| # hidden file to it.) | |
| syncthing cli config folders add --id $FOLDER_ID --path /path/to/folder | |
| # Share the folder to the other device | |
| syncthing cli config folders $FOLDER_ID devices add --device-id $OTHER_DEVICE_ID | |
| #+end_src | |
| Each of these three steps must be run on both machines. | |
| Here's a worked example: | |
| ** Step zero: Setup | |
| First, we *install and run syncthing*. On both machines, we install =syncthing=, =tmux=, and =jq=: | |
| #+begin_src shell | |
| kimmy@syncOne:~$ sudo apt install -y syncthing tmux jq | |
| #+end_src | |
| Then, pop open a tmux panel and run =syncthing= in the foreground on both machines. | |
| It looks like this: | |
| [[https://pasteboard.co/KdXNgI8CsVv9.png]] | |
| I have two terminals open, one connected to each machine. Each terminal is running syncthing in the top and has a shell on the bottom. | |
| ** Step one: Introduce devices to each other | |
| #+begin_quote | |
| ๐ *Key idea:* Two devices are *introduced* if they appear in each other's device list. | |
| #+end_quote | |
| There's no key exchange, you just tell each device the other's ID. The ID serves as both the username and the password, so *keep it secret, keep it safe.* | |
| To start, we need to retrieve both device IDs. On =syncOne=, we have: | |
| #+begin_src shell | |
| kimmy@syncOne:~$ syncthing cli show system | jq -r .myID | |
| DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV | |
| #+end_src | |
| And on =syncTwo=, the ID is: | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ syncthing cli show system | jq -r .myID | |
| TLLN7FX-W3IBVGI-GL22U7H-JNP3KOB-4LUSCDV-FZSWFFL-2RDYFFY-IOEXTAE | |
| #+end_src | |
| Now, *add =syncTwo= to =syncOne='s device list.* On =syncOne=, run | |
| #+begin_src shell | |
| kimmy@syncOne:~$ syncthing cli config devices add --device-id TLLN7FX-W3IBVGI-GL22U7H-JNP3KOB-4LUSCDV-FZSWFFL-2RDYFFY-IOEXTAE --name syncTwo | |
| #+end_src | |
| *Check:* After five seconds, =syncTwo= should show =syncOne='s pending invitation: | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ syncthing cli show pending devices | |
| { | |
| "DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV": { | |
| "address": "198.19.249.77:22000", | |
| "name": "syncOne", | |
| "time": "2025-01-23T01:24:59Z" | |
| } | |
| } | |
| #+end_src | |
| Excellent. Accept this invitation by performing the reverse operation on =syncTwo= (adding =syncOne='s ID to =syncTwo='s device list): | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ syncthing cli config devices add --device-id DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV --name syncOne | |
| #+end_src | |
| ** Make a folder | |
| Let's make a pre-existing folder starting on =syncOne=. | |
| #+begin_src shell | |
| kimmy@syncOne:~$ mkdir mydata | |
| kimmy@syncOne:~$ cd mydata | |
| kimmy@syncOne:~/mydata$ touch hello-world | |
| kimmy@syncOne:~/mydata$ date > foobar | |
| kimmy@syncOne:~/mydata$ ls | |
| foobar hello-world | |
| kimmy@syncOne:~/mydata$ cat foobar | |
| Wed Jan 22 20:32:06 EST 2025 | |
| kimmy@syncOne:~/mydata$ cd | |
| kimmy@syncOne:~$ | |
| #+end_src | |
| We first register this folder on =syncOne=. The two critical parameters are *label* and *path*. | |
| #+begin_src shell | |
| kimmy@syncOne:~$ syncthing cli config folders add --label mydata --path ~/mydata | |
| syncthing: error: unexpected HTTP status returned: 400 Bad Request | |
| folder has empty ID | |
| #+end_src | |
| Unfortunately, we need to make up a random folder ID. *This must not be guessable*, so I'll use the hash of some random bytes as my ID. | |
| #+begin_src shell | |
| kimmy@syncOne:~$ dd if=/dev/urandom count=1024 | sha1sum | |
| ... | |
| 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 - | |
| kimmy@syncOne:~$ syncthing cli config folders add --label mydata --path ~/mydata --id 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 | |
| #+end_src | |
| After this, there are two changes on =syncOne=. First, syncthing created a =.stfolder= hidden folder inside our folder: | |
| #+begin_src shell | |
| kimmy@syncOne:~$ ls -a mydata/ | |
| . .. .stfolder foobar hello-world | |
| #+end_src | |
| Second, =syncOne= now lists its own device ID on the folder's shared device list (in other words, it's registered to share to itself): | |
| #+begin_src shell | |
| kimmy@syncOne:~$ syncthing cli config folders 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 dump-json | |
| { | |
| "id": "96feab5b3bd18ed3554abf04b1ce64c5ccee3a96", | |
| "label": "mydata", | |
| "filesystemType": "basic", | |
| "path": "/home/kimmy/mydata", | |
| "type": "sendreceive", | |
| "devices": [ | |
| { | |
| "deviceID": "DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV", | |
| "introducedBy": "", | |
| "encryptionPassword": "" | |
| } | |
| ], | |
| ... other stuff ... | |
| } | |
| #+end_src | |
| ** Share the folder | |
| On =syncOne=, share the folder to =syncTwo=: | |
| #+begin_src shell | |
| kimmy@syncOne:~$ syncthing cli config folders 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 devices add --device-id TLLN7FX-W3IBVGI-GL22U7H-JNP3KOB-4LUSCDV-FZSWFFL-2RDYFFY-IOEXTAE | |
| #+end_src | |
| *Check:* =syncTwo= should now show the pending folder invitation. | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ syncthing cli show pending folders | |
| { | |
| "96feab5b3bd18ed3554abf04b1ce64c5ccee3a96": { | |
| "offeredBy": { | |
| "DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV": { | |
| "label": "mydata", | |
| "receiveEncrypted": false, | |
| "remoteEncrypted": false, | |
| "time": "2025-01-23T01:41:11Z" | |
| } | |
| } | |
| } | |
| } | |
| #+end_src | |
| ** Share the folder back | |
| #+begin_quote | |
| ๐ *Key idea:* Two devices are *introduced* if they appear in each other's device list. | |
| #+end_quote | |
| On =syncTwo=, we need to *add* the folder and we also need to *share* the folder back to =syncOne=. | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ syncthing cli config folders add --id 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 --label mydata --path ~/mydata | |
| kimmy@syncTwo:~$ syncthing cli config folders 96feab5b3bd18ed3554abf04b1ce64c5ccee3a96 devices add --device-id DAP76ZM-QQCBKBH-FREZULQ-IVWCASB-EJZOJJS-QE2NRRN-YMN6UAI-UHHHIAV | |
| #+end_src | |
| That's it! After a short sync period, =syncTwo= can see the folder and can add to it: | |
| #+begin_src shell | |
| kimmy@syncTwo:~$ ls mydata/ | |
| foobar hello-world | |
| kimmy@syncTwo:~$ echo "Hello from syncTwo" > mydata/syncTwo | |
| kimmy@syncTwo:~$ ls mydata/ | |
| foobar hello-world syncTwo | |
| kimmy@syncTwo:~$ cat mydata/foobar mydata/syncTwo | |
| Wed Jan 22 20:32:06 EST 2025 | |
| Hello from syncTwo | |
| #+end_src | |
| The sync is two-way, so =syncOne= can also see these changes: | |
| #+begin_src shell | |
| kimmy@syncOne:~$ ls mydata | |
| foobar hello-world syncTwo | |
| kimmy@syncOne:~$ cat mydata/foobar mydata/syncTwo | |
| Wed Jan 22 20:32:06 EST 2025 | |
| Hello from syncTwo | |
| #+end_src |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment