# Building Security-Hardened Embedded Systems with meta-sulka-distro

**URL:** <https://hub.mender.io/t/building-security-hardened-embedded-systems-with-meta-sulka-distro/7891>\
**Category:** Yocto Project\
**Created:** [July 16, 2025, 2:22pm UTC](https://hub.mender.io/t/building-security-hardened-embedded-systems-with-meta-sulka-distro/7891 "2025-07-16T14:22:06Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![TheYoctoJester](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/theyoctojester/32/1444_2.png) [@TheYoctoJester](https://hub.mender.io/u/TheYoctoJester)\
**Post date:** [July 16, 2025, 2:22pm UTC](https://hub.mender.io/t/building-security-hardened-embedded-systems-with-meta-sulka-distro/7891/1 "2025-07-16T14:22:06Z")

</div>

## Yocto Project releases

| Yocto Project | Tutorial applies | Maintenance |
| --- | --- | --- |
| whinlatter (5.3) | :test_fails: | :test_works: development |
| walnascar (5.2) | :test_fails: | :test_works: stable |
| styhead (5.1) | :test_fails: | :test_fails: EOL |
| scarthgap (5.0) | :test_works: | :test_works: LTS |

_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](https://codeberg.org/AltidSec/meta-sulka-distro) for the most current information.

* * *

 ![LF_17_02_Yocto-Badge-Update_Participant_Final](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/1X/758c60e0e8309c4dc2519392b78668e7396c15bd.png)

## 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` and `kas`
- 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:

```bash
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:

```yaml
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:

```yaml
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:

```bash
# 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:

```bash
# 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:

```yaml
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:

```bitbake
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:

```python
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:

```yaml
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:

```yaml
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`](https://github.com/mendersoftware/meta-mender-community/kas/demos/qemuarm64-sulka.yml), please review the full setup for additional information.

### Complete Kas Configuration

Create `sulka-hardened.yml`:

```yaml
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

```bash
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

1. Boot your device using the generated image
2. Attempt to login as root (should fail)
3. Login using your configured service user credentials

### Network Security Verification

Test the firewall configuration:

```bash
# 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:

```bash
# 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:

1. **Remove insecure IMAGE\_FEATURES** :

2. **Check for conflicting configurations** :  
Review your `local.conf` for any security-related overrides

### Network Connectivity Issues

This is expected behavior! Configure the firewall to allow required traffic:

1. **Edit firewall configuration** :

2. **Restart nftables service** :

### Login Problems

Verify password configuration:

1. **Check password hash generation** :

2. **Verify escaping in configuration** :  
Ensure all `$` characters are escaped as `\\$`

## Best Practices

1. **Use specific layer commits** in production builds
2. **Document security policy decisions** for compliance
3. **Keep service user credentials and API keys secure** , make sure they do not leak out through accidental commits.

## Further Reading

- [Yocto Project Security Manual](https://docs.yoctoproject.org/dev-manual/security.html)
- [nftables Documentation](https://wiki.nftables.org/)
- [AIDE File Integrity Monitoring](https://aide.github.io/)
- [meta-security Layer Documentation](https://git.yoctoproject.org/meta-security/)
