# Tauri Deployment Setup

> Expert guide for setting up Tauri deployment pipelines with GitHub Actions, code signing, and Oasis update server integration.

- Skill: `porkytheblack/tauri-deployment-setup` (Agent Skill)
- Install (CLI): `npx skillmds@latest add porkytheblack/tauri-deployment-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/porkytheblack/tauri-deployment-setup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: porkytheblack (https://skillmd.com/u/porkytheblack)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/porkytheblack/tauri-deployment-setup

---


# Tauri Deployment Setup — Development Guide

You are an expert on Tauri deployment pipelines. Use this knowledge when setting up CI/CD, configuring code signing, or integrating with the Oasis update server.

## What It Is

A comprehensive deployment system for Tauri desktop applications that handles multi-platform builds, code signing, artifact storage, and automatic updates.

**Reusable workflow**: `porkytheblack/oasis/.github/workflows/tauri-release.yml@main`
**This project's workflow**: `.github/workflows/release.yaml`

## Architecture at a Glance

```
Developer pushes tag → GitHub Actions triggers
                              ↓
        ┌─────────────────────┴─────────────────────┐
        ↓                     ↓                     ↓
   macOS Build           Windows Build         Linux Build
   (Apple signed)        (optional sign)       (AppImage)
        ↓                     ↓                     ↓
        └─────────────────────┬─────────────────────┘
                              ↓
                    Tauri Update Signing
                              ↓
        ┌─────────────────────┼─────────────────────┐
        ↓                     ↓                     ↓
   Upload to R2         Register with Oasis    GitHub Release
   (CDN storage)        (update manifest)      (user downloads)
```

## Quick Start

### 1. Install dependencies

```bash
pnpm add -D @tauri-apps/cli
```

### 2. Generate signing keys

```bash
npx @tauri-apps/cli signer generate -w ~/.tauri/keys/your-app.key
# Save the public key for tauri.conf.json
# Save the private key as TAURI_SIGNING_PRIVATE_KEY secret
```

### 3. Create release workflow

```yaml
# .github/workflows/release.yaml
name: Release

on:
  push:
    tags: ["v*"]

permissions:
  contents: write

jobs:
  release:
    uses: porkytheblack/oasis/.github/workflows/tauri-release.yml@main
    with:
      app_slug: your-app
      app_name: Your App
      artifact_prefix: YourApp
      app_dir: app
      distribute_to: r2,oasis,github
    secrets:
      APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
      APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
      APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
      APPLE_ID: ${{ secrets.APPLE_ID }}
      APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
      APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
      TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
      TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
      CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
      CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
      CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
      R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}
      OASIS_SERVER_URL: ${{ secrets.OASIS_SERVER_URL }}
      OASIS_CI_KEY: ${{ secrets.OASIS_CI_KEY }}
```

### 4. Configure updater in tauri.conf.json

```json
{
  "plugins": {
    "updater": {
      "pubkey": "YOUR_PUBLIC_KEY_HERE",
      "endpoints": [
        "https://oasis.yourdomain.com/{app_slug}/update/{{target}}-{{arch}}/{{current_version}}"
      ]
    }
  }
}
```

### 5. Trigger release

```bash
./app/scripts/bump-version.sh patch
git push && git push --tags
```

## Version Files to Sync

| File | Format | Location |
|------|--------|----------|
| `package.json` | `"version": "X.Y.Z"` | App root |
| `tauri.conf.json` | `"version": "X.Y.Z"` | src-tauri/ |
| `Cargo.toml` | `version = "X.Y.Z"` | src-tauri/ |
| Status bar | `vX.Y.Z` display | UI component |

Use `./app/scripts/bump-version.sh` to update all files automatically.

## Distribution Targets

| Target | Purpose | When to Use |
|--------|---------|-------------|
| `github` | GitHub Releases page | User downloads, changelog |
| `r2` | Cloudflare R2 CDN | Fast artifact delivery |
| `oasis` | Update server | Auto-update manifests |

Combine with comma: `distribute_to: r2,oasis,github`

## Required Secrets

### Apple Code Signing (macOS)

| Secret | Description |
|--------|-------------|
| `APPLE_CERTIFICATE` | Base64-encoded .p12 certificate |
| `APPLE_CERTIFICATE_PASSWORD` | Certificate password |
| `APPLE_SIGNING_IDENTITY` | e.g., "Developer ID Application: Your Name" |
| `APPLE_ID` | Apple ID email |
| `APPLE_PASSWORD` | App-specific password (not Apple ID password) |
| `APPLE_TEAM_ID` | 10-character Team ID |

### Tauri Update Signing

| Secret | Description |
|--------|-------------|
| `TAURI_SIGNING_PRIVATE_KEY` | Private key from signer generate |
| `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` | Password used during generation |

### Cloudflare R2

| Secret | Description |
|--------|-------------|
| `CLOUDFLARE_ACCOUNT_ID` | Account ID from dashboard |
| `CLOUDFLARE_R2_ACCESS_KEY_ID` | R2 API token ID |
| `CLOUDFLARE_R2_SECRET_ACCESS_KEY` | R2 API token secret |
| `R2_BUCKET_NAME` | Bucket name |

### Oasis Server

| Secret | Description |
|--------|-------------|
| `OASIS_SERVER_URL` | e.g., `https://oasis.yourdomain.com` |
| `OASIS_CI_KEY` | CI authentication key |

## Tauri Capabilities

Add to `capabilities/default.json`:

```json
{
  "permissions": [
    "core:default",
    "core:window:default",
    "core:window:allow-start-dragging",
    "shell:default",
    "shell:allow-open",
    "dialog:default",
    "fs:default",
    "http:default",
    "updater:default",
    "updater:allow-check",
    "updater:allow-download-and-install",
    "process:default",
    "process:allow-restart"
  ]
}
```

## Release Commands (This Project)

| Action | Command |
|--------|---------|
| Bump patch | `./app/scripts/bump-version.sh patch` |
| Bump minor | `./app/scripts/bump-version.sh minor` |
| Bump major | `./app/scripts/bump-version.sh major` |
| Set version | `./app/scripts/bump-version.sh --set 2.0.0` |
| Preview | `./app/scripts/bump-version.sh patch --dry-run` |
| Push release | `git push && git push --tags` |
| Redeploy | `./app/scripts/redeploy.sh` |

## Common Gotchas

1. **Apple signing identity must match exactly** — Copy the full name from Keychain Access, including "Developer ID Application:" prefix.
2. **App-specific password, not Apple ID password** — Generate at appleid.apple.com under Security → App-Specific Passwords.
3. **Public key mismatch** — If updates fail signature verification, regenerate keys and update both `tauri.conf.json` and the GitHub secret.
4. **R2 public URL required** — Set `R2_PUBLIC_URL` as a repository variable (not secret) for the CDN base URL.
5. **Version mismatch breaks updates** — All version files must match. Use the bump script, not manual edits.
6. **Tag format matters** — Workflow triggers on `v*` tags. Use `v0.1.0`, not `0.1.0`.
7. **Workflow permissions** — Ensure `contents: write` permission for creating GitHub releases.
8. **macOS notarization takes time** — Apple notarization can take 5-15 minutes. Don't cancel the workflow early.
9. **Secrets are case-sensitive** — Double-check secret names match exactly.
10. **Dry run first** — Use `workflow_dispatch` with `dry_run: true` to test without uploading.

