A gRPC server that facilitates provisioning and updating containers.
It uses skopeo under the hood for inspecting image archives and copying them from mass storage to local registry.
- Skopos is pronounced as skop-os' and means an observer, a watchman
- Ormos (one of the skopos services) means archive keeper in the Magic: The Gathering card game
Replace IP address accordingly.
grpcurl -plaintext 10.0.0.42:50052 listExample output:
grpc.reflection.v1.ServerReflection
unit.containers.v0.OrmosReplace IP address accordingly.
grpcurl -plaintext 10.0.0.42:50052 list unit.containers.v0.OrmosExample output:
unit.containers.v0.Ormos.InspectImageArchive
unit.containers.v0.Ormos.ListImageArchives
unit.containers.v0.Ormos.ListUsbDevices
unit.containers.v0.Ormos.LoadImageArchive
unit.containers.v0.Ormos.MountUsbDevice
unit.containers.v0.Ormos.UnmountUsbDeviceReplace IP address accordingly.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{}' '10.0.0.42:50052' unit.containers.v0.Ormos.ListUsbDevicesExample output (device not mounted):
{
"devices": [
{
"devicePath": "/dev/sda"
},
{
"devicePath": "/dev/sda1"
}
]
}Example output (device mounted):
{
"devices": [
{
"devicePath": "/dev/sda"
},
{
"devicePath": "/dev/sda1",
"isMounted": true,
"mountPoint": "/mnt/usb"
}
]
}Replace IP address accordingly.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{"device_path": "/dev/sda1", "mount_point": "/mnt/usb"}' '10.0.0.42:50052' unit.containers.v0.Ormos.MountUsbDeviceReplace IP address accordingly.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{"path": "/mnt/usb"}' '10.0.0.42:50052' unit.containers.v0.Ormos.ListImageArchivesExample output:
{
"imageArchives": [
{
"filePath": "/mnt/usb/alpine-arm64.tar",
"fileSizeBytes": "8468992",
"sha256Checksum": "0b070f92dd64e2bfead9f0c494511c9ce486f18900ec8297f374e5000a5f2994"
}
]
}
Replace IP address and archive path accordingly, pretty printing underlying skopeo commands stdout if request successful.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{"file_path": "/mnt/usb/alpine-arm64.tar"}' '10.0.0.42:50052' unit.containers.v0.Ormos.InspectImageArchive | jq 'if .isSuccess then .stdout | fromjson else . end'Example output (success):
{
"Digest": "sha256:058c92d86112aa6f641b01ed238a07a3885b8c0815de3e423e5c5f789c398b45",
"RepoTags": [],
"Created": "2025-02-14T03:28:36Z",
"DockerVersion": "",
"Labels": null,
"Architecture": "arm64",
"Os": "linux",
"Layers": [
"sha256:a16e98724c05975ee8c40d8fe389c3481373d34ab20a1cf52ea2accc43f71f4c"
],
"LayersData": [
{
"MIMEType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"Digest": "sha256:a16e98724c05975ee8c40d8fe389c3481373d34ab20a1cf52ea2accc43f71f4c",
"Size": 8461312,
"Annotations": null
}
],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
]
}Example output (failed):
{
"stderr": "time=\"2025-06-08T16:15:16Z\" level=fatal msg=\"Error parsing image name \\\"docker-archive:/mnt/usb/dne.tar\\\": opening file \\\"/mnt/usb/dne.tar\\\": open /mnt/usb/dne.tar: no such file or directory\"\n"
}Replace IP address accordingly.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{"mount_point": "/mnt/usb"}' '10.0.0.42:50052' unit.containers.v0.Ormos.UnmountUsbDeviceReplace IP address accordingly.
grpcurl -plaintext -import-path ./proto -proto ormos.proto -d '{"file_path": "/mnt/usb/alpine-arm64.tar", "image_name": "alpine", "image_tag": "latest"}' '10.0.0.42:50052' unit.containers.v0.Ormos.LoadImageArchive