Attach and Safely Replace a systemd Portable Service Image
portablectl attaches a whole operating system image as live systemd units, so a bad attach is not something you casually undo. You will inspect an image, attach its matching units to the host, confirm the attachment state, and remove it cleanly. The examples use the portablectl shipped by systemd 255.4-1ubuntu8.17 on Ubuntu. Allow roughly 10 minutes if the image already exists. You need root access for operations that change the system manager.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
- Know what a portable image is. It is an operating system tree containing systemd unit files, and it can be a directory, a btrfs subvolume, or a regular
.rawdisk image. - Pick a real path. This guide assumes an image at
/srv/portable/myservice.raw; replace that with a real image and do not run the mutating examples against one you have not inspected. - Understand the lookup rule. Images without a slash are looked up in portable image search paths; a path containing a slash is used directly. The usual persistent storage location is
/var/lib/portables/, while/etc/portables/and/run/systemd/portables/are normally better used for links to images stored elsewhere.
Checkpoint
Continue only when you know which units the image is meant to provide and where its files came from. Attaching copies unit files and adds drop-ins to the host; it is not a read-only preview.
1. Check what is already discoverable
Start with a non-mutating list. Disable the pager so the result is predictable in a terminal or script:
portablectl --no-pager list
This lists images found in the configured search paths, with brief metadata and state. It does not limit other commands to those images: an image at /srv/portable can still be inspected by its full path even if it is absent from this list.
Inspect the candidate directly. The normal form summarises its operating system metadata and matching unit files:
portablectl --no-pager inspect /srv/portable/myservice.raw
Use --cat when you need the unprocessed os-release data and unit file contents:
portablectl --no-pager --cat inspect /srv/portable/myservice.raw
Check that the listed units have the prefix you expect. By default, attach derives a prefix from the image filename: it removes .raw and stops at the first underscore. For example, myservice_2026.09.raw selects names beginning myservice-, myservice., or myservice@. Supply explicit prefixes after the image path if that default does not match your unit names.
2. Attach it persistently
Elevated command: attach the image only after inspecting it:
sudo portablectl --no-pager attach /srv/portable/myservice.raw
On success, matching .service, .socket, .target, .timer, and .path files become available through the host service manager, and service units receive a root setting pointing into the image.
defaultis the standard profile, fairly restrictive while still allowing logging and system D-Bus access.nonetworkremoves network access.stricttightens things further.trustedis deliberately relaxed and runs services with full privileges. Do not reach for it as a troubleshooting shortcut without reviewing the service and its image; it changes the host's actual security boundary.
Choose a profile explicitly when the image should have no network access:
sudo portablectl --no-pager --profile=nonetwork attach /srv/portable/myservice.raw
Persistent attachment places generated files under /etc/systemd/system.attached/. To attach only until the next reboot, add --runtime, which puts the files under /run/systemd/system.attached/ instead:
sudo portablectl --no-pager --runtime attach /srv/portable/myservice.raw
The manager is reloaded after attach by default. --no-reload suppresses that reload, so use it only when you have a deliberate plan to reload later.
3. Verify the result before starting anything
Ask portablectl for the attachment state:
portablectl --no-pager is-attached /srv/portable/myservice.raw
The output is one of states such as attached, attached-runtime, enabled, or running. Add --quiet to suppress the text and leave the exit status as the useful result in a script:
if portablectl --quiet is-attached /srv/portable/myservice.raw; then
echo "portable image is attached"
else
echo "portable image is not attached" >&2
exit 1
fi
Attaching does not automatically start or enable the service. If you have identified the intended service unit, request that behaviour during attachment with --now and --enable; both touch live host state, so check the unit names and image contents first:
sudo portablectl --no-pager --now --enable attach /srv/portable/myservice.raw
Checkpoint
After a start, inspect the unit with systemctl status myservice.service and review its journal before treating the deployment as healthy. If the service fails, undo the enablement and stop it before detaching:
sudo portablectl --no-pager --now --enable detach /srv/portable/myservice.raw
4. Replace an image with less interruption
When a new image replaces an existing one, reattach detaches the old image and attaches the new one in a single step. It permits versioned names that share the part before the first underscore, and it will not detach the old image if the replacement does not exist:
sudo portablectl --no-pager reattach /srv/portable/myservice_2026.09.raw
Running units are not stopped during the basic reattach operation. If the service must be restarted or enabled as part of the change, add --now and, where appropriate, --enable. That is a service-disrupting action: plan a maintenance window and verify the new image with inspect first.
5. Detach or remove it
Warning
Detach removes the host-side unit copies, drop-ins, and image link. It does not remove the image itself. Stop services and disable them first, or let --now stop and --enable disable the associated units:
sudo portablectl --no-pager --now --enable detach /srv/portable/myservice.raw
portablectl --no-pager is-attached /srv/portable/myservice.raw
The final command should report detached. To delete an image itself, use remove only after confirming the exact path and retaining any backup you need:
sudo portablectl --no-pager remove /srv/portable/myservice.raw
If the argument is a symbolic link, remove removes the link rather than the image it points to. That is still destructive to that directory entry, so verify with readlink -f and ls -l before running it.
Done means
- Metadata checked.
inspectshowed the expected metadata and unit files. - Profile and lifetime deliberate. The chosen profile and persistent or runtime lifetime were intentional.
- State confirmed.
is-attachedreturned the state you expected. - Started unit checked. Any started unit was checked with
systemctland its journal. - Removal ordered correctly. Detach was used before removal, and the image path was verified before any deletion.