Backlog · Board · Releases · Code reviews · Wiki — self-hosted on .NET and SQL Server
Live demo · Documentation · Quick start · Changelog · Discussions
Taskist is a self-hosted task, change request and bug tracker built with ASP.NET Core MVC and Microsoft SQL Server. Plan work on a backlog and board, ship it in versioned releases, review merge requests from GitHub or GitLab, and keep your team's knowledge in a built-in wiki — without per-seat pricing.
Why Taskist?
- Yours to run — MIT-licensed and self-hosted; your data stays in your own SQL Server.
- Code-aware — branches, merge/pull requests, reviews and issue sync for GitHub and GitLab, cloud or self-hosted.
- Ready in minutes — one
docker compose upgives you the app, the database and a seeded admin. - Secure by default — PBKDF2 passwords, encrypted secrets, permission-checked attachments and hardened outbound requests (SECURITY.md).
|
📋 Work items
|
🔗 Code
|
|
👥 Team
|
⚙️ Administration
|
Built with ASP.NET Core MVC (.NET 10) · EF Core 10 · SQL Server 2019+ · Hangfire · Mapperly · FluentValidation · CoreUI + Bootstrap 5 · ClosedXML — every front-end library vendored locally, no CDN.
Requires Docker Desktop or Docker Engine with Compose v2.
git clone https://github.com/Taskist/taskist.git
cd taskist
cp .env.example .env # then set a strong MSSQL_SA_PASSWORD
docker compose up -dOpen http://localhost:8080 and sign in as admin@taskist.org / Admin@123.
Warning
Change the admin password right after the first sign-in, and never expose the seeded account on a reachable network.
- Set
SEED_DUMMY_DATA=truein.envbefore the first start for a sample client, project and modules. docker compose logs -f webfollows the logs;docker compose down -vdeletes everything, including the encryption keys.- The sample stack serves plain HTTP (
TASKIST_REQUIRE_HTTPS_COOKIES=false). Put it behind TLS before exposing it — see Configuration.
Prerequisites: .NET 10 SDK, SQL Server (Express, LocalDB or Docker), and the EF Core tools (dotnet tool install --global dotnet-ef).
-
Clone and restore:
git clone https://github.com/Taskist/taskist.git cd taskist dotnet restore src/Taskist.sln
-
Create
src/Presentation/Taskist.Web/appsettings.Development.json(git-ignored):{ "ConnectionStrings": { "AppContext": "Server=.\\SQLEXPRESS;Database=Taskist;Integrated Security=True;TrustServerCertificate=True;" } } -
Create the schema:
dotnet ef database update --project src/Libraries/Taskist.Data --startup-project src/Libraries/Taskist.Data
-
Run
sql-scripts/02_defaults.sql, then03_locale.sql(see Database). -
Start the app and browse to https://localhost:7025:
dotnet run --project src/Presentation/Taskist.Web
In Development, background jobs run inline instead of on a Hangfire server, so webhooks and notifications work without extra setup. Run the tests with dotnet test src/Taskist.sln — no database needed.
Taskist reads appsettings.json, appsettings.{Environment}.json, user-secrets and environment variables; environment variables win. Nested keys use a double underscore: Security:RequireHttpsCookies → Security__RequireHttpsCookies.
| Setting | Default | Description |
|---|---|---|
ConnectionStrings:AppContext |
— | Required. SQL Server connection string |
App:BaseUrl |
https://localhost:7025/ |
Public address, used in e-mail links, OAuth callbacks and webhook URLs |
Security:RequireHttpsCookies |
true |
Sign-in cookie over HTTPS only. false is for deliberate plain-HTTP setups and also skips HTTPS redirection and HSTS |
Security:ForwardedHeaders:Enabled |
false |
Trust X-Forwarded-For / X-Forwarded-Proto from a reverse proxy |
Security:ForwardedHeaders:KnownProxies |
[] |
Proxy IP addresses to trust (loopback is always trusted) |
Security:ForwardedHeaders:KnownNetworks |
[] |
Proxy networks in CIDR form, e.g. 172.16.0.0/12 |
DataProtection:KeysPath |
App_Data/DataProtectionKeys |
Encryption key ring folder; must be writable |
DataProtection:CertificatePath / CertificatePassword |
— | Encrypt the key ring at rest with a PFX certificate |
DataProtection:CertificateThumbprint |
— | …or with a certificate from the machine store |
DataProtection:ProtectWithDpapi / DpapiLocalMachine |
false |
…or with Windows DPAPI |
App:IsBeta / App:BetaMessage |
true / text |
Beta banner |
Sentry:Enabled / Sentry:Dsn |
false / — |
Optional error tracking with Sentry: unhandled exceptions and logged errors. Needs both; see SECURITY.md for what is sent |
Sentry:Environment / Sentry:TracesSampleRate |
environment name / 0 |
Sentry environment label; share of requests sent as performance traces (0 = errors only) |
Everything else — password policy, lockout, session length, e-mail, Git, notifications, report layouts — lives in the app under Configuration → Settings.
Behind a reverse proxy (nginx, Traefik, IIS, a cloud load balancer): keep RequireHttpsCookies=true, set ForwardedHeaders:Enabled=true and list the proxy in KnownProxies or KnownNetworks, and set App:BaseUrl to the public https:// address. In Docker these are TASKIST_REQUIRE_HTTPS_COOKIES, TASKIST_FORWARDED_HEADERS, TASKIST_PROXY_NETWORK and APP_BASE_URL in .env; Sentry uses SENTRY_ENABLED, SENTRY_DSN, SENTRY_ENVIRONMENT and SENTRY_TRACES_SAMPLE_RATE.
Schema = EF Core migrations:
dotnet ef database update --project src/Libraries/Taskist.Data --startup-project src/Libraries/Taskist.DataTaskist.Data is its own startup project; add --connection "<connection string>" to target another database.
Seed data lives in sql-scripts/ as idempotent scripts, matched on business keys, so re-running them is safe. Run them in numeric order (with sqlcmd, pass -f 65001):
| Script | Required | Contents |
|---|---|---|
01_schema.sql |
Alternative | Full idempotent schema, for when you can't run dotnet ef |
02_defaults.sql |
✅ | Language, roles and permissions, menu, task types / severities / statuses, settings, email templates, administrator account (only into an empty user table) |
03_locale.sql |
✅ | English (India) translations |
04_demo.sql |
Optional | Sample client, project and modules |
Upgrading? See UPGRADING.md and the changelog.
Please report vulnerabilities privately as described in SECURITY.md, not as public issues.
Before going live: serve over HTTPS, change the seeded admin password, use a least-privilege SQL login, and back up the Data Protection key folder — losing it signs everyone out and makes stored Git tokens, webhook secrets and notification URLs unreadable. SECURITY.md has the full deployment checklist.
| 🙏 Questions | Discussions → Q&A |
| 💡 Ideas | Discussions → Ideas |
| 🐛 Bugs | Open an issue |
| 🛠 Code | CONTRIBUTING.md — setup, conventions and what CI checks |
| 📖 Docs | docs.taskist.org · Git integration |
By participating, you agree to uphold our Code of Conduct.
Thanks to the providers who support this project with free licenses and services:
If Taskist helps you, ⭐ star the repository and share it with your team.
MIT © 2025-2026 Somaraj and Taskist contributors. Bundled third-party libraries keep their own licences — see THIRD-PARTY-NOTICES.md.



