{"id":44332383,"url":"https://github.com/bringauto/package-to-image-placer","last_synced_at":"2026-02-11T10:09:54.932Z","repository":{"id":285725538,"uuid":"947413625","full_name":"bringauto/package-to-image-placer","owner":"bringauto","description":"Copy packages to images in defined way","archived":false,"fork":false,"pushed_at":"2025-08-04T09:08:24.000Z","size":11968,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-04T13:09:36.892Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bringauto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-12T16:42:47.000Z","updated_at":"2025-08-04T09:07:41.000Z","dependencies_parsed_at":"2025-04-25T08:33:39.526Z","dependency_job_id":null,"html_url":"https://github.com/bringauto/package-to-image-placer","commit_stats":null,"previous_names":["bringauto/package-to-image-placer"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bringauto/package-to-image-placer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bringauto%2Fpackage-to-image-placer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bringauto%2Fpackage-to-image-placer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bringauto%2Fpackage-to-image-placer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bringauto%2Fpackage-to-image-placer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bringauto","download_url":"https://codeload.github.com/bringauto/package-to-image-placer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bringauto%2Fpackage-to-image-placer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29331743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T06:13:03.264Z","status":"ssl_error","status_checked_at":"2026-02-11T06:12:55.843Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-11T10:09:54.336Z","updated_at":"2026-02-11T10:09:54.925Z","avatar_url":"https://github.com/bringauto.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Package To Image Placer\n\nThis tool is used to place a package into a system image without the need to use `sudo`.\nIt is used to create a disk image with a package installed.\nThis way the target system can be used with new packages without the need to generate a whole image and know yocto.\n\nIt takes a package (archive) and a system image (disk image) as input and creates a new disk image with the package.\nIf the package contains any service files, they can be activated.\n\nFor working with the image, the tool uses `libguestfs` to mount the image's filesystems. This way, the tool can work with the image without root permissions.\n\nThe tool supports interactive mode, which allows the user to select the package, target partition, and the service files to activate.\nThen it can generate a config file for the tool to use in non-interactive mode.\n\n## Requirements\n\n* golang \u003e= 1.23\n* libguestfs\n  * See [libguest installation] section for install instructions.\n* ssty\n\n## Usage\n\n### Build\n\n```bash\ngo get package-to-image-placer\ngo build\n```\n\n## Run\n\nFor interactive mode, run:\n\n```bash\n./package-to-image-placer -source=\u003csource_image_path\u003e -target=\u003ctarget_image_path\u003e [ -package-dir=\u003cpackage_dir\u003e ... ]\n```\n\nFor non-interactive mode, run:\n\n```bash\n./package-to-image-placer -config=\u003cconfig_file_path\u003e [ \u003coverrides\u003e ]\n```\n\n⚠️ In non-interactive mode, if the target image already exists, it will be modified. If the operation fails, the target image will be removed to prevent an inconsistent state.\n\nWhen passing arguments through the command line, it is recommended to use the `-name=value` format when the equal sign is used.\n\n### Arguments\n\n* `-source` - Path to the source image.\n* `-target` - Path to the target image. The path will be created and can't be same as source image path.\n  * If used with no-clone option this file must exist and will be changed.\n* `-config` - Path to the config file. Sets Non-interactive mode.\n* `-no-clone` - Do not clone the source image. The target image must exist. If the operation fails, it may leave the image in an inconsistent state.\n* `-package-dir` - Initial directory for the package selection. Interactive mode only.\n* `-log-path` - Directory for the log file. Default is the current directory (`.`). The log file will be created at `log-path/package-to-image-placer.log`.\n* `-h` - Show usage.\n\n\u003e Command line arguments are overriding the config file values.\n\nFor the mock use case, please consult the [Use Case Example Documentation](doc/UseCaseExample.md).\n\n## Tests\n\n### Unit Tests\n\nTo run all unit tests, run:\n\n```bash\ngo test ./...\n```\n\n### Integration Tests\n\nTo run integration tests, refer to the [tests/README.md](tests/README.md) file.\n\n## Config File\n\nThe configuration for the image customization process can be generated through an interactive run. Alternatively, you can directly edit a configuration file to specify the packages to be applied, the target partitions for these changes, and the service files that should be activated.\n\nThe example configuration file is located at [example_config.json](./resources/example_config.json).\n\nThe structure of the configuration file is defined in JSON format as follows:\n\n```json lines\n{\n  \"source\": \"\u003csource-image-path\u003e\",\n  \"target\": \"\u003ctarget-image-path\u003e\",\n  \"no-clone\": \"\u003cbool\u003e\",\n  \"packages\": [\n    {\n     \"package-path\": \"package-path.zip\",\n     \"enable-services\": \"\u003cbool\u003e\",\n     \"service-name-suffix\": \"\u003cservice-name-suffix\u003e\",\n     \"target-directory\": \"\u003ctarget-directory\u003e\",\n     \"overwrite-files\": [\n       \"\u003cfile-name-1\u003e\",\n       \"\u003cfile-name-2\u003e\"\n     ]\n    }\n  ],\n  \"partition-numbers\": [\n    \"\u003cpartition-number\u003e\"\n  ],\n  \"configuration-packages\": [\n    {\n     \"package-path\": \"configuration-package-path.zip\",\n     \"overwrite-files\": [\n       \"\u003cfile-name-1\u003e\",\n       \"\u003cfile-name-2\u003e\"\n     ]\n    }\n  ],\n  \"log-path\": \"\u003clog-path\u003e\",\n}\n```\n\n* The `source` or `target` in the case of `-no-clone` must be a valid image file using a GPT partition table and must have at least one partition with an Ext4 filesystem, as the tool can only write to this filesystem. If you want to enable services from the copied package, the destination partition must contain the directories `/etc/systemd/system/` and `/etc/systemd/system/multi-user.target.wants/`, where the service files will be copied.\n* The `packages` and `configuration-packages` must be valid zip files containing the files to be copied to the image. Additionally, a package can contain a service file that can be activated in the image. The service file must be included in the package and must have a `.service` extension. If a configuration package contains a service file, it is processed as a normal file and is simply copied to the image, not activated as a service.\n* The `service-name-suffix` is used to add a suffix to the service file name and thus avoid name conflicts. The suffix is added to the service file name in the image. For example, if the service file name is `my-service.service` and the suffix is `test`, the service file name in the image will be `my-service-test.service`. The suffix must not start with a hyphen.\n* The `overwrite-files` paths are relative to their location within the package zip file. If a file already exists in the image and is not listed under `overwrite-files`, an error will occur. However, if the file is included in `overwrite-files`, it will be copied to the image, overwriting the existing file regardless of its presence.\n* The `partition-numbers` must be valid partition numbers in the image. The partition numbers are 1-based, meaning the first partition is 1, the second is 2, and so on.\n* Paths in the configuration file can be absolute or relative to the location of the configuration file.\n* The difference between package and configuration packages is that the configuration packages are not placed in the specified directory with the package name, and are always placed into the root of the image and services from them cannot be activated.\n\n## Services\n\nThe tool can activate service files in the image.\nThe service files are activated by copying them to `/etc/systemd/system/` and creating a symlink to the file in `/etc/systemd/system/multi-user.target.wants/`.\n\nThe paths in the service are updated based on the `WorkingDirectory`. See [Service Paths](#service-paths) section for more details.\n\n### Service Requirements\n\nThe service file must:\n\n* be in the package.\n* service file name must end with `.service`.\n* multiple services for the same package are not supported.\n* service file suffix must not start with a hyphen.\n* contain the following fields:\n  * `ExecStart`\n    * Executable in `ExecStart` must be present in the package.\n    * The executable path is absolute\n  * `User`\n  * `RestartSec`\n  * `WorkingDirectory`\n  * `Type=simple`\n  * `WantedBy=multi-user.target`\n\n\n### Service Paths\n\nThe `WorkingDirectory` field is updated to the package path in the target image. \nThe package path consist of the TargetDirectory set for the package in configuration and \nthe package directory name, determined by finding the executable in the added package.\n\nIn `ExecStart` field every occurrence of the original `WorkingDirectory` path is replaced with the new one.\n\nThe executable path in `ExecStart` is always prefixed with the new `WorkingDirectory` path. \nThe reason is that the service should always start an executable from the package as it represents virtual standalone sysroot, not from the system.\nExecutable path example: `/usr/bin/echo` is updated to `/package-path/usr/bin/echo`.\n\nFull path example:\n```\nWorkingDirectory=/original-path/\nExecStart=/bin/executable --argument=/original-path/argument --relative-path=./etc/relative-path --absolute-path=/etc/absolute-path\n```\nis updated to:\n```\nWorkingDirectory=/package-path/\nExecStart=/package-path/bin/executable --argument=/package-path/argument --relative-path=./etc/relative-path --absolute-path=/etc/absolute-path\n```\n\n\u003e Note: If the `WorkingDirectory` is set to `/`, all paths in the `ExecStart` will be updated to the package path\n\n## Libguest Installation\n\nLibquestfs is a library for modifying disk images. It is used to mount the disk image without root permissions.\n\n### Debian Based\n\n```bash\nsudo apt-get install libguestfs-tools\n\n# Add user kernel, which can be accessed without sudo. Other option is to give permissions to the existing kernel.\napt-get download linux-image-$(uname -r)\ndpkg-deb -x linux-image-$(uname -r)*.deb ./\nexport SUPERMIN_KERNEL=./boot/vmlinuz-image-$(uname -r)\n```\n\n`install libguestfs-tools` will install the tools, but it needs read access to the kernel (e.g. `/boot/vmlinuz-*`) image.\nYou can either create a new kernel image, that `supermin` will use (as shown above), or give read access to the existing one.\nTo test functionality or to find the used kernel image, run:\n\n```bash\nlibguestfs-test-tool\n```\n\n### Fedora\n\n```bash\nsudo dnf install libguestfs-tools\n```\n\n## Troubleshooting\n\n### Libvirt Error\n\nIf you have error that look like this:\n\n``` text\nlibguestfs: error: could not create appliance through libvirt. \nOriginal error from libvirt: internal error: \nprocess exited while connecting to monitor: 2025-03-03T14:51:53.981133Z qemu-kvm: -device {\"driver\":\"scsi-hd\",\"bus\":\"scsi0.0\",\"channel\":0,\"scsi-id\":0,\"lun\":0,\"device_id\":\"drive-scsi0-0-0-0\",\"drive\":\"libvirt-2-storage\",\"id\":\"scsi0-0-0-0\",\"bootindex\":1,\"write-cache\":\"on\"}: Failed to get \"write\" lock\n        Is another process using the image?\n```\n\nMake sure you have `kvm` enabled.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbringauto%2Fpackage-to-image-placer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbringauto%2Fpackage-to-image-placer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbringauto%2Fpackage-to-image-placer/lists"}