Getting started
Manual installation
Install Vaultigen on a Linux server with PHP and your own database, step by step.
This guide installs a production instance directly on a clean host, with your own PHP, web server and database. Most organizations should use the Docker Compose installation instead: it needs no PHP, Composer or Node.js on the host and sets up HTTPS, the worker and the scheduler for you. Choose the manual installation if you want SQLite, MySQL or MariaDB, an existing PHP hosting setup, or no containers.
Plan for about an hour, including the first backup. If something in your environment differs, the hardening guide explains the reasoning behind each setting.
Before you start: decide where you will keep the installation’s keys. Vaultigen creates several key files during setup, and losing them makes your data permanently unreadable. Have a safe place ready (an offline copy and a second person who can reach it).
1. Get the code and dependencies
Run these commands as the unprivileged user that will run PHP, in the directory you will serve from (for example /var/www/vaultigen):
git clone https://github.com/vaultigen/vaultigen.git .
git checkout v1.0.0 # the release you want
composer install --no-dev --optimize-autoloader
npm ci
npm run build
2. Create the environment file
cp .env.example .env
php artisan key:generate
Edit .env and set at least:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://vault.example.com
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=vaultigen
DB_USERNAME=vaultigen
DB_PASSWORD=change-me
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=change-me
MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME=Vaultigen
If Vaultigen runs behind a reverse proxy or load balancer that terminates TLS, also set VAULTIGEN_TRUSTED_PROXIES. See Hardening.
3. Create the installation identity and keys
php artisan vaultigen:initialize
This writes two owner-only files to storage/app/private:
installation.json: the installation ID, the audit-integrity key and a reserved passkey secret.kek.json: the installation key-encryption key (KEK) that protects every vault key.
Copy both files to your escrow now, together with APP_KEY from .env. See Key management.
4. Migrate the database
php artisan config:clear
php artisan migrate --force
5. Create the first administrator
php artisan vaultigen:bootstrap [email protected] --name="Administrator"
The command asks for a password at a hidden prompt. Outside local development it must be at least 15 characters long and must not appear in known breaches. The command is interactive on purpose; do not add --no-interaction.
6. Create the backup key
php artisan vaultigen:backup-key:generate --if-missing
This creates storage/app/private/backup.json, the key that encrypts backup sets. It is deliberately independent from the installation key. Escrow it separately from the other key files.
7. Configure the web server
Point the document root at public/. Nothing else in the directory may be reachable. A minimal nginx server block:
server {
listen 443 ssl http2;
server_name vault.example.com;
root /var/www/vaultigen/public;
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
client_max_body_size 30m;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
server {
listen 80;
server_name vault.example.com;
return 301 https://$host$request_uri;
}
Vaultigen sets its own security headers (HSTS, X-Frame-Options, a framing-focused CSP and more). Do not log request bodies at the proxy.
8. Start the queue worker and the scheduler
Both must run permanently. Example systemd units:
# /etc/systemd/system/vaultigen-queue.service
[Unit]
Description=Vaultigen queue worker
After=network.target
[Service]
User=www-data
WorkingDirectory=/var/www/vaultigen
ExecStart=/usr/bin/php artisan queue:work --tries=1
Restart=always
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/vaultigen-scheduler.service
[Unit]
Description=Vaultigen scheduler
After=network.target
[Service]
User=www-data
WorkingDirectory=/var/www/vaultigen
ExecStart=/usr/bin/php artisan schedule:work
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now vaultigen-queue vaultigen-scheduler
Instead of schedule:work you can use a cron entry: * * * * * cd /var/www/vaultigen && php artisan schedule:run. On SQLite, run exactly one queue worker.
9. Check the installation
Sign in, wait a minute, and open System → Installation status. Every check should be green: database, sodium, installation identity, keys, mail, scheduler and queue heartbeats, storage headroom and license.
10. Take the first backup and practise a restore
Open System → Operations and run a backup. Then follow the restore drill on a separate machine. Do this before you store real passwords, not after the first incident.
For recurring backups, explicitly enable VAULTIGEN_BACKUP_SCHEDULE_ENABLED=true; the existing
scheduler queues the default nightly 02:30 UTC backup. Remove an old backup-specific cron first.
Scheduling and local deletion are off by default. See Backups for configuration,
separate recovery inputs, off-host copying, and interrupted-run recovery.
Next: First steps.
Found a mistake? Tell us at [email protected].