Installation
Recommended Self-Hosted Setup
- Generate an app key:
1
docker run --rm ghcr.io/darkdragon14/volumevault:latest php artisan key:generate --show
- Create a
docker-compose.ymlfile and paste the generated value inAPP_KEY:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
volumevault:
image: ghcr.io/darkdragon14/volumevault:latest
ports:
- "8080:8080"
volumes:
- volumevault_data:/app/storage
- /var/run/docker.sock:/var/run/docker.sock
environment:
APP_KEY: base64:paste-generated-key-here
restart: unless-stopped
volumes:
volumevault_data:
- Start VolumeVault:
1
docker compose up -d
- Open
http://localhost:8080. - Create the first administrator account from the onboarding screen, or import an existing installation save.
The recommended setup runs one container. At startup it prepares storage, runs database migrations, then starts nginx, PHP-FPM, the queue worker, and the scheduler under process supervision.
Production defaults are built into VolumeVault. Add environment variables only when you need to override them, for example APP_URL, APP_TIMEZONE, or SMTP settings.
Reverse Proxy And HTTPS Termination
When VolumeVault runs behind a reverse proxy such as Pangolin, Caddy, Traefik, or nginx, TLS is usually terminated by the proxy and the container receives plain HTTP traffic on port 8080. In that setup, configure Laravel to trust your proxy so generated URLs, redirects, and Vite assets use the original HTTPS scheme.
Use the reverse proxy container IP or Docker network CIDR for TRUSTED_PROXIES:
Replace proxy_network with the Docker network name shared by VolumeVault and your reverse proxy container.
1
2
3
4
5
6
7
8
9
10
11
12
13
services:
volumevault:
image: ghcr.io/darkdragon14/volumevault:latest
networks:
- proxy_network
volumes:
- volumevault_data:/app/storage
- /var/run/docker.sock:/var/run/docker.sock
environment:
APP_KEY: base64:paste-generated-key-here
APP_URL: https://volumevault.example.com
TRUSTED_PROXIES: 172.18.0.0/16
restart: unless-stopped
You can inspect the Docker network subnet with:
1
docker network inspect proxy_network
TRUSTED_PROXIES="*" is also supported for simple homelab setups where proxy IPs change, but using the proxy IP or network CIDR is stricter. If TRUSTED_PROXIES is empty, VolumeVault does not trust forwarded proxy headers.
Large Installation Compose
For larger installations, you can split the migration, web app, queue worker, and scheduler into separate services while keeping the same image and storage volume:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
x-volumevault-environment: &volumevault-environment
APP_KEY: ${APP_KEY:?Set APP_KEY before starting VolumeVault}
x-volumevault-service: &volumevault-service
image: ghcr.io/darkdragon14/volumevault:latest
volumes:
- volumevault_data:/app/storage
- /var/run/docker.sock:/var/run/docker.sock
environment:
<<: *volumevault-environment
x-volumevault-runtime-service: &volumevault-runtime-service
<<: *volumevault-service
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
services:
migrate:
<<: *volumevault-service
entrypoint: ["sh", "-lc"]
command: "mkdir -p /app/storage/database /app/storage/framework/cache/data /app/storage/framework/sessions /app/storage/framework/views /app/storage/logs /app/bootstrap/cache && touch /app/storage/database/database.sqlite && chown -R www-data:www-data /app/storage /app/bootstrap/cache && /command/s6-setuidgid www-data php artisan migrate --force"
restart: "no"
app:
<<: *volumevault-runtime-service
ports:
- "8080:8080"
environment:
<<: *volumevault-environment
VOLUMEVAULT_MIGRATIONS_ENABLED: "false"
VOLUMEVAULT_QUEUE_ENABLED: "false"
VOLUMEVAULT_SCHEDULER_ENABLED: "false"
command: ["/init"]
queue:
<<: *volumevault-runtime-service
command: ["/command/s6-setuidgid", "www-data", "php", "artisan", "queue:work", "--tries=1", "--timeout=0"]
scheduler:
<<: *volumevault-runtime-service
command: ["/command/s6-setuidgid", "www-data", "php", "artisan", "schedule:work"]
volumes:
volumevault_data:
This layout is useful when you want separate container lifecycle, logs, and resource limits for runtime concerns. The app service keeps the image entrypoint so nginx and PHP-FPM are prepared correctly, but disables migrations because the separate migrate service already handles them.
The container listens on port 8080. You can expose any host port by changing the value on the left, for example 9090:8080, and should set APP_URL to the public URL you use.
Update Summaries
After an application update, VolumeVault can show each signed-in user a short in-app summary of the changes they have not seen yet. The summary uses the version embedded in the container image and the local changelog shipped with the application, so it does not require GitHub access from your server.
Users can dismiss the update summary after reading it, and can reopen the full changelog from the user menu or the version link in the footer. Images built from main show unreleased entries when they are available.
When APP_VERSION is a tagged release, VolumeVault can also check GitHub for a newer release and show a discreet footer notice plus a card on the changelog page. This check is cached and can be disabled with VOLUMEVAULT_UPDATE_CHECK_ENABLED=false for offline or restricted installations.
Environment Variables
APP_KEY: required for encrypted destination credentials, notification URLs, and installation saves.APP_ENV: defaults toproduction.APP_DEBUG: defaults tofalse.APP_TIMEZONE: timezone used to interpret backup schedules and display backup job dates, defaults toUTC. Use an IANA timezone such asEurope/Paris.APP_URL: public URL, defaults tohttp://localhost:8080.TRUSTED_PROXIES: reverse proxy IP, CIDR, comma-separated list, or*when running behind HTTPS termination. Leave empty when exposing VolumeVault directly.VOLUMEVAULT_HOST_PATH_ALLOWLIST: optional comma-separated list of Docker host path prefixes allowed for host-path backup jobs, for example/srv,/mnt/data. Leave empty to allow any non-root absolute host directory path.DB_CONNECTION: defaults tosqlite.DB_DATABASE: defaults to/app/storage/database/database.sqliteinside the Docker image.QUEUE_CONNECTION: defaults todatabase.CACHE_STORE: defaults todatabase.SESSION_DRIVER: defaults todatabase.VOLUMEVAULT_MIGRATIONS_ENABLED: set tofalseonly when running migrations in a separate container.VOLUMEVAULT_QUEUE_ENABLED: set tofalseonly when splitting queue workers into separate containers.VOLUMEVAULT_SCHEDULER_ENABLED: set tofalseonly when splitting the scheduler into a separate container.VOLUMEVAULT_UPDATE_CHECK_ENABLED: set tofalseto disable the cached GitHub latest-release check shown in the footer and changelog page.MAIL_MAILER: usesmtpor another real mail transport to enable email password reset links. The defaultlogmode hides email reset in the UI.
You can override values directly in Compose:
1
2
3
4
5
environment:
APP_KEY: base64:paste-generated-key-here
APP_URL: https://volumevault.example.com
APP_TIMEZONE: Europe/Paris
VOLUMEVAULT_HOST_PATH_ALLOWLIST: /srv,/mnt/data
Or load an environment file:
1
2
3
env_file: .env
environment:
APP_KEY: ${APP_KEY:?Set APP_KEY before starting VolumeVault}
Do not reuse a local development .env in production without review. Values such as APP_ENV=local or APP_DEBUG=true override the safe production defaults.
Secrets And APP_KEY
Destination credentials and notification URLs are encrypted using Laravel’s encrypted casts. Plaintext secrets are never sent back to the frontend or API, and edit forms intentionally leave secret fields blank.
If you lose APP_KEY, encrypted credentials and secure installation saves can no longer be decrypted. Back up APP_KEY securely before trusting scheduled backups.
Onboarding And Users
The first account created through /onboarding is always an admin. After that, admins can create more admins or regular users from the Users screen.
Roles:
admin: full access, including users, destinations, notification channels, restore flows, API tokens, installation saves, and Docker actions.user: read-only access to dashboard, volumes, jobs, runs, and logs.
VolumeVault prevents deleting your own account and prevents deleting or demoting the last admin.
During onboarding, you can either create the first administrator or import a .vvsave from a previous VolumeVault installation.