Development Setup
Local development setup for Vaulthalla contributors.
Development Setup
This guide is for contributors getting from clone to useful local work.
If you are doing docs-only work, you do not need the full Linux runtime environment. If you are touching core runtime, FUSE, packaging, systemd, PostgreSQL, TPM/swtpm, or install lifecycle behavior, you do.
Platform Assumptions
Vaulthalla is Linux-native software.
Meaningful validation for these areas requires a Linux environment:
- core daemon work
- FUSE behavior
- package lifecycle scripts
- systemd services
- PostgreSQL bootstrap and state handling
- TPM or
swtpmintegration
Debian and Ubuntu-style environments are the safest contributor path because the repo scripts and package metadata assume apt, sudo, systemd, and Debian packaging.
If you are on macOS or Windows, docs work is fine, and some web or release-tooling work may still be possible. Do not pretend that means you fully validated Linux runtime behavior.
Quick Health Check
From the repo root:
1bash .codex/scripts/doctor.sh2bash .codex/scripts/index.sh
doctor.sh checks for git, python3, node, pnpm, meson, ninja, the presence of web/node_modules, and the top-level project files the repo expects.
Toolchains
Streamlined local install via Makefile
If you want the repo's higher-level entrypoints instead of driving the scripts manually, the top-level Makefile is the streamlined route.
Common targets:
1make install2make dev3make test4make run_test5make clean_test6make clean
What they do at a high level:
make installruns the normal install guard, then./bin/install.shmake devruns./bin/uninstall.sh, then the install guard, then./bin/install.shmake testandmake run_testrebuild the integration-test environment throughbin/tests/*
Use these deliberately. They are host-mutating install workflows, not lightweight build aliases.
Web/admin work
The web client uses:
- Node pinned by
web/.nvmrc(24.13) pnpm- Next.js, React, TypeScript, ESLint
Setup:
1cd web2pnpm install --frozen-lockfile3pnpm test4pnpm dev
Release-tooling work
The release tooling uses Python dependencies from requirements.txt.
Setup:
1python3 -m venv .venv2. .venv/bin/activate3pip install -r requirements.txt4python3 -m tools.release check
Core/runtime work
For Linux contributors on a machine or VM you are comfortable modifying, the repo provides an install-deps helper:
1./bin/setup/install_deps.sh
That script adds the Vaulthalla APT repository if needed and installs native dependencies such as Meson, Ninja, PostgreSQL, FUSE, PDFium, libpqxx, libsodium, libtss2, swtpm, and related packages.
Run it deliberately. It changes the host.
Preferred Dev Workflow
The fastest rebuild-and-reinstall loop in this repo is the destructive dev workflow behind make dev.
It is fast because it starts from a fresh local install every time.
It is dangerous because make dev begins by running ./bin/uninstall.sh, which can wipe Vaulthalla directories and local database state with no interactive warning path once dev mode is active.
Dev mode guardrails
The repo requires two guardrails before the destructive dev workflow is considered valid:
- set
VH_BUILD_MODE=dev - create a repo-root sentinel file named
enable_dev_modewhose contents are exactlytrue
Example:
1export VH_BUILD_MODE=dev2printf 'true\n' > enable_dev_mode3make dev
This behavior is enforced by bin/lib/dev_mode.sh. If VH_BUILD_MODE=dev is set without the sentinel, the scripts fail. If the sentinel exists but VH_BUILD_MODE is not dev, the scripts warn about the mismatch.
If you use this workflow, do it on a machine or VM where destroying the local Vaulthalla install is acceptable.
Custom install path
If you want the same install plumbing without using the Makefile, the equivalent lower-level path is:
1./bin/install.sh
For destructive dev-mode reinstall behavior, the Makefile target is just wrapping:
1./bin/uninstall.sh2./bin/install.sh
Core Build Path
The current CI-style core build path is Meson-based:
1meson setup build --buildtype=debug -Dbuild_unit_tests=true -Dinstall_data=false2meson compile -C build3meson test -C build
That matches the shape used in .github/actions/build/action.yml and .github/actions/test/action.yml.
The repo root is the Meson project root. core/ remains the C++ subsystem, and compile_commands.json is emitted at build/compile_commands.json.
If your work needs an installed runtime rather than just a compiled binary, the repository also provides higher-level install and test helpers under bin/.
Integration And Runtime Test Path
For Linux-only runtime validation:
1./bin/tests/install.sh --run2./bin/tests/uninstall.sh
What that setup path does:
- installs native dependencies
- prepares users and directories
- prepares PostgreSQL state
- builds the core integration target
- runs the integration binary when
--runis provided
This path depends on sudo, Linux, FUSE, PostgreSQL, and other host-level pieces. Use it when your change affects runtime behavior rather than simple docs or web copy.
Test database requirements
For the integration test path and some DB-backed unit tests, you need the test database variables to resolve to the expected test database:
1VH_TEST_DB_USER=vaulthalla_test2VH_TEST_DB_HOST=127.0.0.13VH_TEST_DB_PORT=54324VH_TEST_DB_NAME=vh_cli_test
Current script behavior matters here:
- the database name is hard-coded in the test setup scripts as
vh_cli_test - the role is hard-coded as
vaulthalla_test bin/tests/install_db.shgeneratesVH_TEST_DB_PASSautomatically during test-environment setup
You should not assume the password is static. The current scripts generate it as part of the test setup flow.
Local Config And Environment Notes
- Default runtime config ships from
deploy/config/config.yaml. - Install scripts copy config into
/etc/vaulthalla/config.yaml. - The web service unit uses
deploy/systemd/vaulthalla-web.service.in. - Some local scripts look for
deploy/vaulthalla.env.
The repo only ships deploy/vaulthalla.env.example as a public template. If you need real storage-backed test credentials or environment values, create your own local deploy/vaulthalla.env from that template and keep secrets out of commits.
R2/S3 test environment
If you want the dev workflow to carry R2 test credentials into the installed environment:
- copy
deploy/vaulthalla.env.exampletodeploy/vaulthalla.env - uncomment and fill in the
VAULTHALLA_TEST_R2_*variables
The example variables are:
1# VAULTHALLA_TEST_R2_ACCESS_KEY=<your_access_key>2# VAULTHALLA_TEST_R2_SECRET_ACCESS_KEY=<your_secret_key>3# VAULTHALLA_TEST_R2_ENDPOINT=https://<your_unique_id>.r2.cloudflarestorage.com4# VAULTHALLA_TEST_R2_REGION=auto5# VAULTHALLA_TEST_R2_BUCKET=<your_bucket_name>
When deploy/vaulthalla.env exists, bin/setup/install_dirs.sh installs it as /etc/vaulthalla/vaulthalla.env.
Optional dev R2 test vault seeding
deploy/config/config.yaml includes:
1dev:2 enabled: false3 init_r2_test_vault: false
If dev mode is enabled in config and init_r2_test_vault is set to true, the storage manager can seed an R2 Test Vault automatically during startup when the required VAULTHALLA_TEST_R2_* environment variables are present.
Keep this workflow-specific and local. Do not commit real credentials.
Known Practical Snags
Missing web/node_modules
bash .codex/scripts/doctor.sh will flag this. Run:
1cd web2pnpm install --frozen-lockfile
Web build failures caused by missing private icons
The CI web build syncs private icons from ~/vaulthalla-web-icons before pnpm build. If local web build work depends on those assets, coordinate with the maintainer instead of committing fake replacements.
Integration test scripts expecting deploy/vaulthalla.env
Some scripts reference deploy/vaulthalla.env, while the repo only includes deploy/vaulthalla.env.example. If your test path needs environment values, create the local file explicitly.
make dev is not a safe default
It is a rebuild convenience for contributors who intentionally want a fresh local install every time. It is not a normal "development server" command and it is not safe on a machine whose Vaulthalla state you care about keeping.
Cross-platform false confidence
If you changed FUSE, packaging, auth/session, systemd, PostgreSQL lifecycle, or TPM behavior from a non-Linux machine, your local check is not enough. Say that plainly in the PR and ask for the right Linux validation.
Where To Go Next
- Read Contribution Boundaries before picking sharp work.
- Use the Architecture Map to find the right subsystem.
- Follow the Validation Guide before opening a PR.
