🐳 Ephemeral Containers
Fresh Ubuntu 22.04 environment for every test run
This repository uses an innovative ephemeral Docker container approach for local testing and development. This ensures every build is tested in a clean, reproducible environment that mirrors production conditions.
Traditional package testing often suffers from:
Our ephemeral approach solves all of these problems by creating a fresh, isolated environment for every test run.
🐳 Ephemeral Containers
Fresh Ubuntu 22.04 environment for every test run
🔐 Temporary GPG Keys
Auto-generated keys that expire in 30 days
📡 Local HTTPS Server
nginx with SSL certificates for realistic testing
🔄 Complete Automation
End-to-end testing from build to verification
The testing environment starts with a clean Ubuntu 22.04 base:
FROM ubuntu:22.04
RUN apt update && \apt install -y wget curl gnupg jq dpkg-dev apt-utils tar rng-tools && \wget https://github.com/mikefarah/yq/releases/download/v4.45.4/yq_linux_amd64 -O /usr/local/bin/yq && \chmod +x /usr/local/bin/yq
RUN apt install -y ca-certificates libnss3-tools nginx && \curl -sJLO 'https://dl.filippo.io/mkcert/latest?for=linux/amd64' && \chmod +x mkcert-v*-linux-amd64 && \cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert
For realistic testing, we set up a complete HTTPS server:
RUN mkcert -install && \mkdir -p /etc/nginx/certs && \cd /etc/nginx/certs && \mkcert localhost
This creates:
localhost
The container generates temporary GPG keys specifically for testing:
# WARNING: This GPG key generation is ONLY for local testing/development# NEVER use this in production - it creates ephemeral keys that are not secure
RUN mkdir -p ~/.gnupg && \chmod 700 ~/.gnupg && \echo 'pinentry-mode loopback' >> ~/.gnupg/gpg.conf && \echo 'use-agent' >> ~/.gnupg/gpg.conf
The ephemeral keys are configured with appropriate security parameters:
echo 'Key-Type: RSA' >> /tmp/gpg-batch.conf && \echo 'Key-Length: 2048' >> /tmp/gpg-batch.conf && \echo 'Subkey-Type: RSA' >> /tmp/gpg-batch.conf && \echo 'Subkey-Length: 2048' >> /tmp/gpg-batch.conf && \echo 'Name-Real: APT Archive Test Key' >> /tmp/gpg-batch.conf && \echo 'Name-Comment: EPHEMERAL - FOR TESTING ONLY' >> /tmp/gpg-batch.conf && \echo 'Name-Email: test@localhost.local' >> /tmp/gpg-batch.conf && \echo 'Expire-Date: 30d' >> /tmp/gpg-batch.conf && \echo '%no-protection' >> /tmp/gpg-batch.conf
Key features:
GPG environment variables are set dynamically at container startup:
#!/bin/bash# Export GPG key ID and private key as environment variablesexport GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG 2>/dev/null | grep 'sec ' | sed 's/.*rsa[0-9]*\/\([A-F0-9]\{16\}\).*/\1/')export GPG_PRIVATE_KEY=$(gpg --armor --export-secret-keys $GPG_KEY_ID 2>/dev/null | base64 -w 0)echo 'GPG_KEY_ID=$GPG_KEY_ID' > /tmp/gpg-envecho 'GPG_PRIVATE_KEY=$GPG_PRIVATE_KEY' >> /tmp/gpg-envsource /tmp/gpg-env
When you run docker-compose up build
, the container executes a comprehensive testing workflow:
#!/bin/bashset -e
export DEBIAN_FRONTEND=noninteractive
info 'Before adding, updating official packages'apt update -qq && apt upgrade -qq -y
debug 'Executing cleanup of previous runs'if [ -d dists ]; then rm -r dists; fiif [ -d pool ]; then rm -r pool; fi
info 'Setting up ephemeral GPG environment variables'source /usr/local/bin/set-gpg-env.sh
info 'Loading GPG profile'scripts/load-gpg-profile.sh
The container builds all packages from specifications:
info 'Using specs to generate .deb packages'for f in specs/*.yml; dodebug 'Generating .deb for $f'bash scripts/wrap-to-deb.sh '$f'done
info 'Building APT repository'bash scripts/build-repo.sh
The container creates a complete APT repository server:
debug 'Preparing test HTTPS server'cp -r dists /usr/share/nginx/html/distscp -r pool /usr/share/nginx/html/poolcp public.gpg /usr/share/nginx/html/public.gpg
debug 'Generating nginx 443 configuration'rm /etc/nginx/sites-enabled/defaultecho 'server {listen 443 ssl;server_name localhost;
ssl_certificate /etc/nginx/certs/localhost.pem;ssl_certificate_key /etc/nginx/certs/localhost-key.pem;
location / {root /usr/share/nginx/html;index index.html index.htm;}}' >> /etc/nginx/sites-enabled/default
debug 'Starting up nginx server'nginx &
The container performs complete APT repository testing:
info 'Adding custom APT to testing runtime (does not require sudo)'curl -fsSL https://localhost/public.gpg | tee /usr/share/keyrings/apt.fuabioo.gpg > /dev/nullecho 'deb [signed-by=/usr/share/keyrings/apt.fuabioo.gpg] https://localhost stable main' | tee /etc/apt/sources.list.d/apt.fuabioo.list
info 'After adding, updating packages and installing dontrm'apt update && apt install dontrm
info 'Verifying repository by installing and executing one package'dontrm version
info 'Installing fastfetch to verify external pre-built .deb package'apt install fastfetchfastfetch
The testing process includes comprehensive signature verification:
# Build repository with signaturesapt-ftparchive -c=conf/release.conf release dists/stable > dists/stable/Release
# Sign the Release filegpg --default-key '$GPG_KEY_ID' \--digest-algo SHA256 \-abs \-o dists/stable/Release.gpg dists/stable/Release
# Create signed InRelease filegpg --default-key '$GPG_KEY_ID' \--digest-algo SHA256 \--clearsign \-o dists/stable/InRelease dists/stable/Release
# Export public keygpg --export '$GPG_KEY_ID' > public.gpg
# Verify signaturesgpg --verify dists/stable/Release.gpg dists/stable/Release
Each package undergoes multiple integrity checks:
✅ Reproducible Builds - Same environment every time
✅ Isolated Testing - No host system contamination
✅ Automated Cleanup - No manual cleanup required
✅ Production Parity - Testing mirrors production environment
✅ Fast Iteration - Quick feedback on changes
🔒 Contained Risks - Test keys never leave the container
🗑️ Automatic Cleanup - All test artifacts destroyed
⏰ Time-limited Keys - GPG keys expire automatically
🛡️ Isolation - No impact on host GPG keyring
🧪 Comprehensive Testing - Full installation and verification cycle
📊 Consistent Results - Eliminates “works on my machine” issues
🔄 Continuous Integration - Easy to integrate with CI/CD pipelines
⚡ Fast Feedback - Quick detection of packaging issues
# Clone the repositorygit clone https://github.com/Fuabioo/apt-archive.gitcd apt-archive
# Run the ephemeral testing environmentdocker-compose up build
# The container will:# 1. Generate ephemeral GPG keys# 2. Build all packages from specs/# 3. Create repository structure# 4. Set up local HTTPS server# 5. Test repository installation# 6. Verify package functionality# 7. Destroy itself with all test artifacts
The testing process provides detailed logging:
This ephemeral testing approach integrates seamlessly with continuous integration:
# Example GitHub Actions workflowname: Test Repositoryon: [push, pull_request]
jobs:test:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3- name: Test APT Repositoryrun: docker-compose up --exit-code-from build build
The ephemeral nature ensures:
The ephemeral Docker container testing approach provides a robust, secure, and reliable way to test APT repositories. It ensures that every package is thoroughly tested in a production-like environment while maintaining security best practices and development efficiency.
This methodology can be adapted for other packaging systems and serves as a model for secure, automated package testing workflows.
Want to understand more about the repository structure? Check out the How It Works page for detailed technical explanations.