How to zip → tar.gz for linux & container engineers
- Step 1Identify what your downstream actually consumes — A Docker
ADD foo.tar.gz /auto-extracts gzipped tarballs; a Helmfile://chart wants.tgz;pip/go modsource tarballs want.tar.gz. All of these accept the standard TAR.GZ this tool emits. Confirm the consumer wants TAR.GZ (not raw TAR) before converting. - Step 2Drop the vendor archive — Drag the
.zip(or.7z/.rar) onto the dropzone. On free you're limited to 50 MB and 500 entries — most SDK drops fit; large layer bundles need Pro (500 MB) or higher. - Step 3Press Process — there are no options — This tool has no compression slider, no path-strip control, no password field. It unzips, builds a TAR (mode 0644 per entry), GZIPs at level 6, and emits
name.tar.gz. - Step 4Restore executable bits if a binary is inside — Because every entry comes out 0644, any binary or script that must run will need
chmod +xafter extraction. In a Dockerfile:RUN tar -xzf app.tar.gz && chmod +x /app/bin/server. OrRUN chmod -Rthe relevant paths. - Step 5Normalise paths if the ZIP has a wrapper folder — Vendor ZIPs often nest everything under
package/orsdk-1.2.3/. If your Dockerfile expects files at the root, strip the prefix with the path prefix remover on the ZIP before converting (it operates on ZIPs). - Step 6Checksum the result before it enters the pipeline — Run the converted tarball through the checksum generator (SHA-256) and record the digest in your manifest. Note: re-converting the same ZIP yields a different hash because the mtime changes — checksum the artifact you actually ship, not a re-run.
TAR.GZ consumers in a Linux/container pipeline
Where the converted tarball plugs in, and the gotcha for each.
| Consumer | Accepts this output? | Gotcha to handle |
|---|---|---|
Docker ADD app.tar.gz / | Yes (auto-extracts) | Files land at 0644 — chmod +x binaries in a later RUN |
Docker COPY + RUN tar -xzf | Yes | Same 0644 caveat; set perms explicitly |
Helm chart .tgz | Yes (it's TAR.GZ) | Chart structure must match Helm's layout; this tool won't restructure |
Ansible unarchive | Yes | mode: on the task to fix permissions post-extract |
pip / go mod source tarball | Yes | Path layout must match the tool's expectations; strip wrapper dirs first |
systemd / entrypoint tar -xzf | Yes | Add chmod for executables in the unit/entrypoint |
Metadata: what survives the conversion
Critical for container engineers — the tool's real behaviour, not the ZIP's original metadata.
| Attribute | In the source ZIP | In the TAR.GZ output |
|---|---|---|
| File mode (permissions) | ZIP doesn't expose Unix mode cleanly | Forced to 0644 for every entry |
| Executable bit (+x) | Sometimes present | Lost — re-apply with chmod |
| Symlinks | May exist | Flattened to regular files |
| Modification time | Per entry | Set to conversion time (Date.now) |
| Empty directories | Stored as placeholders | Dropped — only files written |
| File contents | Compressed | Identical bytes, re-GZIPped at level 6 |
Cookbook
Conversions framed for container and Linux work, with the post-extract steps that keep your image correct.
Vendor SDK ZIP into a Docker build context
A partner shipped sdk.zip; your Dockerfile wants a tarball to ADD. Convert, then fix the one binary's bit.
Convert: sdk.zip → sdk.tar.gz (browser, 0 bytes uploaded) Dockerfile: ADD sdk.tar.gz /opt/sdk/ # everything extracted at 0644 RUN chmod +x /opt/sdk/bin/cli Verify in image: $ ls -l /opt/sdk/bin/cli → -rwxr-xr-x
Windows CI artifact (zip) to a Helm-friendly tarball
Frontend built on Windows CI emits a .zip. The chart packaging step expects TAR.GZ.
frontend-dist.zip → frontend-dist.tar.gz tar -tzf frontend-dist.tar.gz index.html assets/app.js assets/app.css # ready to embed in the chart's files/
A 7z vendor drop on an agent with no p7zip
The drop arrived as .7z; the agent has no 7-Zip. The browser WASM reader converts it to the TAR.GZ the pipeline wants.
vendor-bits.7z → vendor-bits.tar.gz (WASM reader) In the pipeline: tar -xzf vendor-bits.tar.gz -C /build/vendor chmod -R u+rwX,go+rX /build/vendor
Strip the wrapper folder before converting
The ZIP nests everything under release-2.4.0/. The Dockerfile wants files at the context root, so strip first, then convert.
Step 1: path-prefix-remover on release.zip strips release-2.4.0/ → flat.zip Step 2: zip-to-tar-gz on flat.zip → flat.tar.gz tar -tzf flat.tar.gz → app.js, package.json (no wrapper)
Checksum the shipped tarball for the supply chain
Record the SHA-256 of the exact artifact you ship. Re-converting changes the hash (mtime), so checksum once and keep that file.
Convert once: build.zip → build.tar.gz checksum-generator (SHA-256) → 9f2c…ab routed into manifest Do NOT re-run the conversion expecting the same hash: the TAR mtime = Date.now(), so the digest changes each run.
Edge cases and what actually happens
Executable bit lost on a binary
Not preservedEvery TAR entry is written at mode 0644, so a binary or shell script that was executable in the source is no longer marked executable. In a container this means permission denied at runtime unless you chmod +x after extraction. Always re-apply +x in a RUN step or entrypoint.
Symlinks in the source archive
FlattenedThe reader resolves symlinks to their target bytes, so the TAR contains duplicated regular files instead of links. For images that rely on symlinked libs (e.g. libfoo.so → libfoo.so.1), recreate the links in the Dockerfile after extracting.
Reproducible image layers
Not reproducibleThe TAR mtime is the conversion time, so the tarball — and any layer built from it — differs between runs, breaking layer caching and bit-for-bit reproducibility. For reproducible builds, generate the tarball on the CLI with --mtime/--owner=0, or normalise timestamps before/after as a separate step.
Encrypted vendor ZIP
RejectedPassword-protected vendor drops fail here — no password field. Decrypt with the vendor's instructions first, or extract with the multi-format extractor (which has a password input) and repackage.
Wrapper directory not at the path your Dockerfile expects
By designThe tool preserves the ZIP's internal paths exactly, including a leading package/ or sdk-x.y.z/ folder. If ADD/COPY expects files at the root, strip the prefix with the path prefix remover on the ZIP before converting.
`__MACOSX/` and `.DS_Store` from a Mac-zipped drop
Carried throughZIPs created on macOS include __MACOSX/ resource-fork entries and .DS_Store files; they pass straight into the TAR as regular files and pollute your image. Filter them out before converting, or rm -rf __MACOSX */.DS_Store after extraction.
Empty directories the image needs
DroppedIf your runtime expects an empty /var/cache/app directory to exist, note the converter drops empty folder entries. Create the directory explicitly in the Dockerfile (RUN mkdir -p /var/cache/app) rather than relying on the tarball to carry it.
Archive over the tier cap on a small free account
Blocked (limit)Large layer bundles exceed 50 MB free / 500 MB Pro. The size check fires before processing with an explicit message. Use a higher tier, or for multi-gigabyte artifacts fall back to the CLI on the build agent.
Highly compressed ZIP that expands to gigabytes
May fail (memory)Conversion is in-memory and decompresses fully. A small ZIP that inflates to several GB can crash the tab. On an agent, the streaming CLI is safer for such artifacts; the browser is for the common MB-to-hundreds-of-MB case.
Output verified before pipeline entry
RecommendedBefore the tarball enters your supply chain, list it (tar -tzf), test integrity with the archive integrity tester, and record a SHA-256 from the checksum generator. Treat the converted artifact as the source of truth, not a re-run.
Frequently asked questions
Will the converted TAR.GZ work with Docker ADD?
Yes. ADD app.tar.gz /dest/ auto-extracts standard gzipped tarballs, and that's exactly what this tool produces (ustar TAR in GZIP level 6). The catch: extracted files are mode 0644, so chmod +x any binaries in a subsequent RUN step.
Does it preserve executable permissions for my binaries?
No. Every TAR entry is written at mode 0644 because ZIP doesn't expose Unix mode bits cleanly. Re-apply executable bits after extraction: RUN chmod +x /path/to/binary in the Dockerfile, or set mode: on an Ansible unarchive task.
Can I get reproducible tarballs for cached layers?
Not from this tool — it stamps the conversion time as the mtime on every entry, so the bytes (and any layer hash) change each run. For reproducibility, build the tarball on the CLI with --mtime, --owner=0 --group=0 --numeric-owner, and --sort=name.
What if the vendor archive is a .7z or .rar?
Drop it anyway — a libarchive WASM bridge reads 7z, RAR, BZ2, XZ and ISO and converts them to TAR.GZ. You don't need p7zip or unrar installed on the agent. For generic target-format choice, the archive format converter lets you pick TAR.GZ, ZIP or GZIP.
The ZIP nests everything under a version folder — how do I flatten it?
Strip the prefix before converting. Run the ZIP through the path prefix remover to drop the release-x.y.z/ wrapper, then convert the flattened ZIP. The converter itself doesn't restructure paths.
Does it handle encrypted vendor ZIPs?
No — there's no password field, so encrypted archives are rejected with a clear error. Decrypt using the vendor's tooling, or extract with the multi-format extractor which accepts a password, then repackage to TAR.GZ.
Is anything uploaded? We have a no-third-party-upload policy.
Nothing is uploaded. fflate and the WASM reader run in the browser tab; the result panel shows 0 bytes uploaded. The only server-side record is an anonymous usage counter for signed-in users — never file content. This satisfies typical no-upload data-handling policies.
How big an artifact can I convert?
Free caps at 50 MB and 500 entries; Pro at 500 MB / 50,000; Pro-media and Developer at 2 GB / 500,000. Conversion is in-memory, so even within the cap a hugely-expanding archive can strain the tab. Multi-gigabyte layer bundles are better handled by the CLI on the build agent.
What about __MACOSX and .DS_Store junk in Mac-made ZIPs?
Those entries carry through into the TAR as regular files. Remove them before converting (filter the ZIP), or clean up after extraction with rm -rf __MACOSX */.DS_Store so they don't bloat your image.
Will empty directories my app expects survive?
No — the TAR builder only writes file entries, so empty directories are dropped. If your runtime needs an empty dir to exist, create it explicitly in the image (RUN mkdir -p) rather than relying on the tarball.
How do I verify the tarball before it ships?
List it with tar -tzf, run the archive integrity tester to confirm it's well-formed, and record a SHA-256 with the checksum generator. Checksum the exact artifact you ship — re-converting changes the hash because of the mtime.
Can I wire this into CI without uploading?
On paid tiers, pair the @jadapps/runner; jobs route to http://127.0.0.1:9789/v1/tools/zip-to-tar-gz locally so artifacts never leave the agent. GET /api/v1/tools/zip-to-tar-gz returns the (empty) schema — the tool takes no options. See the developer workflow guide.
Privacy first
Every JAD Archive tool runs entirely in your browser using fflate, @zip.js/zip.js, and the libarchive WASM bridge. Your archives never leave your device — verified by zero outbound network requests during processing.