From 53b202bff3ffebfe069c16a26d13e77ec9ce4033 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Thu, 14 Mar 2024 18:30:57 +0800 Subject: [PATCH 1/7] docs(features): update updater page --- pnpm-lock.yaml | 82 +++--- src/content/docs/features/stronghold.mdx | 233 ++++++++++++++- src/content/docs/features/updater.mdx | 360 ++++++++++++++++++++++- src/content/docs/features/upload.mdx | 85 +++++- 4 files changed, 704 insertions(+), 56 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f236c977cf..f7736e62db 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,13 +18,13 @@ importers: version: 4.3.0 '@astrojs/starlight': specifier: ^0.21.0 - version: 0.21.1(astro@4.5.3) + version: 0.21.1(astro@4.5.5) '@types/json-schema': specifier: ^7.0.15 version: 7.0.15 astro: specifier: ^4.4.4 - version: 4.5.3 + version: 4.5.5 astro-feelback: specifier: ^0.3.4 version: 0.3.4 @@ -45,13 +45,13 @@ importers: version: 0.33.2 shiki: specifier: ^1.1.7 - version: 1.1.7 + version: 1.2.0 starlight-blog: specifier: ^0.5.0 - version: 0.5.1(@astrojs/starlight@0.21.1)(astro@4.5.3) + version: 0.5.1(@astrojs/starlight@0.21.1)(astro@4.5.5) starlight-links-validator: specifier: ^0.6.0 - version: 0.6.0(@astrojs/starlight@0.21.1)(astro@4.5.3) + version: 0.6.0(@astrojs/starlight@0.21.1)(astro@4.5.5) packages/config-generator: dependencies: @@ -60,7 +60,7 @@ importers: version: 7.0.15 '@types/node': specifier: ^20.11.20 - version: 20.11.27 + version: 20.11.28 github-slugger: specifier: ^2.0.0 version: 2.0.0 @@ -96,7 +96,7 @@ importers: version: 6.2.0 simple-git: specifier: ^3.22.0 - version: 3.22.0 + version: 3.23.0 tsm: specifier: ^2.3.0 version: 2.3.0 @@ -177,7 +177,7 @@ packages: remark-parse: 11.0.0 remark-rehype: 11.1.0 remark-smartypants: 2.1.0 - shiki: 1.1.7 + shiki: 1.2.0 unified: 11.0.4 unist-util-remove-position: 5.0.0 unist-util-visit: 5.0.0 @@ -187,7 +187,7 @@ packages: - supports-color dev: false - /@astrojs/mdx@2.1.1(astro@4.5.3): + /@astrojs/mdx@2.1.1(astro@4.5.5): resolution: {integrity: sha512-AgGFdE7HOGmoFooGvMSatkA9FiSKwyVW7ImHot/bXJ6uAbFfu6iG2ht18Cf1pT22Hda/6iSCGWusFvBv0/EnKQ==} engines: {node: '>=18.14.1'} peerDependencies: @@ -196,7 +196,7 @@ packages: '@astrojs/markdown-remark': 4.2.1 '@mdx-js/mdx': 3.0.1 acorn: 8.11.3 - astro: 4.5.3 + astro: 4.5.5 es-module-lexer: 1.4.1 estree-util-visit: 2.0.0 github-slugger: 2.0.0 @@ -227,18 +227,18 @@ packages: zod: 3.22.4 dev: false - /@astrojs/starlight@0.21.1(astro@4.5.3): + /@astrojs/starlight@0.21.1(astro@4.5.5): resolution: {integrity: sha512-nQ5EwKnB3eI8jxQrbgzZJJcyxeIiL3GzsAhl//1fE541MlD+PKy53v1PsYPi/RILdjt1Pg39rf1fkJC/rhXRgw==} peerDependencies: astro: ^4.2.7 dependencies: - '@astrojs/mdx': 2.1.1(astro@4.5.3) + '@astrojs/mdx': 2.1.1(astro@4.5.5) '@astrojs/sitemap': 3.1.1 '@pagefind/default-ui': 1.0.4 '@types/hast': 3.0.4 '@types/mdast': 4.0.3 - astro: 4.5.3 - astro-expressive-code: 0.33.4(astro@4.5.3) + astro: 4.5.5 + astro-expressive-code: 0.33.4(astro@4.5.5) bcp-47: 2.1.0 hast-util-from-html: 2.0.1 hast-util-select: 6.0.2 @@ -756,7 +756,7 @@ packages: resolution: {integrity: sha512-XnDchHqCGk046hgQnu83t9+SDrRjsvpvUEBiI0wl4RljVDr1E0yllx0y6C1yEuKfFfasib6BxX/PkItgQdi/0Q==} dependencies: '@expressive-code/core': 0.33.4 - shiki: 1.1.7 + shiki: 1.2.0 dev: false /@expressive-code/plugin-text-markers@0.33.4: @@ -1197,8 +1197,8 @@ packages: dev: false optional: true - /@shikijs/core@1.1.7: - resolution: {integrity: sha512-gTYLUIuD1UbZp/11qozD3fWpUTuMqPSf3svDMMrL0UmlGU7D9dPw/V1FonwAorCUJBltaaESxq90jrSjQyGixg==} + /@shikijs/core@1.2.0: + resolution: {integrity: sha512-OlFvx+nyr5C8zpcMBnSGir0YPD6K11uYhouqhNmm1qLiis4GA7SsGtu07r9gKS9omks8RtQqHrJL4S+lqWK01A==} dev: false /@types/acorn@4.0.6: @@ -1296,8 +1296,8 @@ packages: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false - /@types/node@20.11.27: - resolution: {integrity: sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==} + /@types/node@20.11.28: + resolution: {integrity: sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==} dependencies: undici-types: 5.26.5 dev: false @@ -1420,12 +1420,12 @@ packages: hasBin: true dev: false - /astro-expressive-code@0.33.4(astro@4.5.3): + /astro-expressive-code@0.33.4(astro@4.5.5): resolution: {integrity: sha512-PtXLjd89WBA1WsDYlt3V1LZs9Pa8FFoXilaGDSyfxtbYJ2OPHjWh2JJvCiXmfXmY3HkPJ2oW9Jjo6om5vUlVcg==} peerDependencies: astro: ^3.3.0 || ^4.0.0-beta dependencies: - astro: 4.5.3 + astro: 4.5.5 hast-util-to-html: 8.0.4 remark-expressive-code: 0.33.4 dev: false @@ -1436,8 +1436,8 @@ packages: '@feelback/js': 0.3.4 dev: false - /astro@4.5.3: - resolution: {integrity: sha512-MEiLeAr3+THeadTZCQ4U+DI9VTTUZdYrPEPedSKmQwqnkiPkLjpLgx4yOcyH7Yp4t57+SWiC6W0rt7lPGM36Fg==} + /astro@4.5.5: + resolution: {integrity: sha512-gZ3jR06dLmY9/SMkKMr+3pRSrUjhuwjnXt+9abFJV3WGwhCnLZbSNsTBrLMsaFHpAS1ReJChcTWyKRCvs/jCIQ==} engines: {node: '>=18.14.1', npm: '>=6.14.0'} hasBin: true dependencies: @@ -1491,7 +1491,7 @@ packages: rehype: 13.0.1 resolve: 1.22.8 semver: 7.6.0 - shiki: 1.1.7 + shiki: 1.2.0 string-width: 7.1.0 strip-ansi: 7.1.0 tsconfck: 3.0.3 @@ -1592,8 +1592,8 @@ packages: is-decimal: 2.0.1 dev: false - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} dev: false @@ -1651,7 +1651,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001597 - electron-to-chromium: 1.4.704 + electron-to-chromium: 1.4.708 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.23.0) dev: false @@ -1967,8 +1967,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: false - /electron-to-chromium@1.4.704: - resolution: {integrity: sha512-OK01+86Qvby1V6cTiowVbhp25aX4DLZnwar+NocAOXdzKAByd+jq5156bmo4kHwevWMknznW18Y/Svfk2dU91A==} + /electron-to-chromium@1.4.708: + resolution: {integrity: sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA==} dev: false /emoji-regex@10.3.0: @@ -2857,7 +2857,7 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 dev: false /is-buffer@2.0.5: @@ -4515,10 +4515,10 @@ packages: vscode-textmate: 8.0.0 dev: false - /shiki@1.1.7: - resolution: {integrity: sha512-9kUTMjZtcPH3i7vHunA6EraTPpPOITYTdA5uMrvsJRexktqP0s7P3s9HVK80b4pP42FRVe03D7fT3NmJv2yYhw==} + /shiki@1.2.0: + resolution: {integrity: sha512-xLhiTMOIUXCv5DqJ4I70GgQCtdlzsTqFLZWcMHHG3TAieBUbvEGthdrlPDlX4mL/Wszx9C6rEcxU6kMlg4YlxA==} dependencies: - '@shikijs/core': 1.1.7 + '@shikijs/core': 1.2.0 dev: false /shikiji-core@0.9.19: @@ -4556,8 +4556,8 @@ packages: dev: false optional: true - /simple-git@3.22.0: - resolution: {integrity: sha512-6JujwSs0ac82jkGjMHiCnTifvf1crOiY/+tfs/Pqih6iow7VrpNKRRNdWm6RtaXpvvv/JGNYhlUtLhGFqHF+Yw==} + /simple-git@3.23.0: + resolution: {integrity: sha512-P9ggTW8vb/21CAL/AmnACAhqBDfnqSSZVpV7WuFtsFR9HLunf5IqQvk+OXAQTfkcZep8pKnt3DV3o7w3TegEkQ==} dependencies: '@kwsites/file-exists': 1.1.1 '@kwsites/promise-deferred': 1.1.1 @@ -4605,27 +4605,27 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: false - /starlight-blog@0.5.1(@astrojs/starlight@0.21.1)(astro@4.5.3): + /starlight-blog@0.5.1(@astrojs/starlight@0.21.1)(astro@4.5.5): resolution: {integrity: sha512-3zJ7sJDe3rsE+9vJU/hDOKpKXEJwEMN0ha24DmKmKPKN5mtrN43p/ZJdrhRpb+PyJoJR4eNAtMLNgFyEu40cGA==} engines: {node: '>=18.14.1'} peerDependencies: '@astrojs/starlight': '>=0.19.0' astro: '>=4.2.7' dependencies: - '@astrojs/starlight': 0.21.1(astro@4.5.3) - astro: 4.5.3 + '@astrojs/starlight': 0.21.1(astro@4.5.5) + astro: 4.5.5 github-slugger: 2.0.0 dev: false - /starlight-links-validator@0.6.0(@astrojs/starlight@0.21.1)(astro@4.5.3): + /starlight-links-validator@0.6.0(@astrojs/starlight@0.21.1)(astro@4.5.5): resolution: {integrity: sha512-YXzKKZHM79ccBTO61l2WSmgdCG3406gldpVM6J2LhqZ5CeXsOgj6lho2xMLkc/p5nWcNSuYI2qNzsNUrLTmR5w==} engines: {node: '>=18.14.1'} peerDependencies: '@astrojs/starlight': '>=0.15.0' astro: '>=4.0.0' dependencies: - '@astrojs/starlight': 0.21.1(astro@4.5.3) - astro: 4.5.3 + '@astrojs/starlight': 0.21.1(astro@4.5.5) + astro: 4.5.5 github-slugger: 2.0.0 hast-util-from-html: 2.0.1 hast-util-has-property: 3.0.0 diff --git a/src/content/docs/features/stronghold.mdx b/src/content/docs/features/stronghold.mdx index 530b4c5ac1..d250e4df10 100644 --- a/src/content/docs/features/stronghold.mdx +++ b/src/content/docs/features/stronghold.mdx @@ -3,12 +3,235 @@ title: Stronghold description: Encrypted, secure database. --- -import Stub from '@components/Stub.astro'; import PluginLinks from '@components/PluginLinks.astro'; +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; - - Based on - https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/stronghold - +Store secrets and keys using the [IOTA Stronghold](https://github.com/iotaledger/stronghold.rs) encrypted database and secure runtime. + +## Supported Platforms + +- Windows +- Linux +- macOS + +## Setup + +_This plugin requires a Rust version of at least **1.75**_ + +Install the stronghold plugin to get started. + + + + Use your project's package manager to add the dependency: + + { ' ' } + + + + + + + + 1. Install the stronghold plugin by adding the following to your `Cargo.toml` file: + + ```toml title="src-tauri/Cargo.toml" + [dependencies] + tauri-plugin-stronghold = "2.0.0-beta" + # alternatively with Git: + tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. Modify `lib.rs` to initialize the plugin: + + ```rust title="src-tauri/src/lib.rs" ins={3} + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_stronghold::Builder::new(|password| {}).build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. Install the JavaScript Guest bindings using your preferred JavaScript package manager: + + + + + + + + +## Usage + +### Initialize with custom password hash function + +```rust title="src-tauri/src/lib.rs" +pub fn run() { + tauri::Builder::default() + .plugin( + tauri_plugin_stronghold::Builder::new(|password| { + // Hash the password here with e.g. argon2, blake2b or any other secure algorithm + // Here is an example implementation using the `rust-argon2` crate for hashing the password + use argon2::{hash_raw, Config, Variant, Version}; + + let config = Config { + lanes: 4, + mem_cost: 10_000, + time_cost: 10, + variant: Variant::Argon2id, + version: Version::Version13, + ..Default::default() + }; + let salt = "your-salt".as_bytes(); + let key = + hash_raw(password.as_ref(), salt, &config).expect("failed to hash password"); + + key.to_vec() + }) + .build(), + ) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +### Initialize with argon2 password hash function + +```rust title="src-tauri/src/lib.rs" +use tauri::Manager; + +pub fn run() { + tauri::Builder::default() + .setup(|app| { + let salt_path = app + .path() + .app_local_data_dir() + .expect("could not resolve app local data path") + .join("salt.txt"); + app.handle().plugin(tauri_plugin_stronghold::Builder::with_argon2(&salt_path).build())?; + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +### Usage from JavaScript + +The stronghold plugin is available in JavaScript. + +```js +import { Client, Stronghold } from '@tauri-apps/plugin-stronghold'; +import { appDataDir } from '@tauri-apps/api/path'; + +const initStronghold = async () => { + const vaultPath = `${await appDataDir()}/vault.hold`; + const vaultPassword = 'vault password'; + const stronghold = await Stronghold.load(vaultPath, vaultPassword); + + let client: Client; + const clientName = 'name your client'; + try { + client = await stronghold.loadClient(clientName); + } catch { + client = await stronghold.createClient(clientName); + } + + return { + stronghold, + client, + }; +}; + +// Insert a record to the store +async function insertRecord(store: any, key: string, value: string) { + const data = Array.from(new TextEncoder().encode(value)); + await store.insert(key, data); +} + +// Read a record from store +async function getRecord(store: any, key: string): Promise { + const data = await store.get(key); + return new TextDecoder().decode(new Uint8Array(data)); +} + +const { stronghold, client } = await initStronghold(); + +const store = client.getStore(); +const key = 'my_key'; + +// Insert a record to the store +insertRecord(store, key, 'secret value'); + +// Read a record from store +const value = await getRecord(store, key); +console.log(value); // 'secret value' + +// Save your updates +await stronghold.save(); + +// Remove a record from store +await store.remove(key); +``` + +## Permissions + +By default all plugin commands are blocked and cannot be accessed. You must define a list of permissions in your `capabilities` configuration. + +See [Access Control List](/references/v2/acl) for more information. + +```json title="src-tauri/capabilities/main.json" ins={8-14} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "path:default", + "stronghold:allow-initialize", + "stronghold:allow-create-client", + "stronghold:allow-load-client", + "stronghold:allow-save", + "stronghold:allow-save-store-record" + "stronghold:allow-get-store-record", + "stronghold:allow-remove-store-record", + ] +} +``` + +| Permission | Description | +| -------------------------------------- | ------------------------------------------------------------------------- | +| `stronghold:allow-create-client` | Enables the create_client command without any pre-configured scope. | +| `stronghold:deny-create-client` | Denies the create_client command without any pre-configured scope. | +| `stronghold:allow-destroy` | Enables the destroy command without any pre-configured scope. | +| `stronghold:deny-destroy` | Denies the destroy command without any pre-configured scope. | +| `stronghold:allow-execute-procedure` | Enables the execute_procedure command without any pre-configured scope. | +| `stronghold:deny-execute-procedure` | Denies the execute_procedure command without any pre-configured scope. | +| `stronghold:allow-get-store-record` | Enables the get_store_record command without any pre-configured scope. | +| `stronghold:deny-get-store-record` | Denies the get_store_record command without any pre-configured scope. | +| `stronghold:allow-initialize` | Enables the initialize command without any pre-configured scope. | +| `stronghold:deny-initialize` | Denies the initialize command without any pre-configured scope. | +| `stronghold:allow-load-client` | Enables the load_client command without any pre-configured scope. | +| `stronghold:deny-load-client` | Denies the load_client command without any pre-configured scope. | +| `stronghold:allow-remove-secret` | Enables the remove_secret command without any pre-configured scope. | +| `stronghold:deny-remove-secret` | Denies the remove_secret command without any pre-configured scope. | +| `stronghold:allow-remove-store-record` | Enables the remove_store_record command without any pre-configured scope. | +| `stronghold:deny-remove-store-record` | Denies the remove_store_record command without any pre-configured scope. | +| `stronghold:allow-save` | Enables the save command without any pre-configured scope. | +| `stronghold:deny-save` | Denies the save command without any pre-configured scope. | +| `stronghold:allow-save-secret` | Enables the save_secret command without any pre-configured scope. | +| `stronghold:deny-save-secret` | Denies the save_secret command without any pre-configured scope. | +| `stronghold:allow-save-store-record` | Enables the save_store_record command without any pre-configured scope. | +| `stronghold:deny-save-store-record` | Denies the save_store_record command without any pre-configured scope. | diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 0c694d4b0e..3d7d282001 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -3,12 +3,362 @@ title: Updater description: In-app updates for Tauri applications. --- -import Stub from '@components/Stub.astro'; import PluginLinks from '@components/PluginLinks.astro'; +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; - - Based on - https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/updater - +Updater plugin offers a updater for: + +- NSIS (Windows) +- MSI (Windows) +- AppImage (Linux) +- App bundle (macOS) + +Once your Tauri project is ready, you can configure Tauri's updater to enable auto updating for your users. + +## Supported Platforms + +- Windows +- Linux +- macOS + +## Setup + +_This plugin requires a Rust version of at least **1.75**_ + +Install the updater plugin to get started. + + + + Use your project's package manager to add the dependency: + + { ' ' } + + + + + + 1. Install the updater plugin by adding the following to your `Cargo.toml` file: + + ```toml title="src-tauri/Cargo.toml" + # you can add the dependencies on the `[dependencies]` section if you do not target mobile + [target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] + tauri-plugin-updater = "2.0.0-beta" + # alternatively with Git: + tauri-plugin-updater = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. Modify `lib.rs` to initialize the plugin: + + ```rust title="src-tauri/src/lib.rs" ins={3-7} + fn run() { + tauri::Builder::default() + .setup(|app| { + #[cfg(desktop)] + app.handle().plugin(tauri_plugin_updater::Builder::new().build())?; + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. Install the JavaScript Guest bindings using your preferred JavaScript package manager: + + + + + + +## Signing Updates + +Tauri's cli has a built-in signature mechanism to ensure that updates are safe to be installed. + +To sign your updates you need two things: + +1. The _public key_, which will be added to your `tauri.conf.json` file later, to validate update artifacts before the installation. +2. The _private key_, which is used to sign your update artifacts and should NEVER be shared with anyone. Also, if you lose this key, you will NOT be able to publish new updates to your current user base. It is crucial to store it in a safe place where you can always access it. + +To generate the keys on Linux and macOS you can use the Tauri CLI: + + + +If you are on Windows, you should use `$HOME/.tauri/myapp.key` or a different path of your choice instead: + + + +## Tauri Configuration + +Now you need to configure Tauri's updater. To do this, add this to your Tauri config: + +```json title="tauri.conf.json" +{ + "plugins": { + "updater": { + "endpoints": [ + "https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}" + ], + "pubkey": "YOUR_UPDATER_SIGNATURE_PUBKEY_HERE", + "windows": { + "installMode": "passive", + "installerArgs": [] + } + } + } +} +``` + +The required keys are `"endpoints"` and `"pubkey"` to enable the updater. + +`"endpoints"`: must be an array of updater endpoint URLs as strings. TLS is enforced in production mode.
+Each updater URL can contain the following variables allowing you to determine [server-side](#static-json-file) if an update is available: + +- `{{current_version}}`: The version of the app that is requesting the update. +- `{{target}}`: The operating system name (one of `linux`, `windows` or `darwin`). +- `{{arch}}`: The architecture of the machine (one of `x86_64`, `i686`, `aarch64` or `armv7`). + +`"pubkey"`: must be a valid public key generated with Tauri's CLI [above](#signing-updates). + +`"windows"`: (optional) The [Windows configuration](#windows-configuration) for the updater. + +### Windows Configuration + +`"installMode"`: The installation mode for the update on Windows. Defaults to `passive`. Can be any **ONE** of the following types: + +- `"passive"`: There will be a small window with a progress bar. The update will be installed without requiring any user interaction. Generally recommended and the default mode. +- `"basicUi"`: There will be a basic user interface shown which requires user interaction to finish the installation. +- `"quiet"`: There will be no progress feedback to the user. With this mode the installer cannot request admin privileges by itself so it only works in user-wide installations or when your app itself already runs with admin privileges. Generally not recommended. + +`"installerArgs"`: Array of command string. Additional arguments given to the NSIS or WiX installer. + +## Update Artifacts + +Tauri's bundler will automatically generate and sign update artifacts once the updater is correctly configured and enabled. + +Before building your app, you need to set environment variables for the private key and password: + +- `TAURI_SIGNING_PRIVATE_KEY`: Path or content of your private key +- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`: Your private key password (optional) + +If you want to set these variables for the current console session you could execute these commands in the console which you will use to build the app later: + + + + ```shell + export TAURI_SIGNING_PRIVATE_KEY="content of the generated key" + export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="password" + ``` + + + ```powershell + $env:TAURI_SIGNING_PRIVATE_KEY="content of the generated key" + $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD="password" + ``` + + + +After that, you can run `tauri build` as usual and Tauri will generate the update bundle and its signature. + +- **Linux**: On Linux, Tauri will create a `.tar.gz` archive from the AppImage inside the `target/release/bundle/appimage/` folder: + + - `myapp.AppImage` - the standard app bundle. + - `myapp.AppImage.tar.gz` - the updater bundle. + - `myapp.AppImage.tar.gz.sig` - the signature of the update bundle. + +- **macOS**: On macOS, Tauri will create a `.tar.gz` archive from the application bundle inside the `target/release/bundle/macos/` folder: + + - `myapp.app` - the standard app bundle. + - `myapp.app.tar.gz` - the updater bundle. + - `myapp.app.tar.gz.sig` - the signature of the update bundle. + +- **Windows**: On Windows, Tauri will create `.zip` archives from the MSI and NSIS installers inside the `target/release/bundle/msi/` and `target/release/bundle/nsis` folders: + - `myapp-setup.exe` - the standard app bundle. + - `myapp-setup.nsis.zip` - the updater bundle. + - `myapp-setup.nsis.zip.sig` - the signature of the update bundle. + - `myapp.msi` - the standard app bundle. + - `myapp.msi.zip` - the updater bundle. + - `myapp.msi.zip.sig` - the signature of the update bundle. + +The signature can be uploaded and shared safely as long as your private key is secure. + +## Server Support + +Tauri's updater supports two ways of announcing update data: + +- A static JSON file (to use on services like S3 or GitHub gists) +- A dynamic update server + +The static JSON file is easier to use while a dynamic update server will give you finer control over the update mechanism. + +### Static JSON File + +With this approach, Tauri will always request the same JSON file and determine if the app needs to be updated by comparing the version field of the response with the requesting app's current version. Tauri will expect a response in this format: + +```json +{ + "version": "v1.0.0", + "notes": "Test version", + "pub_date": "2020-06-22T19:25:57Z", + "platforms": { + "darwin-x86_64": { + "signature": "Content of app.tar.gz.sig", + "url": "https://github.com/username/reponame/releases/download/v1.0.0/app-x86_64.app.tar.gz" + }, + "darwin-aarch64": { + "signature": "Content of app.tar.gz.sig", + "url": "https://github.com/username/reponame/releases/download/v1.0.0/app-aarch64.app.tar.gz" + }, + "linux-x86_64": { + "signature": "Content of app.AppImage.tar.gz.sig", + "url": "https://github.com/username/reponame/releases/download/v1.0.0/app-amd64.AppImage.tar.gz" + }, + "windows-x86_64": { + "signature": "Content of app-setup.nsis.sig or app.msi.sig, depending on the chosen format", + "url": "https://github.com/username/reponame/releases/download/v1.0.0/app-x64-setup.nsis.zip" + } + } +} +``` + +The required keys are `"version"`, `"platforms.[target].url"` and `"platforms.[target].signature"`; the others are optional. + +- `"version"` must be a valid semver, with or without a leading `v`, meaning that both `1.0.0` and `v1.0.0` are valid. +- `"platforms"`: Each platform key is in the `OS-ARCH` format, where `OS` is one of `linux`, `darwin` or `windows`, and `ARCH` is one of `x86_64`, `aarch64`, `i686` or `armv7`. +- `"url"` must be a valid url to the update bundle. +- `"signature"` must be the **content** of the generated `.sig` file. The signature may change each time you run `tauri build` so make sure to always update it. +- `"notes"`: Here you can add notes about the update, like release notes. Tauri's default dialog will present this to the user when it asks if it's allowed to update. +- `"pub_date"` must be formatted according to [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) if present. + +Note that Tauri will validate the _whole_ file before checking the version field, so make sure all existing platform configurations are valid and complete. + +### Dynamic Update Server + +With this approach, Tauri will follow the update server's instructions. To disable the internal version check you can [overwrite Tauri's version comparison](https://docs.rs/tauri-plugin-updater/latest/tauri_plugin_updater/struct.UpdaterBuilder.html#method.version_comparator) to always install the version sent by the server. This could be useful if you need to roll back your app version quickly. + +Your server can use variables defined in the [`endpoint`](#config-enpoints) url above to determine if an update is required. If you need more data, you can include additional [request headers in Rust](https://docs.rs/tauri-plugin-updater/latest/tauri_plugin_updater/struct.UpdaterBuilder.html#method.header) to your liking. + +Your server should respond with a status code of [`204 No Content`](http://tools.ietf.org/html/rfc2616#section-10.2.5) if there is no update available. + +If an update is required, your server should respond with a status code of [`200 OK`](http://tools.ietf.org/html/rfc2616#section-10.2.1) and a JSON response in this format: + +```json +{ + "version": "0.2.0", + "pub_date": "2020-09-18T12:29:53+01:00", + "url": "https://mycompany.example.com/myapp/releases/myrelease.tar.gz", + "signature": "Content of the relevant .sig file", + "notes": "These are some release notes" +} +``` + +The required keys are "url", "version" and "signature"; the others are optional. + +- `"version"` must be a valid semver, with or without a leading `v`, meaning that both `1.0.0` and `v1.0.0` are valid. +- `"url"` must be a valid url to the update bundle. +- `"signature"` must be the **content** of the generated `.sig` file. The signature may change each time you run `tauri build` so make sure to always update it. +- `"notes"`: Here you can add notes about the update, like release notes. Tauri's default dialog will present this to the user when it asks if it's allowed to update. +- `"pub_date"` must be formatted according to [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) if present. + +## Usage + + + + ```js + import { check } from "@tauri-apps/plugin-updater"; + + const update = await check(); + if (update?.available) { + await update.downloadAndInstall(); + } + ``` + + + ```rust title="src-tauri/src/lib.rs" + use tauri_plugin_updater::UpdaterExt; + + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) + .setup(|app| { + let app_handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + let builder = app_handle.updater_builder(); + let updater = builder.build().unwrap(); + + match updater.check().await { + Ok(Some(update)) => { + if let Err(e) = update + .download_and_install( + || {}, + || { + println!("Download complete."); + }, + ) + .await + { + println!("Failed to download and install the update: {e}"); + } else { + println!("Update complete."); + } + } + Ok(None) => { + println!("No updates available."); + } + Err(e) => { + println!("Failed to check for updates: {e}"); + } + } + }); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + + +## Permissions + +By default, all plugin commands are blocked and cannot be accessed. You must define a list of permissions in your `capabilities` configuration. + +See [Access Control List](/references/v2/acl) for more information. + +```json title="src-tauri/capabilities/main.json" ins={6} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": ["updater:default"] +} +``` + +| Permission | Description | +|--------------------------------------|----------------------------------------------------------------------------| +| `updater:default` | Allows checking for new updates and installing them | +| `updater:allow-check` | Enables the check command without any pre-configured scope. | +| `updater:deny-check` | Denies the check command without any pre-configured scope. | +| `updater:allow-download-and-install` | Enables the download_and_install command without any pre-configured scope. | +| `updater:deny-download-and-install` | Denies the download_and_install command without any pre-configured scope. | diff --git a/src/content/docs/features/upload.mdx b/src/content/docs/features/upload.mdx index 0773a3000c..78a60ee6eb 100644 --- a/src/content/docs/features/upload.mdx +++ b/src/content/docs/features/upload.mdx @@ -3,12 +3,87 @@ title: Upload description: File uploads through HTTP. --- -import Stub from '@components/Stub.astro'; import PluginLinks from '@components/PluginLinks.astro'; +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; - - Based on - https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/upload - +Upload files from disk to a remote server over HTTP. Download files from a remote HTTP server to disk. + +## Setup + +_This plugin requires a Rust version of at least **1.75**_ + + + + + Use your project's package manager to add the dependency: + + + + + + + + + 1. Run `cargo add tauri-plugin-upload` to add the plugin to the project's dependencies in `Cargo.toml`. + + 2. Modify `lib.rs` to initialize the plugin: + + ```rust title="src-tauri/src/lib.rs" ins={5} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pb fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_upload::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. Install the JavaScript Guest bindings using your preferred JavaScript package manager: + + + + + + + + +## Usage + +Once you've completed the registration and setup process for the plugin, you can access all of its APIs through the JavaScript guest bindings. + +Here's an example of how you can use the plugin to upload and download files: + +```js +import { upload } from 'tauri-plugin-upload-api'; + +upload( + 'https://example.com/file-upload', + './path/to/my/file.txt', + (progress, total) => console.log(`Uploaded ${progress} of ${total} bytes`), // a callback that will be called with the upload progress + { 'Content-Type': 'text/plain' } // optional headers to send with the request +); +``` + +```js +import { download } from 'tauri-plugin-upload-api'; + +download( + 'https://example.com/file-download-link', + './path/to/save/my/file.txt', + (progress, total) => console.log(`Downloaded ${progress} of ${total} bytes`), // a callback that will be called with the download progress + { 'Content-Type': 'text/plain' } // optional headers to send with the request +); +``` From 2a4add1cc7ddbb9944d494482634c898dd7ddd6e Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Mon, 18 Mar 2024 16:32:40 +0800 Subject: [PATCH 2/7] Update src/content/docs/features/updater.mdx Co-authored-by: Fabian-Lars --- src/content/docs/features/updater.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 3d7d282001..5f68edbf99 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -9,7 +9,7 @@ import CommandTabs from '@components/CommandTabs.astro'; -Updater plugin offers a updater for: +The Updater plugin offers an update mechanism for Tauri applications distributed via: - NSIS (Windows) - MSI (Windows) From 356ca1247d4f7fe653a430b54bbe5d6eb233c3e5 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Mon, 18 Mar 2024 16:32:46 +0800 Subject: [PATCH 3/7] Update src/content/docs/features/updater.mdx Co-authored-by: Fabian-Lars --- src/content/docs/features/updater.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 5f68edbf99..9d3db7fa87 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -247,7 +247,7 @@ The required keys are `"version"`, `"platforms.[target].url"` and `"platforms.[t - `"platforms"`: Each platform key is in the `OS-ARCH` format, where `OS` is one of `linux`, `darwin` or `windows`, and `ARCH` is one of `x86_64`, `aarch64`, `i686` or `armv7`. - `"url"` must be a valid url to the update bundle. - `"signature"` must be the **content** of the generated `.sig` file. The signature may change each time you run `tauri build` so make sure to always update it. -- `"notes"`: Here you can add notes about the update, like release notes. Tauri's default dialog will present this to the user when it asks if it's allowed to update. +- `"notes"`: Here you can add notes about the update, like release notes. - `"pub_date"` must be formatted according to [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) if present. Note that Tauri will validate the _whole_ file before checking the version field, so make sure all existing platform configurations are valid and complete. From fb78a7b90abb9f1e911d6f91f8c20055fe842e40 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Mon, 18 Mar 2024 16:32:51 +0800 Subject: [PATCH 4/7] Update src/content/docs/features/updater.mdx Co-authored-by: Fabian-Lars --- src/content/docs/features/updater.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 9d3db7fa87..221c8dc138 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -277,7 +277,7 @@ The required keys are "url", "version" and "signature"; the others are optional. - `"version"` must be a valid semver, with or without a leading `v`, meaning that both `1.0.0` and `v1.0.0` are valid. - `"url"` must be a valid url to the update bundle. - `"signature"` must be the **content** of the generated `.sig` file. The signature may change each time you run `tauri build` so make sure to always update it. -- `"notes"`: Here you can add notes about the update, like release notes. Tauri's default dialog will present this to the user when it asks if it's allowed to update. +- `"notes"`: Here you can add notes about the update, like release notes. - `"pub_date"` must be formatted according to [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) if present. ## Usage From 41007b19580fef539a2a4043902756bcc0e1ef55 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Mon, 18 Mar 2024 16:33:03 +0800 Subject: [PATCH 5/7] Update src/content/docs/features/updater.mdx Co-authored-by: Fabian-Lars --- src/content/docs/features/updater.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 221c8dc138..9e0703fa87 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -129,7 +129,7 @@ Now you need to configure Tauri's updater. To do this, add this to your Tauri co } ``` -The required keys are `"endpoints"` and `"pubkey"` to enable the updater. +The required keys are `"endpoints"` and `"pubkey"` to enable the updater. The `"endpoints"` field can also be set later in Rust. `"endpoints"`
: must be an array of updater endpoint URLs as strings. TLS is enforced in production mode.
Each updater URL can contain the following variables allowing you to determine [server-side](#static-json-file) if an update is available: From fe44b494a7eed82424fb599e51d2f3e10a439d99 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Mon, 18 Mar 2024 16:33:09 +0800 Subject: [PATCH 6/7] Update src/content/docs/features/updater.mdx Co-authored-by: Fabian-Lars --- src/content/docs/features/updater.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 9e0703fa87..4c7c2aa7a4 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -132,6 +132,7 @@ Now you need to configure Tauri's updater. To do this, add this to your Tauri co The required keys are `"endpoints"` and `"pubkey"` to enable the updater. The `"endpoints"` field can also be set later in Rust. `"endpoints"`
: must be an array of updater endpoint URLs as strings. TLS is enforced in production mode.
+All endpoints should generally return the same content, Tauri will fall back to the next endpoint URL if it couldn't connect to the first one or if it returned a non-2XX status code.
Each updater URL can contain the following variables allowing you to determine [server-side](#static-json-file) if an update is available: - `{{current_version}}`: The version of the app that is requesting the update. From a9dca83cd2e17243c2093ce1060cc4f1a4182657 Mon Sep 17 00:00:00 2001 From: Jason Tsai Date: Tue, 19 Mar 2024 14:38:29 +0800 Subject: [PATCH 7/7] docs(updater): add a note for windows bundle --- src/content/docs/features/updater.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/content/docs/features/updater.mdx b/src/content/docs/features/updater.mdx index 4c7c2aa7a4..4a80040180 100644 --- a/src/content/docs/features/updater.mdx +++ b/src/content/docs/features/updater.mdx @@ -4,7 +4,7 @@ description: In-app updates for Tauri applications. --- import PluginLinks from '@components/PluginLinks.astro'; -import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; import CommandTabs from '@components/CommandTabs.astro'; @@ -18,6 +18,10 @@ The Updater plugin offers an update mechanism for Tauri applications distributed Once your Tauri project is ready, you can configure Tauri's updater to enable auto updating for your users. + + ## Supported Platforms - Windows