Initial commit: Comprehensive Debian bootc documentation

- Complete documentation for all bootc commands and subcommands
- Debian-specific adaptations and workarounds
- Manual installation methods to bypass bootc reliability issues
- Technical guides with Rust source code analysis
- Flowcharts and external command references
- Hidden command documentation (bootc internals, state, etc.)
- Composefs integration analysis
- Base image creation guides (with and without bootc binary)
- Management scripts and automation
- Comprehensive troubleshooting and examples
This commit is contained in:
robojerk 2025-09-15 14:02:28 -07:00
commit 526f1c1afd
67 changed files with 34174 additions and 0 deletions

434
lint/bootc-lint-guide.md Normal file
View file

@ -0,0 +1,434 @@
# bootc container lint - Comprehensive Guide
## Overview
`bootc container lint` is a static analysis tool that performs comprehensive checks on bootc-compatible container images during the build process. It validates that container images meet the requirements for successful bootc installation and runtime operation.
## Purpose
The lint tool serves several critical purposes:
1. **Build-time Validation**: Catch issues early in the container build process
2. **Compatibility Assurance**: Ensure images work correctly with bootc installation
3. **Best Practice Enforcement**: Promote proper container image construction
4. **Runtime Prevention**: Avoid installation failures and runtime issues
## Command Syntax
```bash
bootc container lint [OPTIONS...]
```
### Basic Usage
```bash
# Lint current container image
bootc container lint
# Lint specific rootfs
bootc container lint --rootfs /path/to/rootfs
# List all available lints
bootc container lint --list
# Skip specific lints
bootc container lint --skip var-log --skip buildah-injected
# Make warnings fatal
bootc container lint --fatal-warnings
# Show full output (no truncation)
bootc container lint --no-truncate
```
## Lint Categories
### 1. Fatal Lints
These lints **must** pass for the container to be installable. Failure will prevent bootc installation.
#### var-run
**Purpose**: Ensures `/var/run` is a symlink to `/run`
**Check**: Verifies `/var/run` is not a physical directory
**Rationale**: `/var/run` should always be a symlink to `/run` for proper systemd operation
```bash
# This will fail:
mkdir -p /var/run
# This will pass:
ln -sf /run /var/run
```
#### etc-usretc
**Purpose**: Prevents both `/etc` and `/usr/etc` from existing
**Check**: Ensures only `/etc` exists in container images
**Rationale**: Having both causes undefined behavior; `/usr/etc` is a bootc implementation detail
```bash
# This will fail:
mkdir -p /etc /usr/etc
# This will pass:
mkdir -p /etc
# OR
mkdir -p /usr/etc
```
#### bootc-kargs
**Purpose**: Validates kernel argument configuration files
**Check**: Parses `/usr/lib/bootc/kargs.d/*.toml` files for syntax errors
**Rationale**: Invalid kernel arguments will cause boot failures
```bash
# Valid kargs.d file:
echo '[kargs]
append = ["console=ttyS0", "quiet"]' > /usr/lib/bootc/kargs.d/99-console.toml
```
#### kernel
**Purpose**: Ensures exactly one kernel is present
**Check**: Validates only one `/usr/lib/modules/$kver` directory exists
**Rationale**: Multiple kernels cause ambiguity during boot
```bash
# This will fail:
mkdir -p /usr/lib/modules/5.4.0 /usr/lib/modules/6.1.0
# This will pass:
mkdir -p /usr/lib/modules/6.1.0
```
#### utf8
**Purpose**: Ensures all filenames and symlink targets are UTF-8
**Check**: Recursively validates filesystem entries
**Rationale**: Non-UTF-8 names cause ostree backend failures
```bash
# This will fail:
touch "file\xffname"
# This will pass:
touch "filename"
```
#### api-base-directories
**Purpose**: Verifies required API directories exist
**Check**: Ensures `/dev`, `/proc`, `/sys`, `/run`, `/tmp`, `/var` exist as directories
**Rationale**: These are required by systemd and Linux standards
```bash
# Required directories:
mkdir -p /dev /proc /sys /run /tmp /var
```
#### baseimage-root
**Purpose**: Validates bootc-specific root filesystem structure
**Check**: Ensures `/sysroot` exists and `/ostree` symlinks to `sysroot/ostree`
**Rationale**: Required for proper bootc operation
```bash
# Required structure:
mkdir -p /sysroot/ostree
ln -sf sysroot/ostree /ostree
```
### 2. Warning Lints
These lints indicate potential issues but don't prevent installation.
#### buildah-injected
**Purpose**: Detects empty files injected by container build systems
**Check**: Looks for empty `/etc/hostname` or `/etc/resolv.conf` files
**Rationale**: These files should contain actual content, not be empty placeholders
```bash
# This will warn:
touch /etc/hostname
# This will pass:
echo "myhostname" > /etc/hostname
```
#### baseimage-composefs
**Purpose**: Recommends enabling composefs for ostree
**Check**: Validates composefs configuration in `/usr/lib/ostree/prepare-root.conf`
**Rationale**: Composefs improves performance and security
```bash
# Enable composefs:
echo '[composefs]
enabled = true' > /usr/lib/ostree/prepare-root.conf
```
#### var-log
**Purpose**: Warns about non-empty log files in `/var/log`
**Check**: Identifies regular files with content in `/var/log`
**Rationale**: Log files should be generated at runtime, not shipped in images
```bash
# This will warn:
echo "log content" > /var/log/app.log
# This will pass:
mkdir -p /var/log
# OR
ln -sf /dev/null /var/log/app.log
```
#### var-tmpfiles
**Purpose**: Checks for missing systemd tmpfiles.d entries
**Check**: Validates `/var` content has corresponding tmpfiles.d configuration
**Rationale**: Ensures proper initialization across upgrades
```bash
# Create tmpfiles.d entry:
echo 'd /var/log/app 0755 root root -' > /usr/lib/tmpfiles.d/app.conf
```
#### sysusers
**Purpose**: Validates user/group definitions have systemd sysusers.d entries
**Check**: Ensures `/etc/passwd` and `/etc/group` entries have corresponding sysusers.d files
**Rationale**: Prevents user/group drift across upgrades
```bash
# Create sysusers.d entry:
echo 'u app 1000 "Application User"' > /usr/lib/sysusers.d/app.conf
```
#### nonempty-boot
**Purpose**: Warns about content in `/boot` directory
**Check**: Ensures `/boot` is empty in container images
**Rationale**: Kernel content should be in `/usr/lib/modules`, not `/boot`
```bash
# This will warn:
echo "content" > /boot/somefile
# This will pass:
mkdir -p /boot
# Keep /boot empty
```
## Integration with Container Builds
### Dockerfile Integration
```dockerfile
FROM debian:forky-slim
# Install bootc
RUN apt update && apt install -y bootc && apt clean
# ... your container setup ...
# Lint the container image
RUN bootc container lint
# Continue with build...
```
### Podman Build Integration
```bash
# Build with linting
podman build --tag my-bootc-image .
# Or run lint separately
podman run --rm my-bootc-image bootc container lint
```
### CI/CD Integration
```yaml
# GitHub Actions example
- name: Lint bootc container
run: |
podman run --rm ${{ matrix.image }} bootc container lint --fatal-warnings
```
## Advanced Usage
### Custom Root Filesystem
```bash
# Lint specific rootfs
bootc container lint --rootfs /path/to/rootfs
```
### Selective Linting
```bash
# Skip specific lints
bootc container lint --skip var-log --skip buildah-injected
# List available lints
bootc container lint --list
```
### Warning Management
```bash
# Make warnings fatal (fail build on warnings)
bootc container lint --fatal-warnings
# Allow warnings but show full output
bootc container lint --no-truncate
```
## Common Issues and Solutions
### 1. /var/run Directory Issue
**Problem**: `/var/run` exists as a directory instead of symlink
**Solution**:
```bash
rm -rf /var/run
ln -sf /run /var/run
```
### 2. Both /etc and /usr/etc Exist
**Problem**: Container has both directories
**Solution**:
```bash
# Choose one approach:
# Option 1: Use /etc only
rm -rf /usr/etc
# Option 2: Use /usr/etc only (not recommended)
rm -rf /etc
```
### 3. Multiple Kernels
**Problem**: Multiple kernel versions present
**Solution**:
```bash
# Keep only one kernel
rm -rf /usr/lib/modules/5.4.0
# Keep /usr/lib/modules/6.1.0
```
### 4. Non-UTF-8 Filenames
**Problem**: Files with non-UTF-8 names
**Solution**:
```bash
# Find and rename files
find / -name "*" -print0 | xargs -0 -I {} sh -c 'echo "Found: {}"'
# Rename problematic files
```
### 5. Missing API Directories
**Problem**: Required directories missing
**Solution**:
```bash
mkdir -p /dev /proc /sys /run /tmp /var
```
## Best Practices
### 1. Container Image Construction
- Use minimal base images
- Install only necessary packages
- Clean up package caches
- Avoid creating log files
- Use symlinks for `/var/run`
### 2. User and Group Management
- Use systemd sysusers.d for user/group definitions
- Avoid direct `/etc/passwd` modifications
- Use `DynamicUser=yes` in systemd services when possible
### 3. Filesystem Organization
- Keep `/boot` empty
- Use `/usr/lib/modules` for kernel content
- Place configuration in `/usr` when possible
- Use tmpfiles.d for runtime directory creation
### 4. Build Process
- Run lint early in build process
- Use `--fatal-warnings` in CI/CD
- Fix issues immediately
- Test with actual bootc installation
## Troubleshooting
### Debug Mode
```bash
# Enable debug output
RUST_LOG=debug bootc container lint
```
### Verbose Output
```bash
# Show all issues without truncation
bootc container lint --no-truncate
```
### Specific Lint Testing
```bash
# Test specific lint
bootc container lint --skip $(bootc container lint --list | grep -v var-run | awk '{print $1}' | tr '\n' ' ')
```
## Integration with Other Tools
### Pre-commit Hooks
```bash
#!/bin/bash
# .git/hooks/pre-commit
podman run --rm -v $(pwd):/workspace my-bootc-image bootc container lint --rootfs /workspace
```
### Makefile Integration
```makefile
lint:
podman run --rm $(IMAGE) bootc container lint --fatal-warnings
build: lint
podman build --tag $(IMAGE) .
```
### Docker Compose
```yaml
version: '3'
services:
lint:
image: my-bootc-image
command: bootc container lint --fatal-warnings
volumes:
- .:/workspace
working_dir: /workspace
```
## Performance Considerations
- Lint runs are relatively fast
- Recursive checks (like UTF-8) may take longer on large filesystems
- Use `--skip` to exclude expensive checks during development
- Run full lint in CI/CD pipelines
## Future Enhancements
- Additional security checks
- Performance optimization suggestions
- Integration with more container runtimes
- Enhanced reporting formats
- Custom lint rule support
---
This comprehensive guide provides everything needed to effectively use `bootc container lint` for validating bootc-compatible container images.

View file

@ -0,0 +1,578 @@
# bootc container lint - Examples and Troubleshooting
## Practical Examples
### 1. Basic Container Image Linting
#### Minimal Working Example
```dockerfile
FROM debian:bookworm-slim
# Install bootc
RUN apt update && apt install -y bootc && apt clean
# Create required API directories
RUN mkdir -p /dev /proc /sys /run /tmp /var
# Create proper /var/run symlink
RUN ln -sf /run /var/run
# Create /sysroot and /ostree structure
RUN mkdir -p /sysroot/ostree && ln -sf sysroot/ostree /ostree
# Create kernel structure
RUN mkdir -p /usr/lib/modules/6.1.0 && \
echo "kernel" > /usr/lib/modules/6.1.0/vmlinuz
# Create empty /boot directory
RUN mkdir -p /boot
# Lint the container
RUN bootc container lint
```
#### Common Issues and Fixes
**Issue**: `/var/run` is a directory instead of symlink
```bash
# Problem
mkdir -p /var/run
# Fix
rm -rf /var/run
ln -sf /run /var/run
```
**Issue**: Both `/etc` and `/usr/etc` exist
```bash
# Problem
mkdir -p /etc /usr/etc
# Fix (choose one)
rm -rf /usr/etc # Keep /etc
# OR
rm -rf /etc # Keep /usr/etc (not recommended)
```
**Issue**: Multiple kernels present
```bash
# Problem
mkdir -p /usr/lib/modules/5.4.0 /usr/lib/modules/6.1.0
# Fix
rm -rf /usr/lib/modules/5.4.0 # Keep only one
```
### 2. Advanced Container Configuration
#### Complete bootc-compatible Image
```dockerfile
FROM debian:bookworm-slim
# Install bootc and dependencies
RUN apt update && \
apt install -y bootc ostree systemd && \
apt clean && \
rm -rf /var/lib/apt/lists/*
# Create required API directories
RUN mkdir -p /dev /proc /sys /run /tmp /var
# Fix /var/run symlink
RUN ln -sf /run /var/run
# Create bootc-specific structure
RUN mkdir -p /sysroot/ostree && \
ln -sf sysroot/ostree /ostree
# Create kernel structure
RUN mkdir -p /usr/lib/modules/6.1.0 && \
echo "kernel" > /usr/lib/modules/6.1.0/vmlinuz && \
echo "initramfs" > /usr/lib/modules/6.1.0/initramfs.img
# Create empty /boot directory
RUN mkdir -p /boot
# Configure composefs
RUN mkdir -p /usr/lib/ostree && \
echo '[composefs]\nenabled = true' > /usr/lib/ostree/prepare-root.conf
# Configure kernel arguments
RUN mkdir -p /usr/lib/bootc/kargs.d && \
echo '[kargs]\nappend = ["console=ttyS0", "quiet"]' > /usr/lib/bootc/kargs.d/99-console.toml
# Create systemd sysusers.d entries
RUN mkdir -p /usr/lib/sysusers.d && \
echo 'u app 1000 "Application User"' > /usr/lib/sysusers.d/app.conf
# Create tmpfiles.d entries
RUN mkdir -p /usr/lib/tmpfiles.d && \
echo 'd /var/log/app 0755 app app -' > /usr/lib/tmpfiles.d/app.conf
# Lint the container
RUN bootc container lint --fatal-warnings
```
### 3. CI/CD Integration Examples
#### GitHub Actions
```yaml
name: Build and Lint bootc Image
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build container image
run: |
podman build --tag my-bootc-image .
- name: Lint container image
run: |
podman run --rm my-bootc-image bootc container lint --fatal-warnings
- name: Test installation
run: |
podman run --rm --privileged my-bootc-image bootc install to-disk /dev/loop0
```
#### GitLab CI
```yaml
stages:
- build
- lint
- test
build:
stage: build
script:
- podman build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- podman push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
lint:
stage: lint
script:
- podman run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA bootc container lint --fatal-warnings
test:
stage: test
script:
- podman run --rm --privileged $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA bootc install to-disk /dev/loop0
```
#### Jenkins Pipeline
```groovy
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'podman build --tag my-bootc-image .'
}
}
stage('Lint') {
steps {
sh 'podman run --rm my-bootc-image bootc container lint --fatal-warnings'
}
}
stage('Test') {
steps {
sh 'podman run --rm --privileged my-bootc-image bootc install to-disk /dev/loop0'
}
}
}
}
```
### 4. Development Workflow Examples
#### Pre-commit Hook
```bash
#!/bin/bash
# .git/hooks/pre-commit
echo "Running bootc container lint..."
# Build the image
podman build --tag temp-bootc-image . || exit 1
# Run lint
podman run --rm temp-bootc-image bootc container lint --fatal-warnings || {
echo "Lint failed. Please fix issues before committing."
podman rmi temp-bootc-image
exit 1
}
# Clean up
podman rmi temp-bootc-image
echo "Lint passed!"
```
#### Makefile Integration
```makefile
.PHONY: build lint test clean
IMAGE_NAME = my-bootc-image
IMAGE_TAG = latest
build:
podman build --tag $(IMAGE_NAME):$(IMAGE_TAG) .
lint: build
podman run --rm $(IMAGE_NAME):$(IMAGE_TAG) bootc container lint --fatal-warnings
test: lint
podman run --rm --privileged $(IMAGE_NAME):$(IMAGE_TAG) bootc install to-disk /dev/loop0
clean:
podman rmi $(IMAGE_NAME):$(IMAGE_TAG) || true
all: test
```
#### Docker Compose
```yaml
version: '3.8'
services:
build:
build: .
image: my-bootc-image:latest
lint:
image: my-bootc-image:latest
command: bootc container lint --fatal-warnings
depends_on:
- build
test:
image: my-bootc-image:latest
command: bootc install to-disk /dev/loop0
privileged: true
depends_on:
- lint
```
## Troubleshooting Guide
### 1. Common Error Messages
#### "Failed lint: var-run: Not a symlink: var/run"
**Problem**: `/var/run` exists as a directory instead of symlink
**Solution**:
```bash
# Remove directory and create symlink
rm -rf /var/run
ln -sf /run /var/run
```
**Dockerfile Fix**:
```dockerfile
RUN rm -rf /var/run && ln -sf /run /var/run
```
#### "Failed lint: etc-usretc: Found /usr/etc - this is a bootc implementation detail"
**Problem**: Both `/etc` and `/usr/etc` exist
**Solution**:
```bash
# Choose one approach
rm -rf /usr/etc # Keep /etc (recommended)
# OR
rm -rf /etc # Keep /usr/etc (not recommended)
```
**Dockerfile Fix**:
```dockerfile
RUN rm -rf /usr/etc # Keep /etc only
```
#### "Failed lint: kernel: Multiple kernels found"
**Problem**: Multiple kernel versions present
**Solution**:
```bash
# Keep only one kernel version
rm -rf /usr/lib/modules/5.4.0
# Keep /usr/lib/modules/6.1.0
```
**Dockerfile Fix**:
```dockerfile
RUN rm -rf /usr/lib/modules/5.4.0 # Keep only 6.1.0
```
#### "Failed lint: utf8: Found non-utf8 filename"
**Problem**: Files with non-UTF-8 names
**Solution**:
```bash
# Find and rename problematic files
find / -name "*" -print0 | xargs -0 -I {} sh -c 'echo "Checking: {}"'
# Rename files with non-UTF-8 names
```
**Prevention**:
```dockerfile
# Use UTF-8 locale
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
```
#### "Failed lint: api-base-directories: Missing API filesystem base directory"
**Problem**: Required directories missing
**Solution**:
```bash
# Create all required directories
mkdir -p /dev /proc /sys /run /tmp /var
```
**Dockerfile Fix**:
```dockerfile
RUN mkdir -p /dev /proc /sys /run /tmp /var
```
### 2. Warning Messages
#### "Lint warning: buildah-injected: /etc/hostname is an empty file"
**Problem**: Empty files injected by build system
**Solution**:
```bash
# Remove empty files or add content
rm /etc/hostname
# OR
echo "myhostname" > /etc/hostname
```
**Dockerfile Fix**:
```dockerfile
RUN rm -f /etc/hostname /etc/resolv.conf
```
#### "Lint warning: var-log: Found non-empty logfiles"
**Problem**: Log files in container image
**Solution**:
```bash
# Remove log files
rm -rf /var/log/*
# OR create symlinks to /dev/null
ln -sf /dev/null /var/log/app.log
```
**Dockerfile Fix**:
```dockerfile
RUN rm -rf /var/log/* && \
mkdir -p /var/log && \
ln -sf /dev/null /var/log/app.log
```
#### "Lint warning: nonempty-boot: Found non-empty /boot"
**Problem**: Content in `/boot` directory
**Solution**:
```bash
# Remove content from /boot
rm -rf /boot/*
# Keep /boot empty
```
**Dockerfile Fix**:
```dockerfile
RUN rm -rf /boot/* && mkdir -p /boot
```
### 3. Debugging Techniques
#### Enable Debug Output
```bash
# Enable detailed logging
RUST_LOG=debug bootc container lint
# Show all issues without truncation
bootc container lint --no-truncate
# List all available lints
bootc container lint --list
```
#### Test Specific Lints
```bash
# Test only fatal lints
bootc container lint --skip var-log --skip buildah-injected --skip baseimage-composefs --skip var-tmpfiles --skip sysusers --skip nonempty-boot
# Test only warning lints
bootc container lint --skip var-run --skip etc-usretc --skip bootc-kargs --skip kernel --skip utf8 --skip api-base-directories --skip baseimage-root
```
#### Inspect Container Structure
```bash
# Explore container filesystem
podman run --rm -it my-image bash
# Check specific directories
ls -la /var/run
ls -la /etc /usr/etc
ls -la /usr/lib/modules/
ls -la /boot
```
### 4. Performance Optimization
#### Skip Expensive Lints During Development
```bash
# Skip recursive UTF-8 check during development
bootc container lint --skip utf8
# Skip all warning lints
bootc container lint --skip var-log --skip buildah-injected --skip baseimage-composefs --skip var-tmpfiles --skip sysusers --skip nonempty-boot
```
#### Use Faster Base Images
```dockerfile
# Use minimal base image
FROM debian:bookworm-slim
# Avoid unnecessary packages
RUN apt update && \
apt install -y --no-install-recommends bootc && \
apt clean && \
rm -rf /var/lib/apt/lists/*
```
### 5. Integration Issues
#### Container Runtime Compatibility
**Problem**: Lint fails in different container runtime
**Solution**:
```bash
# Use podman (recommended)
podman run --rm my-image bootc container lint
# Use docker with proper flags
docker run --rm my-image bootc container lint
```
#### Build Context Issues
**Problem**: Lint fails due to build context
**Solution**:
```dockerfile
# Ensure proper working directory
WORKDIR /
# Copy files explicitly
COPY . /workspace
WORKDIR /workspace
```
#### Permission Issues
**Problem**: Permission denied errors
**Solution**:
```bash
# Run with proper permissions
podman run --rm --user root my-image bootc container lint
# Or fix permissions in container
RUN chmod -R 755 /usr/lib/bootc
```
### 6. Advanced Troubleshooting
#### Custom Lint Configuration
```bash
# Create custom lint script
#!/bin/bash
set -e
echo "Running custom lint checks..."
# Run specific lints
bootc container lint --skip utf8 --skip var-log
# Additional custom checks
if [ -f /etc/hostname ]; then
echo "Warning: /etc/hostname should not exist in container"
fi
echo "Custom lint checks passed!"
```
#### Lint Result Analysis
```bash
# Capture lint output for analysis
bootc container lint --no-truncate > lint-results.txt 2>&1
# Analyze results
grep "Failed lint" lint-results.txt
grep "Lint warning" lint-results.txt
```
#### Automated Fixes
```bash
#!/bin/bash
# Auto-fix common issues
echo "Fixing common bootc lint issues..."
# Fix /var/run
if [ -d /var/run ] && [ ! -L /var/run ]; then
echo "Fixing /var/run symlink..."
rm -rf /var/run
ln -sf /run /var/run
fi
# Fix /usr/etc
if [ -d /usr/etc ] && [ -d /etc ]; then
echo "Removing /usr/etc (keeping /etc)..."
rm -rf /usr/etc
fi
# Fix /boot
if [ -d /boot ] && [ "$(ls -A /boot)" ]; then
echo "Clearing /boot directory..."
rm -rf /boot/*
fi
# Fix log files
if [ -d /var/log ] && [ "$(ls -A /var/log)" ]; then
echo "Clearing log files..."
rm -rf /var/log/*
fi
echo "Auto-fix completed!"
```
This comprehensive examples and troubleshooting guide provides practical solutions for common bootc lint issues and integration patterns.

243
lint/quick-reference.md Normal file
View file

@ -0,0 +1,243 @@
# bootc container lint - Quick Reference
## Command Syntax
```bash
bootc container lint [OPTIONS...]
```
## Common Options
| Option | Description | Example |
|--------|-------------|---------|
| `--rootfs` | Specify root filesystem path | `--rootfs /path/to/rootfs` |
| `--fatal-warnings` | Treat warnings as fatal errors | `--fatal-warnings` |
| `--list` | List all available lints | `--list` |
| `--skip` | Skip specific lints | `--skip var-log --skip buildah-injected` |
| `--no-truncate` | Show full output (no truncation) | `--no-truncate` |
## Fatal Lints (Must Pass)
| Lint | Purpose | Fix |
|------|---------|-----|
| `var-run` | `/var/run` must be symlink to `/run` | `ln -sf /run /var/run` |
| `etc-usretc` | Only `/etc` OR `/usr/etc` (not both) | `rm -rf /usr/etc` |
| `bootc-kargs` | Valid kernel args in `/usr/lib/bootc/kargs.d/` | Fix TOML syntax |
| `kernel` | Exactly one kernel in `/usr/lib/modules/` | `rm -rf /usr/lib/modules/5.4.0` |
| `utf8` | All filenames must be UTF-8 | Rename non-UTF-8 files |
| `api-base-directories` | Required dirs: `/dev`, `/proc`, `/sys`, `/run`, `/tmp`, `/var` | `mkdir -p /dev /proc /sys /run /tmp /var` |
| `baseimage-root` | Required: `/sysroot`, `/ostree -> sysroot/ostree` | `mkdir -p /sysroot/ostree && ln -sf sysroot/ostree /ostree` |
## Warning Lints (Recommended)
| Lint | Purpose | Fix |
|------|---------|-----|
| `buildah-injected` | No empty `/etc/hostname` or `/etc/resolv.conf` | `rm /etc/hostname /etc/resolv.conf` |
| `baseimage-composefs` | Enable composefs in ostree | `echo '[composefs]\nenabled = true' > /usr/lib/ostree/prepare-root.conf` |
| `var-log` | No log files in `/var/log` | `rm -rf /var/log/*` |
| `var-tmpfiles` | `/var` content needs tmpfiles.d entries | Create `/usr/lib/tmpfiles.d/*.conf` |
| `sysusers` | Users/groups need sysusers.d entries | Create `/usr/lib/sysusers.d/*.conf` |
| `nonempty-boot` | `/boot` should be empty | `rm -rf /boot/*` |
## Quick Fixes
### Fix Common Issues
```bash
# Fix /var/run
rm -rf /var/run && ln -sf /run /var/run
# Fix /usr/etc
rm -rf /usr/etc
# Fix /boot
rm -rf /boot/* && mkdir -p /boot
# Fix log files
rm -rf /var/log/*
# Fix empty files
rm -f /etc/hostname /etc/resolv.conf
```
### Create Required Structure
```bash
# API directories
mkdir -p /dev /proc /sys /run /tmp /var
# bootc structure
mkdir -p /sysroot/ostree
ln -sf sysroot/ostree /ostree
# Kernel structure
mkdir -p /usr/lib/modules/6.1.0
echo "kernel" > /usr/lib/modules/6.1.0/vmlinuz
# Empty /boot
mkdir -p /boot
```
## Dockerfile Examples
### Minimal Working Container
```dockerfile
FROM debian:bookworm-slim
# Install bootc
RUN apt update && apt install -y bootc && apt clean
# Fix common issues
RUN rm -rf /var/run && ln -sf /run /var/run
RUN rm -rf /usr/etc
RUN rm -rf /boot/* && mkdir -p /boot
RUN rm -rf /var/log/*
# Create required structure
RUN mkdir -p /dev /proc /sys /run /tmp /var
RUN mkdir -p /sysroot/ostree && ln -sf sysroot/ostree /ostree
RUN mkdir -p /usr/lib/modules/6.1.0
RUN echo "kernel" > /usr/lib/modules/6.1.0/vmlinuz
# Lint
RUN bootc container lint --fatal-warnings
```
### Complete bootc Image
```dockerfile
FROM debian:bookworm-slim
# Install dependencies
RUN apt update && \
apt install -y bootc ostree systemd && \
apt clean && \
rm -rf /var/lib/apt/lists/*
# Fix common issues
RUN rm -rf /var/run && ln -sf /run /var/run
RUN rm -rf /usr/etc
RUN rm -rf /boot/* && mkdir -p /boot
RUN rm -rf /var/log/*
# Create required structure
RUN mkdir -p /dev /proc /sys /run /tmp /var
RUN mkdir -p /sysroot/ostree && ln -sf sysroot/ostree /ostree
RUN mkdir -p /usr/lib/modules/6.1.0
RUN echo "kernel" > /usr/lib/modules/6.1.0/vmlinuz
# Configure composefs
RUN mkdir -p /usr/lib/ostree && \
echo '[composefs]\nenabled = true' > /usr/lib/ostree/prepare-root.conf
# Configure kernel args
RUN mkdir -p /usr/lib/bootc/kargs.d && \
echo '[kargs]\nappend = ["console=ttyS0", "quiet"]' > /usr/lib/bootc/kargs.d/99-console.toml
# Lint
RUN bootc container lint --fatal-warnings
```
## CI/CD Integration
### GitHub Actions
```yaml
- name: Lint bootc container
run: podman run --rm ${{ matrix.image }} bootc container lint --fatal-warnings
```
### GitLab CI
```yaml
lint:
script:
- podman run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA bootc container lint --fatal-warnings
```
### Jenkins
```groovy
stage('Lint') {
steps {
sh 'podman run --rm my-image bootc container lint --fatal-warnings'
}
}
```
## Common Commands
```bash
# Basic lint
bootc container lint
# Lint with warnings as fatal
bootc container lint --fatal-warnings
# Lint specific rootfs
bootc container lint --rootfs /path/to/rootfs
# Skip specific lints
bootc container lint --skip var-log --skip buildah-injected
# Show all issues
bootc container lint --no-truncate
# List available lints
bootc container lint --list
# Debug mode
RUST_LOG=debug bootc container lint
```
## Troubleshooting
### Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `Not a symlink: var/run` | `/var/run` is directory | `ln -sf /run /var/run` |
| `Found /usr/etc` | Both `/etc` and `/usr/etc` exist | `rm -rf /usr/etc` |
| `Multiple kernels found` | Multiple kernel versions | Keep only one |
| `Found non-utf8 filename` | Non-UTF-8 filenames | Rename files |
| `Missing API filesystem base directory` | Missing required dirs | `mkdir -p /dev /proc /sys /run /tmp /var` |
### Debug Commands
```bash
# Check container structure
podman run --rm -it my-image bash
ls -la /var/run
ls -la /etc /usr/etc
ls -la /usr/lib/modules/
ls -la /boot
# Test specific lints
bootc container lint --skip utf8 --skip var-log
# Show full output
bootc container lint --no-truncate
```
## Best Practices
1. **Run lint early** in build process
2. **Use `--fatal-warnings`** in CI/CD
3. **Fix issues immediately** when found
4. **Test with actual bootc installation**
5. **Use minimal base images**
6. **Clean up package caches**
7. **Avoid creating log files**
8. **Use symlinks for `/var/run`**
## File Locations
| Purpose | Location |
|---------|----------|
| Kernel args | `/usr/lib/bootc/kargs.d/*.toml` |
| Composefs config | `/usr/lib/ostree/prepare-root.conf` |
| Sysusers config | `/usr/lib/sysusers.d/*.conf` |
| Tmpfiles config | `/usr/lib/tmpfiles.d/*.conf` |
| Kernel files | `/usr/lib/modules/$kver/vmlinuz` |
| Initramfs | `/usr/lib/modules/$kver/initramfs.img` |

550
lint/technical-reference.md Normal file
View file

@ -0,0 +1,550 @@
# bootc container lint - Technical Reference
## Architecture Overview
The bootc lint system is built on a distributed slice architecture using the `linkme` crate, allowing for modular lint registration and execution. The system supports both regular and recursive lints, with configurable execution and output formatting.
## Core Components
### 1. Lint Registration System
```rust
// From lints.rs:86-87
#[distributed_slice]
pub(crate) static LINTS: [Lint];
```
**Purpose**: Central registry for all lint checks
**Implementation**: Uses `linkme` distributed slices for automatic registration
**Benefits**: Modular design, easy addition of new lints
### 2. Lint Types
#### Fatal Lints
```rust
// From lints.rs:92-98
enum LintType {
Fatal, // Must pass for installation
Warning, // Recommended but not required
}
```
**Fatal Lints**: Prevent bootc installation if they fail
**Warning Lints**: Show warnings but allow installation to proceed
### 3. Root Type Classification
```rust
// From lints.rs:106-111
enum RootType {
Running, // Running system root
Alternative, // Alternative/container root
}
```
**Running**: Lints that apply to running systems
**Alternative**: Lints that apply to container images
## Lint Execution Engine
### 1. Execution Flow
```rust
// From lints.rs:254-364
fn lint_inner<'skip>(
root: &Dir,
root_type: RootType,
config: &LintExecutionConfig,
skip: impl IntoIterator<Item = &'skip str>,
mut output: impl std::io::Write,
) -> Result<LintExecutionResult>
```
**Process**:
1. Filter applicable lints based on root type
2. Separate regular and recursive lints
3. Execute regular lints
4. Execute recursive lints via filesystem walk
5. Collect and report results
### 2. Recursive Lint Execution
```rust
// From lints.rs:295-328
root.walk(
&WalkConfiguration::default()
.noxdev()
.path_base(Path::new("/")),
|e| -> std::io::Result<_> {
// Execute recursive lints on each filesystem entry
},
)?;
```
**Features**:
- Filesystem traversal with `noxdev` (no cross-device)
- Early termination on first error
- Efficient processing of large filesystems
### 3. Output Formatting
```rust
// From lints.rs:200-235
fn format_items<T>(
config: &LintExecutionConfig,
header: &str,
items: impl Iterator<Item = T>,
o: &mut String,
) -> Result<()>
```
**Features**:
- Configurable truncation (default: 5 items)
- Consistent formatting across lints
- Support for custom display implementations
## Individual Lint Implementations
### 1. var-run Lint
```rust
// From lints.rs:397-410
static LINT_VAR_RUN: Lint = Lint::new_fatal(
"var-run",
"Check for /var/run being a physical directory; this is always a bug.",
check_var_run,
);
```
**Purpose**: Ensures `/var/run` is a symlink to `/run`
**Check**: Validates symlink existence and target
**Rationale**: Required for proper systemd operation
### 2. etc-usretc Lint
```rust
// From lints.rs:435-458
static LINT_ETC_USRUSETC: Lint = Lint::new_fatal(
"etc-usretc",
"Verify that only one of /etc or /usr/etc exist...",
check_usretc,
);
```
**Purpose**: Prevents both `/etc` and `/usr/etc` from existing
**Check**: Validates mutual exclusivity
**Rationale**: `/usr/etc` is a bootc implementation detail
### 3. bootc-kargs Lint
```rust
// From lints.rs:461-471
static LINT_KARGS: Lint = Lint::new_fatal(
"bootc-kargs",
"Verify syntax of /usr/lib/bootc/kargs.d.",
check_parse_kargs,
);
```
**Purpose**: Validates kernel argument configuration
**Check**: Parses TOML files in `/usr/lib/bootc/kargs.d/`
**Integration**: Uses `crate::bootc_kargs::get_kargs_in_root`
### 4. kernel Lint
```rust
// From lints.rs:473-486
static LINT_KERNEL: Lint = Lint::new_fatal(
"kernel",
"Check for multiple kernels...",
check_kernel,
);
```
**Purpose**: Ensures exactly one kernel is present
**Check**: Validates `/usr/lib/modules/$kver` directories
**Integration**: Uses `ostree_ext::bootabletree::find_kernel_dir_fs`
### 5. utf8 Lint (Recursive)
```rust
// From lints.rs:489-522
static LINT_UTF8: Lint = Lint {
name: "utf8",
description: "Check for non-UTF8 filenames...",
ty: LintType::Fatal,
root_type: None,
f: LintFnTy::Recursive(check_utf8),
};
```
**Purpose**: Ensures all filenames and symlink targets are UTF-8
**Check**: Recursively validates filesystem entries
**Features**: Handles symlinks, broken links, and special cases
### 6. api-base-directories Lint
```rust
// From lints.rs:535-558
static LINT_API_DIRS: Lint = Lint::new_fatal(
"api-base-directories",
"Verify that expected base API directories exist...",
check_api_dirs,
);
```
**Purpose**: Validates required systemd API directories
**Check**: Ensures `/dev`, `/proc`, `/sys`, `/run`, `/tmp`, `/var` exist
**Rationale**: Required by systemd and Linux standards
### 7. baseimage-root Lint
```rust
// From lints.rs:610-632
static LINT_BASEIMAGE_ROOT: Lint = Lint::new_fatal(
"baseimage-root",
"Check that expected files are present in the root...",
check_baseimage_root,
);
```
**Purpose**: Validates bootc-specific root structure
**Check**: Ensures `/sysroot` exists and `/ostree` symlinks correctly
**Integration**: Checks embedded documentation for consistency
## Warning Lints
### 1. buildah-injected Lint
```rust
// From lints.rs:412-433
static LINT_BUILDAH_INJECTED: Lint = Lint::new_warning(
"buildah-injected",
"Check for an invalid /etc/hostname or /etc/resolv.conf...",
check_buildah_injected,
)
.set_root_type(RootType::Alternative);
```
**Purpose**: Detects empty files injected by build systems
**Check**: Looks for empty `/etc/hostname` or `/etc/resolv.conf`
**Scope**: Only applies to alternative roots (container images)
### 2. baseimage-composefs Lint
```rust
// From lints.rs:560-581
static LINT_COMPOSEFS: Lint = Lint::new_warning(
"baseimage-composefs",
"Check that composefs is enabled for ostree...",
check_composefs,
);
```
**Purpose**: Recommends composefs for ostree
**Check**: Validates composefs configuration
**Integration**: Uses `ostree_prepareroot` for configuration parsing
### 3. var-log Lint
```rust
// From lints.rs:656-682
static LINT_VARLOG: Lint = Lint::new_warning(
"var-log",
"Check for non-empty regular files in /var/log...",
check_varlog,
);
```
**Purpose**: Warns about log files in container images
**Check**: Identifies non-empty files in `/var/log`
**Features**: Recursive directory scanning with size checking
### 4. var-tmpfiles Lint
```rust
// From lints.rs:684-712
static LINT_VAR_TMPFILES: Lint = Lint::new_warning(
"var-tmpfiles",
"Check for content in /var that does not have corresponding systemd tmpfiles.d entries...",
check_var_tmpfiles,
)
.set_root_type(RootType::Running);
```
**Purpose**: Validates tmpfiles.d configuration
**Check**: Ensures `/var` content has corresponding tmpfiles.d entries
**Scope**: Only applies to running systems
**Integration**: Uses `bootc_tmpfiles` crate
### 5. sysusers Lint
```rust
// From lints.rs:714-743
static LINT_SYSUSERS: Lint = Lint::new_warning(
"sysusers",
"Check for users in /etc/passwd and groups in /etc/group...",
check_sysusers,
);
```
**Purpose**: Validates user/group definitions
**Check**: Ensures sysusers.d entries exist for passwd/group entries
**Integration**: Uses `bootc_sysusers` crate
### 6. nonempty-boot Lint
```rust
// From lints.rs:745-773
static LINT_NONEMPTY_BOOT: Lint = Lint::new_warning(
"nonempty-boot",
"The /boot directory should be present, but empty...",
check_boot,
);
```
**Purpose**: Warns about content in `/boot` directory
**Check**: Ensures `/boot` is empty in container images
**Rationale**: Kernel content should be in `/usr/lib/modules`
## Configuration and Options
### 1. LintExecutionConfig
```rust
// From lints.rs:69-72
struct LintExecutionConfig {
no_truncate: bool,
}
```
**no_truncate**: Controls output truncation (default: false, shows 5 items)
### 2. WarningDisposition
```rust
// From lints.rs:101-104
enum WarningDisposition {
AllowWarnings, // Warnings don't fail the build
FatalWarnings, // Warnings are treated as fatal
}
```
**Purpose**: Controls how warnings are handled
**Default**: AllowWarnings
### 3. RootType
```rust
// From lints.rs:106-111
enum RootType {
Running, // Running system root
Alternative, // Alternative/container root
}
```
**Purpose**: Determines which lints apply to which root types
**Filtering**: Lints can be restricted to specific root types
## Error Handling
### 1. LintError Type
```rust
// From lints.rs:38-67
struct LintError(String);
impl std::fmt::Display for LintError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
```
**Purpose**: Represents lint failures
**Features**: Custom display implementation for formatted output
### 2. Result Types
```rust
// From lints.rs:44
type LintResult = Result<std::result::Result<(), LintError>>;
```
**Outer Result**: Runtime errors (file system issues, etc.)
**Inner Result**: Lint success/failure
**Pattern**: `Ok(Ok(()))` = success, `Ok(Err(LintError))` = lint failure
### 3. Error Reporting
```rust
// From lints.rs:340-356
if let Err(e) = r {
match lint.ty {
LintType::Fatal => {
writeln!(output, "Failed lint: {name}: {e}")?;
fatal += 1;
}
LintType::Warning => {
writeln!(output, "Lint warning: {name}: {e}")?;
warnings += 1;
}
}
}
```
**Format**: Consistent error message formatting
**Categorization**: Separate handling for fatal vs warning errors
## Performance Optimizations
### 1. Early Termination
```rust
// From lints.rs:300-303
if recursive_lints.is_empty() {
return Ok(ControlFlow::Break(()));
}
```
**Feature**: Stops processing when no recursive lints remain
**Benefit**: Avoids unnecessary filesystem traversal
### 2. Lint Filtering
```rust
// From lints.rs:265-275
let (mut applicable_lints, skipped_lints): (Vec<_>, Vec<_>) = LINTS.iter().partition(|lint| {
if skip.contains(lint.name) {
return false;
}
if let Some(lint_root_type) = lint.root_type {
if lint_root_type != root_type {
return false;
}
}
true
});
```
**Feature**: Only runs applicable lints
**Benefit**: Reduces execution time for irrelevant checks
### 3. Output Truncation
```rust
// From lints.rs:221-233
if config.no_truncate {
// Show all items
} else {
// Show limited items with count
if rest > 0 {
writeln!(o, " ...and {rest} more")?;
}
}
```
**Feature**: Configurable output length
**Default**: 5 items per lint
**Benefit**: Prevents overwhelming output for large issues
## Testing Framework
### 1. Test Fixtures
```rust
// From lints.rs:788-814
fn passing_fixture() -> Result<cap_std_ext::cap_tempfile::TempDir> {
let root = cap_std_ext::cap_tempfile::tempdir(cap_std::ambient_authority())?;
for d in API_DIRS {
root.create_dir(d)?;
}
// ... setup valid filesystem structure
Ok(root)
}
```
**Purpose**: Creates test filesystems for lint validation
**Features**: Both passing and failing test cases
### 2. Individual Lint Tests
```rust
// From lints.rs:816-828
#[test]
fn test_var_run() -> Result<()> {
let root = &fixture()?;
let config = &LintExecutionConfig::default();
// Test passing case
check_var_run(root, config).unwrap().unwrap();
// Test failing case
root.create_dir_all("var/run/foo")?;
assert!(check_var_run(root, config).unwrap().is_err());
Ok(())
}
```
**Coverage**: Each lint has dedicated tests
**Scenarios**: Both success and failure cases
### 3. Integration Tests
```rust
// From lints.rs:844-889
#[test]
fn test_lint_inner() -> Result<()> {
let root = &passing_fixture()?;
let config = &LintExecutionConfig::default();
let mut out = Vec::new();
let root_type = RootType::Alternative;
let r = lint_inner(root, root_type, config, [], &mut out).unwrap();
// Verify results
assert_eq!(r.passed, *ALTROOT_LINTS);
Ok(())
}
```
**Purpose**: Tests the complete lint execution flow
**Validation**: Verifies correct counting and categorization
## Integration Points
### 1. OSTree Integration
- Uses `ostree_ext::bootabletree` for kernel detection
- Integrates with `ostree_prepareroot` for composefs validation
- Leverages OSTree's filesystem understanding
### 2. Systemd Integration
- Validates systemd API directories
- Checks tmpfiles.d configuration
- Validates sysusers.d entries
### 3. Container Runtime Integration
- Designed for container build processes
- Supports various root filesystem types
- Handles container-specific issues
## Future Enhancements
### 1. Extensibility
- Plugin system for custom lints
- Configuration file support
- Custom output formats
### 2. Performance
- Parallel lint execution
- Incremental checking
- Caching mechanisms
### 3. Integration
- IDE integration
- CI/CD pipeline optimization
- Real-time feedback
This technical reference provides comprehensive understanding of the bootc lint system's architecture, implementation, and usage patterns.