5q12 Indexer - Build System
This directory contains the Docker build system for the 5q12 Indexer application. The build system uses Alpine Linux with s6-overlay for process management.
Directory Structure
.
├── build.sh # Main build script (includes all functionality)
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Development compose file
├── README.md # This file
├── docker/ # Docker configuration files
│ ├── nginx.conf # Nginx main configuration
│ ├── 5q12-indexer.conf # Nginx site configuration
│ ├── php-fpm.conf # PHP-FPM configuration
│ ├── s6-services/ # S6-overlay service definitions
│ │ ├── nginx/ # Nginx service
│ │ │ ├── dependencies.d/
│ │ │ │ └── init-indexer
│ │ │ ├── run
│ │ │ └── type
│ │ ├── php-fpm/ # PHP-FPM service
│ │ │ ├── dependencies.d/
│ │ │ │ └── init-indexer
│ │ │ ├── run
│ │ │ └── type
│ │ ├── init-indexer/ # Initialization service
│ │ │ ├── run
│ │ │ ├── type
│ │ │ └── up
│ │ ├── user/ # User bundle (nginx + php-fpm)
│ │ │ ├── contents.d/
│ │ │ │ ├── nginx
│ │ │ │ └── php-fpm
│ │ │ └── type
│ │ └── user2/ # User2 bundle (contains user)
│ │ ├── contents.d/
│ │ │ └── user
│ │ └── type
│ └── scripts/ # Initialization scripts
│ └── init-indexer.sh # Main initialization script
└── source/ # Application source code
├── index.php # Main application file
└── config/ # Default configuration
Architecture Overview
Volume Mount Strategy
The indexer uses a
clean separation architecture with individual symlinks:
Mount Points:
/config - Configuration files only (config.json, config-reference.txt)
/app - Application files only (icons, favicon, local_api, php, caches)
/files - User files to be indexed (read-only)
Symlink Structure:
/www/indexer/.indexer_files/ (directory with individual symlinks)
├── config.json → /config/config.json
├── config-reference.txt → /config/config-reference.txt
├── icons → /app/icons
├── favicon → /app/favicon
├── local_api → /app/local_api
├── php → /app/php
├── zip_cache → /app/zip_cache
├── index_cache → /app/index_cache
└── (all other /app contents)
Key Benefits:
- No file conflicts: Config files only in
/config, app files only in /app
- Live config changes: Edits to
/config/config.json take effect immediately
- Clean mounts: Both
/config and /app can be mounted externally without symlink issues
- Always current reference:
config-reference.txt refreshed on every restart
- Optimal persistence: User changes in
/config, cache in /app, source files in /files
Configuration File Flow
- Startup Merge:
/container-app/default-config/config.json merged with /config/config.json
- Environment Override: Environment variables applied to
/config/config.json
- Live Access: PHP app reads/writes
/www/indexer/.indexer_files/config.json → /config/config.json
- Persistence: Changes to
/config/config.json survive container restarts
- Reference Update:
config-reference.txt copied fresh to /config on each restart
Version System
The project uses a revision-based versioning system for security patches:
- Base Version:
X.Y.Z (e.g., 1.1.19)
- Security Patches:
X.Y.Z-rN (e.g., 1.1.19-r1, 1.1.19-r2)
Where:
X.Y.Z represents major.minor.patch versions for feature releases
rN represents revision number for security patches and hotfixes
Build Scripts
build.sh
The main build script that handles all build system functionality including Docker image creation, s6-overlay setup, and deployment operations.
Usage:
./build.sh # Build with default version
./build.sh 1.1.19-r1 # Build with custom version
./build.sh --no-cache # Build with no cache
./build.sh 1.1.19-r1 --no-cache # Build custom version with no cache
Generated Tags:
5q12/5q12-indexer:VERSION
5q12/5q12-indexer:latest
5q12/5q12-indexer:VERSION-s6
Prerequisites:
- Docker installed and running
- All required files present (automatically checked)
- S6-overlay services configured (automatically set up if needed)
Docker Configuration
Process Management
The build system uses s6-overlay v3 instead of supervisor for better security and container-native process management.
Services:
init-indexer: Initialization and configuration setup
nginx: Web server (depends on init-indexer)
php-fpm: PHP FastCGI Process Manager (depends on init-indexer)
user: Service bundle containing nginx and php-fpm
user2: Service bundle containing user
Environment Variables
The build system supports comprehensive environment variable configuration:
Main Configuration:
INDEXER_ACCESS_URL: Base URL for the application
INDEXER_CACHE_TYPE: Cache type (sqlite/json)
INDEXER_ICON_TYPE: Icon display type (default/disabled)
INDEXER_INDEX_ALL: Index all files (true/false)
INDEXER_INDEX_HIDDEN: Include hidden files (true/false)
INDEXER_DISABLE_FILE_DOWNLOADS: Disable file downloads (true/false)
INDEXER_DISABLE_FOLDER_DOWNLOADS: Disable folder downloads (true/false)
INDEXER_MAX_DOWNLOAD_SIZE_FILE: Maximum file download size
INDEXER_MAX_DOWNLOAD_SIZE_FOLDER: Maximum folder download size
INDEXER_DENY_LIST: Comma-separated list of denied patterns
INDEXER_ALLOW_LIST: Comma-separated list of allowed patterns
Filetype Controls:
INDEXER_VIEW_FILETYPE_*: Control file viewing (use underscores or hyphens)
- Example:
INDEXER_VIEW_FILETYPE_PHP=true
- Example:
INDEXER_VIEW_FILETYPE_NON-DESCRIPT-FILES=true
INDEXER_INDEX_FILETYPE_*: Control file indexing
- Example:
INDEXER_INDEX_FILETYPE_LOG=false
System Settings:
TZ: Timezone setting (e.g., America/New_York)
S6_VERBOSITY: S6-overlay logging level (0-2, default 1)
Building Images
Prerequisites Check
The build script automatically verifies:
- Required files exist
- Directory structure is correct
- S6 services are configured
- Script permissions are set
- Environment variable processing is present
Build Process
- Validation: Checks all required files and directories
- Permission Setup: Makes scripts executable
- Docker Build: Creates multi-tagged images
- Verification: Shows build results and usage examples
Development Workflow
# Clean build environment
docker system prune -a --volumes --force
# Build development image
./build.sh devtest-r1 --no-cache
# Test locally with individual mounts
mkdir -p test-indexer/{config,app,files}
docker run -d --name test-indexer-s6 -p 5012:5012 \
-v $(pwd)/test-indexer/config:/config \
-v $(pwd)/test-indexer/app:/app \
-v $(pwd)/test-indexer/files:/files \
-e INDEXER_CACHE_TYPE=json \
-e INDEXER_ICON_TYPE=disabled \
5q12/5q12-indexer:devtest-r1
# Verify symlink structure
docker exec test-indexer-s6 ls -la /www/indexer/.indexer_files/
# Test live config changes
docker exec test-indexer-s6 cat /config/config.json
# Edit config.json in test-indexer/config/ from host
# Changes take effect immediately without restart
# Test environment variables
docker exec test-indexer-s6 cat /config/config.json | grep cache_type
# Check logs
docker logs test-indexer-s6
# Clean up
docker rm -f test-indexer-s6
rm -rf test-indexer/
Volume Mount Examples
Minimal Setup (Config Only)
version: '3.8'
services:
indexer:
image: 5q12/5q12-indexer:1.1.19
ports:
- "5012:5012"
volumes:
- ./config:/config
- ./files:/files
environment:
- TZ=UTC
- INDEXER_CACHE_TYPE=json
Full Setup (Config + App + Files)
version: '3.8'
services:
indexer:
image: 5q12/5q12-indexer:1.1.19
ports:
- "5012:5012"
volumes:
- ./config:/config # Config files (editable, persisted)
- ./app:/app # App files (icons, caches, persisted)
- ./files:/files:ro # Source files (read-only)
environment:
- TZ=America/New_York
- INDEXER_CACHE_TYPE=sqlite
- INDEXER_ICON_TYPE=default
- INDEXER_INDEX_ALL=true
- INDEXER_VIEW_FILETYPE_PHP=true
Production Setup with Environment Variables
version: '3.8'
services:
indexer:
image: 5q12/5q12-indexer:1.1.19
container_name: indexer-prod
ports:
- "5012:5012"
volumes:
- /mnt/configs/indexer:/config
- /mnt/cache/indexer:/app
- /mnt/data:/files:ro
environment:
- TZ=UTC
- INDEXER_ACCESS_URL=https://files.example.com
- INDEXER_CACHE_TYPE=sqlite
- INDEXER_ICON_TYPE=default
- INDEXER_INDEX_ALL=false
- INDEXER_INDEX_HIDDEN=false
- INDEXER_DISABLE_FOLDER_DOWNLOADS=false
- INDEXER_MAX_DOWNLOAD_SIZE_FILE=2048 MB
- INDEXER_MAX_DOWNLOAD_SIZE_FOLDER=2048 MB
- INDEXER_VIEW_FILETYPE_PHP=false
- INDEXER_VIEW_FILETYPE_JS=false
restart: unless-stopped
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5012/"]
interval: 30s
timeout: 10s
retries: 3
Configuration Management
Accessing Config Files
From Host (when mounted):
# Edit config
vim ./config/config.json
# View reference
cat ./config/config-reference.txt
# Changes to config.json take effect immediately
From Container:
# View current config
docker exec CONTAINER_NAME cat /config/config.json
# View through app symlink
docker exec CONTAINER_NAME cat /www/indexer/.indexer_files/config.json
# Both paths point to the same file
Config File Locations
| Path | Type | Purpose | Editable | Persists |
|---|
/config/config.json | Real file | Source of truth | Yes | Yes (if mounted) |
/config/config-reference.txt | Real file | Documentation | No (refreshed) | Yes (if mounted) |
/www/indexer/.indexer_files/config.json | Symlink | App access point | Yes | Via /config |
/www/indexer/.indexer_files/config-reference.txt | Symlink | App access point | No | Via /config |
Config Merge Behavior
On container startup:
- Default config from
/container-app/default-config/config.json is loaded
- Existing
/config/config.json is read (if present)
- Missing fields are added from default
- Version is updated to match container version
- Existing user values are preserved
- Environment variables override config values
- Result is written back to
/config/config.json
Security Features
Process Management
- No supervisor vulnerabilities
- Reduced Python attack surface
- Container-native s6-overlay
- Proper signal handling
File System Isolation
- Config files isolated in
/config
- App files isolated in
/app
- Source files read-only in
/files
- No file conflicts between mounts
- Clean separation of concerns
Environment Variable Processing
- Multiple fallback methods for reading variables
- Support for s6-overlay environment files
- Enhanced debugging and error reporting
- Secure configuration merging
- Type-safe boolean conversions
Container Hardening
- Non-root user execution (www-data)
- Minimal Alpine Linux base
- Position-independent executables
- Stack-smashing protection
- Read-only source file mount
Troubleshooting
Common Build Issues
Missing s6-services directory:
The build script will check for this automatically and warn you if the s6-overlay structure is missing.
Permission errors:
chmod +x build.sh
chmod +x docker/scripts/*.sh
Missing files:
- Check that all files in the build script's validation exist
- Verify source directory structure
- Ensure Docker configuration files are present
Environment variables not working:
- Verify
init-indexer.sh contains enhanced processing
- Check s6-overlay environment files in
/var/run/s6/container_environment/
- Use
S6_VERBOSITY=2 for debugging
Common Runtime Issues
Config changes not taking effect:
- Config changes take effect immediately without restart
- Verify you're editing
/config/config.json (source of truth)
- Check file permissions (should be owned by www-data)
Symlink issues:
# Verify symlink structure
docker exec CONTAINER_NAME ls -la /www/indexer/.indexer_files/
# Should show individual symlinks to /config and /app
Cache issues:
# Clear caches (if /app is mounted)
rm -rf ./app/zip_cache/*
rm -rf ./app/index_cache/*
# Or from within container
docker exec CONTAINER_NAME rm -rf /app/zip_cache/*
docker exec CONTAINER_NAME rm -rf /app/index_cache/*
Build Script Validation
The build script performs comprehensive validation:
- File and directory existence
- Script permissions
- S6 service structure
- Environment variable processing presence
Testing Environment Variables
# Test specific variable
docker run --rm -e INDEXER_CACHE_TYPE=json IMAGE_NAME \
sh -c 'cat /config/config.json | grep cache_type'
# Test multiple variables
docker run --rm \
-e INDEXER_CACHE_TYPE=json \
-e INDEXER_INDEX_ALL=true \
IMAGE_NAME sh -c 'cat /config/config.json | grep -E "(cache_type|index_all)"'
# Test filetype variable with special characters
docker run --rm \
-e INDEXER_VIEW_FILETYPE_NON-DESCRIPT-FILES=true \
IMAGE_NAME sh -c 'cat /config/config.json | grep "view_non-descript-files"'
Migration Notes
From Supervisor to S6-Overlay
If migrating from supervisor-based builds:
- Run
./s6.sh to set up s6 services
- Remove any supervisor configuration references
- Update any custom scripts to use s6-overlay patterns
- Test thoroughly with environment variables
From Single Mount to Split Mounts
If migrating from a single volume mount:
- Create separate mount points:
mkdir -p config app files
- Move config files to
config/ directory
- Move cache/icon files to
app/ directory
- Update docker-compose.yml with new mount structure
- Test with new volumes before removing old setup
Legacy Compatibility
The build system maintains backward compatibility for:
- Volume mount points (
/config, /app, /files)
- Port configuration (5012)
- Environment variable names
- Health check endpoints
- API endpoints and behavior
Development Guidelines
Adding New Environment Variables
- Update
init-indexer.sh environment mapping in $envMappings array
- Add to build script documentation and README
- Test with fallback methods (getenv, $_ENV, s6 files)
- Update docker-compose examples
- Document in config-reference.txt
Modifying S6 Services
- Edit service definitions in
docker/s6-services/
- Ensure proper dependencies are set
- Test service startup order
- Verify logging and error handling
- Test service restart behavior
Modifying Symlink Structure
- Edit
init-indexer.sh symlink creation section
- Ensure no file conflicts between
/config and /app
- Test with both mounted and unmounted volumes
- Verify PHP app can access all required files
- Test config change propagation
Security Considerations
- Always validate input from environment variables
- Use proper file permissions (www-data ownership)
- Test with minimal privileges
- Regular security updates for base image
- Audit symlink targets for security
- Never symlink outside container filesystem
Cache Management
The
/app directory contains performance-critical caches:
zip_cache/ - Cached ZIP file listings
index_cache/ - Cached directory indexes
Recommendations:
- Mount
/app to fast storage (SSD)
- Regular cache cleanup for large deployments
- Monitor cache directory sizes
- Use
INDEXER_CACHE_TYPE=sqlite for better performance
Icon Storage
Icons are stored in
/app/icons/:
- Set
INDEXER_ICON_TYPE=disabled to reduce storage and bandwidth
- Icons are regenerated if missing (one-time performance hit)
- Consider pre-populating icons for faster startup
Support and Documentation
- GitHub Issues: Report bugs and request features
- Docker Hub:
5q12/5q12-indexer
- Documentation: See
config-reference.txt for all config options
- Logs:
docker logs CONTAINER_NAME for troubleshooting