@domsync/linux-x64 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -62
- package/domsync +0 -0
- package/package.json +20 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# domsync
|
|
2
2
|
|
|
3
|
-
`domsync` keeps
|
|
3
|
+
`domsync` keeps local sectioned domain lists in sync with OpenClash/Mihomo rule-provider files on your servers. One config lists any number of servers, and each server lists any number of **pairs**: one local domain list and one provider file. For every pair `domsync` reads the local list and the provider file over SSH, merges them (the local entries win, provider-only domains go into an `other` section), validates everything, then atomically rewrites each file that changed and optionally runs per-server post-write commands.
|
|
4
4
|
|
|
5
|
-
It never silently rewrites anything it cannot parse: an ambiguous local file or a malformed provider line stops
|
|
5
|
+
Pairs are independent: a dead server or a broken pair is reported and the rest still run. It never silently rewrites anything it cannot parse: an ambiguous local file or a malformed provider line stops that pair before a single byte is written.
|
|
6
6
|
|
|
7
|
-
**Not supported in v1:** homeproxy, subscription URLs or any remote source other than the current provider file, SSH password authentication, `ProxyJump`, a fallback to the system `ssh`, IDN domains (use punycode), and cryptographic verification of updates inside the CLI. There is no daemon, watcher or scheduler; run `domsync` from cron or by hand.
|
|
7
|
+
**Not supported in v1:** homeproxy, subscription URLs or any remote source other than the current provider file, SSH password authentication, `ProxyJump`, a fallback to the system `ssh`, IDN domains (use punycode), and cryptographic verification of updates inside the CLI. One local list cannot be shared by two pairs (cross-sync), servers and pairs cannot be selected on the command line, and execution is sequential. There is no daemon, watcher or scheduler; run `domsync` from cron or by hand.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -42,46 +42,48 @@ The script downloads the release archive and `checksums.txt`, verifies the SHA-2
|
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
44
|
cp domsync.example.yaml domsync.yaml
|
|
45
|
-
|
|
45
|
+
mkdir -p domains
|
|
46
|
+
cat > domains/media.txt <<'EOF'
|
|
46
47
|
[media]
|
|
47
48
|
+.example.com
|
|
48
49
|
+.example.net
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
EOF
|
|
51
|
+
cat > domains/ai.txt <<'EOF'
|
|
52
|
+
[ai]
|
|
51
53
|
+.example.org
|
|
52
54
|
EOF
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
Edit `domsync.yaml
|
|
57
|
+
Edit `domsync.yaml`: in the `router` server set `host`, `user`, `ssh_key` and the `target` of each file. The example also lists a second server, `vps-1`, to show the shape; delete that entry or fix its settings before running. Set `enabled: false` instead to park it. Make sure each server's host key is already in `known_hosts`, then run:
|
|
56
58
|
|
|
57
59
|
```sh
|
|
58
60
|
domsync
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
The config is looked up in this order: `--config <path>`, the `DOMSYNC_CONFIG` environment variable, then `./domsync.yaml` in the current directory. Relative paths inside the config (`
|
|
63
|
+
The config is looked up in this order: `--config <path>`, the `DOMSYNC_CONFIG` environment variable, then `./domsync.yaml` in the current directory. Relative paths inside the config (`servers[].ssh_key`, `servers[].known_hosts`, `servers[].files[].source`, `logging.file`) are resolved against the config file's directory; `~` and `~/...` are expanded to your home directory.
|
|
62
64
|
|
|
63
|
-
A first run needs
|
|
65
|
+
A first run needs each server's host key in `known_hosts`. If it is missing, the error includes the SHA-256 fingerprint and the exact `ssh-keyscan -H ... >> ~/.ssh/known_hosts` command to add it.
|
|
64
66
|
|
|
65
67
|
## OpenClash provider
|
|
66
68
|
|
|
67
|
-
Add
|
|
69
|
+
Add one provider per synced file to the OpenClash configuration:
|
|
68
70
|
|
|
69
71
|
```yaml
|
|
70
72
|
rule-providers:
|
|
71
|
-
|
|
73
|
+
media:
|
|
72
74
|
type: file
|
|
73
75
|
behavior: domain
|
|
74
76
|
format: text
|
|
75
|
-
path: ./rule_provider/
|
|
77
|
+
path: ./rule_provider/media.txt
|
|
76
78
|
```
|
|
77
79
|
|
|
78
80
|
`format: text` is **mandatory**. Without it Mihomo parses the file as YAML, the provider ends up empty, and OpenClash gives no error.
|
|
79
81
|
|
|
80
|
-
`target
|
|
82
|
+
Each pair's `target` in `domsync.yaml` is the absolute path of the same file; OpenClash keeps provider files under `/etc/openclash/rule_provider/`.
|
|
81
83
|
|
|
82
84
|
`/etc/init.d/openclash reload` does **not** re-read provider files. Use `restart`, which is why the example config's post-write command is `/etc/init.d/openclash restart`. Any other command that genuinely reloads providers works too.
|
|
83
85
|
|
|
84
|
-
In the provider file, `# [section]` lines are comments for humans only: Mihomo ignores lines starting with `#` or `//`. domsync writes section headers only in that commented form, because a bare `[media]` line would be accepted by Mihomo as a literal domain and silently inflate the rule count. Comments are never preserved from the
|
|
86
|
+
In the provider file, `# [section]` lines are comments for humans only: Mihomo ignores lines starting with `#` or `//`. domsync writes section headers only in that commented form, because a bare `[media]` line would be accepted by Mihomo as a literal domain and silently inflate the rule count. Comments are never preserved from the server: the file is regenerated from the local state.
|
|
85
87
|
|
|
86
88
|
## Local file format
|
|
87
89
|
|
|
@@ -100,9 +102,9 @@ In the provider file, `# [section]` lines are comments for humans only: Mihomo i
|
|
|
100
102
|
|
|
101
103
|
### Sections
|
|
102
104
|
|
|
103
|
-
A section header is `[name]` on its own line, optionally with surrounding whitespace. Names must be non-empty, at most 64 characters, free of control characters, and unique. Section order follows first appearance in the local file, but the `
|
|
105
|
+
A section header is `[name]` on its own line, optionally with surrounding whitespace. Names must be non-empty, at most 64 characters, free of control characters, and unique. Section order follows first appearance in the local file, but the pair's `other_section` section (default `other`) is always rendered last. Empty sections are dropped, together with their comments.
|
|
104
106
|
|
|
105
|
-
A file with no section headers is a flat list and stays flat; in that case no `other` section is ever created, even if
|
|
107
|
+
A file with no section headers is a flat list and stays flat; in that case no `other` section is ever created, even if provider-only domains are adopted.
|
|
106
108
|
|
|
107
109
|
### Patterns
|
|
108
110
|
|
|
@@ -128,10 +130,10 @@ Rules enforced by the parser:
|
|
|
128
130
|
|
|
129
131
|
A leading `-` is the only structural marker: `-` followed by any valid pattern is a deletion directive. A `+` or `*` inside the pattern is Mihomo syntax, not a sign.
|
|
130
132
|
|
|
131
|
-
- `-pattern` with no positive entry for the same pattern **deletes** it from the
|
|
132
|
-
- `-pattern` plus a positive entry for the same pattern in a **different** section **moves** it to that section. On the
|
|
133
|
+
- `-pattern` with no positive entry for the same pattern **deletes** it from the provider file and from the local snapshot.
|
|
134
|
+
- `-pattern` plus a positive entry for the same pattern in a **different** section **moves** it to that section. On the server only the section comment changes.
|
|
133
135
|
- `-pattern` and a positive entry in the **same** section is redundant: the positive entry wins and a warning is printed. With `--strict` it is an error.
|
|
134
|
-
- A `-pattern` that exists neither locally nor
|
|
136
|
+
- A `-pattern` that exists neither locally nor in the provider file produces a warning; `--strict` turns it into an error.
|
|
135
137
|
|
|
136
138
|
To delete a domain that still has a positive line, remove that positive line and add `-pattern`. While the positive line remains, domsync treats the pair as a move, not a deletion.
|
|
137
139
|
|
|
@@ -139,7 +141,7 @@ After a successful sync the `-` lines disappear from the local file: the domain
|
|
|
139
141
|
|
|
140
142
|
### Comments
|
|
141
143
|
|
|
142
|
-
- `#` at the start of a line is a comment. Comments are local-only: they are kept in the local snapshot and are never written to the
|
|
144
|
+
- `#` at the start of a line is a comment. Comments are local-only: they are kept in the local snapshot and are never written to the provider file.
|
|
143
145
|
- Comments attach to the current section and are rendered immediately after that section's header, in their original order. Comments before the first section stay at the top of the file.
|
|
144
146
|
- Inline comments are invalid. The line `+.example.com # note` is a validation error; put the note on its own line.
|
|
145
147
|
- `//` is not a local comment. A local line starting with `//` is a pattern and is rejected.
|
|
@@ -147,77 +149,103 @@ After a successful sync the `-` lines disappear from the local file: the domain
|
|
|
147
149
|
|
|
148
150
|
### Output rules
|
|
149
151
|
|
|
150
|
-
Within each section, patterns are sorted; section order is otherwise preserved; the `other_section` is last. The local file is rewritten as a snapshot of the merged state, comments included. When the local file has sections, the
|
|
152
|
+
Within each section, patterns are sorted; section order is otherwise preserved; the `other_section` is last. The local file is rewritten as a snapshot of the merged state, comments included. When the local file has sections, the provider file contains `# [section]` headers followed by the same sorted patterns; a flat local file produces a flat provider file. Provider-only domains are added to `other_section`; if the local file already has that section it is reused, so a second one is never created.
|
|
151
153
|
|
|
152
|
-
A missing local file is treated as an empty list, so the first run bootstraps the local snapshot from the
|
|
154
|
+
A missing local file is treated as an empty list, so the first run bootstraps the local snapshot from the provider file: every provider-only domain is adopted and written locally. An empty local file with an empty provider file is a no-op. A plan whose final list would be empty while the provider file is not is an error: domsync refuses to wipe the provider file.
|
|
153
155
|
|
|
154
|
-
Concurrent runs are refused. A run holds an exclusive lock on `<
|
|
156
|
+
Concurrent runs are refused. A run holds an exclusive lock on `<config-path>.domsync.lock` next to the config file from the moment the configuration is loaded until every write and post-write command has finished, so a cron job and a manual run cannot interleave their reads and writes. One lock covers the whole config, so two different configs can run at the same time. The lock file stays on disk after the run; the lock itself is released by the operating system when the process exits, including after a crash.
|
|
155
157
|
|
|
156
|
-
###
|
|
158
|
+
### Provider file validation
|
|
157
159
|
|
|
158
|
-
When reading the provider file from
|
|
160
|
+
When reading the provider file from a server, domsync ignores blank lines and lines starting with `#` or `//`. Every other line must be a valid pattern; otherwise that pair fails with the file, line number and offending text, and nothing is written for it. Duplicate patterns are collapsed. A bare `[media]` header on the server is therefore an error, not a domain.
|
|
159
161
|
|
|
160
162
|
## Configuration reference
|
|
161
163
|
|
|
162
164
|
YAML parsing is strict: unknown fields, multiple YAML documents and an empty file are errors.
|
|
163
165
|
|
|
166
|
+
Top-level keys:
|
|
167
|
+
|
|
164
168
|
| Key | Type | Default | Meaning |
|
|
165
169
|
|---|---|---|---|
|
|
166
|
-
| `version` | integer | required | Must be `1
|
|
167
|
-
| `
|
|
168
|
-
| `target.host` | string | required | Router host name or address. |
|
|
169
|
-
| `target.port` | integer | `22` | SSH port (1-65535). |
|
|
170
|
-
| `target.user` | string | required | SSH user. |
|
|
171
|
-
| `target.ssh_key` | path | empty | Private key (ed25519, ecdsa or rsa). If empty, `SSH_AUTH_SOCK` must provide an agent. Both are used when available. |
|
|
172
|
-
| `target.known_hosts` | path | `~/.ssh/known_hosts` | Must already exist and be a regular file. |
|
|
173
|
-
| `target.path` | string | required | Absolute path of the provider file on the router; a trailing `/` is rejected. |
|
|
174
|
-
| `target.other_section` | string | `other` | Section that receives router-only domains. |
|
|
175
|
-
| `target.mode` | string | `0644` | Octal permissions for the written provider file, at most `0777`. Quote it in YAML. |
|
|
176
|
-
| `target.backup` | boolean | `true` | Copy the previous provider file to the backup path before replacing it. |
|
|
177
|
-
| `target.backup_suffix` | string | `.domsync.bak` | Suffix appended to `target.path` for the backup file. |
|
|
178
|
-
| `target.post_write.run` | string | `on_change` | When to run `target.post_write.commands`: `on_change`, `always` or `never`. |
|
|
179
|
-
| `target.post_write.timeout` | duration string | `120s` | Timeout for each command. See the note below. |
|
|
180
|
-
| `target.post_write.commands` | list of strings | empty | Commands run sequentially over the existing SSH connection. |
|
|
170
|
+
| `version` | integer | required | Must be `2`; a `version: 1` config is rejected. |
|
|
171
|
+
| `servers` | list | required | One or more servers; at least one entry. |
|
|
181
172
|
| `update.check` | boolean | `true` | Check GitHub for a newer release at launch. `--no-update-check` overrides it. |
|
|
182
|
-
| `logging.file` | path | empty (disabled) | When set, one summary line is appended on
|
|
173
|
+
| `logging.file` | path | empty (disabled) | When set, one summary line is appended on every non-dry-run run that reaches the end, including runs with failed pairs or servers. |
|
|
183
174
|
|
|
184
|
-
|
|
175
|
+
Server keys:
|
|
176
|
+
|
|
177
|
+
| Key | Type | Default | Meaning |
|
|
178
|
+
|---|---|---|---|
|
|
179
|
+
| `name` | string | required | Unique across servers, `[a-z0-9][a-z0-9_-]*`, at most 32 characters. Used in reports and logs. |
|
|
180
|
+
| `enabled` | boolean | `true` | `false` skips the server entirely, `validate` included. See below. |
|
|
181
|
+
| `host` | string | required | Server host name or address. |
|
|
182
|
+
| `port` | integer | `22` | SSH port (1-65535). |
|
|
183
|
+
| `user` | string | required | SSH user. |
|
|
184
|
+
| `ssh_key` | path | empty | Private key (ed25519, ecdsa or rsa). If empty, `SSH_AUTH_SOCK` must provide an agent. Both are used when available. |
|
|
185
|
+
| `known_hosts` | path | `~/.ssh/known_hosts` | Must already exist and be a regular file. |
|
|
186
|
+
| `post_write.run` | string | `on_change` | When to run `post_write.commands`: `on_change`, `always` or `never`. |
|
|
187
|
+
| `post_write.timeout` | duration string | `120s` | Timeout for each command. See the note below. |
|
|
188
|
+
| `post_write.commands` | list of strings | empty | Commands run sequentially over the existing SSH connection, after the server's pairs. |
|
|
189
|
+
| `files` | list | required | One or more pairs; at least one entry, even when the server is disabled. |
|
|
190
|
+
|
|
191
|
+
File (pair) keys:
|
|
185
192
|
|
|
186
|
-
|
|
187
|
-
|
|
193
|
+
| Key | Type | Default | Meaning |
|
|
194
|
+
|---|---|---|---|
|
|
195
|
+
| `source` | path | required in version 2 | Local domain list, resolved relative to the config file. A regular file or absent; absent means an empty list. Must be unique across the whole config. |
|
|
196
|
+
| `target` | string | required | Absolute path of the provider file on that server; a trailing `/` is rejected. Must be unique within the server; the same target on two servers is fine. |
|
|
197
|
+
| `other_section` | string | `other` | Section that receives provider-only domains. |
|
|
198
|
+
| `mode` | string | `0644` | Octal permissions for the written provider file, between `0001` and `0777`. Quote it in YAML. |
|
|
199
|
+
| `backup` | boolean | `true` | Copy the previous provider file to the backup path before replacing it. |
|
|
200
|
+
| `backup_suffix` | string | `.domsync.bak` | Suffix appended to `target` for the backup file. |
|
|
201
|
+
|
|
202
|
+
Two pairs may not share a `source` (resolved absolute path): both would rewrite it, so the config is rejected naming both positions. Two pairs on the same server may not share a `target`; the same path on two different servers is fine. Relative paths resolve against the config file's directory and `~` expands to your home, as described in Quick start.
|
|
203
|
+
|
|
204
|
+
`post_write.run` values:
|
|
205
|
+
|
|
206
|
+
- `on_change` - run the commands when at least one pair on this server changed something, on the server or locally.
|
|
207
|
+
- `always` - run them after every non-dry-run sync of the server, including a run with no changes and a run in which a pair failed.
|
|
188
208
|
- `never` - never run them.
|
|
189
209
|
|
|
190
|
-
`--dry-run` never runs commands, and
|
|
210
|
+
`--dry-run` never runs commands, and a server whose connection failed runs none. A command failure is recorded and does not undo any write; the sequence stops at the first failing command.
|
|
211
|
+
|
|
212
|
+
`enabled: false` parks a server: `sync` and `validate` skip it entirely, and the report marks it `skipped`. Every shape check still applies to a disabled server — required fields, name syntax and uniqueness, `port`, `mode`, `other_section`, `post_write.run`, absolute `target`, unique `source` across the whole config, and unique `target` within the server — so a typo in a parked server is a config error, not a surprise on the day it is switched on. Only filesystem and environment checks are skipped: `ssh_key` exists, `known_hosts` exists, `SSH_AUTH_SOCK` when `ssh_key` is empty, and `source` being a regular file or absent. That makes `enabled: false` a legitimate way to park a server whose key is not on this machine yet.
|
|
191
213
|
|
|
192
214
|
**The command timeout cannot be disabled.** `timeout` applies to each command separately. A value of `0s` is treated as "unset" and replaced by the built-in default of `120s`; negative values are rejected. Choose a large finite value if a command legitimately runs long.
|
|
193
215
|
|
|
194
216
|
**Host keys are always verified.** This is true for key-file authentication and for ssh-agent authentication alike. There is no trust-on-first-use mode.
|
|
195
217
|
|
|
196
|
-
Config validation runs before SSH is dialled: a missing key file, a missing `known_hosts`,
|
|
218
|
+
Config validation runs before SSH is dialled: a missing key file, a missing `known_hosts`, an empty `ssh_key` with `SSH_AUTH_SOCK` unset, or a `source` that is not a regular file fails with exit code 1 before any connection is attempted. Disabled servers are exempt from these filesystem checks.
|
|
197
219
|
|
|
198
220
|
## Validation
|
|
199
221
|
|
|
200
|
-
`domsync validate` loads the configuration and parses
|
|
222
|
+
`domsync validate` loads the configuration, walks every enabled server's pairs and parses each local list without opening an SSH connection. It covers everything `domsync` checks before dialling — the config schema, path resolution, cross-pair uniqueness, the existence of each server's `ssh_key` and `known_hosts`, and every local list's syntax — and nothing that needs a server. Disabled servers are skipped and reported as `skipped`.
|
|
223
|
+
|
|
224
|
+
Validation continues past a broken pair: it is reported and the remaining pairs are still checked.
|
|
201
225
|
|
|
202
226
|
```sh
|
|
203
227
|
domsync validate
|
|
204
228
|
domsync --json validate
|
|
205
229
|
```
|
|
206
230
|
|
|
207
|
-
Exit codes follow the table below: `1` for a configuration or read error and `2` for an invalid local list.
|
|
231
|
+
Exit codes follow the table below: `1` for a configuration or read error and `2` for an invalid local list. When several pairs fail, the exit code is the code of the first failure in config order (server order, then file order).
|
|
232
|
+
|
|
233
|
+
With `--json` the output is one object with `ok` and `servers`; each server carries `name`, `ok`, `skipped` and `files`, and each file carries `source`, `ok`, `total`, `sections` and, on failure, an `error` object with the exit code and message. A config-level error produces `ok: false` with an `error` object and exits 1 before any pair is examined. Without `--json` the human output prints the resolved config path, then a block per server (`name`, then each local file with its counts) and the usual summary line (`domsync: N доменов, M секций`); a failed file prints `ошибка: ...`.
|
|
208
234
|
|
|
209
235
|
## Exit codes
|
|
210
236
|
|
|
211
237
|
| Code | Meaning |
|
|
212
238
|
|---|---|
|
|
213
239
|
| `0` | Success, including "no changes". Also `--help` and `--version`. |
|
|
214
|
-
| `1` | Usage or configuration error, local file read/write error, log write error, or another run holding the
|
|
215
|
-
| `2` | Validation error in
|
|
240
|
+
| `1` | Usage or configuration error, local file read/write error, log write error, or another run holding the config lock. |
|
|
241
|
+
| `2` | Validation error in a local list or a provider file, including `--strict` warnings, and an empty final list. |
|
|
216
242
|
| `3` | SSH connection, authentication, host-key or remote read/write/verify error. |
|
|
217
|
-
| `4` | Update error, including the Homebrew/npm refusal. |
|
|
243
|
+
| `4` | Update error, including the Homebrew/npm refusal; uninstall cancelled or left to a package manager. |
|
|
218
244
|
| `5` | A post-write command failed (non-zero exit or transport error). |
|
|
219
245
|
|
|
220
|
-
|
|
246
|
+
When several things fail, the exit code is the code of the first failure in execution order: server order, then file order. A server that cannot be dialled counts at its own position, before its pairs, so a connection error beats a later pair failure. A failure in one pair or one server never stops the rest.
|
|
247
|
+
|
|
248
|
+
`--strict` only promotes local warnings (deletion target not found, redundant `+`/`-` in one section) to errors, and fails only that pair. Problems in a provider file are always errors, and a failed launch-time update check never changes the sync exit code.
|
|
221
249
|
|
|
222
250
|
## Updates
|
|
223
251
|
|
|
@@ -247,32 +275,55 @@ domsync установлен через npm. Обновление: npm i -g @dom
|
|
|
247
275
|
|
|
248
276
|
So update those installs with `brew upgrade --cask domsync` or `npm i -g @domsync/cli@latest`. The same refusal applies to `domsync update --check`, because install detection happens first. A standalone binary is replaced atomically after its archive has been checked against `checksums.txt`.
|
|
249
277
|
|
|
278
|
+
## Uninstall
|
|
279
|
+
|
|
280
|
+
`domsync uninstall` removes what the installation created: the binary and the cache directory (`os.UserCacheDir()/domsync`, which holds the update cache). It never touches your config, domain lists or log file.
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
domsync uninstall # asks: Удалить domsync и созданные им файлы? [y/N]
|
|
284
|
+
domsync uninstall --yes # no question, for scripts
|
|
285
|
+
domsync --dry-run uninstall # print what would be removed and change nothing
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Enter, or anything other than `y`, `yes`, `д` or `да`, cancels and exits with code 4. Without a terminal the question cannot be asked, so `--yes` is required.
|
|
289
|
+
|
|
290
|
+
The install method is detected the same way as for updates. Homebrew and npm installs are removed through the package manager: domsync runs `brew uninstall --cask --zap domsync` or `npm uninstall -g @domsync/cli` itself and then removes the cache directory. The cask declares a `zap` stanza for that directory, so `brew uninstall --cask --zap domsync` is just as complete without this command. On Windows a running npm package cannot delete itself, so the command prints the npm command and exits 4; the same happens when `brew` or `npm` is not on `PATH`, except the cache directory is still removed.
|
|
291
|
+
|
|
292
|
+
The empty `<config>.domsync.lock` beside a config is a run lock, not an install artifact; it goes away with the config.
|
|
293
|
+
|
|
294
|
+
With `--json` the output is the usual envelope, with `removed` listing the paths and `dry_run` set for `--dry-run`.
|
|
295
|
+
|
|
250
296
|
## Output
|
|
251
297
|
|
|
252
|
-
The default human report is Russian and looks like this for a run that changed
|
|
298
|
+
The default human report is Russian and looks like this for a run that changed one pair:
|
|
253
299
|
|
|
254
300
|
```text
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
301
|
+
router (192.168.1.1)
|
|
302
|
+
domains/media.txt → /etc/openclash/rule_provider/media.txt
|
|
303
|
+
роутер: +2 −1, записан, бэкап /etc/openclash/rule_provider/media.txt.domsync.bak
|
|
304
|
+
локально: +1, перемещён 1
|
|
305
|
+
domains/ai.txt → /etc/openclash/rule_provider/ai.txt: без изменений
|
|
306
|
+
команда: /etc/init.d/openclash restart — ok, 0.8s
|
|
307
|
+
vps-1: пропущен (disabled)
|
|
308
|
+
domsync: 42 домена, 7 секций
|
|
259
309
|
```
|
|
260
310
|
|
|
261
|
-
-
|
|
311
|
+
- Each server block starts with its name and host, followed by one line per pair. A skipped server is a single `name: пропущен (disabled)` line; a server that failed to connect prints its name and the error, with the number of pairs that were not attempted.
|
|
312
|
+
- A pair with no changes on either side stays on one line with `без изменений`; a failed pair prints `ошибка: <message>` on its own line.
|
|
262
313
|
- `роутер` and `локально` show added and removed counts with the U+2212 minus sign. The router line adds `записан` only when the file was actually written, and the backup path when a backup was made; the local line adds `перемещён N` for moved patterns.
|
|
263
|
-
-
|
|
314
|
+
- The final line reports the total number of domains and non-empty sections across every pair that ran. A successful run without changes says `domsync: изменений нет (N доменов, M секций)`.
|
|
264
315
|
- With `--dry-run`, each changed file is marked `будет записан (dry-run)`.
|
|
265
316
|
- Command results are `ok, <duration>` or `ошибка <exit code>`; a transport failure prints `ошибка: <message>`.
|
|
266
317
|
- Warnings print as `предупреждение: <message>`.
|
|
267
318
|
|
|
268
|
-
`--dry-run` still connects to
|
|
319
|
+
`--dry-run` still connects to every enabled server and reads the current provider files; it skips both writes and all commands. It is not an offline mode.
|
|
269
320
|
|
|
270
|
-
- `--json` writes a single JSON object to stdout; errors after argument parsing are JSON as well.
|
|
321
|
+
- `--json` writes a single JSON object to stdout; errors after argument parsing are JSON as well. Top-level fields are `ok`, `changed`, `dry_run`, `total`, `sections`, `servers`, `warnings`, `update` and `error`; each server carries `name`, `host`, `ok`, `changed`, `skipped`, `skipped_pairs`, `files`, `commands` and `error`; each file carries `source`, `target`, `ok`, `changed`, `total`, `sections`, `router`, `local`, `warnings` and `error`.
|
|
271
322
|
- `--quiet` prints only errors; `--verbose` adds update-check failures to the warnings; `--strict` treats local warnings as errors.
|
|
272
323
|
|
|
273
324
|
## Security
|
|
274
325
|
|
|
275
|
-
- **Strict host key checking.** Every connection verifies the
|
|
326
|
+
- **Strict host key checking.** Every connection verifies the server key against `known_hosts` using `golang.org/x/crypto/ssh/knownhosts`, whether authentication uses a key file or the ssh-agent. An unknown key aborts with its SHA-256 fingerprint and a `ssh-keyscan` hint; a changed key aborts naming both the presented and the expected fingerprints. TOFU does not exist in v1. The host key type is negotiated from the algorithms recorded for the host in `known_hosts`, so a host with only one recorded key type is not rejected merely because the server also offers another.
|
|
276
327
|
- **Updates in v1 rely on SHA-256 only.** The binary checks the downloaded archive against `checksums.txt` from the release and extracts only the expected executable, rejecting path traversal. GoReleaser also publishes a cosign keyless signature bundle (`checksums.txt.sigstore.json`) and GitHub build attestations; these are for manual verification, not checked by the CLI. To verify a release by hand:
|
|
277
328
|
|
|
278
329
|
```sh
|
package/domsync
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1 +1,20 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "@domsync/linux-x64",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"packageManager": "npm@11.5.1+sha512.232e6f5d9e799bcb486920b3e9ba907fdf96e576cf7e8c9446c8162e33a416096a1d37a9e910d9a918f6b1f606791c99bc6bb61ee2569b496ec74af13d0dbd95",
|
|
5
|
+
"os": "linux",
|
|
6
|
+
"cpu": "x64",
|
|
7
|
+
"files": [
|
|
8
|
+
"domsync",
|
|
9
|
+
"domsync.exe"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/neiromaster/domsync.git"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"provenance": true,
|
|
18
|
+
"access": "public"
|
|
19
|
+
}
|
|
20
|
+
}
|