Yocto Project releases
Yocto Project | Tutorial applies | Maintenance |
---|---|---|
whinlatter (5.3) | ![]() |
![]() |
walnascar (5.2) | ![]() |
![]() |
styhead (5.1) | ![]() |
![]() |
scarthgap (5.0) | ![]() |
![]() |
Currently only the scarthgap
release is actively supported
A failure in the ‘tutorial applies’ column indicates that the instructions do not work without modification.
Note: This tutorial content is prone to change as the Sulka distribution is under active development. Configuration options, layer dependencies, and security policies may evolve. Always refer to the latest meta-sulka-distro
documentation for the most current information.
Introduction
The meta-sulka-distro
layer provides a security-hardened Yocto Project distribution designed for production IoT and edge devices. Unlike the default Poky reference distribution that prioritizes ease of use, Sulka implements a “secure by default” philosophy where all potentially dangerous features are disabled by default.
This tutorial will guide you through integrating meta-sulka-distro
into your Yocto build to create embedded systems with security hardening, including restrictive firewall policies, disabled root access, and comprehensive security monitoring.
The techniques covered here apply to any embedded project requiring enhanced security posture, making it particularly valuable for industrial IoT, medical devices, and edge computing applications.
Prerequisites
- Working Yocto Project build environment
- Basic familiarity with
bitbake
andkas
- Understanding of Linux networking and user management concepts
What you will learn
- How to integrate
meta-sulka-distro
into existing Yocto builds - Configure security-hardened user management
- Implement restrictive firewall policies with nftables
- Enable security monitoring and file integrity checking
Step 1: Understanding Sulka’s Security Model
Before implementing Sulka, it’s important to understand its core security principles:
Deny by Default: All network traffic (including outgoing) is blocked by default
No Root Access: Root login is completely disabled
Service User Model: A single non-root user with sudo access for administration
Proactive Security Checks: Build-time validation prevents insecure configurations
Create a test directory for this tutorial:
mkdir sulka-tutorial && cd sulka-tutorial
Step 2: Adding meta-sulka-distro
to Your Build
The meta-sulka-distro
layer has specific dependencies that must be included in your build configuration.
Layer Dependencies
Add the following to your kas
configuration file:
repos:
meta-sulka-distro:
url: https://codeberg.org/AltidSec/meta-sulka-distro.git
commit: 64c1f5c0d484bd201e7f2f617040e2c5973d17cb
meta-security:
url: git://git.yoctoproject.org/meta-security.git
commit: bc865c5276c2ab4031229916e8d7c20148dfbac3
meta-openembedded:
layers:
meta-python:
meta-networking:
Required Variables
The layer checks for essential security configuration during build:
local_conf_header:
sulka: |
DISTRO = "sulka"
SULKA_SERVICEUSER_USERNAME = "mender"
SULKA_SERVICEUSER_PASSWORD = "$encrypted_hash_here"
Step 3: Generating Secure User Credentials
Sulka requires a properly encrypted password for the service user account.
Creating the Password Hash
Use the mkpasswd
utility to generate a secure hash:
# Install mkpasswd if not available
sudo apt-get install whois
# Generate password hash (replace 'your_password' with actual password)
mkpasswd -m yescrypt -s -R 8 your_password
Escaping for Yocto Configuration
The password hash contains dollar signs that must be escaped for BitBake:
# Generate and escape in one command
mkpasswd -m yescrypt -s -R 8 your_password | sed 's/\$/\\$/g'
Copy the resulting escaped hash to your configuration, which looks similar to this:
SULKA_SERVICEUSER_PASSWORD = "\\$y\\$jCT\\$odv3AoU98sQjAtgZRT1\\$xPty.dqoENrSyksek7i3"
Step 4: Understanding Sulka’s Security Components
Core Security Package Group
The packagegroup-sulka
recipe defines the essential security components:
RDEPENDS:${PN} = "\
aide \ # File integrity monitoring
auditd \ # Security event logging
nftables \ # Modern firewall framework
nftables-configuration \
sudo \ # Controlled privilege escalation
"
Firewall Configuration
Sulka includes several firewall templates in recipes-filter/nftables-configuration/files/
:
nftables-drop-everything.conf
(default - blocks all traffic)nftables-allow-established-lo-outgoing.conf
(allows established connections)nftables-allow-established-lo-ssh-icmp-outgoing.conf
(adds SSH and ICMP)
Security Validation
The variable-check.bbclass
prevents common security misconfigurations:
insecure_features = [
"debug-tweaks",
"empty-root-password",
"allow-empty-password",
"allow-root-login",
"serial-autologin-root"
]
Step 5: Customizing Security Policies
Selecting Firewall Templates
Choose an appropriate firewall template based on your connectivity requirements:
local_conf_header:
firewall: |
SULKA_NFTABLES_CONF = "nftables-allow-established-lo-ssh-icmp-outgoing.conf"
Enabling Graphics Support
Graphics support is disabled by default for minimal attack surface:
graphics: |
SULKA_DISABLE_GRAPHICS = "0" # Enable if needed
Sudo Configuration
Service user sudo access can be configured by modifying the template in recipes-extended/sudo/files/serviceuser.conf
.
Step 6: Building Your Hardened Image
This example is a shortened version of the qemuarm64-sulka.yml
, please review the full setup for additional information.
Complete Kas Configuration
Create sulka-hardened.yml
:
header:
version: 14
includes:
- kas/include/mender-full.yml
distro: sulka
repos:
meta-sulka-distro:
url: https://codeberg.org/AltidSec/meta-sulka-distro.git
commit: 64c1f5c0d484bd201e7f2f617040e2c5973d17cb
meta-security:
url: git://git.yoctoproject.org/meta-security.git
commit: bc865c5276c2ab4031229916e8d7c20148dfbac3
meta-openembedded:
layers:
meta-python:
meta-networking:
local_conf_header:
sulka: |
SULKA_SERVICEUSER_USERNAME = "mender"
SULKA_SERVICEUSER_PASSWORD = "$your_escaped_hash"
CORE_IMAGE_EXTRA_INSTALL:append = " packagegroup-sulka "
target:
- core-image-minimal
Execute the Build
kas build sulka-hardened.yml
The build will fail immediately if any insecure IMAGE_FEATURES
are detected.
Step 7: Testing Your Hardened System
Initial Boot Verification
- Boot your device using the generated image
- Attempt to login as root (should fail)
- Login using your configured service user credentials
Network Security Verification
Test the firewall configuration:
# Check firewall rules
sudo nft list ruleset
# Attempt outgoing connection (should fail with default config)
ping google.com
# Check network interfaces
ip addr show
Security Monitoring
Verify security components are active:
# Check audit daemon
sudo systemctl status auditd
# Initialize AIDE database
sudo aide --init
# Check file integrity
sudo aide --check
Troubleshooting
Build Fails with Security Errors
If you encounter security-related build failures:
-
Remove insecure IMAGE_FEATURES:
IMAGE_FEATURES:remove = "debug-tweaks empty-root-password"
-
Check for conflicting configurations:
Review yourlocal.conf
for any security-related overrides
Network Connectivity Issues
This is expected behavior! Configure the firewall to allow required traffic:
-
Edit firewall configuration:
sudo vi /etc/nftables.conf
-
Restart nftables service:
sudo systemctl restart nftables
Login Problems
Verify password configuration:
-
Check password hash generation:
mkpasswd -m yescrypt -s -R 8 test_password
-
Verify escaping in configuration:
Ensure all$
characters are escaped as\\$
Best Practices
- Use specific layer commits in production builds
- Document security policy decisions for compliance
- Keep service user credentials and API keys secure, make sure they do not leak out through accidental commits.