Skip to content

Offline & Mirroring

Deploy Stout in air-gapped and offline environments.


Overview

Stout's mirroring feature allows you to:

  • Create offline copies of packages
  • Serve packages on local networks
  • Deploy in air-gapped environments
  • Reduce external bandwidth usage

Creating a Mirror

Basic Mirror

Create a mirror with specific packages:

stout mirror create ./my-mirror jq curl wget

This downloads: - The package index - Specified packages - All dependencies - Checksums and signatures

Include Dependencies

Dependencies are automatically included:

stout mirror create ./mirror [email protected]
# Includes: [email protected], openssl, readline, sqlite, xz, etc.

Large Mirror

Create a comprehensive development mirror:

stout mirror create ./dev-mirror \
    git \
    [email protected] \
    node@20 \
    rust \
    go \
    jq \
    curl \
    wget \
    vim \
    neovim

Mirror Contents

A mirror contains:

my-mirror/
├── index/
│   ├── formulas.db          # SQLite index
│   ├── formulas.db.sig      # Index signature
│   └── casks.db              # Cask index
├── bottles/
│   ├── jq-1.7.1.arm64_monterey.bottle.tar.gz
│   ├── curl-8.4.0.arm64_monterey.bottle.tar.gz
│   └── ...
├── casks/
│   └── ...
└── manifest.json             # Mirror manifest

Serving a Mirror

Built-in HTTP Server

Serve the mirror over HTTP:

stout mirror serve ./my-mirror --port 9000

Access at http://localhost:9000

Custom Host Binding

stout mirror serve ./my-mirror --host 0.0.0.0 --port 9000

Behind a Reverse Proxy

For production, use nginx or similar:

server {
    listen 443 ssl;
    server_name packages.internal.company.com;

    location / {
        root /var/www/stout-mirror;
        autoindex on;
    }
}

Using a Mirror

Command Line

stout --mirror=http://localhost:9000 install jq

Configuration

[index]
base_url = "http://localhost:9000/index"

[mirror]
url = "http://localhost:9000"

File-based Mirror

For truly offline environments:

stout --mirror=file:///mnt/usb/stout-mirror install jq

Mirror Management

View Mirror Info

stout mirror info ./my-mirror

Output:

Mirror: ./my-mirror
Created: 2024-01-15T10:30:00Z
Packages: 45
Size: 1.2 GB

Packages:
  jq 1.7.1
  curl 8.4.0
  wget 1.21.4
  ...

Verify Mirror Integrity

stout mirror verify ./my-mirror

Checks: - All files present - SHA256 checksums match - Signatures valid

Update Mirror

Add new packages to an existing mirror:

stout mirror create ./my-mirror --update new-package

Air-Gapped Workflow

1. Create Mirror (Connected Machine)

stout mirror create ./transfer-mirror [email protected] node@20

2. Transfer to Air-Gapped Environment

# Copy to USB drive
cp -r ./transfer-mirror /mnt/usb/

# Or create archive
tar -czf stout-mirror.tar.gz ./transfer-mirror

3. Deploy on Air-Gapped Machine

# Extract if archived
tar -xzf stout-mirror.tar.gz

# Serve locally
stout mirror serve ./transfer-mirror --port 9000 &

# Configure stout
cat > ~/.stout/config.toml << EOF
[index]
base_url = "http://localhost:9000/index"
auto_update = false

[mirror]
url = "http://localhost:9000"
EOF

4. Install Packages

stout install [email protected] node@20

CI/CD with Mirrors

Self-Hosted Mirror for Build Servers

  1. Create mirror on a scheduled job:
# Weekly job to update mirror
stout mirror create /var/www/stout-mirror \
    $(cat /etc/stout/approved-packages.txt)
  1. Configure build agents:
[index]
base_url = "http://build-mirror.internal:9000/index"

[mirror]
url = "http://build-mirror.internal:9000"
  1. Faster, reproducible builds:

  2. No external network calls

  3. Consistent package versions
  4. Reduced bandwidth

Bandwidth Optimization

Mirror Specific Architectures

Only mirror what you need:

stout mirror create ./mirror --arch arm64 --os monterey [email protected]

Exclude Development Dependencies

stout mirror create ./mirror --no-dev-deps production-package

Troubleshooting

Mirror Verification Failed

$ stout mirror verify ./my-mirror
Error: Checksum mismatch for jq-1.7.1.bottle.tar.gz

Re-download the affected package:

stout mirror create ./my-mirror --force jq

Package Not Found in Mirror

$ stout install missing-package
Error: Package 'missing-package' not found in mirror

Add the package to the mirror on a connected machine and re-transfer.

Signature Expired

Signatures have a maximum age. Re-create the mirror to get fresh signatures:

stout mirror create ./new-mirror --from ./old-mirror