From 0ce61a0edadcb1e945d34c6ad0380806db86ce67 Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:03:23 +0400 Subject: [PATCH 1/2] docs: add name resolution setup to SMP server guide (#7251) * docs: add name resolution setup to SMP server guide * docs: link SMP server names section to public names overview * link --------- Co-authored-by: Evgeny --- docs/SERVER.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/SERVER.md b/docs/SERVER.md index a35ede5cd0..547cf6a352 100644 --- a/docs/SERVER.md +++ b/docs/SERVER.md @@ -28,6 +28,7 @@ revision: 12.10.2024 - [Installation for onion address](#installation-for-onion-address) - [SOCKS port for SMP PROXY](#socks-port-for-smp-proxy) - [Server information page](#server-information-page) +- [Name resolution](#name-resolution) - [Documentation](#documentation) - [SMP server address](#smp-server-address) - [Systemd commands](#systemd-commands) @@ -1217,6 +1218,80 @@ _Please note:_ this configuration is supported since `v6.1.0-beta.2`. 10. Access the webpage you've deployed from your browser (`https://smp.example.org`). You should see the smp-server information that you've provided in your ini file. +## Name resolution + +SimpleX public names (like `alice.simplex`) resolve to contact and channel addresses. These records are stored in the SimpleX Namespace registry contracts on Ethereum, so resolving a name means reading from an Ethereum node. Read more about [SimpleX Public Names](./protocol/names-overview.md). + +With the `[NAMES]` section enabled, your smp-server resolves names for the clients connected to it: it forwards their lookups to a local REST resolver and returns the addresses. Resolution is off by default and requires running a resolver stack (an Ethereum node plus the resolver service), which needs: + +- 300 GB or more of NVMe SSD (TLC, not QLC, which stalls during sync) +- 32 GB RAM and a fast multi-core CPU +- about one day for the initial Ethereum sync + +### 1. Deploy the resolver stack + +The resolver stack (a reth + nimbus Ethereum node plus the resolver service) ships in [`scripts/resolver`](https://github.com/simplex-chat/simplexmq/tree/master/scripts/resolver) and starts with one command. See its [README](https://github.com/simplex-chat/simplexmq/blob/master/scripts/resolver/README.md) for details. + +```sh +git clone https://github.com/simplex-chat/simplexmq +cd simplexmq/scripts/resolver +docker compose up -d +``` + +The shipped `.env` targets Ethereum mainnet and needs no changes. Open the peer-to-peer ports so the node can sync: + +```sh +ufw allow 30303 &&\ +ufw allow 9000 +``` + +The resolver returns errors until the node finishes syncing, which takes about a day. + +### 2. Check the resolver + +Once synced, confirm the resolver is healthy and resolves a name: + +```sh +curl -s http://127.0.0.1:8000/health +curl -s http://127.0.0.1:8000/resolve/foobar.testing +``` + +The first should report `"ok": true`. The second should return the records for the test name `foobar.testing`. + +### 3. Point smp-server at the resolver + +In `/etc/opt/simplex/smp-server.ini`, set the `[NAMES]` section: + +```ini +[NAMES] +enable: on +resolver_endpoint: http://127.0.0.1:8000 +``` + +No authentication is needed while smp-server and the resolver share a host over loopback. Behind a TLS reverse proxy on another host, use its HTTPS address and add credentials (`resolver_auth` over plain `http` is only allowed for loopback): + +```ini +[NAMES] +enable: on +resolver_endpoint: https://names.example.com:443 +resolver_auth: basic : +``` + +### 4. Restart smp-server + +```sh +systemctl restart smp-server +``` + +The server logs the resolver status on start: + +``` +[NAMES] resolver enabled, endpoint=http://127.0.0.1:8000 +[NAMES] endpoint probe ok +``` + +If the node is still syncing the server starts anyway, and name lookups fail until the resolver is ready. + ## Documentation All necessary files for `smp-server` are located in `/etc/opt/simplex/` folder. From 937c79bc3cb99fa0e99f40dd0569aad56b538bbb Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:11:45 +0400 Subject: [PATCH 2/2] website: fix broken GitHub links for project files in docs (#7229) * website: fix broken GitHub links for project files in docs * website: fix broken links across docs and pages Render glossary tooltips through the shared replaceLink transform so their relative links become absolute site URLs instead of 404ing when injected across pages; add the English-only routes (downloads, faq, jobs, reproduce, security, transparency) to supportedRoutes so the language switcher stops emitting href="undefined"; passthrough-copy docs/guide/images, docs/guide/diagrams and docs/themes. Fix the SIMPLEX.md p2p anchor typo and correct image paths in CLI, the v0.4 blog post and the fr/pl translation docs to point at the existing shared assets. --- blog/20210914-simplex-chat-v0.4-released.md | 4 +- docs/CLI.md | 6 +- docs/GLOSSARY.md | 2 +- docs/lang/fr/TRANSLATIONS.md | 4 +- docs/lang/pl/SERVER.md | 2 +- docs/lang/pl/TRANSLATIONS.md | 4 +- docs/lang/pl/WEBRTC.md | 6 +- website/.eleventy.js | 84 ++++++++++++--------- 8 files changed, 61 insertions(+), 51 deletions(-) diff --git a/blog/20210914-simplex-chat-v0.4-released.md b/blog/20210914-simplex-chat-v0.4-released.md index 31adf022a9..253745015b 100644 --- a/blog/20210914-simplex-chat-v0.4-released.md +++ b/blog/20210914-simplex-chat-v0.4-released.md @@ -30,13 +30,13 @@ To create a group use the `/g ` command. You can then invite contacts to **Please note:** Groups are not stored on any server; they are maintained as a list of members in the app database. Sending a message to the group sends a message to each member of the group. -![simplex-chat](../images/groups.gif) +![simplex-chat](/images/groups.gif) ### File transfer Sharing files is simple! To send a file to a contact, use the `/f @ ` command. The recipient will have to accept before the file is sent. -![simplex-chat](../images/files.gif) +![simplex-chat](/images/files.gif) ## We're always looking for help! diff --git a/docs/CLI.md b/docs/CLI.md index 628fe2a4af..dc7f85cd38 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -220,7 +220,7 @@ Use `/help` in chat to see the list of available commands. To create a group use `/g `, then add contacts to it with `/a `. You can then send messages to the group by entering `# `. Use `/help groups` for other commands. -![simplex-chat](../images/groups.gif) +![simplex-chat](/images/groups.gif) > **Please note**: the groups are not stored on any server, they are maintained as a list of members in the app database to whom the messages will be sent. @@ -228,7 +228,7 @@ To create a group use `/g `, then add contacts to it with `/a ` - the recipient will have to accept it before it is sent. Use `/help files` for other commands. -![simplex-chat](../images/files.gif) +![simplex-chat](/images/files.gif) You can send files to a group with `/f # `. @@ -242,4 +242,4 @@ User address is "long-term" in a sense that it is a multiple-use connection link Use `/help address` for other commands. -![simplex-chat](../images/user-addresses.gif) +![simplex-chat](/images/user-addresses.gif) diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md index c8fdd56bdd..5ea32c73e9 100644 --- a/docs/GLOSSARY.md +++ b/docs/GLOSSARY.md @@ -163,7 +163,7 @@ In the context of SimpleX network, these are the identifiers generated by SMP re Peer-to-peer (P2P) is the network architecture when participants have equal rights and communicate directly via a general purpose transport or overlay network. Unlike client-server architecture, all peers in a P2P network both provide and consume the resources. In the context of messaging, P2P architecture usually means that the messages are sent between peers, without user accounts or messages being stored on any servers. Examples are Tox, Briar, Cwtch and many others. -The advantage is that the participants do not depend on any servers. There are [multiple downsides](./SIMPLEX.md#comparison-with-p2p9-messaging-protocols) to that architecture, such as no asynchronous message delivery, the need for network-wide peer addresses, possibility of network-wide attacks, that are usually mitigated only by using a centralized authority. These disadvantages are avoided with [proxied P2P](#proxied-peer-to-peer) architecture. +The advantage is that the participants do not depend on any servers. There are [multiple downsides](./SIMPLEX.md#comparison-with-p2p-messaging-protocols) to that architecture, such as no asynchronous message delivery, the need for network-wide peer addresses, possibility of network-wide attacks, that are usually mitigated only by using a centralized authority. These disadvantages are avoided with [proxied P2P](#proxied-peer-to-peer) architecture. [Wikipedia](https://en.wikipedia.org/wiki/Peer-to-peer). diff --git a/docs/lang/fr/TRANSLATIONS.md b/docs/lang/fr/TRANSLATIONS.md index 1e216900e7..cb7de707ff 100644 --- a/docs/lang/fr/TRANSLATIONS.md +++ b/docs/lang/fr/TRANSLATIONS.md @@ -26,7 +26,7 @@ Ce document est créé pour accélérer ce processus, et partager quelques astuc 2. Certaines des chaînes n'ont pas besoin d'être traduites, mais elles doivent quand même être copiées - il y a un bouton dans l'interface weblate pour cela : -weblate: copy source to translation +weblate: copy source to translation 3. Weblate propose également des suggestions automatiques qui peuvent accélérer le processus. Parfois, elles peuvent être utilisées telles quelles, parfois elles nécessitent quelques retouches - cliquez pour les utiliser dans les traductions. @@ -34,7 +34,7 @@ Ce document est créé pour accélérer ce processus, et partager quelques astuc 5. Quand vous traduisez [l'app iOS](https://hosted.weblate.org/projects/simplex-chat/ios/), la plupart des chaînes de caractères sont identiques, elles peuvent être copiées en un clic dans la section Glossaire. L'indice visuel que cela est possible est que la chaîne source entière est surlignée en jaune. De nombreuses autres chaînes sont très similaires, elles ne diffèrent que par la syntaxe d'interpolation ou la façon dont la police en gras est utilisée - elles ne nécessitent qu'une édition minimale. Certaines chaînes sont propres à la plate-forme iOS. Elles doivent être traduites séparément. -weblate: automatic suggestions +weblate: automatic suggestions ## Une fois la traduction terminée diff --git a/docs/lang/pl/SERVER.md b/docs/lang/pl/SERVER.md index f4bffc1bcc..e3ffe40c16 100644 --- a/docs/lang/pl/SERVER.md +++ b/docs/lang/pl/SERVER.md @@ -482,4 +482,4 @@ Możliwe jest również udostępnienie adresu swojego serwera znajomym, pozwalaj _Uwaga_: Do obsługi haseł wymagany jest serwer SMP w wersji 4.0. Jeśli już posiadasz serwer, możesz dodać hasło do niego poprzez wpisanie hasła do pliku INI serwera. -       +       diff --git a/docs/lang/pl/TRANSLATIONS.md b/docs/lang/pl/TRANSLATIONS.md index 36daa5a148..531177dba5 100644 --- a/docs/lang/pl/TRANSLATIONS.md +++ b/docs/lang/pl/TRANSLATIONS.md @@ -39,7 +39,7 @@ Kroki są następujące: 2. Niektóre ciągi nie wymagają tłumaczenia, ale nadal trzeba je skopiować - w interfejsie użytkownika weblate znajduje się odpowiedni przycisk: -weblate: copy source to translation +weblate: copy source to translation 3. Weblate posiada również automatyczne sugestie, które mogą przyspieszyć ten proces. Czasami mogą być używane w niezmienionej formie, a czasami wymagają edycji - kliknij, aby użyć ich w tłumaczeniach. @@ -68,7 +68,7 @@ My wtedy: Serdecznie dziękujemy! To ogromny wysiłek i wielka pomoc dla rozwoju sieci SimpleX. -weblate: automatic suggestions +weblate: automatic suggestions ## Częste błędy w tłumaczeniu diff --git a/docs/lang/pl/WEBRTC.md b/docs/lang/pl/WEBRTC.md index d279491fb8..e291d887b5 100644 --- a/docs/lang/pl/WEBRTC.md +++ b/docs/lang/pl/WEBRTC.md @@ -139,7 +139,7 @@ To tyle - teraz możesz wykonywać połączenia audio i wideo za pośrednictwem 2. W sekcji **Build up ICE Server List** dodaj: - + - `STUN: stun::` kliknij `Add STUN` - `TURN: turn::`, `Username: `, `Credential: ` kliknij `Add TURN` @@ -148,11 +148,11 @@ To tyle - teraz możesz wykonywać połączenia audio i wideo za pośrednictwem 3. Powinieneś zobaczyć swoje serwery w sekcji **ICE server list**. Jeśli wszystko jest skonfigurowane poprawnie, naciśnij `Start test`: - + 4. W sekcji **Results** powinieneś zobaczyć coś takiego: - + Jeśli wyniki pokazują `srflx` i `relay`, wszystko jest skonfigurowane poprawnie! diff --git a/website/.eleventy.js b/website/.eleventy.js index 122e5bb673..a96614e4ba 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -21,10 +21,50 @@ linksData.forEach(entry => { entry.imageExists = entry.image && fs.existsSync(path.join(linkImagesDir, entry.image)) }) +// Rewrites relative markdown links to website permalinks or GitHub URLs. +// Shared by the main markdown renderer (markdownLib) and the glossary renderer +// below, so glossary tooltips injected into pages get absolute, working links. +function replaceLink(link, _env) { + let parsed = uri.parse(link) + if (parsed.scheme || parsed.host) return link + + let hostFile = path.resolve(_env.page.inputPath) + let linkFile = path.resolve(hostFile, '..', parsed.path) + if (parsed.path.startsWith('/')) { + let srcIndex = hostFile.indexOf("/src") + if (srcIndex !== -1) { + linkFile = path.join(hostFile.slice(0, srcIndex + 4), parsed.path) + } + } + + if (fs.existsSync(linkFile) && fs.statSync(linkFile).isFile()) { + // this condition works if the link is a valid website file + const fileContent = fs.readFileSync(linkFile, 'utf8') + parsed.path = (matter(fileContent).data?.permalink || parsed.path).replace(/\.md$/, ".html").toLowerCase() + } else if (!fs.existsSync(linkFile)) { + linkFile = linkFile.replace('/website/src', '') + if (fs.existsSync(linkFile)) { + // this condition works if the link is a valid project file + const githubUrl = "https://github.com/simplex-chat/simplex-chat/blob/stable" + const repoRoot = hostFile.slice(0, hostFile.indexOf('/website/src')) + const repoPath = linkFile.slice(repoRoot.length) + return `${githubUrl}${repoPath}` + } else { + // if the link is not a valid website file or project file + throw new Error(`Broken link: ${parsed.path} in ${hostFile}`) + } + } + + return uri.serialize(parsed) +} + // The implementation of Glossary feature -const md = new markdownIt() +const md = new markdownIt({ replaceLink }).use(markdownItReplaceLink) +// Resolve the glossary's relative links (e.g. ./SIMPLEX.md) as if rendered from +// its built location, so tooltips embedded on other pages get absolute URLs. +const glossaryInputPath = path.resolve(__dirname, 'src/docs/GLOSSARY.md') const glossaryMarkdownContent = fs.readFileSync(path.resolve(__dirname, '../docs/GLOSSARY.md'), 'utf8') -const glossaryHtmlContent = md.render(glossaryMarkdownContent) +const glossaryHtmlContent = md.render(glossaryMarkdownContent, { page: { inputPath: glossaryInputPath } }) const glossaryDOM = new JSDOM(glossaryHtmlContent) const glossaryDocument = glossaryDOM.window.document const glossary = require('./src/_data/glossary.json') @@ -63,7 +103,7 @@ const globalConfig = { } const translationsDirectoryPath = './langs' -const supportedRoutes = ["blog", "contact", "invitation", "messaging", "docs", "fdroid", "why", "file", ""] +const supportedRoutes = ["blog", "contact", "invitation", "messaging", "docs", "fdroid", "why", "file", "downloads", "faq", "reproduce", "transparency", "security", "jobs", ""] let supportedLangs = [] fs.readdir(translationsDirectoryPath, (err, files) => { if (err) { @@ -320,6 +360,9 @@ module.exports = function (ty) { ty.addPassthroughCopy("src/blog/images") ty.addPassthroughCopy("src/docs/*.png") ty.addPassthroughCopy("src/docs/images") + ty.addPassthroughCopy("src/docs/guide/images") + ty.addPassthroughCopy("src/docs/guide/diagrams") + ty.addPassthroughCopy("src/docs/themes") ty.addPassthroughCopy("src/docs/protocol/diagrams") ty.addPassthroughCopy("src/docs/protocol/*.json") ty.addPassthroughCopy("src/images") @@ -418,40 +461,7 @@ module.exports = function (ty) { html: true, breaks: true, linkify: true, - replaceLink: function (link, _env) { - let parsed = uri.parse(link) - if (parsed.scheme || parsed.host) return link - - let hostFile = path.resolve(_env.page.inputPath) - let linkFile = path.resolve(hostFile, '..', parsed.path) - if (parsed.path.startsWith('/')) { - let srcIndex = hostFile.indexOf("/src") - if (srcIndex !== -1) { - linkFile = path.join(hostFile.slice(0, srcIndex + 4), parsed.path) - } - } - - if (fs.existsSync(linkFile) && fs.statSync(linkFile).isFile()) { - // this condition works if the link is a valid website file - const fileContent = fs.readFileSync(linkFile, 'utf8') - parsed.path = (matter(fileContent).data?.permalink || parsed.path).replace(/\.md$/, ".html").toLowerCase() - } else if (!fs.existsSync(linkFile)) { - linkFile = linkFile.replace('/website/src', '') - if (fs.existsSync(linkFile)) { - // this condition works if the link is a valid project file - const githubUrl = "https://github.com/simplex-chat/simplex-chat/blob/stable" - const keyword = "/simplex-chat" - index = linkFile.indexOf(keyword) - linkFile = linkFile.substring(index + keyword.length) - parsed.path = `${githubUrl}${linkFile}` - } else { - // if the link is not a valid website file or project file - throw new Error(`Broken link: ${parsed.path} in ${hostFile}`) - } - } - - return uri.serialize(parsed) - } + replaceLink: replaceLink }).use(markdownItAnchor, { slugify: (str) => slugify(str, {