# Hostkeeper V2 — Build System > **Status**: V2 Planning Complete > **Last Updated**: 2026-06-29 --- ## 1. Build Overview Hostkeeper V2 produces **4 platform outputs** from a single codebase: | Platform | Output | Wrapper | Backend | |----------|--------|---------|---------| | macOS (ARM64) | `.dmg` | Electron | Go binary (embedded) | | macOS (x64) | `.dmg` | Electron | Go binary (embedded) | | Windows (x64) | `.exe` installer | Electron | Go binary (embedded) | | Linux (x64) | `.AppImage` | Electron | Go binary (embedded) | | Android (ARM64) | `.aab` / `.apk` | WebView | Go library (.aar) | | iOS (ARM64) | `.ipa` | WKWebView | Go framework (.xcframework) | --- ## 2. Build Pipeline ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Go Build │ │ Frontend │ │ Electron │ │ Platform │ │ (backend) │ → │ Build │ → │ Package │ → │ Sign │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ``` ### Step 1: Go Backend Cross-Compile ```bash # macOS ARM64 CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 \ go build -ldflags="-s -w" -o dist/hostkeeper-server . # macOS x64 CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 \ go build -ldflags="-s -w" -o dist/hostkeeper-server . # Windows x64 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 \ go build -ldflags="-s -w" -o dist/hostkeeper-server.exe . # Linux x64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ go build -ldflags="-s -w" -o dist/hostkeeper-server . # Linux ARM64 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \ go build -ldflags="-s -w" -o dist/hostkeeper-server . ``` **Notes**: - `CGO_ENABLED=0` — pure Go, no C dependencies - `-ldflags="-s -w"` — strip debug info, reduce binary size - Go binary size: ~15-20 MB (compressed) ### Step 2: Frontend Build ```bash cd app/frontend npm ci npm run build # Output: app/frontend/dist/ ``` **Vite config** (`app/frontend/vite.config.ts`): ```typescript import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], build: { outDir: 'dist', sourcemap: false, minify: 'terser', rollupOptions: { output: { manualChunks: { xterm: ['@xterm/xterm', '@xterm/addon-fit'], react: ['react', 'react-dom'], }, }, }, }, server: { proxy: { '/api': 'http://localhost:8080', '/ws': { target: 'ws://localhost:8080', ws: true, }, }, }, }); ``` ### Step 3: Electron Package ```yaml # app/electron/electron-builder.yml appId: com.hostkeeper.app productName: Hostkeeper copyright: Copyright © 2026 directories: output: ../../dist files: - "**/*" - "!**/node_modules/*/{CHANGELOG.md,README.md,readme.md,LICENSE}" extraResources: - from: "../backend/hostkeeper-server" to: "hostkeeper-server" - from: "../frontend/dist" to: "frontend" mac: category: public.app-category.developer-tools icon: assets/icon.icns target: - dmg - zip hardenedRuntime: true notarize: true win: icon: assets/icon.ico target: - nsis certificateFile: env.WIN_CERTIFICATE_FILE linux: icon: assets/icon.png target: - AppImage - deb category: Development nsis: oneClick: false allowToChangeInstallationDirectory: true ``` --- ## 3. Mobile Build ### Android ```bash # Prerequisites: # - Android SDK installed # - Go 1.26+ with gomobile # - Java 17+ # Install gomobile go install golang.org/x/mobile/cmd/gomobile@latest gomobile init # Build Go library cd mobile/gomobile gomobile bind -target=android -o=../android/app/libs/hostkeeper.aar \ ./go/ # Build Android app cd ../android ./gradlew assembleRelease # Output: mobile/android/app/build/outputs/apk/release/app-release.apk ``` ### iOS ```bash # Prerequisites: # - Xcode 15+ # - Go 1.26+ with gomobile # Build Go framework cd mobile/gomobile gomobile bind -target=ios -o=../ios/Hostkeeper/Hostkeeper.xcframework \ ./go/ # Build iOS app cd ../ios xcodebuild -project Hostkeeper.xcodeproj \ -scheme Hostkeeper \ -sdk iphoneos \ -configuration Release # Output: mobile/ios/build/Release-iphoneos/Hostkeeper.app ``` --- ## 4. Build Scripts ### `scripts/build.sh` (Full Build) ```bash #!/bin/bash set -e VERSION=${1:-"dev"} PLATFORM=${2:-"all"} echo "=== Building Hostkeeper V2 v${VERSION} ===" # Step 1: Build Go backend echo "Step 1: Building Go backend..." cd app/backend case $PLATFORM in macos|all) CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server . ;; windows|all) CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server.exe . ;; linux|all) CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server . ;; esac cd ../.. # Step 2: Build frontend echo "Step 2: Building frontend..." cd app/frontend npm ci npm run build cd ../.. # Step 3: Package Electron echo "Step 3: Packaging Electron..." cd app/electron case $PLATFORM in macos) npx electron-builder --mac --arm64 ;; windows) npx electron-builder --win --x64 ;; linux) npx electron-builder --linux --x64 ;; all) npx electron-builder --mac --win --linux ;; esac cd ../.. # Step 4: Generate checksums echo "Step 4: Generating checksums..." cd dist shasum -a 256 *.dmg *.exe *.AppImage 2>/dev/null > checksums.txt echo "=== Build complete ===" echo "Output: dist/" ls -la dist/ ``` ### `scripts/build-mobile.sh` ```bash #!/bin/bash set -e PLATFORM=${1:-"android"} echo "=== Building Hostkeeper Mobile (${PLATFORM}) ===" case $PLATFORM in android) cd mobile/gomobile gomobile bind -target=android -o=../android/app/libs/hostkeeper.aar ./go/ cd ../android ./gradlew assembleRelease echo "APK: mobile/android/app/build/outputs/apk/release/" ;; ios) cd mobile/gomobile gomobile bind -target=ios -o=../ios/Hostkeeper/Hostkeeper.xcframework ./go/ cd ../ios xcodebuild -project Hostkeeper.xcodeproj -scheme Hostkeeper -sdk iphoneos -configuration Release echo "IPA: mobile/ios/build/Release-iphoneos/" ;; esac echo "=== Mobile build complete ===" ``` --- ## 5. Development Workflow ### Quick Start ```bash # Terminal 1: Go backend cd app/backend go run . # Terminal 2: Frontend (with hot reload) cd app/frontend npm run dev # Open browser: http://localhost:5173 ``` ### With Electron ```bash # Terminal 1: Go backend cd app/backend go run . # Terminal 2: Frontend cd app/frontend npm run dev # Terminal 3: Electron cd app/electron npm run dev # Electron opens with hot reload ``` ### VS Code Launch Config ```json { "version": "0.2.0", "configurations": [ { "name": "Go Backend", "type": "go", "request": "launch", "program": "${workspaceFolder}/app/backend", "cwd": "${workspaceFolder}/app/backend" }, { "name": "Electron", "type": "node", "request": "launch", "program": "${workspaceFolder}/app/electron/node_modules/.bin/electron", "args": ["."], "cwd": "${workspaceFolder}/app/electron" } ] } ``` --- ## 6. CI/CD (GitHub Actions) ```yaml # .github/workflows/build.yml name: Build on: push: tags: ['v*'] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - run: go test -race ./app/backend/... - uses: actions/setup-node@v4 with: node-version: '22' - run: cd app/frontend && npm ci && npm test build-macos: needs: test runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - uses: actions/setup-node@v4 with: node-version: '22' - run: ./scripts/build.sh ${{ github.ref_name }} macos - uses: actions/upload-artifact@v4 with: name: hostkeeper-macos path: dist/*.dmg build-windows: needs: test runs-on: windows-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - uses: actions/setup-node@v4 with: node-version: '22' - run: ./scripts/build.sh ${{ github.ref_name }} windows - uses: actions/upload-artifact@v4 with: name: hostkeeper-windows path: dist/*.exe build-linux: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - uses: actions/setup-node@v4 with: node-version: '22' - run: ./scripts/build.sh ${{ github.ref_name }} linux - uses: actions/upload-artifact@v4 with: name: hostkeeper-linux path: dist/*.AppImage ``` --- ## 7. Binary Size Optimization | Technique | Impact | |-----------|--------| | `-ldflags="-s -w"` | -20% Go binary size | | UPX compression (optional) | -60% Go binary size | | Vite tree shaking | -40% JS bundle size | | Code splitting (lazy load) | -30% initial load | | Image optimization | -50% icon sizes | | Terser minification | -30% JS size | | CSS purging (Tailwind) | -80% CSS size | **Target sizes**: - Go backend binary: ~15 MB (5 MB compressed) - Frontend dist: ~2 MB (500 KB compressed) - Electron package: ~200 MB total - Mobile APK: ~50 MB - Mobile IPA: ~60 MB --- ## 8. Version Management ### Version Format ``` vMAJOR.MINOR.PATCH ``` - **MAJOR**: Breaking changes (data format, API) - **MINOR**: New features - **PATCH**: Bug fixes ### Version Injection ```go // In main.go var version = "dev" func main() { fmt.Printf("Hostkeeper v%s\n", version) // ... } ``` ```bash # Build with version go build -ldflags="-X main.version=v2.0.0" -o hostkeeper-server . ``` ### Changelog Format ```markdown ## [v2.1.0] - 2026-07-15 ### Added - Port forwarding support (local, remote, dynamic) - Import from ~/.ssh/config ### Changed - Improved terminal performance with WebGL renderer ### Fixed - Fixed SFTP upload progress not updating - Fixed vault auto-lock not triggering on sleep ``` --- ## 9. Code Signing ### macOS ```bash # Requires Apple Developer account + certificates export CSC_LINK="path/to/certificate.p12" export CSC_KEY_PASSWORD="certificate-password" # electron-builder handles signing + notarization npx electron-builder --mac --publish always ``` ### Windows ```bash # Requires code signing certificate export WIN_CERTIFICATE_FILE="path/to/certificate.pfx" export WIN_CERTIFICATE_PASSWORD="certificate-password" npx electron-builder --win --publish always ``` ### Linux No code signing required. AppImage is self-contained. --- ## 10. Release Workflow ```bash # 1. Update version npm version minor # or major, patch # 2. Update CHANGELOG.md # 3. Commit git add . git commit -m "chore: release v2.1.0" # 4. Tag git tag -a v2.1.0 -m "Release v2.1.0" # 5. Push git push origin main --tags # 6. GitHub Actions builds + publishes artifacts # 7. Create GitHub Release gh release create v2.1.0 \ --title "Hostkeeper v2.1.0" \ --notes-file CHANGELOG.md \ dist/*.dmg dist/*.exe dist/*.AppImage ```