Self-Host Solidtime: An Open-Source Toggl Alternative

An open-source time tracker for agencies that bill by the hour. What's free, what costs extra, and the billable-rate setting that can rewrite last month.

Self-Host Solidtime: An Open-Source Toggl Alternative

It's the last Friday of the month and someone at the agency is sending the same Slack message to eight people: "Please log your hours before 5pm, invoices go out Monday." Half the team logged everything. The other half is reconstructing Tuesday from their browser history. And the time tracker the whole process depends on gets more expensive with every hire, because it's billed per seat.

I've been that person. So I tested Solidtime to see whether it can take over from Toggl for a small agency. Short answer: for most teams that bill by the hour, yes. There's one thing you pay for if you want it, and one setting that can quietly rewrite last month's numbers. I'll cover both.

What Solidtime actually is

Solidtime is an open-source time tracker built for freelancers and agencies. It's licensed AGPL-3.0, has close to 9,000 stars on GitHub, and shipped v0.21.0 on September 22, 2026. It isn't at 1.0 yet, but releases come out every couple of weeks, and v0.20.1 on September 16 was a security release that fixed two reported issues. That's the kind of maintenance you want from something that holds your billing data.

What you get:

  • A timer, manual entries, a calendar view and a weekly timesheet
  • Clients, projects, tasks and tags
  • Billable rates at four levels (organization, member, project, project member)
  • Reports you can filter and export
  • Roles: Owner, Admin, Manager, Employee
  • Several organizations under one login, useful if you run two businesses
  • A desktop app and browser extensions for Chrome and Firefox
  • Importers for Toggl, Clockify, Harvest and generic CSV

That covers what most agencies use Toggl for day to day.

What's free and what isn't

This is the part the landing pages tend to blur. Solidtime is open core in one specific place: invoicing. The self-hosted open-source edition includes all the core features but not the built-in invoice generator. That sits in the On-Premise Business license, which starts at €49 per year for one user and costs €199 per year for five. You get it by pulling a different Docker image from Solidtime's private registry, and your data stays where it is.

For many agencies this doesn't matter. You already invoice from your accounting tool, and what you need from the tracker is an accurate export of billable hours per client. The free edition handles that fine.

Toggl's free plan is fine for a handful of people, but billable rates and team reports start at the paid Starter tier, so that's the fair comparison. Here's what a 10-person agency would pay per year at current public prices (Solidtime lists its prices in euros):

Option Pricing 10 users, per year
Toggl Track Starter $9 per user per month, billed annually $1,080
Toggl Track Premium $16 per user per month, billed annually $1,920
Solidtime Cloud Professional €8 per user per month, billed annually €960
Solidtime self-hosted on Elestio $16 per month for the server (2 vCPU, 4 GB RAM), no license fee $192

The last line is a flat server cost. It stays $192 whether you have 10 people or 25. If you also want built-in invoicing, add the Business license on top; it's priced by team size, so check the current tier for your headcount.

Moving your history off Toggl

You don't have to start from zero. Go to Admin > Import, pick Toggl, and follow the steps it shows for exporting from Toggl. There are two Toggl importers, and the order matters: run the "Toggl Data Importer" first (clients, projects, tasks, members), then "Toggl Time Entries". If you do it the other way round, entries come in without the project details you wanted to keep.

Imported people arrive as placeholder users. They own their historical entries but can't log in until you invite them from the Members page. That's intentional: you can bring in three years of history on a Monday and invite the team when you're ready.

The setting that rewrites last month

This is the one that would have caught me. Billable rates cascade: a rate for a person on a specific project wins over the project rate, which wins over that person's organization rate, which wins over the organization default.

When you change a rate, Solidtime asks you to confirm that the new rate will apply to all existing time entries that use it. If you cancel, the rate isn't saved. As far as I can tell from the docs, there's no way to say "starting next month."

So if a client's rate goes from €90 to €100 in October and you edit the project rate, September's hours get repriced to €100 as well. If September hasn't been invoiced yet, you've just made that invoice wrong.

What works: invoice or export first, then change the rate. Or, for a rate change in the middle of a contract, create a new project ("Acme Retainer 2027") with the new rate and track new work there. The old project keeps its old numbers.

Getting it running

The simplest route is to deploy Solidtime on Elestio, which handles the server, SSL, backups and updates. Under the hood it's the standard setup: the web app, a scheduler, a queue worker, PostgreSQL and Gotenberg (the service that renders PDFs).

A few commands you'll want, run from the terminal in the app folder:

# Create a user (prints a random password)
docker compose exec scheduler php artisan admin:user:create "Jane Doe" "jane@youragency.com" --verify-email

# Let the desktop app sign in
docker compose exec scheduler php artisan passport:client --name=desktop --redirect_uri=solidtime://oauth/callback --public -n

# Let users create personal API tokens (run once)
docker compose exec scheduler php artisan passport:client --personal --name="API"

For an agency I'd set APP_ENABLE_REGISTRATION="invite-only" in the environment settings. Only people you invite can create accounts, which is what you want for a tool full of client rates.

Troubleshooting

Invitation and password reset emails never arrive. Check the SMTP settings (MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD), then check that the queue worker is running. Solidtime hands work like this to the queue worker, so if the worker is down, emails sit in the queue and you won't see an error.

The desktop app or browser extension can't log in. Each needs its own OAuth client. The desktop command is above; the browser extension version, with its longer list of redirect URLs, is in the official Docker guide. Paste the client ID it prints into the app's "Instance Settings" along with your instance URL.

There's no API token option in user settings. You haven't run the passport:client --personal command yet. It only needs to run once per instance.

PDF exports fail. The app can't reach Gotenberg. Make sure the container is running and that GOTENBERG_URL points at it (http://gotenberg:3000 in the default setup).

Postgres warns about a "collation version mismatch" after an update. Open a psql shell and run REINDEX DATABASE solidtime; followed by ALTER DATABASE solidtime REFRESH COLLATION VERSION;, replacing solidtime with your database name.

Should your agency switch?

If you need Toggl's capacity planning or its long list of integrations, stay where you are for now. Solidtime is younger and doesn't try to do everything.

If what you actually need is "people track hours against clients, the rates are right, and I get a clean export at month end," Solidtime does that well. You own the data, and the cost doesn't grow every time you hire. Set up your rates properly before you import, and don't touch them in the middle of a billing period.

If you'd rather not run the server yourself, you can deploy Solidtime on Elestio and have your team tracking hours the same afternoon.

Thanks for reading ❤️ See you in the next one 👋