Docker
There is no way to revert after migrating to v2 without a proper backup.
Hosting under a path like https://example.domain/planka is not currently supported.
Consider using a subdomain instead.
Before proceeding, ensure you are running >= 1.26.2 of PLANKA.
If not, update to this version first.
1. Create a Backup
Navigate to the directory containing your docker-compose.yml file.
Database Backup
The instance should be running while performing the backup.
docker compose exec postgres pg_dump -U postgres planka > planka_backup_$(date +%Y%m%d).sql
Volume Backups
Important: Replace the volume names (
planka_user-avatars,planka_attachments,planka_project-background-images) below with the actual volume names used in your setup.After running the commands, verify the created
.tar.gzfiles contain the expected data.
docker run --rm -v $(pwd):/backup -v planka_user-avatars:/data alpine tar -czvf /backup/user-avatars.tar.gz -C /data .
docker run --rm -v $(pwd):/backup -v planka_attachments:/data alpine tar -czvf /backup/attachments.tar.gz -C /data .
docker run --rm -v $(pwd):/backup -v planka_project-background-images:/data alpine tar -czvf /backup/project-background-images.tar.gz -C /data .
2. Stop and Remove Containers
docker compose down
3. Add New Volumes
Update the volumes sections:
services:
planka:
...
volumes:
+ - data:/app/data
- user-avatars:/app/public/user-avatars
- project-background-images:/app/public/project-background-images
+ - background-images:/app/public/background-images
- attachments:/app/private/attachments
...
volumes:
+ data:
user-avatars:
project-background-images:
+ background-images:
attachments:
db-data:
4. Clean Up Environment Variables
Remove Deprecated Variables
Delete the following from your environment section:
ALLOW_ALL_TO_CREATE_PROJECTS— Now managed via user-specific global roles.SLACK_*,GOOGLE_*,TELEGRAM_*— Replaced by in-app notifications with support for 100+ services.TZ- No longer needed, now handled automatically.
Update the TRUST_PROXY Value
Regardless of whether you've previously set the TRUST_PROXY environment variable, you have to ensure it uses the correct boolean string value. If it's currently set to 0, update it to false (even if the variable is commented out). If it's set to 1, update it to true. The use of numeric values (0 or 1) is no longer supported and may lead to unexpected behavior.
Add New Variables
Add these new environment variable if needed:
# - MAX_UPLOAD_FILE_SIZE=
# - STORAGE_LIMIT=
# - ACTIVE_USERS_LIMIT=
# The default application language used as a fallback when a user's language is not set.
# This language is also used for per-board notifications.
# - DEFAULT_LANGUAGE=en-US
# All outgoing HTTP requests (SMTP, webhooks, Apprise notifications, favicon fetching, etc.)
# will be sent through this proxy if set.
# If commented out, an internal Squid proxy will be started inside the container,
# which you can control via OUTGOING_BLOCKED_* and OUTGOING_ALLOWED_* below.
# - OUTGOING_PROXY=http://proxy:3128
# - OIDC_USE_OAUTH_CALLBACK=true
# - OIDC_PROJECT_OWNER_ROLES=project_owner
# - OIDC_BOARD_USER_ROLES=board_user
# - OIDC_DEBUG=true
# - SMTP_NAME=
# Using Gravatar directly exposes user IPs and hashed emails to a third party (GDPR risk).
# Use a proxy you control for privacy, or leave commented out or empty to disable.
# - GRAVATAR_BASE_URL=https://www.gravatar.com/avatar/
# --------------------------------------------------------------------
# Outgoing traffic control (internal Squid proxy)
# --------------------------------------------------------------------
# These IPs/hostnames will always be blocked (highest priority)
# - OUTGOING_BLOCKED_IPS=
# - OUTGOING_BLOCKED_HOSTS=localhost,postgres
# Only these IPs/hostnames will be reachable
# - OUTGOING_ALLOWED_IPS=
# - OUTGOING_ALLOWED_HOSTS=
If you are using S3, OIDC, or other internal integrations, we recommend uncommenting OUTGOING_BLOCKED_HOSTS and adding their hostnames to the blocked list.
5. Pull the Docker Image
Ensure the PLANKA image is set to the latest tag in your docker-compose.yml.
docker compose pull
6. Copy Background Images to New Location
Copy existing background images to the new volume:
docker compose run --rm --user root planka sh -c 'cp -av /app/public/project-background-images/. /app/public/background-images && chown -R node:node /app/public/background-images'
7. Run the Upgrade Script
This must be done before starting PLANKA for the first time.
docker compose run --rm planka npm run db:upgrade
8. Upgrade to New Data Structure
Copy data files to the new unified volume:
docker compose run --rm planka sh -c 'mkdir -p /app/data/protected /app/data/private && for folder in user-avatars background-images; do cp -av /app/public/$folder /app/data/protected; done && cp -av /app/private/attachments /app/data/private'
9. Remove the Old Volume Reference
Update your docker-compose.yml to remove the old volumes:
services:
planka:
...
volumes:
- data:/app/data
- - user-avatars:/app/public/user-avatars
- - project-background-images:/app/public/project-background-images
- - background-images:/app/public/background-images
- - attachments:/app/private/attachments
...
volumes:
data:
- user-avatars:
- project-background-images:
- background-images:
- attachments:
db-data:
10. Restore Due Date Completion States
In the initial v2 release, we removed the due date toggle (because we introduced the Closed list type) and later restored it in the final version. During the upgrade, the field is removed from the database first and then re-added during the post-upgrade migration in a non-completed state.
To restore all completion states, follow these additional steps:
- Run the migration script to apply additional database changes:
docker compose run --rm planka npm run db:migrate
- Generate an SQL file with
UPDATEstatements (replaceplanka_backup_20260212.sqlwith the path to your v1 SQL backup file):
awk '
BEGIN { in_copy=0 }
/^COPY public\.card/ {
split($0, a, "\\(|\\)");
split(a[2], cols, ", ");
for(i in cols) gsub("\"","",cols[i]);
for(i in cols) col_index[cols[i]]=i;
in_copy=1; next
}
in_copy && $0=="\\." { in_copy=0; next }
in_copy {
n=split($0, vals, "\t");
id=vals[col_index["id"]];
val=vals[col_index["is_due_date_completed"]];
if(val=="t") val="TRUE";
else if(val=="f") val="FALSE";
else next;
printf "UPDATE card SET is_due_completed = %s WHERE id = ''%s'';\n", val, id
}
' planka_backup_20260212.sql > due_completion_fix.sql
- Execute the SQL updates:
docker compose up -d postgres && cat due_completion_fix.sql | docker compose exec -T postgres bash -c 'until pg_isready -U postgres; do sleep 2; done; psql -U postgres -d planka'
- Remove the generated file:
rm due_completion_fix.sql
11. Start PLANKA and Verify
Start PLANKA:
docker compose up -d
Monitor logs for issues:
docker compose logs -f
Verify:
- Application starts successfully
- You can log in
- Projects, boards, and cards are displayed
- All uploaded images and files appear correctly
12. Clean Up
Once confirmed everything works, remove the old volumes:
docker volume rm planka_user-avatars planka_project-background-images planka_background-images planka_attachments
Troubleshooting
If you encounter issues:
- Check logs with
docker compose logs -f planka - Ensure every command completed successfully
- If necessary, restore from your backup and try again