Exploring Open Source Project Management Systems - Vikunja
I have been looking to implement a project management solution that works effectively at both the individual and team level, and I reviewed several open-source platforms to assess their suitability. My goal was to find a tool that balances functionality with ease of use, even for non-technical or non-PM users.
Evaluation Criteria:
- User-Friendly Interface: The platform should be intuitive and easy to use for team members without technical backgrounds. The tool must be flexible enough to manage projects that are not related to software development.
- Gantt Chart Support: A visual way to track project timelines is essential.
- Notifications and Alerts: The platform should be able to send automated reminders for due dates and notifications for mentions.
- Multi-Team Management: The tool should support the coordination of multiple teams working on different projects.
Tools Evaluated:
- Wekan
- Pros: Decent feature set.
- Cons: Outdated UI and navigation options. While custom themes can address these issues, I expected better out-of-the-box usability.
- Redmine
- Pros: Useful for software development tracking.
- Cons: Severely outdated interface and navigation focused primarily on development workflows.
- Zentao
- Pros: Clean layout.
- Cons: Limited translation support, which makes it challenging to use for non-Chinese speakers. Heavily focused on software development.
- Focalboard
- Pros: Modern design and easy to use.
- Cons: Lacks collaboration options, making it difficult to manage team projects effectively. More importantly, the project is no longer developed.
- Planka
- Pros: Amazing tool for personal projects or small-scale use.
- Cons: Gets cluttered and inefficient when multiple people work on a larger project.
- OpenProject
- Pros: Decent range of features.
- Cons: Many key features are locked behind a paid tier, reducing its value as a free solution.
- Plane
- Cons: Was unable to deploy due to poor documentation. Way too many docker containers are required for it to operate.
- Kanboard
- Pros: Strong feature set.
- Cons: Outdated interface and cumbersome navigation make it impractical for production use.
- Leantime
- Pros: Offers a flexible project management setup.
- Cons: Provides too many irrelevant options by default. The platform is largely marketed toward ADHD users, so this might be expected.
- Taiga
- Cons: Could not deploy successfully despite multiple attempts using the official guide. Documentation needs improvement.
- Vikunja
- Pros: Combines Kanban, Gantt charts, and basic collaboration options. Supports email notifications and has good project tracking capabilities.
- Cons: Self-hosted version has limited user management options, which must be configured via the command line (relatively easy to automate, though).
I found Vikunja to be the best "middle-ground" solution. It offers a good balance of features—Kanban boards, Gantt charts, and email notifications—making it a suitable choice for both individuals and teams. The only drawback is that user management in the self-hosted version requires command-line interaction, but this can be streamlined through automation.
Focalboard:
version: '2'
services:
focalboard:
image: mattermost/focalboard:latest #the Docker image for Focalboard that we are using
container_name: focalboard
volumes:
- focalboard:/data
ports:
- "3020:8000" #any port that you have free in your machine
restart: always
volumes:
focalboard:
Kanboard:
services:
kanboard:
image: kanboard/kanboard:latest
restart: always
ports:
- "8091:80"
- "8092:443"
volumes:
- kanboard_data:/var/www/app/data
- kanboard_plugins:/var/www/app/plugins
- kanboard_ssl:/etc/nginx/ssl
volumes:
kanboard_data:
driver: local
kanboard_plugins:
driver: local
kanboard_ssl:
driver: local
Planka:
version: '3'
services:
planka:
image: ghcr.io/plankanban/planka:latest
restart: always
volumes:
- user-avatars:/app/public/user-avatars
- project-background-images:/app/public/project-background-images
- attachments:/app/private/attachments
ports:
- 3010:1337
environment:
- BASE_URL=https://yourdomain.com
- DATABASE_URL=postgresql://postgres@postgres/planka
- SECRET_KEY=
- TRUST_PROXY=1
- TOKEN_EXPIRES_IN=365 # In days
# related: https://github.com/knex/knex/issues/2354
# As knex does not pass query parameters from the connection string we
# have to use environment variables in order to pass the desired values, e.g.
# - PGSSLMODE=<value>
# Configure knex to accept SSL certificates
# - KNEX_REJECT_UNAUTHORIZED_SSL_CERTIFICATE=false
- [email protected] # Do not remove if you want to prevent this user from being edited/deleted
- DEFAULT_ADMIN_PASSWORD=strongpassword
- DEFAULT_ADMIN_NAME=Your Name
- [email protected]
# - ALLOW_ALL_TO_CREATE_PROJECTS=true
# - OIDC_ISSUER=
# - OIDC_CLIENT_ID=
# - OIDC_CLIENT_SECRET=
# - OIDC_ID_TOKEN_SIGNED_RESPONSE_ALG=
# - OIDC_USERINFO_SIGNED_RESPONSE_ALG=
# - OIDC_SCOPES=openid email profile
# - OIDC_RESPONSE_MODE=fragment
# - OIDC_USE_DEFAULT_RESPONSE_MODE=true
# - OIDC_ADMIN_ROLES=admin
# - OIDC_EMAIL_ATTRIBUTE=email
# - OIDC_NAME_ATTRIBUTE=name
# - OIDC_USERNAME_ATTRIBUTE=preferred_username
# - OIDC_ROLES_ATTRIBUTE=groups
# - OIDC_IGNORE_USERNAME=true
# - OIDC_IGNORE_ROLES=true
# - OIDC_ENFORCED=true
# Email Notifications (https://nodemailer.com/smtp/)
- SMTP_HOST=smtp.office365.com
- SMTP_PORT=587
- SMTP_NAME=IT
- SMTP_SECURE=true
- [email protected]
- SMTP_PASSWORD=strongpassword
- SMTP_FROM="Your Name" <[email protected]>
# Optional fields: accessToken, events, excludedEvents
# - |
# WEBHOOKS=[{
# "url": "http://localhost:3001",
# "accessToken": "notaccesstoken",
# "events": ["cardCreate", "cardUpdate", "cardDelete"],
# "excludedEvents": ["notificationCreate", "notificationUpdate"]
# }]
# - SLACK_BOT_TOKEN=
# - SLACK_CHANNEL_ID=
depends_on:
postgres:
condition: service_healthy
networks:
- shared_network
postgres:
image: postgres:14-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=planka
- POSTGRES_HOST_AUTH_METHOD=trust
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d planka"]
interval: 10s
timeout: 5s
retries: 5
networks:
- shared_network
volumes:
user-avatars:
project-background-images:
attachments:
db-data:
networks:
shared_network:
external: false
And finally, Vikunja:
services:
vikunja:
image: vikunja/vikunja
environment:
VIKUNJA_SERVICE_PUBLICURL: https://yourdomain.com
VIKUNJA_DATABASE_HOST: vikunja-db
VIKUNJA_DATABASE_PASSWORD: "strongpassword"
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_USER: vikunja
VIKUNJA_DATABASE_DATABASE: vikunja
VIKUNJA_SERVICE_JWTSECRET: "strongpassword"
VIKUNJA_SERVICE_ENABLETASKATTACHMENTS: 0
VIKUNJA_SERVICE_ENABLEREGISTRATION: 0
VIKUNJA_SERVICE_ENABLEEMAILREMINDERS: 1
VIKUNJA_MAILER_ENABLED: true
VIKUNJA_MAILER_AUTHTYPE: login
VIKUNJA_MAILER_HOST: smtp.office365.com
VIKUNJA_MAILER_PORT: 587
VIKUNJA_MAILER_FROMEMAIL: [email protected]
VIKUNJA_MAILER_USERNAME: [email protected]
VIKUNJA_MAILER_PASSWORD: strongpassword
VIKUNJA_DEFAULTSETTINGS_EMAIL_REMINDERS_ENABLED: true
VIKUNJA_DEFAULTSETTINGS_DISCOVERABLE_BY_NAME: true
VIKUNJA_DEFAULTSETTINGS_DISCOVERABLE_BY_EMAIL: true
VIKUNJA_DEFAULTSETTINGS_OVERDUE_TASKS_REMINDERS_ENABLED: true
VIKUNJA_DEFAULTSETTINGS_WEEK_START: 1
VIKUNJA_SERVICE_CUSTOMLOGOURL: https://domain.com/logo.png
ports:
- 3456:3456
volumes:
- app:/app/vikunja/files
depends_on:
vikunja-db:
condition: service_healthy
restart: unless-stopped
networks:
- shared_network
vikunja-db:
image: postgres:16
environment:
POSTGRES_PASSWORD: "strongpassword"
POSTGRES_USER: vikunja
volumes:
- vikunja-db:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"]
interval: 2s
networks:
- shared_network
volumes:
vikunja-db:
app:
networks:
shared_network:
external: false
I do want to highlight that Vikunja does not have a management UI for user management (or any management at all). All system-wide changes are based on CLI commands. To simplify usage, I leveraged n8n automations to provision and deprovision user accounts easily.
User creation:
docker exec -i vikunja-vikunja-1 /app/vikunja/vikunja user create -u {{ $json.username }} -e {{ $json.email }} -p "{{ $json.password }}"
User deprovisioning is more complicated as users are assigned a system ID. This system ID must be extracted first in order to manipulate the account: