+
+
npm
elixir
+
+
::
django
+
โ‰ 
+
json
+
fiber
+
+
gcp
+
~
+
ractive
eslint
+
linux
+
marko
django
+
aws
+
rails
+
+
elixir
+
+
argocd
+
+
+
htmx
+
+
+
+
+
+
choo
+
xgboost
cdn
+
+
ember
+
flask
+
vb
$
+
kotlin
=>
+
cassandra
+
cypress
spring
clj
+
notepad++
?
+
sql
goland
+
saml
grafana
===
+
+
jest
0x
toml
netlify
mocha
torch
+
astro
+
s3
Back to Blog
Implementing Package Post-install Scripts ๐Ÿ“‹
alpine-linux packages post-install

Implementing Package Post-install Scripts ๐Ÿ“‹

Published Jun 3, 2025

Master Alpine Linux post-install script implementation for automated configuration, service setup, and deployment automation. Complete guide with ABUILD integration and advanced scripting techniques.

5 min read
0 views
Table of Contents

Post-install scripts in Alpine Linux packages enable automated configuration, service initialization, and system integration immediately after package installation. This comprehensive guide covers implementing, testing, and optimizing post-install scripts for reliable package deployment.

๐Ÿ” Understanding Alpine Package Post-install Scripts

Alpine Linux uses ABUILD package format with support for various installation hooks, including post-install scripts that execute automatically after package installation to configure services and system integration.

Script Types and Execution Order

  • Pre-install - Runs before package installation ๐Ÿ“ฅ
  • Post-install - Runs after package installation โœ…
  • Pre-deinstall - Runs before package removal โš ๏ธ
  • Post-deinstall - Runs after package removal ๐Ÿ—‘๏ธ
  • Pre-upgrade - Runs before package upgrade โฌ†๏ธ
  • Post-upgrade - Runs after package upgrade ๐Ÿ”„

Script Environment and Context

# Environment variables available in post-install scripts
echo "Package name: $pkgname"
echo "Package version: $pkgver"
echo "Package release: $pkgrel"
echo "Installation root: $pkgdir"
echo "Target root: $ROOT"
echo "Alpine version: $alpine_version"

๐Ÿ› ๏ธ Basic Post-install Script Implementation

Simple Post-install Script Structure

# Create basic APKBUILD with post-install
cat > APKBUILD << 'EOF'
# Maintainer: Your Name <[email protected]>
pkgname=my-web-service
pkgver=1.0.0
pkgrel=0
pkgdesc="Custom web service package"
url="https://example.com"
arch="all"
license="MIT"
depends="nginx openssl"
makedepends=""
install="$pkgname.post-install"
source="my-web-service.tar.gz"

package() {
    mkdir -p "$pkgdir/usr/bin"
    mkdir -p "$pkgdir/etc/nginx/sites-available"
    mkdir -p "$pkgdir/var/www/html"
    
    cp my-web-service "$pkgdir/usr/bin/"
    cp nginx.conf "$pkgdir/etc/nginx/sites-available/my-web-service"
    cp -r html/* "$pkgdir/var/www/html/"
}
EOF

# Create post-install script
cat > my-web-service.post-install << 'EOF'
#!/bin/sh

# Post-install script for my-web-service package
echo "Configuring my-web-service..."

# 1. Enable nginx site
if [ -f /etc/nginx/sites-available/my-web-service ]; then
    ln -sf /etc/nginx/sites-available/my-web-service /etc/nginx/sites-enabled/
    echo "โœ… Nginx site enabled"
fi

# 2. Set proper permissions
chown -R nginx:nginx /var/www/html
chmod -R 755 /var/www/html
echo "โœ… File permissions set"

# 3. Generate SSL certificate if needed
if [ ! -f /etc/ssl/certs/my-web-service.crt ]; then
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
        -keyout /etc/ssl/private/my-web-service.key \
        -out /etc/ssl/certs/my-web-service.crt \
        -subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
    echo "โœ… SSL certificate generated"
fi

# 4. Enable and start services
rc-update add nginx default
rc-service nginx restart

# 5. Create system user if needed
if ! id -u webservice >/dev/null 2>&1; then
    adduser -D -H -s /sbin/nologin webservice
    echo "โœ… Service user created"
fi

echo "โœ… my-web-service configuration completed"
EOF

chmod +x my-web-service.post-install

Database Package Post-install Script

# PostgreSQL post-install script example
cat > postgresql-custom.post-install << 'EOF'
#!/bin/sh

# PostgreSQL custom package post-install script
echo "Setting up PostgreSQL..."

# 1. Initialize database if not exists
if [ ! -d /var/lib/postgresql/data ]; then
    echo "Initializing PostgreSQL database..."
    mkdir -p /var/lib/postgresql/data
    chown postgres:postgres /var/lib/postgresql/data
    chmod 700 /var/lib/postgresql/data
    
    su - postgres -c "initdb -D /var/lib/postgresql/data"
    echo "โœ… Database initialized"
fi

# 2. Configure PostgreSQL
if [ -f /var/lib/postgresql/data/postgresql.conf ]; then
    # Backup original config
    cp /var/lib/postgresql/data/postgresql.conf /var/lib/postgresql/data/postgresql.conf.backup
    
    # Apply optimizations
    cat >> /var/lib/postgresql/data/postgresql.conf << 'PGCONF'

# Custom optimizations
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
PGCONF
    
    echo "โœ… PostgreSQL configuration optimized"
fi

# 3. Configure authentication
if [ -f /var/lib/postgresql/data/pg_hba.conf ]; then
    # Backup original
    cp /var/lib/postgresql/data/pg_hba.conf /var/lib/postgresql/data/pg_hba.conf.backup
    
    # Configure secure authentication
    cat > /var/lib/postgresql/data/pg_hba.conf << 'HBACONF'
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             postgres                                peer
local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
HBACONF
    
    echo "โœ… Authentication configured"
fi

# 4. Create application database and user
su - postgres -c "psql -c \"CREATE DATABASE myapp;\"" 2>/dev/null || true
su - postgres -c "psql -c \"CREATE USER myapp_user WITH PASSWORD 'secure_password';\"" 2>/dev/null || true
su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE myapp TO myapp_user;\"" 2>/dev/null || true

# 5. Enable and start PostgreSQL
rc-update add postgresql default
rc-service postgresql start

# 6. Wait for PostgreSQL to be ready
echo "Waiting for PostgreSQL to start..."
timeout=30
while [ $timeout -gt 0 ]; do
    if su - postgres -c "pg_isready" >/dev/null 2>&1; then
        echo "โœ… PostgreSQL is ready"
        break
    fi
    sleep 1
    timeout=$((timeout - 1))
done

if [ $timeout -eq 0 ]; then
    echo "โš ๏ธ  PostgreSQL startup timeout"
fi

echo "โœ… PostgreSQL setup completed"
EOF

chmod +x postgresql-custom.post-install

๐Ÿ”ง Advanced Post-install Script Techniques

Environment-Aware Configuration

# Environment-aware post-install script
cat > environment-aware.post-install << 'EOF'
#!/bin/sh

# Environment-aware post-install script
ENVIRONMENT="${ALPINE_ENV:-production}"
CONFIG_DIR="/etc/myapp"

echo "Configuring package for environment: $ENVIRONMENT"

# 1. Detect environment if not explicitly set
if [ "$ENVIRONMENT" = "production" ] && [ -z "$ALPINE_ENV" ]; then
    # Auto-detect based on hostname or other indicators
    if hostname | grep -q "dev\|test\|staging"; then
        ENVIRONMENT="development"
    elif [ -f /etc/alpine-release ] && grep -q "edge" /etc/alpine-release; then
        ENVIRONMENT="development"
    fi
fi

echo "Detected environment: $ENVIRONMENT"

# 2. Environment-specific configuration
case "$ENVIRONMENT" in
    production)
        echo "Applying production configuration..."
        
        # Production settings
        cat > "$CONFIG_DIR/config.yaml" << 'PRODCONF'
environment: production
debug: false
log_level: warn
database:
  pool_size: 20
  timeout: 30
security:
  strict_mode: true
  audit_logging: true
cache:
  enabled: true
  ttl: 3600
PRODCONF
        
        # Enable monitoring
        rc-update add my-monitor default
        
        # Set secure permissions
        chmod 600 "$CONFIG_DIR/config.yaml"
        ;;
        
    staging)
        echo "Applying staging configuration..."
        
        cat > "$CONFIG_DIR/config.yaml" << 'STAGCONF'
environment: staging
debug: true
log_level: info
database:
  pool_size: 10
  timeout: 60
security:
  strict_mode: true
  audit_logging: false
cache:
  enabled: true
  ttl: 1800
STAGCONF
        ;;
        
    development)
        echo "Applying development configuration..."
        
        cat > "$CONFIG_DIR/config.yaml" << 'DEVCONF'
environment: development
debug: true
log_level: debug
database:
  pool_size: 5
  timeout: 120
security:
  strict_mode: false
  audit_logging: false
cache:
  enabled: false
  ttl: 300
DEVCONF
        
        # Development tools
        apk add --no-cache curl jq htop
        ;;
esac

# 3. Common configuration regardless of environment
chown myapp:myapp "$CONFIG_DIR/config.yaml"
echo "โœ… Environment-specific configuration applied"
EOF

chmod +x environment-aware.post-install

Service Integration and Health Checks

# Service integration post-install script
cat > service-integration.post-install << 'EOF'
#!/bin/sh

# Service integration and health check post-install
SERVICE_NAME="myapp"
SERVICE_USER="myapp"
CONFIG_DIR="/etc/$SERVICE_NAME"
LOG_DIR="/var/log/$SERVICE_NAME"
DATA_DIR="/var/lib/$SERVICE_NAME"

echo "Setting up service integration for $SERVICE_NAME..."

# 1. Create service user and directories
if ! id "$SERVICE_USER" >/dev/null 2>&1; then
    adduser -D -H -s /sbin/nologin "$SERVICE_USER"
    echo "โœ… Service user created: $SERVICE_USER"
fi

for dir in "$CONFIG_DIR" "$LOG_DIR" "$DATA_DIR"; do
    mkdir -p "$dir"
    chown "$SERVICE_USER:$SERVICE_USER" "$dir"
    chmod 755 "$dir"
done

# 2. Create OpenRC service script
cat > "/etc/init.d/$SERVICE_NAME" << 'SERVICEEOF'
#!/sbin/openrc-run

name="myapp"
description="My Application Service"
command="/usr/bin/myapp"
command_args="--config /etc/myapp/config.yaml"
command_user="myapp:myapp"
command_background="yes"
pidfile="/var/run/myapp.pid"
output_log="/var/log/myapp/output.log"
error_log="/var/log/myapp/error.log"

depend() {
    need net
    after postgresql nginx
}

start_pre() {
    # Pre-start checks
    checkpath --directory --owner myapp:myapp --mode 0755 /var/run/myapp
    checkpath --file --owner myapp:myapp --mode 0644 /var/log/myapp/output.log
    checkpath --file --owner myapp:myapp --mode 0644 /var/log/myapp/error.log
    
    # Configuration validation
    if [ ! -f /etc/myapp/config.yaml ]; then
        eerror "Configuration file not found: /etc/myapp/config.yaml"
        return 1
    fi
    
    # Health check for dependencies
    if ! rc-service postgresql status >/dev/null 2>&1; then
        ewarn "PostgreSQL is not running"
    fi
}

start_post() {
    # Post-start verification
    local timeout=30
    local count=0
    
    einfo "Waiting for service to be ready..."
    while [ $count -lt $timeout ]; do
        if [ -f "$pidfile" ] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
            # Additional health check
            if curl -f -s http://localhost:8080/health >/dev/null 2>&1; then
                einfo "Service is healthy and ready"
                return 0
            fi
        fi
        sleep 1
        count=$((count + 1))
    done
    
    eerror "Service failed to start properly"
    return 1
}

stop_pre() {
    # Graceful shutdown preparation
    if [ -f "$pidfile" ]; then
        local pid=$(cat "$pidfile")
        einfo "Sending graceful shutdown signal to PID $pid"
        kill -TERM "$pid"
        
        # Wait for graceful shutdown
        local count=0
        while [ $count -lt 10 ] && kill -0 "$pid" 2>/dev/null; do
            sleep 1
            count=$((count + 1))
        done
    fi
}
SERVICEEOF

chmod +x "/etc/init.d/$SERVICE_NAME"
echo "โœ… OpenRC service script created"

# 3. Create health check script
cat > "/usr/local/bin/check-$SERVICE_NAME-health" << 'HEALTHEOF'
#!/bin/sh

# Health check script for myapp
SERVICE_NAME="myapp"
HEALTH_URL="http://localhost:8080/health"
TIMEOUT=10

# 1. Process check
if ! pgrep -f "$SERVICE_NAME" >/dev/null; then
    echo "CRITICAL: $SERVICE_NAME process not running"
    exit 2
fi

# 2. HTTP health check
if command -v curl >/dev/null 2>&1; then
    if curl -f -s --max-time $TIMEOUT "$HEALTH_URL" >/dev/null; then
        echo "OK: $SERVICE_NAME is healthy"
        exit 0
    else
        echo "WARNING: $SERVICE_NAME health check failed"
        exit 1
    fi
else
    echo "OK: $SERVICE_NAME process running (no HTTP check available)"
    exit 0
fi
HEALTHEOF

chmod +x "/usr/local/bin/check-$SERVICE_NAME-health"
echo "โœ… Health check script created"

# 4. Setup log rotation
cat > "/etc/logrotate.d/$SERVICE_NAME" << 'LOGROTATEEOF'
/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 myapp myapp
    postrotate
        /etc/init.d/myapp reload 2>/dev/null || true
    endscript
}
LOGROTATEEOF

echo "โœ… Log rotation configured"

# 5. Add to default runlevel and start
rc-update add "$SERVICE_NAME" default
rc-service "$SERVICE_NAME" start

# 6. Verify service started successfully
sleep 5
if rc-service "$SERVICE_NAME" status >/dev/null 2>&1; then
    echo "โœ… $SERVICE_NAME service started successfully"
else
    echo "โš ๏ธ  $SERVICE_NAME service failed to start"
    # Show logs for debugging
    tail -20 "/var/log/$SERVICE_NAME/error.log" 2>/dev/null || true
fi

echo "โœ… Service integration completed"
EOF

chmod +x service-integration.post-install

๐Ÿ“Š Script Testing and Validation

Post-install Script Testing Framework

# Create testing framework for post-install scripts
cat > /usr/local/bin/test-post-install << 'EOF'
#!/bin/sh

# Post-install script testing framework
SCRIPT_PATH="$1"
TEST_ROOT="/tmp/post-install-test-$$"

if [ -z "$SCRIPT_PATH" ] || [ ! -f "$SCRIPT_PATH" ]; then
    echo "Usage: $0 <post-install-script-path>"
    exit 1
fi

echo "=== Post-install Script Testing ==="
echo "Script: $SCRIPT_PATH"
echo "Test root: $TEST_ROOT"
echo ""

# 1. Setup test environment
echo "1. Setting up test environment..."
mkdir -p "$TEST_ROOT"/{etc,var,usr,tmp}
mkdir -p "$TEST_ROOT/var/log"
mkdir -p "$TEST_ROOT/var/lib"
mkdir -p "$TEST_ROOT/usr/bin"

# Mock environment variables
export pkgname="test-package"
export pkgver="1.0.0"
export pkgrel="0"
export ROOT="$TEST_ROOT"

echo "โœ… Test environment created"

# 2. Pre-execution state capture
echo ""
echo "2. Capturing pre-execution state..."
PROCESSES_BEFORE=$(ps -eo comm | sort | uniq -c)
SERVICES_BEFORE=$(rc-status --list 2>/dev/null || echo "No OpenRC services")

# 3. Execute post-install script in test environment
echo ""
echo "3. Executing post-install script..."
echo "Command: $SCRIPT_PATH"
echo "Working directory: $TEST_ROOT"

cd "$TEST_ROOT"
START_TIME=$(date +%s)

# Execute with error handling
if timeout 60 "$SCRIPT_PATH"; then
    END_TIME=$(date +%s)
    EXECUTION_TIME=$((END_TIME - START_TIME))
    echo "โœ… Script executed successfully in ${EXECUTION_TIME}s"
else
    EXIT_CODE=$?
    echo "โŒ Script execution failed with exit code: $EXIT_CODE"
fi

# 4. Post-execution analysis
echo ""
echo "4. Post-execution analysis..."

# Check for created files
echo "Files created in test environment:"
find "$TEST_ROOT" -type f 2>/dev/null | head -20

# Check for created directories
echo ""
echo "Directories created:"
find "$TEST_ROOT" -type d 2>/dev/null | head -10

# Check for permission changes
echo ""
echo "Permission analysis:"
find "$TEST_ROOT" -type f -perm /u+x 2>/dev/null | head -10

# 5. Service and process impact
echo ""
echo "5. Service and process impact..."
PROCESSES_AFTER=$(ps -eo comm | sort | uniq -c)
SERVICES_AFTER=$(rc-status --list 2>/dev/null || echo "No OpenRC services")

# Compare process lists
echo "New processes started:"
echo "$PROCESSES_AFTER" > /tmp/processes_after_$$
echo "$PROCESSES_BEFORE" > /tmp/processes_before_$$
comm -13 /tmp/processes_before_$$ /tmp/processes_after_$$ | head -10

# 6. Validation checks
echo ""
echo "6. Validation checks..."
ISSUES=0

# Check for common issues
if grep -r "sudo\|su -" "$SCRIPT_PATH" >/dev/null 2>&1; then
    echo "โš ๏ธ  Script contains privilege escalation commands"
    ISSUES=$((ISSUES + 1))
fi

if grep -r "rm -rf /\|rm -rf \*" "$SCRIPT_PATH" >/dev/null 2>&1; then
    echo "โŒ Script contains dangerous file operations"
    ISSUES=$((ISSUES + 1))
fi

if ! grep -q "#!/bin/sh\|#!/bin/bash" "$SCRIPT_PATH"; then
    echo "โš ๏ธ  Script missing shebang line"
    ISSUES=$((ISSUES + 1))
fi

# Check if script is executable
if [ ! -x "$SCRIPT_PATH" ]; then
    echo "โš ๏ธ  Script is not executable"
    ISSUES=$((ISSUES + 1))
fi

# 7. Security analysis
echo ""
echo "7. Security analysis..."

# Check for hardcoded credentials
if grep -i "password\|secret\|key.*=" "$SCRIPT_PATH" >/dev/null 2>&1; then
    echo "โš ๏ธ  Potential hardcoded credentials detected"
    ISSUES=$((ISSUES + 1))
fi

# Check for network operations
if grep -E "curl|wget|download" "$SCRIPT_PATH" >/dev/null 2>&1; then
    echo "โ„น๏ธ  Script performs network operations"
fi

# 8. Summary and recommendations
echo ""
echo "8. Test Summary:"
echo "================"
if [ $ISSUES -eq 0 ]; then
    echo "โœ… No critical issues found"
else
    echo "โš ๏ธ  Found $ISSUES potential issues"
fi

echo ""
echo "Script analysis completed for: $SCRIPT_PATH"

# Cleanup
rm -rf "$TEST_ROOT"
rm -f /tmp/processes_*_$$

echo "โœ… Test environment cleaned up"
EOF

chmod +x /usr/local/bin/test-post-install

# Usage example:
# test-post-install my-web-service.post-install

Integration Testing with ABUILD

# Integration testing for ABUILD packages
cat > /usr/local/bin/test-abuild-package << 'EOF'
#!/bin/sh

# ABUILD package integration testing
ABUILD_FILE="$1"
TEST_DIR="/tmp/abuild-test-$$"

if [ -z "$ABUILD_FILE" ] || [ ! -f "$ABUILD_FILE" ]; then
    echo "Usage: $0 <ABUILD-file-path>"
    exit 1
fi

echo "=== ABUILD Package Integration Testing ==="
echo "ABUILD file: $ABUILD_FILE"
echo ""

# 1. Setup test environment
mkdir -p "$TEST_DIR"
cd "$TEST_DIR"
cp "$ABUILD_FILE" .

# Extract package information
source "./$(basename "$ABUILD_FILE")"
echo "Package: $pkgname"
echo "Version: $pkgver-r$pkgrel"
echo "Description: $pkgdesc"
echo ""

# 2. Validate ABUILD file
echo "2. ABUILD Validation:"
echo "===================="

# Check required fields
REQUIRED_FIELDS="pkgname pkgver pkgrel pkgdesc url arch license"
for field in $REQUIRED_FIELDS; do
    eval value=\$$field
    if [ -n "$value" ]; then
        echo "โœ… $field: $value"
    else
        echo "โŒ Missing required field: $field"
    fi
done

# Check post-install script reference
if [ -n "$install" ]; then
    echo "โœ… Post-install script: $install"
    
    # Check if post-install script exists
    if [ -f "$install" ]; then
        echo "โœ… Post-install script file exists"
    else
        echo "โŒ Post-install script file missing: $install"
    fi
else
    echo "โ„น๏ธ  No post-install script configured"
fi

# 3. Build package (if sources available)
echo ""
echo "3. Package Build Test:"
echo "====================="

# Create mock source files if they don't exist
for source_file in $source; do
    if [ ! -f "$source_file" ] && ! echo "$source_file" | grep -q "://"; then
        echo "Creating mock source: $source_file"
        case "$source_file" in
            *.tar.gz|*.tgz)
                mkdir -p mock-source
                echo "Mock source file" > mock-source/README
                tar -czf "$source_file" mock-source/
                ;;
            *)
                echo "Mock file content" > "$source_file"
                ;;
        esac
    fi
done

# Run abuild if available
if command -v abuild >/dev/null 2>&1; then
    echo "Running abuild checksum..."
    abuild checksum
    
    echo "Running abuild build..."
    if abuild -r; then
        echo "โœ… Package built successfully"
        
        # Find generated package
        PACKAGE_FILE=$(find /home/*/packages -name "${pkgname}-${pkgver}-r${pkgrel}.apk" 2>/dev/null | head -1)
        if [ -n "$PACKAGE_FILE" ]; then
            echo "Generated package: $PACKAGE_FILE"
            
            # Test package installation
            echo ""
            echo "4. Package Installation Test:"
            echo "============================"
            
            # Create test container environment
            if command -v docker >/dev/null 2>&1; then
                echo "Testing package installation in Docker container..."
                
                cat > Dockerfile << 'DOCKEREOF'
FROM alpine:latest
RUN apk add --no-cache alpine-sdk
COPY package.apk /tmp/
RUN apk add --allow-untrusted /tmp/package.apk
DOCKEREOF
                
                cp "$PACKAGE_FILE" package.apk
                
                if docker build -t test-package . >/dev/null 2>&1; then
                    echo "โœ… Package installation test passed"
                else
                    echo "โŒ Package installation test failed"
                fi
                
                # Cleanup
                docker rmi test-package >/dev/null 2>&1 || true
            else
                echo "Docker not available for installation testing"
            fi
        fi
    else
        echo "โŒ Package build failed"
    fi
else
    echo "abuild not available for build testing"
fi

# 4. Post-install script analysis
if [ -n "$install" ] && [ -f "$install" ]; then
    echo ""
    echo "5. Post-install Script Analysis:"
    echo "==============================="
    
    # Run post-install script test
    test-post-install "$install"
fi

# 5. Security analysis
echo ""
echo "6. Security Analysis:"
echo "===================="

# Check for security issues in ABUILD
if grep -q "wget.*http://" ABUILD 2>/dev/null; then
    echo "โš ๏ธ  Insecure HTTP download detected"
fi

if grep -q "sudo\|su " ABUILD 2>/dev/null; then
    echo "โš ๏ธ  Privilege escalation in ABUILD"
fi

# Check dependencies for security
for dep in $depends; do
    if [ "$dep" = "sudo" ] || [ "$dep" = "doas" ]; then
        echo "โ„น๏ธ  Package requires privilege escalation: $dep"
    fi
done

echo ""
echo "Integration testing completed for $pkgname"

# Cleanup
cd /
rm -rf "$TEST_DIR"
EOF

chmod +x /usr/local/bin/test-abuild-package

# Usage example:
# test-abuild-package APKBUILD

๐Ÿš€ Advanced Automation and CI/CD Integration

GitLab CI Integration

# .gitlab-ci.yml for automated post-install script testing
stages:
  - validate
  - test
  - build
  - deploy

variables:
  ALPINE_VERSION: "3.18"

validate_abuild:
  stage: validate
  image: alpine:${ALPINE_VERSION}
  before_script:
    - apk add --no-cache alpine-sdk
  script:
    - test-abuild-package APKBUILD
    - abuild checksum
    - abuild -r
  artifacts:
    paths:
      - "*.apk"
    expire_in: 1 hour

test_post_install:
  stage: test
  image: alpine:${ALPINE_VERSION}
  script:
    - test-post-install *.post-install
  dependencies:
    - validate_abuild

security_scan:
  stage: test
  image: alpine:${ALPINE_VERSION}
  script:
    - apk add --no-cache shellcheck
    - shellcheck *.post-install
    - grep -r "hardcoded\|password\|secret" . || true
  allow_failure: true

build_package:
  stage: build
  image: alpine:${ALPINE_VERSION}
  before_script:
    - apk add --no-cache alpine-sdk
  script:
    - abuild -r
    - apk index *.apk
  artifacts:
    paths:
      - "*.apk"
      - "APKINDEX.tar.gz"
    expire_in: 1 week

deploy_to_repository:
  stage: deploy
  image: alpine:${ALPINE_VERSION}
  script:
    - rsync -av *.apk repository-server:/var/cache/alpine-mirror/
  only:
    - main
  dependencies:
    - build_package

GitHub Actions Integration

# .github/workflows/package-test.yml
name: Package Testing

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: alpine:3.18
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Install build dependencies
      run: |
        apk add --no-cache alpine-sdk shellcheck
    
    - name: Validate ABUILD
      run: |
        test-abuild-package APKBUILD
    
    - name: Test post-install scripts
      run: |
        for script in *.post-install; do
          if [ -f "$script" ]; then
            test-post-install "$script"
          fi
        done
    
    - name: Security scan
      run: |
        shellcheck *.post-install || true
        grep -r "TODO\|FIXME\|XXX" . || true
    
    - name: Build package
      run: |
        abuild checksum
        abuild -r
    
    - name: Upload artifacts
      uses: actions/upload-artifact@v3
      with:
        name: alpine-packages
        path: "*.apk"

๐ŸŽฏ Best Practices and Guidelines

Post-install Script Best Practices

# Create best practices documentation
cat > /usr/local/share/post-install-best-practices.md << 'EOF'
# Post-install Script Best Practices

## Script Structure
1. Always include proper shebang (#!/bin/sh)
2. Use set -e for error handling
3. Include descriptive comments
4. Log important actions
5. Provide user feedback

## Error Handling
```bash
#!/bin/sh
set -e  # Exit on any error

# Function for error handling
handle_error() {
    echo "Error occurred in post-install script at line $1"
    exit 1
}
trap 'handle_error $LINENO' ERR

Idempotency

  • Scripts should be safe to run multiple times
  • Check if configuration already exists before creating
  • Use conditional logic for service management

Security Considerations

  • Never hardcode passwords or secrets
  • Validate input parameters
  • Use secure file permissions
  • Avoid privilege escalation when possible

Service Management

  • Always check if service exists before managing
  • Use proper OpenRC service dependencies
  • Implement health checks
  • Handle service failures gracefully

File Operations

  • Create necessary directories before files
  • Set proper ownership and permissions
  • Backup existing configurations
  • Use atomic operations when possible

Testing

  • Test in isolated environments
  • Validate all script paths
  • Check for common shell script issues
  • Verify service integration

Performance

  • Minimize external command calls
  • Use efficient algorithms
  • Avoid unnecessary file operations
  • Consider parallel execution for independent tasks

Maintenance

  • Document script purpose and behavior
  • Version control all scripts
  • Regular security audits
  • Update for Alpine version compatibility EOF

## ๐ŸŽ‰ Conclusion

Implementing effective post-install scripts in Alpine Linux packages enables seamless automation, consistent deployments, and reliable service configuration. With proper design, testing, and integration practices, post-install scripts become powerful tools for package lifecycle management.

Key takeaways:
- **Design scripts for idempotency and reliability** ๐Ÿ”„
- **Implement comprehensive testing frameworks** ๐Ÿงช
- **Follow security best practices consistently** ๐Ÿ”’
- **Integrate with CI/CD pipelines for automation** ๐Ÿš€
- **Document and maintain scripts regularly** ๐Ÿ“š

With well-crafted post-install scripts, your Alpine Linux packages will provide smooth, automated deployments and consistent system configurations! ๐ŸŽฏ