Custom Linux Distro: From Yocto Build to 60% Boot Time Optimization
A key user experience metric for NAS products: how long from pressing power to accessing shared folders? Our target was 30 seconds, but the original took 75 seconds. This post documents the complete journey from 75s to 30s.
1. Why Customize Linux?
1.1 NAS-Specific Requirements
Unlike general servers, NAS devices need:
- Fast boot: Consumer device, users won’t tolerate server-like boot times
- Resource constrained: ARM processor + 1GB RAM
- High stability: 24×7 operation, minimize unnecessary services
- Hardware-specific: Only need to support specific SoC and peripherals
Generic distros (like Ubuntu Server) include tons of features we don’t need — long boot times, high memory usage.
1.2 Solution Options
| Option | Pros | Cons |
|---|---|---|
| Yocto | Full control, minimal | Steep learning curve |
| Buildroot | Simple, lightweight | Weak package management |
| Trimmed Ubuntu | Easy to start | Hard to fully slim down |
We chose Yocto because we need long-term maintenance and fine control.
2. Boot Time Analysis
2.1 Baseline Measurement
Using systemd-analyze:
| |
74.7 seconds — way too slow!
2.2 Bottleneck Identification
| |
Output:
| |
Problems found:
network-online.targetwaiting for network for 32 secondscloud-initis for cloud servers — we don’t need itsnapdalso not needed- Many services starting serially
2.3 Dependency Visualization
| |
From the chart:
- Many services waiting for
network-online.target - But our core service (NAS file sharing) only needs NIC initialization, not fully “online”
3. Optimization Strategies
3.1 Disable Unnecessary Services
| |
Effect: Reduced 30 seconds!
3.2 Optimize Network Wait
Problem: network-online.target defaults to waiting for DHCP to get IP, can take 30+ seconds.
Option 1: Reduce DHCP timeout
| |
Option 2: Make core services not depend on network-online
| |
Effect: Another 20 seconds reduced!
3.3 Service Parallelization
Check critical path:
| |
Output:
| |
Found nas-agent blocked by docker, but they actually have no dependency!
Fix:
| |
Effect: docker and nas-agent now start in parallel, saves 5 seconds.
3.4 Kernel Optimization
3.4.1 Disable unneeded kernel modules
| |
Create module blacklist:
| |
Effect: Kernel boot phase reduced 2 seconds.
3.4.2 Tune initramfs
| |
Slim down initramfs (only keep necessary drivers):
| |
Regenerate:
| |
Effect: initramfs from 50MB to 15MB, load time reduced 3 seconds.
4. Systemd Tuning Tips
4.1 Type=simple vs Type=oneshot
| |
4.2 Lazy Loading: Socket Activation
Not all services need to start immediately. Use socket activation to start on demand:
| |
| |
Effect: 3 fewer services at boot, saves 2 seconds.
4.3 ReadWritePaths Speedup
| |
Systemd doesn’t need to traverse entire filesystem, starts faster.
5. Final Results
5.1 Before/After Comparison
| Stage | Before | After | Reduction |
|---|---|---|---|
| Kernel boot | 8.5s | 5.5s | -3s |
| initramfs | 12.0s | 6.0s | -6s |
| Systemd (network) | 32.0s | 8.0s | -24s |
| Systemd (other services) | 22.0s | 10.0s | -12s |
| Total | 74.7s | 29.5s | -60% |
5.2 Key Optimizations Summary
| Optimization | Time Saved |
|---|---|
| Disable cloud-init/snapd | 30s |
| Reduce network wait | 20s |
| Service parallelization | 5s |
| Kernel module trimming | 2s |
| initramfs trimming | 6s |
| Socket activation | 2s |
6. Continuous Monitoring
6.1 CI Integration for Boot Time Testing
| |
6.2 New Service Checklist
When adding new services, always check:
- Can it use socket activation?
- Does it really need network-online?
- Can it start in parallel?
- Are reasonable resource limits set?
7. Summary
| Technique | Core Command/Config |
|---|---|
| Boot analysis | systemd-analyze blame/plot |
| Dependency chain | systemd-analyze critical-chain |
| Disable services | systemctl disable |
| Network optimization | DHCP Timeout + network.target |
| Parallelization | Check and remove unnecessary After= |
| Kernel trimming | modprobe blacklist |
| initramfs | MODULES=dep |
Core principle: Don’t assume, measure. Back every optimization with data.
Related Posts