Stacks are the feature that turns Portainer from a viewer into a deployer, and once the pattern clicks you can install nearly anything the self-hosted world publishes, because nearly everything publishes a docker-compose file and a stack is exactly that: a compose file Portainer runs and then manages as one unit.
Learn it once and "how do I install Planka with Portainer" and "immich on portainer" and every future variant become the same five-minute answer. So here's the once: a complete worked example with Planka (the self-hosted Trello people keep asking about), then the general recipe, then the app-specific notes for the usual suspects.
Install Planka with a Portainer stack, start to finish
Planka wants two containers (the app plus Postgres), which makes it a perfect first stack: real enough to teach the pattern, small enough to read in one screen.
Create the stack
In Portainer: Stacks » Add stack, name it planka, choose the web editor and paste a compose definition based on Planka's official one:
services:
planka:
image: ghcr.io/plankanban/planka:latest
restart: always
ports:
- "3015:1337"
environment:
- BASE_URL=http://YOUR_SERVER_IP:3015
- DATABASE_URL=postgresql://postgres@postgres-server/planka
- SECRET_KEY=CHANGE_ME_LONG_RANDOM
depends_on:
- postgres-server
volumes:
- planka-favicons:/app/public/favicons
- planka-user-avatars:/app/public/user-avatars
- planka-background-images:/app/public/background-images
- planka-attachments:/app/private/attachments
postgres-server:
image: postgres:16-alpine
restart: always
environment:
- POSTGRES_DB=planka
- POSTGRES_HOST_AUTH_METHOD=trust
volumes:
- planka-db:/var/lib/postgresql/data
volumes:
planka-favicons:
planka-user-avatars:
planka-background-images:
planka-attachments:
planka-db:
Before deploying, edit the two values that are yours: BASE_URL to the address users will visit (your domain once a proxy fronts it) and SECRET_KEY to a long random string (openssl rand -hex 32 makes a good one). Always check the app's own repository for the current compose reference too; projects move, and their README outranks any tutorial's snapshot, mine included.
Deploy and create the admin
Hit Deploy the stack. Portainer pulls the images, wires the containers onto a shared network (note how DATABASE_URL just says postgres-server; container names resolve inside a stack) and both go green in the stack view. Current Planka versions have you create the first admin account on the welcome screen at first visit, so open http://YOUR_SERVER_IP:3015 promptly and claim it. You now have a kanban board whose data lives on your own disk.
Manage it as a unit
The stack view is the payoff: logs per container, restart the whole app in one action, and the editor holds your compose definition for tweaks. Redeploying after an edit recreates only what changed. Updates ride the Update the stack button with re-pull enabled, the flow our Portainer update guide covers alongside its warnings about :latest tags, which apply to the Planka image above verbatim.
The general recipe for any app
Every stack deployment is the same six decisions, and after Planka you've made them all once. Find the project's official compose file. Paste it into a new stack. Change the host-side ports if they collide with anything (left side only). Replace every CHANGE_ME (secrets, passwords, base URLs). Swap bind-mount paths for named volumes or real paths you chose deliberately, because "wherever the tutorial's author kept files" is not a storage plan. Deploy, then check the logs of anything that isn't green. That's the entire craft; the rest is app-specific seasoning.
Two Portainer-specific habits upgrade the experience. Use the environment variables section of the stack editor for secrets instead of hardcoding them into the compose text, which keeps the definition shareable. And when an image lives somewhere that needs login (GHCR private images, Docker Hub rate limits), add the registry once under Registries with a token, and every stack pull on the machine authenticates automatically from then on.
App notes for Immich, n8n, Nextcloud and NetBox
Immich deploys fine as a stack (four containers, one compose file) with one strong caveat: use the release's own compose file and .env, never a simplified copy, because the project evolves fast. Our Immich install guide covers the variables that matter; in Portainer, its .env contents go into the stack's environment variables section. n8n is a gentle single-container stack for starters (the n8n self-hosting guide has the full production shape with Postgres and workers when you outgrow that). Nextcloud and NetBox both follow the Planka pattern exactly, app plus database, with NetBox adding Redis; their official compose files paste in clean. The through-line: nothing here needed a Portainer-specific tutorial, which was the point of learning the pattern.
Verify a stack the same way every time
Green containers in the stack view, the app answering on its port, and logs free of restart loops; those three checks catch practically every failed deploy, and the log line names the cause when one fails (a taken port, a missing secret, a typo'd volume path lead the league). Stacks also make the cleanup honest: removing one removes its containers and networks together, with volumes preserved unless you tick otherwise.
It's tidy enough that trying apps stops feeling like commitment, and that, more than the buttons, is what Portainer stacks change about self-hosting on a Portainer VPS: the cost of "let's just see" drops to nearly nothing.

