Attach and Detach a Portable Service with portablectl
portablectl lets you attach a whole service image to a host, run it, then pull it back off again, without ever unpacking it into a real container. This guide inspects a portable service image, attaches its matching units, starts one deliberately, checks the result, and detaches it cleanly. Allow about twenty minutes, plus time to understand the image you have been given.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a Linux host using systemd, the systemd-container package, a portable service image, and root access for attach, detach and service-management operations. The examples use portablectl with the systemd 255.4-1ubuntu8.17 package installed on this machine. This guide does not create an image or invent a unit name: it uses an existing image path represented by IMAGE_PATH.
Safety boundary
Attaching changes the host's systemd unit search path and can make code from the image available to start. Do not use --now on an unreviewed image. Keep the image at the same path until it is detached, because attached units refer back to that path.
1. Check the installed service and command
The manpage describes systemd-portabled as a system service for attaching, detaching and inspecting portable service images, though most of its interface is exposed through portablectl. Check the package and command as ordinary, read-only operations:
$ systemctl --version
systemd 255
$ dpkg-query -W -f='${Package} ${Version}\n' systemd-container
systemd-container 255.4-1ubuntu8.17
$ command -v portablectl
/usr/bin/portablectl
$ systemctl status systemd-portabled.service --no-pager
The service may sit inactive until a request needs it: that is not, by itself, a failure. It is activated through its D-Bus service name when portablectl talks to it. If the command reports a missing unit or executable, stop here and install the distribution package that supplies systemd-portabled before continuing.
Checkpoint
Confirm the installed systemd version is the one whose option and output behaviour you are about to rely on.
2. Inspect the image without attaching it
Set an explicit path. A path containing a slash is unambiguous and stops portablectl searching its portable-image paths by name:
$ IMAGE_PATH='/srv/portables/REPLACE-ME.raw'
$ sudo portablectl inspect "$IMAGE_PATH"
Image:
...
Units:
...
The exact summary depends on the image. The useful questions are whether it contains a valid os-release, which service, socket, target, timer or path units match, and which unit prefix you intend to attach. For a fuller review, use --cat to display the image's os-release data and matching unit contents:
$ sudo portablectl inspect --cat "$IMAGE_PATH"
A suitable image normally contains an OS tree or raw disk image, an os-release file, and at least one matching unit. Inspecting does not copy units to the host and does not start a service. If inspection fails, do not reach for --force as a diagnostic shortcut; fix the image or its path first.
3. Attach only the units you reviewed
By default, attach derives a prefix from the image filename and copies matching .service, .socket, .target, .timer and .path units into the host's attached-unit directory. A version suffix after an underscore is ignored when deriving that prefix. Pass a prefix explicitly when the filename does not make the intended selection obvious:
$ sudo portablectl attach "$IMAGE_PATH" SERVICE_PREFIX
✓ Image SERVICE_PREFIX.raw attached successfully
The success wording can vary with the systemd build; a zero exit status is what matters. The operation creates host-side unit copies and drop-ins, including the image root setting and a security profile, and normally reloads the system manager. It does not enable or start the copied units unless you ask for --enable or --now.
Warning
Do not combine this first attach with --now. Starting image code is a separate decision. For a reboot-only test, --runtime keeps the attachment under /run until the next reboot, but it is still a live host change and should be removed deliberately once testing is complete.
Checkpoint
Ask whether the image is attached and inspect the unit that appeared:
$ portablectl is-attached "$IMAGE_PATH"
yes
$ systemctl cat SERVICE_PREFIX.service
$ systemctl daemon-reload
portablectl is-attached is a query. systemctl cat lets you confirm the selected unit and its drop-ins before starting it. The final reload is harmless but normally unnecessary after a successful attach; it is shown here as an explicit checkpoint for a manual review.
4. Start and verify the service separately
Start the exact unit you reviewed. This is an elevated, service-disrupting action, since it can launch a daemon and bind resources:
$ sudo systemctl start SERVICE_PREFIX.service
$ systemctl is-active SERVICE_PREFIX.service
active
$ systemctl status SERVICE_PREFIX.service --no-pager
Use journalctl -u SERVICE_PREFIX.service to investigate a failed start. An active unit proves systemd accepted the start and the process is still considered running; it does not prove the daemon is healthy for clients. Check the daemon's own health check, listening socket or expected log message when the service provides one.
- Not a separate VM. Portable services are regular systemd services rooted in the image, not a separate virtual machine.
- Profile is a security decision. The default portable profile applies restrictions;
trusted,strictandnonetworkhave materially different security consequences. Review the resulting unit properties before production use.
5. Stop and detach to undo the host change
When testing is finished, stop the unit before removal. If you enabled it, disable it as well:
$ sudo systemctl disable --now SERVICE_PREFIX.service
$ sudo portablectl detach "$IMAGE_PATH" SERVICE_PREFIX
$ portablectl is-attached "$IMAGE_PATH"
no
detach removes the copied unit files, drop-ins and any image symlink created for the attachment. With --runtime, the files were under /run and disappear at reboot anyway, but an explicit detach still makes the current state clear. If you did not enable the unit, use sudo systemctl stop SERVICE_PREFIX.service instead of the combined disable command.
Recovery
If the service will not stop, inspect its dependencies and logs before forcing processes away. If detaching reports a prefix mismatch, pass the same explicit prefix used during attach. If an image has been moved, restore it to its original path before detaching. Do not delete attached unit files by hand while portablectl still believes the image is attached.
6. Replace an image with reattach
For a reviewed replacement at a new versioned filename, reattach combines detach and attach in one step, and is available in the installed systemd 255 interface:
$ sudo portablectl reattach '/srv/portables/SERVICE_PREFIX_REPLACE.raw' SERVICE_PREFIX
$ portablectl is-attached '/srv/portables/SERVICE_PREFIX_REPLACE.raw'
yes
Do not remove the old image until the replacement has been verified and detached from any old reference. Without --now, reattach changes the attached units but does not start them, so plan the service stop, restart and rollback behaviour yourself, especially if the daemon owns state or a listening endpoint.
Done means
- Versions checked. The installed systemd and
systemd-containerversions were confirmed. - Image reviewed.
portablectl inspect --catidentified the image contents and intended unit prefix. - Attached without starting. The image was attached without running unreviewed code.
- Profile checked. The resulting unit and security profile were reviewed before starting it.
- Health verified. The service was checked independently of the attach operation.
- Cleanly removed. The service was stopped, disabled when necessary, and detached with
portablectl. - Path discipline kept. The image stayed at its recorded path while attached, and
is-attachednow reportsno.