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! ๐ฏ