Application Distribution with ArNS + Manifests
Overview: This guide shows how to distribute software permanently using Arweave manifests and ArNS.
You can publish binaries once and serve them from stable, human-readable URLs that keep working as releases change. Files are stored immutably on Arweave, old versions remain available, and links never break.
What you get:
- Permanent storage for all releases
- Stable URLs via ArNS (for example,
releases_yourapp.arweave.net) - Simple versioned paths for latest and pinned releases
- Automated CI/CD with GitHub Actions and Turbo
- No centralized registries or CDNs
The case study that follows walks through a real implementation for the Harlequin CLI and shows how to apply this pattern to your own software.
Architecture Overview
System Components
Core Technologies
- Arweave: Permanent data storage blockchain
- ArNS: Decentralized naming service for content routing
- Turbo SDK: Efficient data upload and payment handling
- GoReleaser: Multi-platform binary compilation
- GitHub Actions: Automated CI/CD pipeline
Implementation Deep Dive
1. Binary Build Pipeline
The system uses GoReleaser for creating optimized, multi-platform binaries:
# .goreleaser.yaml
builds:
- id: harlequin
main: ./main.go
binary: harlequin
goos: [linux, darwin, windows]
goarch: [amd64, arm64]
flags: [-trimpath]
ldflags:
- -s -w # Strip debug info for smaller binaries
- -X main.version={{.Version}}Platform Matrix:
- Linux: AMD64, ARM64
- macOS: AMD64 (Intel), ARM64 (Apple Silicon)
- Windows: AMD64, ARM64
2. Arweave Storage Strategy
Compression Optimization
All binaries are compressed with gzip before upload, achieving significant storage savings:
// Compress binary before upload
const binaryData = readFileSync(binary);
const compressedData = gzipSync(binaryData);
const compressionRatio = ((1 - compressedData.length / binaryData.length) * 100).toFixed(1);
// Upload with proper content headers
const upload = await turboClient.upload({
data: compressedData,
dataItemOpts: {
tags: [
{name: "Content-Type", value: "application/gzip"},
{name: "Content-Encoding", value: "gzip"},
{name: "Original-Content-Type", value: "application/octet-stream"},
{name: "Original-Size", value: binaryData.length.toString()},
{name: "Compressed-Size", value: compressedData.length.toString()}
]
}
});Storage Efficiency Results:
- Average compression ratio: ~70%
- 10MB binary → ~3MB storage cost
- Significant cost savings at scale
Data Item Tagging
Each upload includes comprehensive metadata for discoverability and management:
const dataItemOptions = {
tags: [
{name: 'Type', value: 'release'},
{name: 'App-Name', value: 'Harlequin-CLI'},
{name: 'App-Version', value: version},
{name: 'Content-Type', value: 'application/gzip'},
{name: 'Platform', value: platform},
{name: 'Architecture', value: arch}
]
}3. Manifest-Based Routing
The system creates an Arweave manifest that provides structured routing for all binaries and metadata:
const manifest: ArweaveManifest = {
manifest: 'arweave/paths',
version: '0.1.0',
index: {
path: 'install_cli.sh' // Default route
},
paths: {
// Version-specific binaries
'releases/1.2.3/linux/amd64': { id: 'arweave_tx_id_1' },
'releases/1.2.3/darwin/arm64': { id: 'arweave_tx_id_2' },
// Latest symlinks for convenience
'releases/latest/linux/amd64': { id: 'arweave_tx_id_1' },
'releases/latest/darwin/arm64': { id: 'arweave_tx_id_2' },
// API endpoints
'releases': { id: 'releases_json_tx_id' },
'install_cli.sh': { id: 'install_script_tx_id' }
}
};4. ArNS URL Structure
Combining ArNS with manifests creates a permanent, human-readable API for your releases. The ArNS undername points to the manifest, and the manifest paths define the URL structure:
// Update ArNS record to point to new manifest
await ant.setRecord({
undername: 'install_cli', // Subdomain
transactionId: manifestId, // New manifest TX ID
ttlSeconds: 60 // Cache TTL
});This creates a complete URL API:
https://install_cli_harlequin.arweave.net/
├── install_cli.sh # Installation script (default)
├── releases # JSON API with version metadata
└── releases/
├── 1.2.3/ # Version-specific binaries
│ ├── linux/amd64
│ ├── darwin/arm64
│ └── windows/amd64
└── latest/ # Latest version aliases
├── linux/amd64
└── darwin/arm64Key Benefits:
install_cli_harlequin.arweave.netprovides a permanent, friendly URL- Manifest paths create a logical REST-like API structure
- Updating the ArNS record points to new releases while preserving the URL
5. Intelligent Installation Script
The installation script provides a sophisticated user experience with platform detection, version management, and error handling:
Platform Detection
# Detect OS and architecture
OS="$(uname -s)"
ARCH="$(uname -m)"
case $OS in
Darwin) PLATFORM="darwin" ;;
Linux) PLATFORM="linux" ;;
CYGWIN*|MINGW*|MSYS*) PLATFORM="windows" ;;
esac
case $ARCH in
x86_64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
armv7*) ARCH="armv7" ;;
esacVersion Management
# Interactive version selection
get_available_versions() {
curl -fsSL "${BASE_URL}/releases" -o /tmp/releases.json
if has_jq; then
jq -r '.[].tag_name' /tmp/releases.json | sed 's/^v//'
else
parse_version < /tmp/releases.json
fi
}
# Upgrade detection
if [ -n "$CURRENT_VERSION" ] && version_gt "$LATEST_VERSION" "$CURRENT_VERSION"; then
prompt "A newer version (v${LATEST_VERSION}) is available. Upgrade? [y/N]"
fiRobust Download & Decompression
# Download with retry logic and progress tracking
curl --fail --location --show-error \
--connect-timeout 30 --max-time 300 \
--retry 3 --retry-delay 2 \
--progress-bar \
--output "$TEMP_COMPRESSED" \
"$BINARY_URL"
# Verify and decompress
if ! gzip -t "$TEMP_COMPRESSED"; then
error "Downloaded file is not a valid gzip archive"
fi
gzip -dc "$TEMP_COMPRESSED" > "$TEMP_FILE"CI/CD Integration
GitHub Actions Workflow
The deployment is fully automated through GitHub Actions:
name: Nx Release
on:
push:
branches: [main, develop]
paths: ['cli/**']
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Setup Go & GoReleaser
uses: goreleaser/goreleaser-action@v6.4.0
- name: Release (Main - Stable)
if: github.ref == 'refs/heads/main'
run: npx nx release patch --yes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARWEAVE_WALLET_JWK: ${{ secrets.ARWEAVE_WALLET_JWK }}
- name: Test Installation
run: |
curl -fsSL https://install_cli_harlequin.daemongate.io | \
DRYRUN=true VERSION=0.1.0 shNx Integration
The system leverages Nx for orchestrating the complex release pipeline:
{
"nx-release-publish": {
"executor": "nx:run-commands",
"options": {
"command": "goreleaser release --clean && cd scripts && yarn deploy"
},
"configurations": {
"dry-run": {
"command": "goreleaser release --skip=publish && yarn deploy:dryrun"
}
}
}
}Pipeline Stages:
- Build: GoReleaser creates multi-platform binaries
- Upload: Turbo SDK uploads compressed binaries to Arweave
- Manifest: Creates routing manifest with all binary paths
- ArNS: Updates domain to point to new manifest
- Verification: Tests installation script functionality
Security & Reliability
Decentralization Benefits
- No Single Point of Failure: Distributed across the entire ar.io network
- Censorship Resistance: No central authority can block access
- Geographic Redundancy: Data replicated globally
Access Control
// Wallet-based deployment authorization
const signer = new ArweaveSigner(wallet);
const turboUploader = TurboFactory.authenticated({signer});
// Only authorized wallet can update ArNS records
await ant.setRecord({
undername: 'install_cli',
transactionId: manifestId
});Conclusion
This implementation demonstrates that Arweave manifests combined with ArNS provide a powerful alternative to traditional application distribution:
- Automated Release Pipeline: CI/CD integration enables seamless multi-platform builds and deployment
- Decentralized and Permanent Storage: Applications are stored immutably across the Arweave network
- Zero Reliance on Centralized Registries: No dependency on npm, GitHub Releases, or traditional CDNs
- Permanent Friendly Names: ArNS provides human-readable URLs with unbreakable links to your releases
Next Steps
Manifests
Learn the fundamentals of Arweave manifest structure and creation.
Working with ArNS
Register and manage ArNS names for your distribution endpoints.
Advanced Uploading
Explore advanced Turbo SDK features for optimized uploads.
Security & Sandboxing
Understand security considerations for permanent data.
How is this guide?