using-crabnebula-cloud-with-tauri
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCrabNebula 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账户
- Navigate to CrabNebula Cloud
- Sign in using GitHub or GitLab authentication
- Create an organization with a unique slug
- Create an application within your organization
- 访问 CrabNebula Cloud
- 使用GitHub或GitLab账号登录
- 创建一个带有唯一标识的组织
- 在组织内创建一个应用
2. Generate API Key
2. 生成API密钥
- Navigate to API Keys section in CrabNebula Cloud
- Generate a new key with Read/Write permissions
- Save this key securely (displayed only once)
- Add as repository secret in GitHub
CN_API_KEY
Important: Use repository secrets, not environment secrets, as environment secrets may appear in logs.
- 进入CrabNebula Cloud的API密钥板块
- 生成一个拥有读写权限的新密钥
- 安全保存该密钥(仅会显示一次)
- 在GitHub中添加为仓库密钥
CN_API_KEY
重要提示:请使用仓库密钥而非环境密钥,因为环境密钥可能会出现在日志中。
CLI Installation
CLI安装
Install the CrabNebula CLI to manage releases locally:
bash
undefined安装CrabNebula CLI以在本地管理发布:
bash
undefinedmacOS/Linux
macOS/Linux
curl -L https://cdn.crabnebula.app/install/cn | sh
curl -L https://cdn.crabnebula.app/install/cn | sh
Or via cargo
或通过cargo安装
cargo install cn-cli
undefinedcargo install cn-cli
undefinedRelease Workflow
发布工作流
The release process follows four steps: draft, upload, publish, fetch.
发布流程分为四个步骤:草稿创建、资源上传、发布、获取最新版本信息。
Manual CLI Commands
手动CLI命令
bash
undefinedbash
undefinedCreate 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
undefinedcn release latest ORG_SLUG/APP_SLUG
undefinedUpload 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| Flag | Description |
|---|---|
| Auto-detect bundles ( |
| Release channel (must match draft channel) |
| Platform identifier for updates |
| Path to binary asset |
| Path to signature file (required with |
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| 标识 | 描述 |
|---|---|
| 自动检测打包类型( |
| 发布渠道(必须与草稿渠道匹配) |
| 更新对应的平台标识符 |
| 二进制资源的路径 |
| 签名文件路径(使用 |
GitHub Actions Workflow
GitHub Actions工作流
Create :
.github/workflows/release.ymlyaml
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.ymlyaml
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.keyThis creates:
- - Private key (keep secret)
~/.tauri/myapp.key - - Public key (add to config)
~/.tauri/myapp.key.pub
Add to GitHub repository secrets:
- : Contents of
TAURI_SIGNING_PRIVATE_KEYmyapp.key - : Your password
TAURI_SIGNING_PRIVATE_KEY_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 , , and placeholders unchanged. Tauri replaces these dynamically at runtime.
{{target}}{{arch}}{{current_version}}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..."
}
}
}重要提示:请勿修改、和占位符。Tauri会在运行时动态替换这些内容。
{{target}}{{arch}}{{current_version}}如果从Tauri v1迁移,请使用。
"createUpdaterArtifacts": "v1Compatible"3. Configure Capabilities
3. 配置权限
Update :
/src-tauri/capabilities/main.jsonjson
{
"$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.jsonjson
{
"$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.tomltoml
[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.tomltoml
[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-process5. Register Plugins (Rust)
5. 注册插件(Rust)
Update :
src-tauri/src/lib.rsrust
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.rsrust
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.tstypescript
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.tstypescript
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
undefinedbash
undefinedCreate 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
undefinedcn release upload ORG/APP RELEASE_ID --framework tauri --channel beta
undefinedOption 2: Separate Applications
选项2:独立应用
Create separate applications in CrabNebula Cloud:
- (stable)
your-org/your-app - (beta)
your-org/your-app-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
环境变量汇总
| Variable | Location | Description |
|---|---|---|
| GitHub Secrets | CrabNebula Cloud API key |
| GitHub Secrets | Contents of private signing key |
| GitHub Secrets | Password for signing key |
| Workflow env | Organization/application slug |
| 变量 | 位置 | 描述 |
|---|---|---|
| GitHub Secrets | CrabNebula Cloud API密钥 |
| GitHub Secrets | 签名私钥内容 |
| GitHub Secrets | 签名密钥密码 |
| 工作流环境变量 | 组织/应用标识 |
Troubleshooting
故障排除
Update Check Fails
更新检查失败
- Verify endpoint URL matches your organization and app slugs
- Ensure public key in config matches the generated key
- Check that is set to
createUpdaterArtifactstrue - Verify capabilities include required permissions
- 验证端点URL与组织和应用标识匹配
- 确保配置中的公钥与生成的密钥一致
- 确认设置为
createUpdaterArtifactstrue - 验证权限包含所需的权限项
Build Fails on Upload
上传时构建失败
- Ensure is set as repository secret (not environment secret)
CN_API_KEY - Verify the draft was created successfully before upload
- Check that signing keys are properly configured
- 确保设置为仓库密钥(而非环境密钥)
CN_API_KEY - 验证草稿在上传前已成功创建
- 检查签名密钥是否配置正确
Signature Mismatch
签名不匹配
- Ensure matches the public key in config
TAURI_SIGNING_PRIVATE_KEY - Verify the same key pair is used across all builds
- For v1 migrations, use
"createUpdaterArtifacts": "v1Compatible"
- 确保与配置中的公钥匹配
TAURI_SIGNING_PRIVATE_KEY - 验证所有构建使用同一密钥对
- 对于v1迁移,使用
"createUpdaterArtifacts": "v1Compatible"