Skip to content

docs(services): document adding your own services, with an example - #121

Open
dakejahl wants to merge 2 commits into
mainfrom
docs/custom-service-example
Open

dakejahl wants to merge 2 commits into
mainfrom
docs/custom-service-example

Conversation

@dakejahl

@dakejahl dakejahl commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #120.

Since #68 moved ARK-OS to system units, the service-manager finds services by their manifest in /usr/lib/ark-os/manifests/ and manages them with system systemctl. Add-ons set up the old way (a user unit plus ~/.local/share/<name>/) no longer appear on the Services page. Until now, the new requirements weren't written down anywhere.

This PR adds:

  • examples/custom-service/: a working add-on, hello-ark, that logs a configurable message. It has a unit, a manifest, a TOML config, and an install.sh (with --uninstall). The install script reads the ARK-OS user from service-manager.service, so the same files work on Jetson, Pi and Modalix.
  • examples/custom-service/README.md, which covers:
    • the requirements;
    • what each manifest field does;
    • what the TOML config editor can and can't edit;
    • what ARK-OS upgrades and purges do to add-on files;
    • a table for migrating an add-on from a user service;
    • troubleshooting.
  • A short "Adding your own services" section in the main README that links to the example.

What an add-on needs:

What Where
systemd system unit with User= and [Install] /etc/systemd/system/<name>.service
Manifest /usr/lib/ark-os/manifests/<name>.manifest.json
Config (optional; TOML, group <ark-user>, mode 0664) /etc/ark-os/<configFile>

An add-on doesn't need a polkit rule or a sudoers entry: the web UI can control any service that has a manifest.

Testing

I ran the example end to end in a Debian bookworm container with systemd, using ARK-OS's real service-manager.service and service_manager.py, with user pi:

  • install.sh installed the four files with the right owners and modes.
  • GET /statuses listed hello-ark with config_file: hello-ark.toml.
  • start, stop, restart, enable and disable through the API all succeeded.
  • GET /config and POST /config worked, and the saved values took effect after a restart.
  • /logs/stream streamed the service's lines with the configured priority.
  • Re-running install.sh kept the config edited through the API.
  • --uninstall removed everything.

shellcheck passes on both scripts. This hasn't been run on real Jetson, Pi or Modalix hardware.

Notes

🤖 Generated with Claude Code

Since the move to system units in #68, the service-manager discovers
services by their manifest in /usr/lib/ark-os/manifests and manages them
with system systemctl, so add-ons installed the old way (user units plus
~/.local/share/<name>) no longer show up on the Services page.

Add examples/custom-service: a hello-ark add-on (unit, manifest, TOML
config, polkit rule, and an install script) and a README covering the
requirements, the manifest fields, what the config editor supports,
polkit, upgrades, migrating from a user service, and troubleshooting.
Link it from a new section in the main README.

Closes #120

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The web UI can control any service that has a manifest, so an add-on
needs no polkit rule (or sudoers entry) of its own. Remove the example's
rule and the README's polkit section, and say that the manifest is what
lets the web UI control the service.

Also drop the caveat about the config editor stripping whitespace from
strings; #122 fixes the parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Ryanf55

Ryanf55 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Note - ArkOS installs all its services via debian, and they end up in a different spot due to being distributed by a debian.
The supplied instructions result in the desired behavior.
Seems like you are now noticing security issues.
Also, of note, services can't read their configs when run as the jetson user because /etc/ark-os/ is not readable.
Might recommend testing this example on hardware to see if you can replicate.

After installing ArkOS on my jetson, I see the following behavior from the debian:

jetson@sn04-jetson:~$ ll /etc/systemd/system/ark-os.target.wants/
total 8
drwxr-xr-x  2 root root 4096 Oct 19 12:53 ./
drwxr-xr-x 31 root root 4096 Oct 23 13:25 ../
lrwxrwxrwx  1 root root   42 Oct 19 12:53 ark-ui-backend.service -> /lib/systemd/system/ark-ui-backend.service
lrwxrwxrwx  1 root root   45 Oct 19 12:53 autopilot-manager.service -> /lib/systemd/system/autopilot-manager.service
lrwxrwxrwx  1 root root   46 Oct 19 12:53 connection-manager.service -> /lib/systemd/system/connection-manager.service
lrwxrwxrwx  1 root root   34 Oct 19 12:53 go2rtc.service -> /lib/systemd/system/go2rtc.service
lrwxrwxrwx  1 root root   38 Oct 19 12:53 jetson-can.service -> /lib/systemd/system/jetson-can.service
lrwxrwxrwx  1 root root   42 Oct 19 12:53 mavlink-router.service -> /lib/systemd/system/mavlink-router.service
lrwxrwxrwx  1 root root   39 Oct 19 12:53 rtsp-server.service -> /lib/systemd/system/rtsp-server.service
lrwxrwxrwx  1 root root   43 Oct 19 12:53 service-manager.service -> /lib/systemd/system/service-manager.service
lrwxrwxrwx  1 root root   42 Oct 19 12:53 system-manager.service -> /lib/systemd/system/system-manager.service
jetson@sn04-jetson:~$ sudo systemctl cat ark-ui-backend.service 
# /lib/systemd/system/ark-ui-backend.service
[Unit]
Description=ARK UI Backend Service
Wants=network-online.target
After=network-online.target nginx.service

[Service]
Type=simple
User=jetson
Group=jetson
WorkingDirectory=/usr/lib/ark-os/ark-ui-backend
ExecStart=/usr/lib/ark-os/bin/node /usr/lib/ark-os/ark-ui-backend/index.js
Restart=on-failure
Environment=NODE_ENV=production
Environment=PATH=/usr/lib/ark-os/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

[Install]
WantedBy=multi-user.target ark-os.target

@dakejahl

Copy link
Copy Markdown
Contributor Author

I'm at the Ardupilot dev conference and will test on hardware when I'm back. Claude found that the polkit rules could result in elevated privileges, but now Claude is refusing my security audit prompt 😂

@Ryanf55

Ryanf55 commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Yea, I was a big fan of the old user services approach because nothing required root. With installing a bunch of FOSS code that's not containerized that it at least doesn't have access to everything on the system. I'm sure it can be figured out how to do it, but it will take more thought.

I'll keep iterating on hardware here and can propose any changes I find.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document user-supplied services install

2 participants