# How to Install vas3k/TaxHacker Locally: Complete Self-Hosting Guide

> Install vas3k TaxHacker locally with this self-hosting guide. Clone the repo, set up dependencies and your database, run migrations, and start the dev server for your own TaxHacker instance.

- Repository: [Vasily Zubarev/TaxHacker](https://github.com/vas3k/TaxHacker)
- Tags: how-to-guide
- Published: 2026-04-01

---

**Clone the repository, install Node.js dependencies, configure your PostgreSQL database URL in `.env`, run Prisma migrations, and start the development server to deploy your local TaxHacker instance on `http://localhost:7331`**

TaxHacker is an open-source, AI-powered accounting web application built with **Next.js 15**, **Prisma**, and **PostgreSQL**. Designed for self-hosting by vas3k, it uses LLM providers like OpenAI or Gemini for automated receipt parsing and financial tracking. This guide walks through the complete local installation process using either native Node.js or Docker containers, referencing the actual source architecture from [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts) and `prisma/schema.prisma`.

## Prerequisites

Before beginning the TaxHacker local installation, ensure you have the following:

- **Node.js** (version 20 or newer) and **npm** installed
- **PostgreSQL 17** or newer instance (local or containerized)
- **Git** for cloning the repository

## Step-by-Step Installation

### 1. Clone the Repository and Install Dependencies

Start by cloning the official repository and installing the required Node.js packages defined in [`package.json`](https://github.com/vas3k/TaxHacker/blob/main/package.json):

```bash
git clone https://github.com/vas3k/TaxHacker.git
cd TaxHacker
npm install

```

This installs Next.js 15, Prisma, LangChain adapters, better-auth, and other core dependencies required by the application.

### 2. Configure Environment Variables

Create your local environment file by copying the template:

```bash
cp .env.example .env

```

Edit `.env` to configure the required variables. Critical settings include:

| Variable | Description | Required |
|----------|-------------|----------|
| `DATABASE_URL` | PostgreSQL connection string (e.g., `postgresql://postgres:postgres@localhost:5432/taxhacker`) | Yes |
| `BETTER_AUTH_SECRET` | Minimum 16-character secret for session signing | Yes |
| `SELF_HOSTED_MODE` | Set to `true` to bypass authentication for local development | Recommended |
| `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `MISTRAL_API_KEY` | LLM API keys for receipt parsing (optional for basic testing) | No |

The application validates all environment variables at startup using **Zod** in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts), which throws clear errors if required fields are missing or malformed.

### 3. Set Up PostgreSQL Database

You need a running PostgreSQL instance before initializing the schema. The quickest method uses Docker:

```bash
docker run -d \
  --name taxhacker-pg \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=taxhacker \
  -p 5432:5432 \
  postgres:17-alpine

```

Update `DATABASE_URL` in your `.env` file to match these credentials if you used different values.

### 4. Initialize the Database Schema

Generate the Prisma client and apply database migrations to create tables defined in `prisma/schema.prisma`:

```bash
npx prisma generate
npx prisma migrate dev

```

The `prisma/schema.prisma` file defines all business entities including **User**, **Transaction**, **Category**, **Project**, and **File** models. The singleton Prisma client in [`lib/db.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/db.ts) manages database connections throughout the application lifecycle.

### 5. Start the Development Server

Launch the Next.js development server:

```bash
npm run dev

```

The application starts on `http://localhost:7331`. When `SELF_HOSTED_MODE=true` is set in your environment, the app bypasses the better-auth login flow for rapid local testing, as configured in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts).

## Alternative: Docker Installation Method

For a containerized approach, TaxHacker includes a production-ready `Dockerfile` and [`docker-compose.yml`](https://github.com/vas3k/TaxHacker/blob/main/docker-compose.yml).

### Using Docker Compose (Recommended)

The simplest method runs both the application and PostgreSQL in linked containers:

```bash
docker compose up -d

```

This uses the pre-built image `ghcr.io/vas3k/taxhacker:latest` and mounts `./data` for persistent file uploads.

### Building Locally with Docker

To build from source instead of using the pre-built image:

```bash
docker build -t taxhacker:local .
docker run -d \
  -p 7331:7331 \
  -e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/taxhacker \
  -e SELF_HOSTED_MODE=true \
  -v $(pwd)/data:/app/data \
  taxhacker:local

```

The `Dockerfile` performs a multi-stage build on Node 23-slim and installs system dependencies (**Ghostscript**, **GraphicsMagick**) required for PDF processing and image generation.

## Configuration Architecture

Understanding these key files helps troubleshoot installation issues:

- **[`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts)**: Centralized configuration using **Zod** validation. Parses `DATABASE_URL`, AI provider keys, and upload paths into a type-safe `config` object used across the app.
- **[`lib/db.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/db.ts)**: Exports a singleton Prisma client. In development, it attaches to the `global` object to prevent hot-reload duplication.
- **[`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts)**: Configures **better-auth** with your `BETTER_AUTH_SECRET`. Handles session management and the `SELF_HOSTED_MODE` bypass logic.
- **[`lib/llm-providers.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/llm-providers.ts)**: Adapter layer for LangChain integrations. Automatically selects the first configured AI provider (OpenAI, Gemini, or Mistral) based on available API keys.

## Summary

- **Clone and install**: Use `git clone` and `npm install` to fetch dependencies
- **Environment setup**: Copy `.env.example` to `.env` and configure `DATABASE_URL` and `BETTER_AUTH_SECRET`
- **Database preparation**: Run PostgreSQL 17+ locally or via Docker, then execute `npx prisma migrate dev`
- **Development launch**: Use `npm run dev` for local development on port 7331
- **Docker option**: Use `docker compose up` for containerized deployment with automatic PostgreSQL provisioning
- **Self-hosted mode**: Enable `SELF_HOSTED_MODE=true` for authentication bypass during local testing

## Frequently Asked Questions

### What are the minimum system requirements for running TaxHacker locally?

You need **Node.js 20+**, **PostgreSQL 17+**, and approximately **2GB RAM** available for the Node.js process. If using Docker, ensure Docker Engine 20.10 or newer is installed. The application processes PDFs and images locally using Ghostscript and GraphicsMagick, which require additional CPU resources during receipt uploads.

### Can I run TaxHacker without an internet connection?

Yes, but with limited functionality. The core accounting features work offline once installed. However, **AI-powered receipt parsing** requires internet connectivity to reach OpenAI, Gemini, or Mistral APIs. You can manually enter transaction data without LLM integration by leaving the AI API keys unset in your `.env` file.

### How do I switch between different AI providers after installation?

Modify your `.env` file to include the desired API keys, then restart the server. The [`lib/llm-providers.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/llm-providers.ts) adapter automatically selects the first available provider in this priority order: OpenAI, Gemini, then Mistral. For example, to use Gemini instead of OpenAI, set `GOOGLE_API_KEY` and remove or comment out `OPENAI_API_KEY`, then run `npm run dev` again.

### What should I do if Prisma migrations fail during setup?

First, verify your `DATABASE_URL` is correctly formatted and the PostgreSQL server is accessible. Check that the database user has **CREATE** permissions. If migration conflicts occur during development, run `npx prisma migrate reset` (warning: this clears development data) or `npx prisma migrate resolve --applied [migration_name]` if a partial migration occurred. The `prisma/migrations` folder contains the full migration history synchronized with `prisma/schema.prisma`.