// install & deploy / manual

Configure PlikShare manually.

Skip the install scripts and run the Docker image directly. Reference for every environment variable, the storage volume layout, file permissions and how updates work.

Using the Docker image directly

PlikShare is published as a Docker image on Docker Hub for both AMD64 and ARM64. Pair it with the reverse proxy of your choice (or none, if you're terminating TLS elsewhere).

Docker Compose configuration

A Docker Compose configuration with every key setting documented inline:

Getting started

  1. Create a docker-compose.yml file with the configuration above.
  2. Adjust the environment variables to your needs.
  3. Ensure the local directories for the volumes exist.
  4. Set the correct permissions on the volume directories.
  5. Run docker compose up -d to start PlikShare.

Note: this setup does not include SSL/TLS. For production, put a reverse proxy like Caddy, Nginx with Let's Encrypt, or a Cloudflare Tunnel in front for HTTPS — or use one of the install scripts that wire all of that up for you.

Configuration reference

PlikShare reads its bootstrap configuration from environment variables. Every key carries the PlikShare_ prefix, and a double underscore __ marks a nested section. In the Compose file above, an entry written as - PlikShare_AppUrl (no value) is passed through from the host environment, while - PlikShare_Volumes__Path=volumes sets the value inline.

Storage, email and SSO are not configured here. Storage backends (S3, R2, Azure, GCS…), email providers and SSO / OIDC are set up inside the running app by an administrator. The variables below only bootstrap the instance itself.

Required

PlikShare_AppUrlrequired
The public URL the instance is served from, e.g. https://plikshare.yourdomain.com. Used for CORS and for the links generated in emails and shares.
PlikShare_AppOwnersrequired
Comma-separated email addresses of the administrator accounts. At least one is required. The app refuses to start without it.
PlikShare_AppOwnersInitialPasswordrequired
Initial password for the administrator accounts above. Minimum 8 characters, with at least one uppercase letter, one lowercase letter, one number and one special character. Change it after the first sign-in.
PlikShare_EncryptionPasswordsrequired
Master password(s) used to encrypt sensitive data at rest. Start with one strong, unique value. To rotate, append new passwords separated by commas (old,new) - never remove an old one, or data encrypted with it becomes unrecoverable. These cannot be recovered if lost. Keep them safe.

Storage volumes

A volume is a directory on the server's own disk, mounted into the container. PlikShare always has one main volume - it holds the application's SQLite database and legal documents - and you can register any number of additional volumes alongside it.

Volumes are what the hard-drive storage backend runs on. When an administrator creates a hard-drive storage inside the app, they pick a volume and a folder within it; every file uploaded to a workspace on that storage is then written into that directory. Adding more volumes lets you spread file storage across separate disks - for example, keep the database on the small system disk and mount a large data disk as its own volume purely for files.

Cloud storages don't use volumes. S3, Cloudflare R2, Azure Blob, Backblaze B2 and the other object-store backends keep their files at the provider. Volumes back only the hard-drive storage type. The main volume is still always required, because the database lives there.
PlikShare_Volumes__Pathrequired
Base directory inside the container that holds every volume. The install script uses volumes.
PlikShare_Volumes__Main__Pathrequired
Sub-directory of the base path for the main volume. It stores the SQLite database and legal files. The install script uses main.
PlikShare_Volumes__Other__0__Pathoptional
Additional volumes used for file storage, indexed from 0 and numbered consecutively (__0__, __1__, …). Each needs its own host directory mounted into the container. Optional - an instance can run on the main volume alone.

Host vs. container, and what ./plikshare_data is

PlikShare runs inside a container: an isolated environment with its own throwaway filesystem. Anything written into that filesystem is lost the moment the container is recreated, which happens on every update. To survive, data has to live on the host - your actual server - instead.

A mount bridges the two. Each line under volumes: has the form host_path : container_path : mode. Take the first one from the Compose file above:

./plikshare_data : /app/volumes/main : rw
  • ./plikshare_data - a folder on the server itself. The ./ means “next to the docker-compose.yml file”, and the name is just this example's choice. It could be plikshare-db or any path you like. This folder is where your data physically lives on the server's disk. You create it before the first start, and it stays untouched when the container is updated or recreated.
  • /app/volumes/main - where that same folder appears inside the container. This is the only side PlikShare itself ever sees.
  • rw - mounted read & write, so PlikShare can both store and read files there.

The PlikShare_Volumes__* variables then tell PlikShare which container paths to treat as volumes. They are relative to the app's working directory /app, so Volumes__Path=volumes plus Volumes__Main__Path=main resolve to /app/volumes/main, exactly the container side of that mount. The two sides have to agree:

Container pathDeclared by (environment)Mounted from host (volumes:)
/app/volumes/mainPlikShare_Volumes__Path=volumes
PlikShare_Volumes__Main__Path=main
./plikshare_data:/app/volumes/main:rw
/app/volumes/volume_1PlikShare_Volumes__Other__0__Path=volume_1./plikshare_volume_1:/app/volumes/volume_1:rw
/app/volumes/volume_2PlikShare_Volumes__Other__1__Path=volume_2./plikshare_volume_2:/app/volumes/volume_2:rw
The rule: every volume in the environment variables needs a matching volumes: mount pointing at the exact same /app/volumes/… path. If they don't line up, PlikShare writes files to a path that isn't persisted, and that data is gone the next time the container is recreated. The host side of a mount (left of the colon) is yours to choose; the container side (right) must match the resolved volume path.

File permissions - the non-root user

For security, the PlikShare image runs as a non-root user with the fixed ID 5678 - no root rights, no shell, no home directory. The user: "5678:5678" line in the Compose file pins the container to that account.

The consequence: every host directory you mount must be owned by user 5678, otherwise PlikShare cannot write to it and fails to store data. Set that up on the host before the first start:

sudo chown -R 5678:5678 ./plikshare_data ./plikshare_volume_1 ./plikshare_volume_2
sudo chmod -R 755 ./plikshare_data ./plikshare_volume_1 ./plikshare_volume_2

The installation scripts do this for you automatically. It only needs your attention with the manual Docker setup.

Optional - tuning & advanced

ASPNETCORE_URLSdefault: http://+:8080
Address and port the server listens on inside the container. Standard ASP.NET Core variable. Note it has no PlikShare_ prefix.
ASPNETCORE_ENVIRONMENTdefault: Production
Selects the settings profile. Leave it as Production for a normal deployment.
PlikShare_ForcePasswordLoginEnableddefault: false
When true, email-and-password login is always available, even if an administrator disabled it in-app (for example to enforce SSO-only sign-in). When false, password login follows the in-app setting.
PlikShare_Queue__ProcessingBatchSizedefault: 30
How many background jobs the queue pulls per batch.
PlikShare_Queue__ParallelConsumersNumberdefault: 5
Number of background-job consumers running in parallel.
PlikShare_Trash__IntervalSecondsdefault: 3600
How often the trash sweeper runs and permanently purges files whose retention window has elapsed.
PlikShare_Trash__MaxItemsPerWorkspacePerTickdefault: 5000
Cap on files purged per workspace per sweep, so one large trash backlog cannot starve other workspaces. Leftovers are picked up on the next tick.

Updating PlikShare

PlikShare ships as a versioned Docker image, so updating means pulling the newer image and recreating the container. Your data lives on the mounted volumes, so it is left untouched:

docker compose pull plikshare
docker compose up -d --no-deps plikshare

--no-deps recreates only the PlikShare container and leaves everything else (such as a reverse proxy) running. The install scripts can also schedule this as a nightly cron job, so updates happen automatically.

// talk to a human

Rather not run it yourself?

If you'd like a hand getting PlikShare running, or you want it fully managed by someone else, let's have a quick chat.

  • Initial setup on your server - Docker, SSL, reverse proxy
  • Storage (S3 / R2 / B2 / Azure / GCS) and email provider
  • Ongoing updates, backups and migrations