# Tracktor: a self-hosted garage book for people with more than one vehicle

> Tracktor is a SvelteKit application that keeps fuel logs, service history, insurance and pollution certificates, reminders and fleet expenses in one place, backed by SQLite and shipped as a Docker image. The README opens with a warning that it is under active development and not stable for production use, which is the first thing to weigh before you point it at real records.

**javedh-dev/tracktor** — Vehicle Tracking Management System

- Repository: https://github.com/javedh-dev/tracktor
- Website: https://tracktor.bytedge.in
- Stars: 1,033 · Forks: 81
- Language: Svelte
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/javedh-dev-tracktor

## The problem is a drawer of receipts

The README opens with a scene that is more precise than most project descriptions. If you own more than one vehicle, you know the drill: fuel receipts in a drawer, insurance PDFs buried in email, a maintenance date you meant to write down somewhere.

Tracktor is a self-hosted app that keeps all of that in one place, with fuel logs, service history, insurance and pollution certificates, reminders before they lapse, and a dashboard that shows what is going on across your fleet. The deployment target is deliberately small: run it on a Raspberry Pi, a home server, or a five dollar VPS, and the data stays yours.

That framing tells you what kind of user this is for. It is not a fleet management system for a company with a compliance department, it is a better place to keep the paperwork for someone with two cars and a scooter who has run out of patience for a spreadsheet.

The feature list follows the paper trail. The garage holds multiple vehicles, each with its own fuel type and history. Fuel tracking logs every fill-up and shows mileage and efficiency trends over time. The maintenance log keeps a full service history per vehicle and tells you what is coming up next. Compliance covers insurance and pollution certificates with renewal dates. Reminders nudge you before something expires or a service is due. Expenses and reports show what the vehicles actually cost. The dashboard is a fleet-wide overview with widgets you can rearrange, and there is username and password login with sessions plus the ability to switch off features you do not need.

The language list has an oddity. The README says 11 languages and then lists English, Hindi, Spanish, French, German, Italian, Arabic, Romanian, Hungarian, Finnish, Russian, Czech and Polish, which is thirteen. The localisation itself is handled by paraglide-js, in the i18n/ directory.

## SvelteKit, SQLite and Drizzle, in a container

The tech stack line is short and complete: SvelteKit with Svelte 5 and Tailwind CSS on the frontend, SvelteKit server routes on the backend, SQLite via the Drizzle ORM for storage, shipped as a Docker image.

Both halves live in one application. There is no separate API service, because SvelteKit server routes are the API, and the same repository holds the form actions that write to the database. The project is a pnpm workspace with a src/ directory, a Dockerfile, a drizzle.config.js, and a svelte.config.js.

The dependencies in the manifest tell you what the application does. Drizzle ORM and drizzle-kit are the database layer, with migration scripts in the package.json. paraglide-js is the internationalisation, which matches the i18n/ directory at the top level. bits-ui and lucide-svelte are the component and icon libraries, and @tanstack/table-core and the d3-array, d3-scale and d3-shape packages are the table and chart machinery behind the fuel trends and the dashboard.

There are also nodemailer, node-cron, pdfkit and @internationalized/date in the dependency list, which points at the reminder notifications, the scheduled jobs behind those reminders, and PDF export.

The scripts are conventional for a SvelteKit project. The dev server is vite dev with or without a host flag, the build is vite build, the production start is node build, the type check is svelte-kit sync followed by svelte-check, and the formatting runs eslint --fix together with prettier --write. The database has its own two commands, drizzle-kit generate and drizzle-kit migrate, and the tests run under Vitest with a coverage variant.

## Docker Compose is the fastest way in

The README recommends Docker Compose as the fastest way to try Tracktor, and gives the whole file.

```yaml
services:
  app:
    image: ghcr.io/javedh-dev/tracktor:latest
    container_name: tracktor-app
    restart: always
    ports:
      - '3333:3000'
    volumes:
      - tracktor-data:/data
volumes:
  tracktor-data:
```

Three lines carry most of the meaning. The image comes from the GitHub container registry rather than Docker Hub. The port mapping publishes the container's 3000 on the host's 3333. And a named volume is mounted at /data, which is where everything persistent lives.

```bash
docker-compose up -d
```

Then you open http://<your_ip_address>:3333 in a browser.

For anything beyond the quick start, the README points at the installation guide, which covers Docker, local development, Proxmox LXC setup and reverse proxies, and at four more documents: the environment variables reference, the authentication notes on how login and sessions work, the feature toggles guide, and the contributing guide.

The Proxmox LXC option is a clue about the intended deployment. A container on a small virtual machine in a home lab is a different commitment from a cloud service, and it is the setup the documentation explicitly supports rather than merely tolerates.

## The image keeps its state in one directory

The Dockerfile is a two stage build on node:22-alpine, and reading it tells you the operational shape of the application.

The builder stage installs pnpm globally, copies package.json, pnpm-lock.yaml and pnpm-workspace.yaml, installs with a frozen lockfile, copies the source, builds, and then runs pnpm prune --prod so the development dependencies do not travel into the final image. The runtime stage copies the build output, the pruned node_modules, the package.json, and the migrations directory from src/server/db/migrations.

Copying the migrations explicitly is the detail that matters most for an operator. It means the image ships the schema history, so a database can be created and brought up to date inside the container rather than by a manual step on the host.

Then the environment. The image sets NODE_ENV to production, HOST to 0.0.0.0 and PORT to 3000, and it points the three stateful paths at the volume, with DB_PATH at /data/tracktor.db, LOG_DIR at /data/logs and UPLOADS_DIR at /data/uploads. It creates those three directories, and it exposes 3000.

One setting deserves a second look. BODY_SIZE_LIMIT is set to Infinity in the image, while the example environment file sets it to 10mb. The image therefore removes the upload ceiling by default, which is convenient for a personal server and unwise for one exposed to the internet, because the limit is the only thing between a logged in user and a disk filling up.

## The environment file, and the defaults worth changing

The .env.example in the repository lists every configuration option with a comment, and it is a good template for a security review of your own deployment.

The two that matter most are APP_SECRET and CORS_ORIGINS. APP_SECRET is the secret key for encrypting sensitive data, and the comment tells you how to generate one, with openssl rand -hex 32. In the example it is empty, which means an operator who copies the file without editing it is running with no encryption key at all. CORS_ORIGINS is set to the wildcard, which for a self-hosted app on a private network is convenient and for anything reachable from the internet is not.

HTTP_MODE is set to http, with a comment explaining that it should be set to https when the app is served over TLS so the auth cookies get the secure flag. That is a small setting with a real consequence: with the wrong value, the session cookie can travel over an unencrypted connection, which matters as soon as you put a reverse proxy in front.

There is also BASE_URL, commented out, described as the base path for a reverse proxy, with an example of a path like /tracktor for a site served under a subdirectory. If you are deploying behind a proxy on a subpath, that is the setting that tells the application where it lives.

The feature switches are in the same file. TRACKTOR_DEMO_MODE, FORCE_DATA_SEED and TRACKTOR_DISABLE_AUTH are all there, and the last one is worth pausing on. A switch that disables authentication is a sensible development convenience and a dangerous production value, and it is one string away in the environment file.

## Read the warning before you trust it with your records

The README's very first block is a warning, and it is unusually direct. Tracktor is under active development, there may be frequent breaking changes, precautions are being taken but it is not stable for production use, and you are asked to keep regular backups of your data.

That warning is consistent with the rest of the project's shape. The default branch is dev, the published versions come in three lines, a 1.3.x line, a 1.4.x line and a 2.x line, and the package manifest still says version 2.0.0 while the latest release tag is 2.1.0. The Docker image tracks the latest tag rather than a pinned version, so a compose file as given will pull whatever was built last, which is a moving target by design.

The practical reading is that Tracktor is a well-built hobby project that its author wants people to try, and that is different from a project that wants to hold your business records. The feature set is broad, the code is modern, the documentation covers installation, environment, authentication and feature toggles, and the maintainer is candid about the stability level.

The advice that follows from that is simple. Run it on a copy of your data first, keep the backups the warning asks for, pin the image tag rather than tracking latest once you are happy, and read the release notes between the 1.x and 2.x lines before you upgrade an existing instance, because the version jump is where the breaking changes will be.

The licence is MIT, so the code can be read, changed and self-hosted as long as the copyright notice is kept.

## Conclusion

Tracktor fits a household or small team with several vehicles that want fuel and service records in one self-hosted place, on a Raspberry Pi or a small VPS, with no account to create and no subscription. It does not fit a fleet that needs a stable long lived deployment, because the project says so itself and asks for regular backups, and it does not fit a team that needs mobile client apps or a company wide compliance workflow. Verify three things before you put real documents in it: that the APP_SECRET is generated and set, since the example leaves it empty and it is the key for encrypting sensitive data, that CORS_ORIGINS is not left as the wildcard, and that your backups cover the data volume rather than just the container, since the SQLite file, the uploads and the logs all live under the mounted path.

## FAQ

### How do I install Tracktor?

With Docker Compose. The compose file pulls ghcr.io/javedh-dev/tracktor:latest, names the container tracktor-app, publishes port 3333 on the host against the container's 3000, and mounts a named volume tracktor-data at /data. Run docker-compose up -d and open http://<your_ip_address>:3333. The documentation also covers local development, Proxmox LXC and reverse proxies.

### Where does Tracktor store my data?

In the mounted volume. The Docker image sets DB_PATH to /data/tracktor.db for the SQLite database, LOG_DIR to /data/logs and UPLOADS_DIR to /data/uploads, and creates those directories. The Compose file mounts a named volume called tracktor-data at /data, so backing up that volume covers the database, the uploads and the logs.

### What must I configure before exposing Tracktor to a network?

At minimum APP_SECRET, which the example file leaves empty and which is the key for encrypting sensitive data, generated with openssl rand -hex 32, and CORS_ORIGINS, which the example sets to a wildcard. HTTP_MODE should be set to https when served over TLS so the auth cookies get the secure flag, and TRACKTOR_DISABLE_AUTH should stay false in production.

### What does Tracktor actually let me track?

A garage of vehicles with their own fuel type and history, fuel fill-ups with mileage and efficiency trends, a per vehicle service history with what is coming up next, insurance and pollution certificates with renewal dates, reminders before something expires, expenses and reports, and a fleet dashboard with rearrangeable widgets. Feature toggles let you turn off what you do not use.

### Is Tracktor ready to use in production?

The README says it is under active development, that there may be frequent breaking changes, and that it is not stable for production use, and it asks you to keep regular backups. The Docker image is tagged latest rather than pinned, and the repository's default branch is dev, so pin a version once you are comfortable with it.

## Sources

- [javedh-dev/tracktor on GitHub](https://github.com/javedh-dev/tracktor)
- [License: MIT](https://github.com/javedh-dev/tracktor/blob/dev/LICENSE)
- [Project website](https://tracktor.bytedge.in)
- [README](https://github.com/javedh-dev/tracktor/blob/dev/README.md)
- [Releases](https://github.com/javedh-dev/tracktor/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/javedh-dev-tracktor
