Technical Deep Dive: Portage & Binary Package Distribution

The single biggest complaint about Gentoo is compilation time. Firefox takes 45 minutes. KDE Plasma takes 3 hours. Chromium takes 6+ hours. LLVM/Clang takes 8 hours.

But here’s the secret: you only compile once.

This guide explains how Argo OS achieves 90%+ time savings by compiling packages on a dedicated build server and distributing pre-built binaries to all other machines.

The Architecture

┌─────────────────────────────────────────────────────────┐
│                 Binary Package Flow                      │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  Tau-Ceti-Lab/Binhost (10.42.0.194)                           │
│  ├─ Compiles ALL packages from source                   │
│  ├─ Automatically creates .gpkg.tar binaries            │
│  ├─ Serves via HTTP (nginx) or SSH                      │
│  └─ 1,100+ packages, ~30GB repository                   │
│                     │                                    │
│                     ▼                                    │
│  Driver Workstation (10.42.0.100)                        │
│  ├─ Points PORTAGE_BINHOST to Tau-Ceti-Lab                   │
│  ├─ Downloads pre-compiled binaries                     │
│  ├─ Installs in seconds instead of hours                │
│  └─ Never runs the compiler                             │
│                                                          │
└─────────────────────────────────────────────────────────┘

Part 1: Configuring the Build Server (Binhost)

make.conf for the Binhost

The binhost needs to create binary packages automatically during every emerge:

# /etc/portage/make.conf (on binhost)

# === Critical: Binary package creation ===
FEATURES="buildpkg binpkg-multi-instance parallel-fetch candy"

# Compression (zstd level 9 = max compression, slower)
BINPKG_COMPRESS="zstd"
BINPKG_COMPRESS_FLAGS="-9"

# Modern package format (replaces old tbz2)
BINPKG_FORMAT="gpkg"

# === CPU Optimization ===
# Use YOUR CPU's native instruction set
COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"

# Parallel compilation
MAKEOPTS="-j$(nproc)"
EMERGE_DEFAULT_OPTS="--jobs=4 --load-average=8"

# === GPU Support ===
# Compile for ALL GPU types your clients might use
VIDEO_CARDS="nvidia amdgpu radeonsi intel"

# === Accept all licenses (internal use) ===
ACCEPT_LICENSE="*"

Key insight: buildpkg is the magic flag. Every time you run emerge firefox, Portage automatically saves the compiled result to /var/cache/binpkgs/www-client/firefox-*.gpkg.tar.

HTTP is faster and more reliable than SSH for package distribution:

# Install nginx
emerge www-servers/nginx

# Create config
cat > /etc/nginx/sites-available/binhost << 'EOF'
server {
    listen 8080;
    server_name _;
    
    root /var/cache/binpkgs;
    autoindex on;
    
    # Enable directory listing for Portage
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Optimize for large binary downloads
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}
EOF

# Enable and start
ln -sf /etc/nginx/sites-available/binhost /etc/nginx/sites-enabled/
rc-update add nginx default
rc-service nginx start

Generating the Package Index

After compiling packages, you must regenerate the index:

# Update the Packages file (required for clients to see updates!)
emaint binhost --fix

# Verify it worked
ls -la /var/cache/binpkgs/Packages

Tip: Add this to a cron job or run it after every emerge @world.

Part 2: Configuring Clients (Driver Machines)

make.conf for Clients

# /etc/portage/make.conf (on client machines)

# === Binary package server ===
PORTAGE_BINHOST="http://10.42.0.194:8080"

# Alternative: SSH (slower but works through firewalls)
# PORTAGE_BINHOST="ssh://[email protected]/var/cache/binpkgs"

# === Features ===
FEATURES="binpkg-multi-instance parallel-fetch getbinpkg"

# CRITICAL: Disable signature verification for internal network
# (Official Gentoo binaries are signed, yours are not)
FEATURES="${FEATURES} -binpkg-signing -binpkg-request-signature"

# === Default behavior: always try binary first ===
EMERGE_DEFAULT_OPTS="--getbinpkg --usepkg"

# === Match binhost optimization ===
# This MUST match what the binhost compiled with
COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"

# GPU must match what binhost compiled
VIDEO_CARDS="nvidia"

Installing Packages from Binary

# Normal emerge now automatically uses binaries
emerge firefox

# Output will show:
# >>> Emerging binary (1 of 1) www-client/firefox-131.0
# >>> Downloading 'http://10.42.0.194:8080/www-client/firefox-131.0.gpkg.tar'
# >>> Installing (1 of 1) www-client/firefox-131.0

That’s it. A 45-minute compile becomes a 30-second download.

Part 3: Real-World Time Savings

PackageSource CompileBinary InstallSavings
Firefox45 minutes30 seconds99%
KDE Plasma (full)3 hours5 minutes97%
LibreOffice2 hours2 minutes98%
Chromium6 hours1 minute99.7%
LLVM/Clang8 hours3 minutes99.4%
gcc2 hours90 seconds99%

Total system install: From Stage 3 to full KDE desktop drops from 20+ hours to ~2 hours.

Part 4: The GPU Compatibility Trap

This is where most people fail.

If your binhost has an AMD GPU (VIDEO_CARDS="amdgpu") and your client has NVIDIA (VIDEO_CARDS="nvidia"), packages like Mesa will be compiled without NVIDIA support. Your client will have broken 3D acceleration.

Solution: Configure the binhost to compile for ALL GPU types:

# On binhost /etc/portage/make.conf
VIDEO_CARDS="nvidia amdgpu radeonsi intel i965 iris"

Then recompile GPU-sensitive packages:

emerge --oneshot mesa vulkan-loader xorg-drivers
emaint binhost --fix

Part 5: USE Flag Synchronization

Another common failure: USE flags must match between binhost and clients.

Scenario: Binhost compiles firefox with USE="-wayland". Client has USE="wayland". Portage will refuse to use the binary and compile from source.

Solution: Keep /etc/portage/package.use/ synchronized across all machines. We use git:

# On binhost
cd /etc/portage
git init
git add .
git commit -m "Initial portage config"
git remote add origin [email protected]:commander/portage-config.git
git push -u origin main

# On clients
cd /etc/portage
git clone [email protected]:commander/portage-config.git .

Part 6: Maintenance

Cleaning Old Packages

Binary packages accumulate. Clean them periodically:

# Remove binaries for packages no longer in the tree
eclean-pkg --deep

# Check repository size
du -sh /var/cache/binpkgs/
find /var/cache/binpkgs/ -name "*.gpkg.tar" | wc -l

Full Update Workflow

# 1. Sync the repository
emerge --sync

# 2. Update world (creates new binaries automatically)
emerge -avuDN @world

# 3. Clean up orphaned dependencies
emerge --depclean

# 4. Rebuild anything with broken dependencies
emerge @preserved-rebuild

# 5. Regenerate binary index (CRITICAL!)
emaint binhost --fix

# 6. Optional: sync to mirrors
rsync -avz --delete /var/cache/binpkgs/ backup-server:/var/www/commander-repo/

Troubleshooting

”Binary package not found"

# Check if index is current
ls -la /var/cache/binpkgs/Packages

# Regenerate
emaint binhost --fix

# Verify package exists
ls /var/cache/binpkgs/www-client/firefox*

"USE flag mismatch”

# Check what USE flags the binary was built with
qtbz2 -l /var/cache/binpkgs/www-client/firefox-*.gpkg.tar

# Compare to local USE
emerge -pv firefox

Client compiling instead of downloading

Check FEATURES and EMERGE_DEFAULT_OPTS in client’s make.conf. Also verify the binhost is accessible:

curl -I http://10.42.0.194:8080/Packages

This system is the backbone of Argo OS. It transforms Gentoo from “compile everything yourself” into “compile once, deploy everywhere” — the best of both worlds.