What PrintStash means by a trusted network
A practical look at PrintStash authentication, collection roles, share links, import guards, stored secrets, and the limits of its security model.
PrintStash is built for a household, workshop, or small team on a network you control. It is not designed as a hostile multi-tenant service where unrelated customers share one installation.
That boundary matters. Authentication and access controls still protect the library, but they do not turn a hobby server into a hardened public platform. If the service is reachable from the internet, put it behind TLS, use strong secrets, and keep the host and proxy maintained.
Accounts, tokens, and API keys
The first-run wizard creates the initial admin account, and it is gated by a setup token so the account-creation endpoint is not open to anyone who reaches the port first. With VAULT_SETUP_TOKEN unset, the API generates one per process and logs it while the vault is unconfigured.
Normal sessions use signed JWT access and refresh tokens. VAULT_JWT_SECRET signs those tokens, and the placeholder shipped in .env.example and the Compose files is public, so the API never signs with it: on first boot it generates a real secret and stores it in its own database. Setting the variable yourself is for when you want to own that value. The production Compose file goes further and refuses to start unless you set it, on the grounds that a host you are deliberately exposing should not be running on a secret you never chose.
Automation uses named API keys. A script sends its username and API key to the login endpoint and receives a JWT for subsequent API requests. The raw key is not used directly as a Bearer token. Create keys on a non-admin account when the job does not need administrative access, and revoke keys that are no longer used.
Collection permissions have view, edit, and admin levels. They are checked in the API, not only by hiding controls in the frontend. Administrative actions and changes are recorded in the audit log.
Public share links
A share token grants read access to one model. Links expire, can be revoked, and are view-only unless file downloads are enabled when the link is created. You can also limit which G-code revisions appear.
Only the token hash is stored in the database. Public endpoints re-check that every requested file belongs to the shared model, return the same not-found response for bad, expired, and revoked tokens, and apply per-IP rate limits.
The token is still a bearer credential. Anyone who receives the URL can use it until it expires or is revoked, so set a lifetime that matches the job and avoid posting the link in a public channel.
Imported files and URLs are untrusted
A trusted LAN does not make downloaded files safe. PrintStash applies limits and path checks while importing:
- URL fetches block loopback, private, link-local, and metadata addresses to reduce SSRF risk.
- Supported marketplace domains are matched exactly instead of by a loose suffix.
- ZIP extraction rejects parent-path traversal and limits archive expansion.
- G-code and BGCODE parsers cap lengths and reads so malformed metadata cannot request unbounded memory.
- Mesh preview work is limited by file size, triangle count, available RAM, and render concurrency.
These checks reduce common failure modes. They are not a promise that every parser dependency is free of vulnerabilities. Keep backups and update the containers when fixes are released.
Secrets are not encrypted at rest
Printer credentials, notification tokens, webhook URLs, and similar configuration are stored in the database. They are not protected from an administrator who can read the database or restore a backup. Notification documentation calls this out explicitly.
Treat backups as sensitive data. Limit access to the Docker host and backup bucket, and do not attach untrusted users as installation administrators.
What the model does not cover
PrintStash does not provide end-to-end encryption for stored model files. It does not protect data from a hostile host administrator. Its collection roles are not a substitute for tenant isolation between strangers, and it does not manage TLS certificates itself.
For a normal self-hosted install, use the production Compose file, keep the API container private, and expose only the frontend through a maintained reverse proxy. The reverse proxy guide has working Caddy, Traefik, and nginx examples.