using-crabnebula-cloud-with-tauri

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CrabNebula Cloud with Tauri

结合Tauri使用CrabNebula Cloud

CrabNebula is an official Tauri partner providing a platform for application distribution that seamlessly integrates with the Tauri updater. The platform offers global CDN distribution, release management, and built-in auto-update support.
CrabNebula是Tauri的官方合作伙伴,提供一个与Tauri更新器无缝集成的应用分发平台。该平台支持全球CDN分发、版本发布管理以及内置的自动更新功能。

Overview

概述

CrabNebula Cloud provides:
  • Global CDN: Worldwide distribution of installers and updates
  • Release Channels: Support for multiple release tracks (stable, beta, nightly)
  • Auto-Updates: Built-in update server compatible with Tauri's updater plugin
  • Download Metrics: Analytics for tracking application downloads
  • CI/CD Integration: GitHub Actions support for automated releases
CrabNebula Cloud提供以下功能:
  • 全球CDN:安装包与更新包的全球范围分发
  • 发布渠道:支持多发布分支(稳定版、测试版、夜间版)
  • 自动更新:内置与Tauri更新器插件兼容的更新服务器
  • 下载统计:追踪应用下载量的分析功能
  • CI/CD集成:支持通过GitHub Actions实现自动化发布

Initial Setup

初始设置

1. Create CrabNebula Cloud Account

1. 创建CrabNebula Cloud账户

  1. Navigate to CrabNebula Cloud
  2. Sign in using GitHub or GitLab authentication
  3. Create an organization with a unique slug
  4. Create an application within your organization
  1. 访问 CrabNebula Cloud
  2. 使用GitHub或GitLab账号登录
  3. 创建一个带有唯一标识的组织
  4. 在组织内创建一个应用

2. Generate API Key

2. 生成API密钥

  1. Navigate to API Keys section in CrabNebula Cloud
  2. Generate a new key with Read/Write permissions
  3. Save this key securely (displayed only once)
  4. Add as
    CN_API_KEY
    repository secret in GitHub
Important: Use repository secrets, not environment secrets, as environment secrets may appear in logs.
  1. 进入CrabNebula Cloud的API密钥板块
  2. 生成一个拥有读写权限的新密钥
  3. 安全保存该密钥(仅会显示一次)
  4. 在GitHub中添加为仓库密钥
    CN_API_KEY
重要提示:请使用仓库密钥而非环境密钥,因为环境密钥可能会出现在日志中。

CLI Installation

CLI安装

Install the CrabNebula CLI to manage releases locally:
bash
undefined
安装CrabNebula CLI以在本地管理发布:
bash
undefined

macOS/Linux

macOS/Linux

Or via cargo

或通过cargo安装

cargo install cn-cli
undefined
cargo install cn-cli
undefined

Release Workflow

发布工作流

The release process follows four steps: draft, upload, publish, fetch.
发布流程分为四个步骤:草稿创建、资源上传、发布、获取最新版本信息。

Manual CLI Commands

手动CLI命令

bash
undefined
bash
undefined

Create a release draft

创建发布草稿

cn release draft ORG_SLUG/APP_SLUG VERSION
cn release draft ORG_SLUG/APP_SLUG VERSION

Upload assets with Tauri framework detection

上传资源,自动检测Tauri框架

cn release upload ORG_SLUG/APP_SLUG RELEASE_ID --framework tauri
cn release upload ORG_SLUG/APP_SLUG RELEASE_ID --framework tauri

Publish the release

发布版本

cn release publish ORG_SLUG/APP_SLUG RELEASE_ID
cn release publish ORG_SLUG/APP_SLUG RELEASE_ID

Fetch latest release info

获取最新版本信息

cn release latest ORG_SLUG/APP_SLUG
undefined
cn release latest ORG_SLUG/APP_SLUG
undefined

Upload Command Options

上传命令选项

bash
cn release upload ORG_SLUG/APP_SLUG RELEASE_ID \
  --framework tauri \
  --channel stable \
  --update-platform linux-x86_64 \
  --file path/to/binary \
  --signature path/to/signature
FlagDescription
--framework
Auto-detect bundles (
tauri
or
packager
)
--channel
Release channel (must match draft channel)
--update-platform
Platform identifier for updates
--file
Path to binary asset
--signature
Path to signature file (required with
--update-platform
)
bash
cn release upload ORG_SLUG/APP_SLUG RELEASE_ID \
  --framework tauri \
  --channel stable \
  --update-platform linux-x86_64 \
  --file path/to/binary \
  --signature path/to/signature
标识描述
--framework
自动检测打包类型(
tauri
packager
--channel
发布渠道(必须与草稿渠道匹配)
--update-platform
更新对应的平台标识符
--file
二进制资源的路径
--signature
签名文件路径(使用
--update-platform
时必填)

GitHub Actions Workflow

GitHub Actions工作流

Create
.github/workflows/release.yml
:
yaml
name: Release

on:
  push:
    branches:
      - main
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CN_APPLICATION: "your-org/your-app"

jobs:
  draft:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.read-version.outputs.version }}
    steps:
      - uses: actions/checkout@v4

      - name: Read version from tauri.conf.json
        id: read-version
        run: |
          VERSION=$(jq -r '.version' src-tauri/tauri.conf.json)
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: Create draft release
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release draft ${{ env.CN_APPLICATION }} ${{ steps.read-version.outputs.version }} --framework tauri
          api-key: ${{ secrets.CN_API_KEY }}

  build:
    needs: draft
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: ubuntu-22.04
            args: ""
          - platform: macos-latest
            args: "--target aarch64-apple-darwin"
          - platform: macos-latest
            args: "--target x86_64-apple-darwin"
          - platform: windows-latest
            args: ""
    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Install Rust stable
        uses: dtolnay/rust-action@stable
        with:
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}

      - name: Install Linux dependencies
        if: matrix.platform == 'ubuntu-22.04'
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

      - name: Install frontend dependencies
        run: npm ci

      - name: Build Tauri app
        uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
          TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
        with:
          args: ${{ matrix.args }}

      - name: Upload assets to CrabNebula Cloud
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release upload ${{ env.CN_APPLICATION }} --framework tauri
          api-key: ${{ secrets.CN_API_KEY }}

  publish:
    needs: [draft, build]
    runs-on: ubuntu-latest
    steps:
      - name: Publish release
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release publish ${{ env.CN_APPLICATION }} ${{ needs.draft.outputs.version }}
          api-key: ${{ secrets.CN_API_KEY }}
创建
.github/workflows/release.yml
yaml
name: Release

on:
  push:
    branches:
      - main
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  CN_APPLICATION: "your-org/your-app"

jobs:
  draft:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.read-version.outputs.version }}
    steps:
      - uses: actions/checkout@v4

      - name: Read version from tauri.conf.json
        id: read-version
        run: |
          VERSION=$(jq -r '.version' src-tauri/tauri.conf.json)
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: Create draft release
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release draft ${{ env.CN_APPLICATION }} ${{ steps.read-version.outputs.version }} --framework tauri
          api-key: ${{ secrets.CN_API_KEY }}

  build:
    needs: draft
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: ubuntu-22.04
            args: ""
          - platform: macos-latest
            args: "--target aarch64-apple-darwin"
          - platform: macos-latest
            args: "--target x86_64-apple-darwin"
          - platform: windows-latest
            args: ""
    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Install Rust stable
        uses: dtolnay/rust-action@stable
        with:
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}

      - name: Install Linux dependencies
        if: matrix.platform == 'ubuntu-22.04'
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

      - name: Install frontend dependencies
        run: npm ci

      - name: Build Tauri app
        uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
          TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
        with:
          args: ${{ matrix.args }}

      - name: Upload assets to CrabNebula Cloud
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release upload ${{ env.CN_APPLICATION }} --framework tauri
          api-key: ${{ secrets.CN_API_KEY }}

  publish:
    needs: [draft, build]
    runs-on: ubuntu-latest
    steps:
      - name: Publish release
        uses: crabnebula-dev/cloud-release@v0
        with:
          command: release publish ${{ env.CN_APPLICATION }} ${{ needs.draft.outputs.version }}
          api-key: ${{ secrets.CN_API_KEY }}

Auto-Updates Configuration

自动更新配置

1. Generate Signing Keys

1. 生成签名密钥

bash
cargo tauri signer generate -w ~/.tauri/myapp.key
This creates:
  • ~/.tauri/myapp.key
    - Private key (keep secret)
  • ~/.tauri/myapp.key.pub
    - Public key (add to config)
Add to GitHub repository secrets:
  • TAURI_SIGNING_PRIVATE_KEY
    : Contents of
    myapp.key
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD
    : Your password
bash
cargo tauri signer generate -w ~/.tauri/myapp.key
该命令会生成:
  • ~/.tauri/myapp.key
    - 私钥(需保密)
  • ~/.tauri/myapp.key.pub
    - 公钥(需添加到配置中)
将以下内容添加到GitHub仓库密钥:
  • TAURI_SIGNING_PRIVATE_KEY
    :
    myapp.key
    的内容
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD
    : 你的密钥密码

2. Configure tauri.conf.json

2. 配置tauri.conf.json

json
{
  "version": "0.1.0",
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "active": true,
      "endpoints": [
        "https://cdn.crabnebula.app/update/YOUR_ORG/YOUR_APP/{{target}}-{{arch}}/{{current_version}}"
      ],
      "dialog": true,
      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk..."
    }
  }
}
Important: Keep the
{{target}}
,
{{arch}}
, and
{{current_version}}
placeholders unchanged. Tauri replaces these dynamically at runtime.
For migrations from Tauri v1, use
"createUpdaterArtifacts": "v1Compatible"
.
json
{
  "version": "0.1.0",
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "active": true,
      "endpoints": [
        "https://cdn.crabnebula.app/update/YOUR_ORG/YOUR_APP/{{target}}-{{arch}}/{{current_version}}"
      ],
      "dialog": true,
      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk..."
    }
  }
}
重要提示:请勿修改
{{target}}
{{arch}}
{{current_version}}
占位符。Tauri会在运行时动态替换这些内容。
如果从Tauri v1迁移,请使用
"createUpdaterArtifacts": "v1Compatible"

3. Configure Capabilities

3. 配置权限

Update
/src-tauri/capabilities/main.json
:
json
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Main capability for the application",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "dialog:default",
    "updater:default",
    "process:default",
    "process:allow-restart"
  ]
}
更新
/src-tauri/capabilities/main.json
json
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Main capability for the application",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "dialog:default",
    "updater:default",
    "process:default",
    "process:allow-restart"
  ]
}

4. Install Dependencies

4. 安装依赖

Add to
src-tauri/Cargo.toml
:
toml
[dependencies]
tauri-plugin-updater = "2"
tauri-plugin-dialog = "2"
tauri-plugin-process = "2"
Install frontend packages:
bash
npm install @tauri-apps/plugin-updater @tauri-apps/plugin-dialog @tauri-apps/plugin-process
src-tauri/Cargo.toml
中添加:
toml
[dependencies]
tauri-plugin-updater = "2"
tauri-plugin-dialog = "2"
tauri-plugin-process = "2"
安装前端包:
bash
npm install @tauri-apps/plugin-updater @tauri-apps/plugin-dialog @tauri-apps/plugin-process

5. Register Plugins (Rust)

5. 注册插件(Rust)

Update
src-tauri/src/lib.rs
:
rust
use tauri::Manager;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_updater::Builder::new().build())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_process::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
更新
src-tauri/src/lib.rs
rust
use tauri::Manager;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_updater::Builder::new().build())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_process::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

6. Implement Update Check (TypeScript)

6. 实现更新检查(TypeScript)

Create
src/updater.ts
:
typescript
import { check } from "@tauri-apps/plugin-updater";
import { ask } from "@tauri-apps/plugin-dialog";
import { relaunch } from "@tauri-apps/plugin-process";

export async function checkForAppUpdates(): Promise<void> {
  try {
    const update = await check();

    if (!update?.available) {
      console.log("No update available");
      return;
    }

    const proceed = await ask(
      `Version ${update.version} is available!\n\nRelease notes:\n${update.body}`,
      {
        title: "Update Available",
        kind: "info",
        okLabel: "Update Now",
        cancelLabel: "Later"
      }
    );

    if (proceed) {
      console.log("Downloading and installing update...");
      await update.downloadAndInstall();
      await relaunch();
    }
  } catch (error) {
    console.error("Update check failed:", error);
  }
}
Call early in your app lifecycle:
typescript
// React example
import { useEffect } from "react";
import { checkForAppUpdates } from "./updater";

function App() {
  useEffect(() => {
    checkForAppUpdates();
  }, []);

  return <div>Your app content</div>;
}
创建
src/updater.ts
typescript
import { check } from "@tauri-apps/plugin-updater";
import { ask } from "@tauri-apps/plugin-dialog";
import { relaunch } from "@tauri-apps/plugin-process";

export async function checkForAppUpdates(): Promise<void> {
  try {
    const update = await check();

    if (!update?.available) {
      console.log("No update available");
      return;
    }

    const proceed = await ask(
      `Version ${update.version} is available!\n\nRelease notes:\n${update.body}`,
      {
        title: "Update Available",
        kind: "info",
        okLabel: "Update Now",
        cancelLabel: "Later"
      }
    );

    if (proceed) {
      console.log("Downloading and installing update...");
      await update.downloadAndInstall();
      await relaunch();
    }
  } catch (error) {
    console.error("Update check failed:", error);
  }
}
在应用生命周期早期调用:
typescript
// React example
import { useEffect } from "react";
import { checkForAppUpdates } from "./updater";

function App() {
  useEffect(() => {
    checkForAppUpdates();
  }, []);

  return <div>Your app content</div>;
}

Release Channels

发布渠道

For multiple distribution channels (beta, stable, nightly):
如需设置多分发渠道(测试版、稳定版、夜间版):

Option 1: Channel Argument

选项1:渠道参数

bash
undefined
bash
undefined

Create draft with channel

创建带渠道的草稿

cn release draft ORG/APP VERSION --channel beta
cn release draft ORG/APP VERSION --channel beta

Upload must specify same channel

上传时必须指定相同渠道

cn release upload ORG/APP RELEASE_ID --framework tauri --channel beta
undefined
cn release upload ORG/APP RELEASE_ID --framework tauri --channel beta
undefined

Option 2: Separate Applications

选项2:独立应用

Create separate applications in CrabNebula Cloud:
  • your-org/your-app
    (stable)
  • your-org/your-app-beta
    (beta)
Configure different update endpoints per channel in your app builds.
在CrabNebula Cloud中创建独立应用:
  • your-org/your-app
    (稳定版)
  • your-org/your-app-beta
    (测试版)
在不同渠道的应用构建中配置不同的更新端点。

Environment Variables Summary

环境变量汇总

VariableLocationDescription
CN_API_KEY
GitHub SecretsCrabNebula Cloud API key
TAURI_SIGNING_PRIVATE_KEY
GitHub SecretsContents of private signing key
TAURI_SIGNING_PRIVATE_KEY_PASSWORD
GitHub SecretsPassword for signing key
CN_APPLICATION
Workflow envOrganization/application slug
变量位置描述
CN_API_KEY
GitHub SecretsCrabNebula Cloud API密钥
TAURI_SIGNING_PRIVATE_KEY
GitHub Secrets签名私钥内容
TAURI_SIGNING_PRIVATE_KEY_PASSWORD
GitHub Secrets签名密钥密码
CN_APPLICATION
工作流环境变量组织/应用标识

Troubleshooting

故障排除

Update Check Fails

更新检查失败

  1. Verify endpoint URL matches your organization and app slugs
  2. Ensure public key in config matches the generated key
  3. Check that
    createUpdaterArtifacts
    is set to
    true
  4. Verify capabilities include required permissions
  1. 验证端点URL与组织和应用标识匹配
  2. 确保配置中的公钥与生成的密钥一致
  3. 确认
    createUpdaterArtifacts
    设置为
    true
  4. 验证权限包含所需的权限项

Build Fails on Upload

上传时构建失败

  1. Ensure
    CN_API_KEY
    is set as repository secret (not environment secret)
  2. Verify the draft was created successfully before upload
  3. Check that signing keys are properly configured
  1. 确保
    CN_API_KEY
    设置为仓库密钥(而非环境密钥)
  2. 验证草稿在上传前已成功创建
  3. 检查签名密钥是否配置正确

Signature Mismatch

签名不匹配

  1. Ensure
    TAURI_SIGNING_PRIVATE_KEY
    matches the public key in config
  2. Verify the same key pair is used across all builds
  3. For v1 migrations, use
    "createUpdaterArtifacts": "v1Compatible"
  1. 确保
    TAURI_SIGNING_PRIVATE_KEY
    与配置中的公钥匹配
  2. 验证所有构建使用同一密钥对
  3. 对于v1迁移,使用
    "createUpdaterArtifacts": "v1Compatible"

Resources

资源