DESKTOP PACKAGING - nself-org/nchat GitHub Wiki

Desktop Packaging Guide

Complete guide for packaging and distributing nchat desktop applications using Electron and Tauri.

Table of Contents

  1. Overview
  2. Prerequisites
  3. Platform-Specific Requirements
  4. Build Commands
  5. Code Signing
  6. Auto-Updates
  7. Testing
  8. Distribution
  9. Troubleshooting

Overview

nchat supports two desktop runtimes:

  • Electron: Cross-platform using Chromium and Node.js
  • Tauri: Lightweight using system WebView and Rust

Supported Platforms

Platform Electron Tauri Formats
macOS .dmg, .zip, .app
Windows .exe (NSIS), .msi, portable
Linux .AppImage, .deb, .rpm, .tar.gz

Prerequisites

All Platforms

  • Node.js >= 20.0.0
  • pnpm >= 9.0.0
  • Git

macOS

# Xcode Command Line Tools
xcode-select --install

# For Tauri
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Windows

# Install Visual Studio Build Tools
# Download from: https://visualstudio.microsoft.com/downloads/

# For Tauri
# Install Rust from: https://rustup.rs/

Linux (Ubuntu/Debian)

# For Electron
sudo apt-get install -y \
  libgtk-3-0 libnotify4 libnss3 libxss1 libxtst6 \
  xdg-utils libatspi2.0-0 libuuid1 libsecret-1-0

# For Tauri
sudo apt-get install -y \
  libwebkit2gtk-4.1-dev libappindicator3-dev \
  librsvg2-dev patchelf libssl-dev libgtk-3-dev

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Platform-Specific Requirements

macOS Code Signing

Required for distribution:

  1. Apple Developer Account ($99/year)

  2. Developer ID Application Certificate

    # Request certificate in Xcode or Apple Developer portal
    # Export as .p12 file with password
    
  3. For Notarization (highly recommended)

    # Create app-specific password at appleid.apple.com
    # Get Team ID from Apple Developer portal
    

Windows Code Signing

Required for Windows SmartScreen reputation:

  1. Code Signing Certificate
    • Purchase from DigiCert, Sectigo, or other CA
    • Export as .pfx file with password
    • Extended Validation (EV) certificate recommended

Linux

  • Optional GPG signing for package repositories
  • No signature required for basic distribution

Build Commands

Quick Start

# Build for current platform (unsigned)
pnpm build:desktop

# Build with code signing
pnpm build:desktop:signed

# Build with code signing and notarization (macOS)
pnpm build:desktop:notarized

# Build specific runtime
pnpm build:desktop --runtime electron
pnpm build:desktop --runtime tauri

# Build specific platform
pnpm build:desktop --platform macos
pnpm build:desktop --platform windows
pnpm build:desktop --platform linux

Advanced Options

# Build with all options
./scripts/build-desktop.sh \
  --runtime all \
  --platform macos \
  --sign \
  --notarize \
  --release \
  --clean

Electron-Specific

cd platforms/electron

# Compile TypeScript
pnpm build:all

# Package for current platform
pnpm dist

# Package for specific platform
pnpm dist:mac
pnpm dist:win
pnpm dist:linux

# Package for all platforms (macOS host recommended)
pnpm dist:all

Tauri-Specific

# Build for current platform
pnpm tauri build

# Build with debug symbols
pnpm tauri build --debug

# Build for specific target (macOS)
pnpm tauri build --target universal-apple-darwin
pnpm tauri build --target x86_64-apple-darwin
pnpm tauri build --target aarch64-apple-darwin

# Build for specific target (Windows)
pnpm tauri build --target x86_64-pc-windows-msvc

# Build for specific target (Linux)
pnpm tauri build --target x86_64-unknown-linux-gnu

Code Signing

Check Signing Credentials

# Check all platforms
pnpm sign:check

# Check specific platform
./scripts/sign-desktop.sh --check --platform macos
./scripts/sign-desktop.sh --check --platform windows

Generate Signing Templates

pnpm sign:generate

This creates:

  • platforms/electron/signing/.env.signing.example
  • platforms/tauri/signing/.env.signing.example
  • platforms/*/signing/README.md

Environment Variables

macOS (Electron)

export CSC_LINK=/path/to/certificate.p12
export CSC_KEY_PASSWORD=your-certificate-password
export [email protected]
export APPLE_PASSWORD=your-app-specific-password
export APPLE_TEAM_ID=YOUR10CHARTEAMID

macOS (Tauri)

export APPLE_CERTIFICATE=/path/to/certificate.p12
export APPLE_CERTIFICATE_PASSWORD=your-certificate-password
export APPLE_SIGNING_IDENTITY="Developer ID Application: Your Name (TEAM_ID)"
export [email protected]
export APPLE_PASSWORD=your-app-specific-password
export APPLE_TEAM_ID=YOUR10CHARTEAMID

Windows (Both)

export WIN_CSC_LINK=/path/to/certificate.pfx
export WIN_CSC_KEY_PASSWORD=your-certificate-password

Tauri Auto-Update Signing

# Generate key pair
pnpm tauri signer generate

# Set private key
export TAURI_SIGNING_PRIVATE_KEY=your-base64-private-key
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD=your-key-password

# Add public key to platforms/tauri/tauri.conf.json
# under plugins.updater.pubkey

Verify Signatures

macOS

# Verify code signature
codesign -vvv --deep --strict /path/to/nchat.app

# Verify notarization
spctl -a -vvv -t install /path/to/nchat.app

# Check entitlements
codesign -d --entitlements - /path/to/nchat.app

Windows

# Verify signature (requires Windows SDK)
signtool verify /pa /v nchat-Setup.exe

# View signature details
signtool verify /pa /v /d nchat-Setup.exe

Linux

# Verify GPG signature (if signed)
gpg --verify package.deb.asc package.deb

Auto-Updates

Electron (electron-updater)

Configuration in platforms/electron/electron-builder.yml:

publish:
  - provider: github
    owner: nself
    repo: nself-chat
    releaseType: release

Update check in main process:

import { autoUpdater } from 'electron-updater';

autoUpdater.checkForUpdatesAndNotify();

Tauri (tauri-plugin-updater)

Configuration in platforms/tauri/tauri.conf.json:

{
  "plugins": {
    "updater": {
      "active": true,
      "pubkey": "YOUR_PUBLIC_KEY_HERE",
      "endpoints": [
        "https://releases.nself.org/nchat/{{target}}/{{arch}}/{{current_version}}"
      ]
    }
  }
}

Testing

Package Structure Testing

# Test package structure and metadata
pnpm test:packaging --runtime electron --package dist-electron/nchat-1.0.0.dmg
pnpm test:packaging --runtime tauri --package platforms/tauri/target/release/bundle/dmg/nchat.dmg

Manual Testing

macOS

# Install from DMG
open dist-electron/nchat-1.0.0.dmg
# Drag to Applications

# Test from Applications folder
open /Applications/nchat.app

# Test protocol handler
open nchat://test

# Check logs
tail -f ~/Library/Logs/nchat/main.log

Windows

# Run installer
dist-electron/nchat-Setup-1.0.0.exe

# Test from Start Menu
# Search for "nchat"

# Test protocol handler
start nchat://test

# Check logs
type %APPDATA%\nchat\logs\main.log

Linux

# AppImage
chmod +x dist-electron/nchat-1.0.0.AppImage
./dist-electron/nchat-1.0.0.AppImage

# Debian
sudo dpkg -i dist-electron/nchat_1.0.0_amd64.deb

# RPM
sudo rpm -i dist-electron/nchat-1.0.0.x86_64.rpm

# Test protocol handler
xdg-open nchat://test

# Check logs
tail -f ~/.config/nchat/logs/main.log

Automated Testing

# Run packaging tests
pnpm test:packaging

# CI/CD testing via GitHub Actions
# See .github/workflows/build-electron.yml
# See .github/workflows/build-tauri.yml

Distribution

GitHub Releases

# Tag release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0

# Upload artifacts via GitHub Actions
# Workflows automatically create draft releases

Direct Distribution

# Upload to S3
aws s3 cp dist-electron/ s3://releases.nself.org/nchat/ --recursive

# Upload to CDN
scp dist-electron/* [email protected]:/var/www/releases/nchat/

Mac App Store (Future)

Requires:

  • Mac App Store distribution certificate
  • App-specific provisioning profile
  • Sandboxed entitlements
  • App Store Connect submission

Microsoft Store (Future)

Requires:

  • Microsoft Store developer account
  • App package (.msix)
  • Store listing

Snap Store / Flathub (Future)

Requires:

  • Snapcraft/Flatpak configuration
  • Store account
  • Package submission

Build Artifacts

Output Locations

# Electron
dist-electron/
├── nchat-1.0.0-mac-x64.dmg          # macOS DMG
├── nchat-1.0.0-mac-arm64.dmg        # macOS ARM DMG
├── nchat-1.0.0-mac.zip              # macOS ZIP
├── nchat-Setup-1.0.0.exe            # Windows installer
├── nchat-1.0.0-Portable.exe         # Windows portable
├── nchat-1.0.0-x64.AppImage         # Linux AppImage
├── nchat_1.0.0_amd64.deb            # Debian package
└── nchat-1.0.0.x86_64.rpm           # RPM package

# Tauri
platforms/tauri/target/
├── universal-apple-darwin/release/bundle/
│   ├── dmg/nchat.dmg                # macOS DMG
│   └── macos/nchat.app              # macOS app bundle
├── release/bundle/
│   ├── msi/nchat.msi                # Windows MSI
│   ├── nsis/nchat.exe               # Windows NSIS
│   ├── appimage/nchat.AppImage      # Linux AppImage
│   ├── deb/nchat.deb                # Debian package
│   └── rpm/nchat.rpm                # RPM package

Typical Sizes

Platform Electron Tauri
macOS ~150MB ~15MB
Windows ~120MB ~10MB
Linux ~130MB ~12MB

Troubleshooting

macOS: "App is damaged and can't be opened"

Cause: Gatekeeper blocking unsigned or improperly signed app

Solution:

# Remove quarantine attribute
xattr -cr /Applications/nchat.app

# Or allow in System Settings > Security & Privacy

macOS: Notarization fails

Causes:

  • Invalid signing certificate
  • Missing entitlements
  • Incorrect bundle structure

Debug:

# Check notarization status
xcrun altool --notarization-info REQUEST_UUID \
  --username "[email protected]" \
  --password "app-specific-password"

# Check notarization log for errors

Windows: SmartScreen warning

Cause: Unsigned app or certificate without reputation

Solutions:

  • Use Extended Validation (EV) certificate (instant reputation)
  • Build download reputation over time
  • Sign with standard certificate and inform users

Linux: AppImage won't execute

Cause: Missing executable permission or FUSE

Solution:

# Add executable permission
chmod +x nchat.AppImage

# Install FUSE (if needed)
sudo apt-get install fuse

# Or extract and run
./nchat.AppImage --appimage-extract
./squashfs-root/AppRun

Build fails: Missing dependencies

Electron:

# Reinstall dependencies
cd platforms/electron
rm -rf node_modules
pnpm install

Tauri:

# Update Rust
rustup update

# Clear Cargo cache
cargo clean

# Rebuild
pnpm tauri build

Code signing fails: Invalid certificate

Check certificate validity:

# macOS
security find-identity -v -p codesigning

# Windows
certutil -dump certificate.pfx

Cross-platform builds fail

Solution: Use platform-specific runners

  • macOS: Can build for macOS, Windows (with wine), Linux (with docker)
  • Windows: Can only build for Windows
  • Linux: Can only build for Linux

Best practice: Use CI/CD with matrix builds

CI/CD Integration

GitHub Actions Secrets

Add these to your repository secrets:

# macOS
CSC_LINK (base64-encoded .p12 file)
CSC_KEY_PASSWORD
APPLE_ID
APPLE_PASSWORD (app-specific password)
APPLE_TEAM_ID

# Windows
WIN_CSC_LINK (base64-encoded .pfx file)
WIN_CSC_KEY_PASSWORD

# Tauri
TAURI_SIGNING_PRIVATE_KEY
TAURI_SIGNING_PRIVATE_KEY_PASSWORD

Workflow Dispatch

# Trigger via GitHub CLI
gh workflow run build-electron.yml \
  -f platform=macos \
  -f sign=true \
  -f release=true

Additional Resources