# makeself: self-extracting archives built from a shell script stub

> makeself.sh turns a directory into a single .run file that unpacks itself and runs an install command. It is portable, old, and deliberately plain, and the trade-offs are worth knowing before you ship one.

**megastep/makeself** — A self-extracting archiving tool for Unix systems, in 100% shell script.

- Repository: https://github.com/megastep/makeself
- Website: https://makeself.io
- Stars: 2,625 · Forks: 408
- Language: Shell
- License: GPL-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/megastep-makeself

## What makeself solves, and who actually needs it

The problem is distribution without a package manager. You have a directory of files and an install script, and the target machine may be Solaris 8, HP-UX 11i, AIX, IRIX 6.5, or a Linux box you do not control. You cannot assume rpm, deb, Homebrew, or a working internet connection to a repository. makeself.sh produces a single file that the user runs with sh, and the README's own summary of the workflow is that the file "appears as a shell script" and "can be launched as is".

The audience is narrower than the topic list suggests. This is for vendors shipping drivers, game patches, and installers to heterogeneous Unix fleets. The README lists nVidia Linux drivers, Google Earth's Linux installer, VirtualBox Linux installers, and Loki Software game patches as public examples. If you are deploying a web service to a Kubernetes cluster, makeself is the wrong shape of tool, and no amount of compression flags changes that.

## The archive is a shell stub glued to a compressed tar

The mechanism is simple enough to describe in one sentence: the output is a compressed TAR archive with a small shell script stub at the front. The stub does the work at runtime, extracting files to a temporary directory, running the embedded command, and removing the temporary files when done. makeself.sh itself only builds archives; it is not involved when the user runs one.

Two consequences follow from that design. First, integrity checking is built in, with CRC and/or MD5/SHA256 checksums, so a truncated download fails loudly rather than half-extracting. Second, portability is a hard constraint on the code, not a marketing claim. The README states the script is "not relying on any bash-specific features" and calls only commands present on a functioning UNIX-compatible system. That is why the compression choice is a flag rather than a default: gzip is the default where it is commonly available, and every other option (bzip2, bzip3, pbzip2, xz, lzo, lz4, zstd, pigz, compress, or none) requires the corresponding command on the target machine.

Encryption and encoding sit after compression, not before. --base64, --gpg-encrypt and --ssl-encrypt all apply to the already-compressed payload, and the README is explicit that gpg and OpenSSL are assumed to be present on the user's side. That ordering matters: the stub has to decode or decrypt before it can decompress, so a user missing gpg gets a failure at the first step, not a partial extraction.

## Installing makeself and building your first .run archive

makeself is distributed as the makeself distribution itself, which the README lists among archives made with the tool. The repository has a Makefile whose all target builds makeself-$(VERSION).run from makeself.sh, makeself-header.sh and VERSION via ./make-release.sh. If you have the sources, that is the build path:

```bash
make
```

The command runs ./make-release.sh and writes the .run file named after the contents of VERSION. Running that file unpacks and installs the tool. Note that the version in the filename comes from the VERSION file, so it changes with the checkout.

Once makeself.sh is on your PATH, the invocation follows the syntax in the README, with the archive directory first, the output filename second, then a label and a startup script:

```bash
makeself.sh [args] archive_dir file_name label startup_script [script_args]
```

This produces the archive from the contents of archive_dir, labelled with label, and runs startup_script after extraction. The user then runs the resulting file with sh. The README recommends the .run or .sh suffix so users understand the file is a shell script with binary data attached.

Compression is the first real decision. gzip is the default on platforms where it is commonly available, and the README suggests encoding the choice in the filename: .bz2.run for bzip2, .xz.run for xz, .lz4.run for lz4, .zstd.run for zstd, .lzo.run for lzop. --complevel sets the level for gzip, bzip2, pbzip2, zstd, xz, lzo and lz4, defaulting to 9, and --comp-extra appends further options to the compressor's command line. --threads controls the thread count for compressors that support it.

If you serve the archive over HTTP, the README has a specific warning: most web servers treat .run files as plain text and display them in the browser. The documented fix is a MIME type in httpd.conf:

```apache
AddType application/x-makeself .run
```

That is a five-second change that prevents the most common support ticket for this format.

## Where makeself breaks, and the cases it cannot cover

The most concrete failure mode is documented in the README itself. Archives created before v2.1.2 used an old syntax for head and tail that GNU coreutils has been progressively obsoleting, so those archives may fail to decompress on current systems. The workaround is an environment variable:

```bash
export _POSIX2_VERSION=199209
```

This is worth reading as a warning about the format itself, not just about old releases. A self-extracting archive is a frozen snapshot of shell assumptions. When the host shell or coreutils change, the archive does not get patched, because it is a file you already shipped.

The second limitation is dependency on the target's compressor. Every non-gzip option requires that command to exist on the user's machine. The README is candid about this: bzip2, xz, lzop, lz4 and zstd must all be in the command path, and the recommended filename suffix exists precisely so users know what they will need. If you pick --zstd for a 20 percent size win and your user is on a minimal Solaris install, the archive simply does not extract.

The third is trust. Checksums catch corruption, not tampering. The README describes CRC and MD5/SHA256 self-validation, and separate encryption flags for the payload, but there is no signature or key-distribution mechanism in what the README documents. If your threat model includes a modified archive, makeself gives you a checksum to compare, not a verification chain.

Finally, makeself does not manage what it installs. There is no manifest, no dependency resolution, no uninstall. The startup script you supply is the entire lifecycle. That is a feature for a driver installer and a liability for anything that needs to be upgraded in place.

## How makeself differs from makeself alternatives

The obvious comparison is a distribution package: rpm, deb, or an equivalent. The difference is not quality, it is the dependency model. A package manager knows what else is installed, resolves dependencies, records files for later removal, and can upgrade in place. A makeself archive knows none of that. It extracts to a temporary directory, runs your script, and deletes the temporary files. The upside is that it runs on a machine with no package manager and no network, which is exactly the situation the README's platform list describes.

The other comparison is a plain tarball plus a README. The difference there is the stub. With tar you ask the user to decompress, find the install script, and run it with the right arguments. With makeself the archive carries the command, the label, and the checksums, and the user types one line. That is a real reduction in support burden when your users are not engineers.

A third option is a container image, and it is worth naming because it is the modern default. Containers solve the same "ship a directory and run something" problem with a different trust model and a much larger runtime requirement. If your target is a Kubernetes cluster, use a container. If your target is an HP-UX box in a lab, makeself is one of the few things that will run at all.

## Maintenance, releases and the GPL-2.0 licence

The repository is not archived, and the last push was on 2026-09-04, which is recent. Releases are numbered and tagged: release-2.7.1 and release-2.7.0 both on 2025-12-10, and release-2.6.0 on 2025-09-27. The CHANGELOG.md sits at the top level, so upgrade cost is a matter of reading that file between your version and the target, then rebuilding any archive you intend to redistribute. Archives already in the field do not change when you upgrade the tool; you have to rebuild and reship them.

The licence is GPL-2.0, per the repository and the badge in the README. The practical question for a vendor is not whether you may use makeself to build an archive, but what the archive itself becomes. makeself.sh concatenates a shell stub (makeself-header.sh) with your compressed payload. If you redistribute the resulting .run file, the stub travels with it. Whether that pulls your product into GPL-2.0 obligations depends on how the stub and your payload are combined and on your own legal position, and this is a question for a lawyer, not for a README. What is clear from the repository is that the tool and its header are GPL-2.0, and that the archives embed the header.

## Conclusion

Use makeself when you need one file that installs on Solaris, AIX, HP-UX and modern Linux without a package manager, and when a shell stub with CRC or SHA256 validation is enough trust for your users. Do not use it when you need signed packages, dependency resolution, or an uninstall path, because the README documents none of those. Before shipping, verify three things: the target machine has the compressor you chose, the startup script is idempotent when run twice, and the archive still extracts with the _POSIX2_VERSION workaround if any user is on a pre-2.1.2 archive.

## FAQ

### How do I install makeself?

Build it from the sources with make, which runs ./make-release.sh and produces makeself-$(VERSION).run, then run that file. The README also points out that the makeself distribution itself is one of the public examples of an archive made with the tool.

### How do I use makeself to create an archive?

The syntax is makeself.sh [args] archive_dir file_name label startup_script [script_args]. The archive directory comes first, then the output filename, a label, and the script to run after extraction. The user then runs the resulting file with sh.

### What are the alternatives to makeself?

A distribution package such as rpm or deb resolves dependencies and records installed files, which a makeself archive does not do. A plain tarball plus instructions is the other option, and the difference is that makeself embeds the startup command and checksums in the file itself. The README does not compare makeself to any of these.

## Sources

- [License: GPL-2.0](https://github.com/megastep/makeself/blob/master/LICENSE)
- [megastep/makeself on GitHub](https://github.com/megastep/makeself)
- [Project website](https://makeself.io)
- [README](https://github.com/megastep/makeself/blob/master/README.md)
- [Releases](https://github.com/megastep/makeself/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/megastep-makeself
