A private file asset platform. Upload, organise, and share files with role-based access control and a clean, fast interface.
- File management — Upload directly to S3/Hetzner Object Storage via presigned URLs, browse files in a folder hierarchy, inline rename, soft-delete
- Access control — Three roles:
admin,editor,viewer; per-resource permission grants - Share links — Generate 7-day public share links with view-count tracking and expiry enforcement
- Admin tools — User management, audit log viewer with action filtering, permission grants
- Audit trail — Every login, upload, delete, rename, and folder operation is logged
| Layer | Tech |
|---|---|
| Language | Go 1.25 |
| Router | Chi v5 |
| Templates | a-h/templ (server-side components) |
| Frontend | HTMX 2.0.3 + Alpine.js 3.14.3 (no build step) |
| Database | PostgreSQL 16 via pgx/v5 + sqlc |
| Sessions | gorilla/sessions backed by Postgres (pgstore) |
| Storage | S3-compatible (Hetzner Object Storage) via AWS SDK Go v2 |
| Migrations | golang-migrate (embedded via embed.FS) |
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | Postgres connection string, e.g. postgres://user:pass@host:5432/db?sslmode=disable |
SESSION_SECRET |
Yes | Random string ≥ 32 chars used to sign session cookies |
PORT |
No | HTTP port (default: 8080) |
SEED_ADMIN_EMAIL |
Yes | Email for the seeded admin account created on first boot |
SEED_ADMIN_PASSWORD |
Yes | Password for the seeded admin (min 8 chars, at least one digit) |
HETZNER_ACCESS_KEY |
Yes | Hetzner Object Storage access key |
HETZNER_SECRET_KEY |
Yes | Hetzner Object Storage secret key |
HETZNER_S3_ENDPOINT |
Yes | Storage endpoint, e.g. https://fsn1.your-objectstorage.com |
HETZNER_BUCKET |
Yes | Bucket name |
Prerequisites: Go 1.25, PostgreSQL, templ CLI, sqlc (for schema changes only)
# 1. Start Postgres
docker run -d --name vaulx-dev \
-e POSTGRES_USER=vaulx -e POSTGRES_PASSWORD=vaulx -e POSTGRES_DB=vaulx \
-p 5432:5432 postgres:16
# 2. Copy and edit env
cp .env.example .env # edit credentials as needed
# 3. Generate templ components (only needed after .templ file changes)
templ generate
# 4. Run the server (auto-runs migrations and seeds admin on first start)
go run ./cmd/serverThe server is available at http://localhost:8080. Log in with the credentials from SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD.
sqlc generate # regenerates internal/db/*.gotempl generate # regenerates web/templates/*_templ.goBuild and run with Docker Compose:
docker compose up --buildThe app will be at http://localhost:8080.
Set
SESSION_SECRETto a random value before use. The default indocker-compose.ymlis a placeholder.
Vaulx ships as a single Docker image with all migrations embedded. Recommended setup:
Use the built-in Postgres service (or an external managed database). Note the connection string.
- Source: your Git repository
- Build type: Dockerfile (uses
Dockerfileat repo root) - Port:
8080
DATABASE_URL=postgres://user:pass@your-pg-host:5432/vaulx?sslmode=disable
SESSION_SECRET=<random 32+ char string>
PORT=8080
SEED_ADMIN_EMAIL=admin@yourdomain.com
SEED_ADMIN_PASSWORD=<strong password>
HETZNER_ACCESS_KEY=<your key>
HETZNER_SECRET_KEY=<your secret>
HETZNER_S3_ENDPOINT=https://fsn1.your-objectstorage.com
HETZNER_BUCKET=<your bucket>
Trigger a deploy from Dokploy. On first start, the app will:
- Run all pending migrations
- Seed the admin account if it doesn't exist
- Start serving on
$PORT
The session cookie has Secure: true, so HTTPS is required for the login flow to work in production.
.
├── cmd/server/ # main.go — router setup, handler wiring
├── internal/
│ ├── auth/ # session middleware, ACL helpers, UserContext
│ ├── db/ # sqlc-generated code + querier interface
│ │ └── queries/ # SQL source files
│ ├── handler/ # HTTP handlers (files, upload, download, share, admin, permissions)
│ ├── seed/ # Admin user seeding on first boot
│ ├── storage/ # S3 client, presign helpers, DeleteObject
│ └── viewmodel/ # View-layer structs and mapping functions
├── migrations/ # SQL migration files (embedded into binary)
├── web/
│ ├── static/ # CSS, JS (served directly)
│ └── templates/ # .templ components + generated Go code
├── Dockerfile
└── docker-compose.yml
On first boot the server seeds one admin account using the SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD env vars. Change these before exposing the app publicly.
| Role | Can do |
|---|---|
admin |
Everything — manage users, hard-delete files, grant permissions, view audit log |
editor |
Upload files, create/rename/delete folders they own, rename/soft-delete their own files, create share links |
viewer |
Browse and download files they have access to |