Zipline: a ShareX server that publishes no image for a CPU without AVX
A ShareX/file upload server that is easy to use, packed with features, and with an easy setup!
At a glance
- What is it?
- Zipline is a TypeScript file upload server with a Docker-first setup, a Postgres backend and optional S3 storage. Its documentation is unusually complete about configuration and unusually quiet about two things: the compose file it prints is not the one in the repository, and the hardware floor has no fallback.
- Who is it for?
- Zipline suits someone self-hosting a screenshot or file server for a small group, who is comfortable with a compose file and wants quotas, invites and passkeys rather than a bare upload endpoint. Four things to check first.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The compose file on the page is not the compose file in the tree
The documentation prints a two service compose file as the recommended setup, and if you copy it you get something that will not work. The page's version gives the database service in full: an image tag, a restart policy, an environment file, the three credential variables with defaults, a named volume for the data directory, and a readiness check that runs the database's own readiness command against a fixed user on a ten second interval. The application service in that snippet has an environment block with nothing in it, no volumes, no health check, and no declared dependency on the database. The compose file actually in the repository has all of those: the database URL assembled from the same variables, a dependency declared on the database becoming healthy before the application starts, three volume mounts for uploads, public assets and themes, and a health check that fetches an API endpoint over HTTP. The page has drifted from the file it is quoting.
There is no image for a CPU without AVX
One warning on the page is a hardware statement rather than a configuration one: the project requires a CPU with AVX support and does not provide binaries or images with support for non-AVX processors. That is stated in a single sentence and it is the most consequential line in the documentation, because there is no workaround offered and no alternative path named. A source build is not presented as an option for that case either; the manual install section points at the documentation site rather than describing a build that avoids the constraint. So the population of machines this software cannot run on is defined by a processor feature rather than by anything a user can configure, and the failure would surface as an unsupported-instruction error at startup rather than as a message from the application. It is worth checking the flag on your hardware before you read any further, because everything else on the page assumes you pass.
The generated secret is 32 characters because the example comment says so
Secret generation is handled with two shell commands that write an environment file, one for the database password and one for the application secret:
echo "POSTGRESQL_PASSWORD=$(openssl rand -base64 42 | tr -dc A-Za-z0-9 | cut -c -32 | tr -d '\n')" > .env
echo "CORE_SECRET=$(openssl rand -base64 42 | tr -dc A-Za-z0-9 | cut -c -32 | tr -d '\n')" >> .envEach one asks the system random source for base64 output, strips everything that is not a letter or a digit, cuts the result to thirty two characters and removes the trailing newline, with the first line of the file written and the second appended. Thirty two characters is not arbitrary and the page explains it a few paragraphs later: the example environment file describes the secret as a secret that is 32 characters long. Then comes the hard requirement, stated on its own line, that without the application secret variable the server will not start. The database password variable is equally mandatory, enforced in the compose file itself with an expansion that treats an empty value as an error rather than defaulting it.
Out of the box the service binds to every interface and the image tag moves
Two defaults combine into a security surface that the documentation describes without flagging. The application binds to all interfaces on port three thousand, and the compose file publishes that port on the host, so a default install is reachable from the local network rather than only from the machine. The page then explains how to change both the port and the hostname through environment variables, which is the mitigation, but it presents the change as a convenience rather than as something to do before first run. The second default is the image reference, which is an unpinned latest tag on the project's own registry. So a compose start may pull a build different from the one you tested last week, and the project knows it: the bug report template asks you to include the image digest or tag if you can, and the development build script passes the current commit hash into the image as a build argument.
The development script opens a Node inspector on every interface
The development scripts come in three variants in the package manifest, and the third one is the interesting one. There is a normal development script that sets the debug namespace and runs the server through a TypeScript loader with source maps, a variant without the debug flag, and a third that additionally passes an inspector option bound to all interfaces on a fixed port. That third script is a debugging session, and binding it to every interface rather than to loopback means anything that can reach your development machine can attach to the running process and evaluate code in it. This is a development-only script rather than the production start script, which does not carry the flag, so the exposure is limited to people running the development environment on a shared or untrusted network. It is still the kind of default that costs nothing to tighten and everything if ignored.
The runtime image inherits the build toolchain it stopped needing
The container build is a multi-stage file on an Alpine based Node image, and the stages are arranged in a way that is worth tracing. The base stage enables the package manager's corepack integration and installs two system packages, a media tool and the timezone database. A dependencies stage installs production dependencies only with a frozen lock file and a mounted cache. A builder stage installs the full dependency set the same way, copies the source and a list of individual configuration files one at a time, and runs the build with an environment flag set. The final stage is built from the base image again, not from something slimmer, and takes the production dependencies and the build output from the earlier stages. The result is that the shipped image carries the package manager integration and the toolchain layer from the base, which the finished server does not use, in exchange for the media tool that the video thumbnail feature does.
There is no upgrade path from the third major version
The migration section is one paragraph and it is unambiguous. The fourth version was a complete rewrite, there is no upgrade path from the third, and the only route is to export the data from the old version and import it into the new one. The project does soften that by shipping a built-in importer for the previous version's data, which is the difference between a migration tool and a manual conversion. What it does not describe is what the import covers, how long it takes on a large library, or whether anything is dropped in translation, and those are the three questions anyone with an existing library will have. The rewrite framing also explains the feature list's shape: the third major's capabilities are not carried forward item by item, so a feature that mattered to you may simply be absent in the fourth rather than configurable off.
Two separate tooling binaries, a schema tool, and a branch called trunk
The repository root describes a toolchain with more moving parts than the average TypeScript service, and each one is a signal about how the project is run. Formatting and linting are two different programs from the same family, configured in separate files at the root, rather than one linter with a formatter mode. The database is handled by a schema-definition tool with its own configuration file and a migrations directory, and the manifest offers two distinct workflows for it, one that pushes the schema straight to the database and one that generates migration files. The build is driven by a bundler configured in TypeScript with a build script on top, and tests run on Node's own test runner through a TypeScript loader with a custom reporter living in the source tree. The default branch is called trunk rather than main. None of this is a problem; together it explains why the project ships a Nix flake and a direnv file.
Editorial conclusion
Zipline suits someone self-hosting a screenshot or file server for a small group, who is comfortable with a compose file and wants quotas, invites and passkeys rather than a bare upload endpoint. Four things to check first. The CPU must support AVX, and the project publishes no binaries or images for hardware that does not, so on such a machine there is no supported path at all. The compose file printed in the page is incomplete relative to the one in the repository, so copy from the repository rather than from the documentation. The image reference is an unpinned latest tag, which is why the project's own bug report template asks you for a digest. And there is no upgrade path from the third major version, only an export and import through a built-in importer.
Frequently asked questions
How do I install and run Zipline?
Docker is the recommended route and the documented compose file starts a Postgres service and the server together. Generate the two required secrets into an environment file first, using the page's openssl based commands, because the server will not start without the application secret and the compose file treats an empty database password as an error. Then start with `docker compose up -d` and open the site on port 3000. A manual install is documented separately on the project site.
What hardware does Zipline need?
A CPU with AVX support. The page states this as a warning and says explicitly that no binaries or images are provided for processors without it. No alternative build path is offered for that case, so on such hardware there is no supported way to run the project.
Can Zipline store uploads in S3 instead of on disk?
Yes, by setting the datasource type to s3 and supplying an access key id, a secret access key, a bucket and a region. The example values name a bucket and a west coast region. The documentation site describes additional storage providers beyond S3. Temporary files default to a subdirectory of the uploads folder, and the page notes that moving them to another filesystem such as a memory-backed one can reduce local upload performance.
How do I upgrade from Zipline v3 to v4?
There is no upgrade path, because v4 was a complete rewrite. You have to export your data from v3 and import it into v4, and the project ships a built-in importer for that data. The page does not describe what the import covers or what, if anything, is lost in translation.
What are Zipline's security-relevant defaults?
The server binds to all interfaces on port 3000 by default and the compose file publishes that port, so a fresh install is reachable from the local network; both are changeable through environment variables. The compose file also references the image by an unpinned latest tag, which is why the project's own bug report template asks you to include the image digest. Password protection, two factor authentication, passkeys, OAuth2, invites and quotas are all on the feature list.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/diced-zipline)