# How to create your first recipe and enable auto-start using systemd

**URL:** <https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195>\
**Category:** Yocto Project\
**Created:** [October 26, 2019, 4:08pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195 "2019-10-26T16:08:19Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [October 26, 2019, 4:08pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/1 "2019-10-26T16:08:19Z")

</div>

## Introduction

The [Yocto Project](https://yoctoproject.org) consists of recipes, dependencies and metadata to instruct the build system how to build software packages for installation into a target Embedded operating system.

This tutorial will guide you through generating a basic recipe to add your application to an existing Yocto project build, including the configuration needed to launch a [systemd](https://www.freedesktop.org/wiki/Software/systemd/) service. Specifically we will launch our new application as a [simple](https://www.freedesktop.org/software/systemd/man/systemd.service.html#Options) service which runs one time at boot.

## Prerequisites

- **A configured Yocto environment**. We will use the QEMU setup for easy testing of the new recipe without requiring physical hardware.

- Please review the following for more background on this:

## Step 1: Generate the initial build and verify that it boots

This is a summary of the steps outlined [here](https://hub.mender.io/t/qemu-the-fast-processor-emulator/420/2).

```auto
export BRANCH="warrior"
mkdir mender-qemu && cd mender-qemu
repo init -u https://github.com/mendersoftware/meta-mender-community \
           -m meta-mender-qemu/scripts/manifest-qemu.xml \
           -b ${BRANCH}
repo sync
source setup-environment qemu
MACHINE=qemux86-64 bitbake core-image-base
 ../sources/meta-mender/meta-mender-qemu/scripts/mender-qemu core-image-base

```

## Step 2: Create a custom layer

We will create a custom layer to hold our new recipe. See [this tutorial](https://hub.mender.io/t/how-to-create-custom-images-using-yocto-project/902) for more details on custom layers.

Please note that the tutorials on this site will re-use this layer and if you have already created this structure by following another tutorial you can skip this step.

Create a new layer called `meta-stargazer` using the `bitbake-layers` helper application:

```auto
bitbake-layers create-layer ../sources/meta-stargazer

```

This will create a basic structure in `meta-stargazer` directory:

```auto
../sources/meta-stargazer/
├── conf
│ └── layer.conf
├── COPYING.MIT
├── README
└── recipes-example
    └── example
        └── example_0.1.bb

3 directories, 4 files

```

Include the layer in our Yocto Project environment:

```auto
bitbake-layers add-layer ../sources/meta-stargazer

```

## Step 3: Create a new recipe

We will use the `recipetool` utility provided by Yocto to generate a new recipe for the [GNU Hello program](https://ftp.gnu.org/gnu/hello/). This package is setup for building properly with [autoconf](https://www.gnu.org/software/autoconf/) and [automake](https://www.gnu.org/software/automake/), and Yocto can automatically generate recipes that use these tools.

```auto
mkdir ../sources/meta-stargazer/recipes-example/gnuhello
recipetool create https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz \
      -o ../sources/meta-stargazer/recipes-example/gnuhello/

```

Now verify that it builds.

```auto
bitbake hello

```

Note that the recipe is setup to automatically download the sources from the GNU URL. The `recipetool` utility can also use URIs from source code management systems such as [Git](https://git-scm.com/). Additionally, the source code for your recipe can be stored directly in the custom layer but it is considered Yocto _best practice_ to keep it separate and have the recipe download it from the appropriate location.

See the [Yocto Project Development Tasks Manual](https://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#new-recipe-writing-a-new-recipe) for more details on the `recipetool` utility.

Now let’s add this to our image, boot and verify that the /usr/bin/hello executable exists.

```auto
cat >> conf/local.conf <<EOF
IMAGE_INSTALL_append = " hello "
EOF
MACHINE=qemux86-64 bitbake core-image-base
 ../sources/meta-mender/meta-mender-qemu/scripts/mender-qemu core-image-base

```

Login as root with no password and execute the new binary:

```auto
qemux86-64 login: root
root@qemux86-64:~# ls -l /usr/bin/hello
-rwxr-xr-x 1 root root 34976 Oct 27 12:44 /usr/bin/hello
root@qemux86-64:~# /usr/bin/hello
Hello, world!
root@qemux86-64:~#

```

## Step 4: Modify recipe to add systemd service file.

For this `hello-world` application, we don’t necessarily need a service file as this application does not provide services to other parts of this operating system. However, for example purposes, we will create an autostart script to run hello at boot time. The output from this invocation will be available in the systemd logs using the `journalctl` command. This service file can also be manually invoked at runtime.

First, we will create the service file itself which is read and processed by systemd:

```auto
mkdir -p ../sources/meta-stargazer/recipes-example/gnuhello/files/
cat > ../sources/meta-stargazer/recipes-example/gnuhello/files/hello.service <<EOF
[Unit]
Description=GNU Hello World startup script

[Service]
ExecStart=/usr/bin/hello

[Install]
WantedBy=multi-user.target
EOF

```

Now let’s add the recipe settings to integrate this into the systemd configuration for our build:

```auto
cat >> ../sources/meta-stargazer/recipes-example/gnuhello/hello_2.10.bb <<EOF
inherit systemd
SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE_\${PN} = "hello.service"

SRC_URI_append = " file://hello.service "
FILES_\${PN} += "\${systemd_unitdir}/system/hello.service"

do_install_append() {
  install -d \${D}/\${systemd_unitdir}/system
  install -m 0644 \${WORKDIR}/hello.service \${D}/\${systemd_unitdir}/system
}
EOF

```

**Note:** Dollar symbols require to be escaped with a backslash (` \$`) to work with `cat`. If you copy-paste these examples remove the backslashes.

Now, rebuild, boot and verify that the service started and the output is visible in the systemd logs.

```auto
MACHINE=qemux86-64 bitbake core-image-base
 ../sources/meta-mender/meta-mender-qemu/scripts/mender-qemu core-image-base

```

```auto
root@qemux86-64:~# systemctl --no-pager status hello
● hello.service - GNU Hello World startup script
   Loaded: loaded (/lib/systemd/system/hello.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sun 2019-10-27 13:56:09 UTC; 52s ago
  Process: 178 ExecStart=/usr/bin/hello (code=exited, status=0/SUCCESS)
 Main PID: 178 (code=exited, status=0/SUCCESS)

Oct 27 13:56:03 qemux86-64 systemd[1]: Started GNU Hello World startup script.
Oct 27 13:56:04 qemux86-64 hello[178]: Hello, world!
Oct 27 13:56:09 qemux86-64 systemd[1]: hello.service: Succeeded.

root@qemux86-64:~# journalctl -u hello --no-pager
-- Logs begin at Sun 2019-10-27 13:55:32 UTC, end at Sun 2019-10-27 13:57:43 UTC. --
Oct 27 13:56:03 qemux86-64 systemd[1]: Started GNU Hello World startup script.
Oct 27 13:56:04 qemux86-64 hello[178]: Hello, world!
Oct 27 13:56:09 qemux86-64 systemd[1]: hello.service: Succeeded.

```

## Conclusion

In this tutorial we covered adding new recipes to Yocto project builds and enabling autostart services with systemd.

For further reading please visit

- [http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html](http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html)
- [https://www.freedesktop.org/wiki/Software/systemd/](https://www.freedesktop.org/wiki/Software/systemd/)
- [https://www.freedesktop.org/software/systemd/man/systemd.service.html](https://www.freedesktop.org/software/systemd/man/systemd.service.html)

_If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!_

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 27, 2020, 1:42pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/2 "2020-02-27T13:42:52Z")

</div>

Thanks for the great support. I copy-pasted most of the steps and failed to `bitbake hallo` (step 3). The log file says (only an excerpt but I think the important part) :

```
mv lib/warn-on-use.h-t lib/warn-on-use.h
| /home/marius/mender-qemu/build/tmp/hosttools/mkdir -p lib/sys
| /bin/bash: line 1: lib/arg-nonnull.h-t: No such file or directory
| /bin/bash: line 30: lib/configmake.h-t: No such file or directory
| /bin/bash: line 1: lib/c++defs.h-t: No such file or directory

```

Did I miss a step here?  
Best regards

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 27, 2020, 1:46pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/3 "2020-02-27T13:46:44Z")

</div>

Just ran `/home/marius/mender-qemu/build/tmp/hosttools/mkdir -p lib/sys` manually and then `bitbake hello` again and it finished. Is this step missing in the documentation or is this meant to be executed automatically?

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 27, 2020, 2:15pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/4 "2020-02-27T14:15:04Z")

</div>

In Step 4 at the end of the systemd service example the `<<` in front of `EOF` at the bottom need to be removed. I don’t think I can edit this myself somehow, can I?

Also, it might be worth noting that the dollar signs need to be escaped to work in the `cat` command in Step 4 in case others also copy and paste that block (just like I did) and then wonder why it doesn’t work. Thus,

```
cat >> ../sources/meta-stargazer/recipes-example/gnuhello/hello_2.10.bb <<EOF
inherit systemd    
SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE_${PN} = "hello.service"

SRC_URI_append = " file://hello.service "
FILES_\${PN} += "\${systemd_unitdir}/system/hello.service"

do_install_append() {
  install -d \${D}/\${systemd_unitdir}/system
  install -m 0644 \${WORKDIR}/hello.service \${D}/\${systemd_unitdir}/system
}
EOF

```

Edit: I just found another missing escape in the line `FILES_\${PN} += "\${systemd_unitdir}/system/hello.service"`. Fixed above.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 27, 2020, 5:13pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/5 "2020-02-27T17:13:53Z")

</div>

Huh. Not sure why but I don’t seem to have edit access either. @mirzak can you take a look?

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 27, 2020, 5:23pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/6 "2020-02-27T17:23:16Z")

</div>

Hi @HerrMuellerluedensch I just ran the steps above in my warrior based build without any such failure. Can you describe your yocto configuration to me? Did you start fresh with the full setup from above?

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 28, 2020, 2:35pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/7 "2020-02-28T14:35:49Z")

</div>

I’m pretty sure I did a plain copy and paste of all steps. Just to make sure I started a fresh repo sync and rebuild. I’ll keep you updated.  
In the meantime you can probably help me with another issue: Isn’t there an `inherit autotools` missing in the receipe in step 4? Without that `bitbake hello` complaints that there is no Makefile.

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 28, 2020, 2:50pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/8 "2020-02-28T14:50:53Z")

</div>

Regarding the autotools: My bad! Too much fumbling in the receipes!

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [February 28, 2020, 8:53pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/9 "2020-02-28T20:53:19Z")

</div>

> [@HerrMuellerluedensch](#):
>
> I’m pretty sure I did a plain copy and paste of all steps. Just to make sure I started a fresh repo sync and rebuild. I’ll keep you updated.

I just ran a full setup from scratch and triggered the failure you reported. I then immediately re-ran ‘bitbake hello’ and it succeeded. This indicates there is likely a race condition somewhere in the upstream hello sources. For the purposes of this tutorial, I think that’s ok since it’s not related to the specific content here.

Drew

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [February 29, 2020, 12:30pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/10 "2020-02-29T12:30:50Z")

</div>

Ok thanks! Sounds ligit.

---

<div class="post-metadata">

**Author:** ![mirzak](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/mirzak/32/2056_2.png) [@mirzak](https://hub.mender.io/u/mirzak)\
**Post date:** [March 3, 2020, 11:08am UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/11 "2020-03-03T11:08:06Z")

</div>

> [@drewmoseley](#):
>
> Huh. Not sure why but I don’t seem to have edit access either. @mirzak can you take a look?

Can you try now? The post was not in “wiki form”, though strange that you could not edit it since you posted it.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [March 3, 2020, 5:15pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/12 "2020-03-03T17:15:32Z")

</div>

Yes, I have edit access again. Thanks.

---

<div class="post-metadata">

**Author:** ![HerrMuellerluedensch](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/herrmuellerluedensch/32/513_2.png) [@HerrMuellerluedensch](https://hub.mender.io/u/HerrMuellerluedensch)\
**Post date:** [March 8, 2020, 11:06am UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/13 "2020-03-08T11:06:23Z")

</div>

I updated the wiki as described before. Feel free to review the changes and cleanup (remove) the chat history.

---

<div class="post-metadata">

**Author:** ![Sourabh1107](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/sourabh1107/32/1464_2.png) [@Sourabh1107](https://hub.mender.io/u/Sourabh1107)\
**Post date:** [January 12, 2022, 9:50pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/14 "2022-01-12T21:50:48Z")

</div>

Hello @drewmoseley @mirzak thanks for the great article. I am trying to achieve the same to start my custom script during boot-up. If I have 2 scripts to be executed once rootfs is mounted or during boot-up how should I include 2 files in image recipe? Should I create 2 separate systemd service files? Can you please let me know how to do this? Assuming script names are custom-script1.sh and custom-script2.sh

Your help will be much appreciated.

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [January 13, 2022, 7:12pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/15 "2022-01-13T19:12:49Z")

</div>

It’s really a matter of personal preference. If the two scripts always run together and consecutively then you can just have a single script to call that that is setup as a systemd service. If you ever have a need to start or stop just one of them, then you will need invidividual service files for each.

Drew

---

<div class="post-metadata">

**Author:** ![MichaelBMiner](https://avatars.discourse-cdn.com/v4/letter/m/d78d45/32.png) [@MichaelBMiner](https://hub.mender.io/u/MichaelBMiner)\
**Post date:** [January 14, 2022, 10:45pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/16 "2022-01-14T22:45:54Z")

</div>

Can you post an example using recipetool and GitHub or GitLab. I am currently building an image using your examples above. In the future however I will need to build in a new recipe(s) from Git repos.

Can you give an example or point me to a different example?

---

<div class="post-metadata">

**Author:** ![MichaelBMiner](https://avatars.discourse-cdn.com/v4/letter/m/d78d45/32.png) [@MichaelBMiner](https://hub.mender.io/u/MichaelBMiner)\
**Post date:** [January 17, 2022, 3:35pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/17 "2022-01-17T15:35:32Z")

</div>

As a quick update I am also seeing an error stating that lib/arg-nonnull.d does not exist. The proposed solution above did not solve my issue.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [January 18, 2022, 1:59pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/18 "2022-01-18T13:59:18Z")

</div>

I’m not following what you are trying to do but I think the [Yocto docs](https://docs.yoctoproject.org/dev-manual/common-tasks.html#writing-a-new-recipe) may help. Specifically `devtool` can help quickly create new recipes from GIT urls.

Drew

---

<div class="post-metadata">

**Author:** ![MichaelBMiner](https://avatars.discourse-cdn.com/v4/letter/m/d78d45/32.png) [@MichaelBMiner](https://hub.mender.io/u/MichaelBMiner)\
**Post date:** [January 28, 2022, 4:29pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/19 "2022-01-28T16:29:46Z")

</div>

I want to use recipetool to create a recipe that uses a private repository. Can you share how to do this?

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [January 28, 2022, 4:47pm UTC](https://hub.mender.io/t/how-to-create-your-first-recipe-and-enable-auto-start-using-systemd/1195/20 "2022-01-28T16:47:54Z")

</div>

[This link](https://stackoverflow.com/questions/34596774/how-to-clone-a-private-git-repo-from-within-a-bitbake-recipe) should help.  
Drew
