Choosing a database
NuGetKeep stores its metadata (packages, feeds, users, keys, audit trail, download counts) in a relational database. Package blobs are separate — they always live in the storage volume, whatever database you pick.
SQLite (the default)
Section titled “SQLite (the default)”Out of the box NuGetKeep uses a single SQLite file inside the /data volume. There is
nothing to install, nothing to configure, and backup is copying one volume. For a single
server instance — most teams — this is the right choice, and it is not a “demo mode”:
the supply-chain gate, SSO, multi-feed, retention, and metrics all run on it.
Choose PostgreSQL instead when:
- your platform team requires a managed database (RDS, Cloud SQL, Azure Database, …),
- you want point-in-time recovery or replication at the database layer,
- write concurrency is high enough that SQLite’s single-writer model shows (rare for a package feed — reads dominate), or
- a future multi-instance/HA topology is on your roadmap.
PostgreSQL
Section titled “PostgreSQL”Two ways to run it, both built into the installer:
Bundled container
Section titled “Bundled container”curl -fsSL https://nugetkeep.com/install | bash -s -- --db postgresThe generated compose stack gains a postgres:17-alpine service with its own
nugetkeep-pgdata volume and a strong generated password (stored in the stack’s .env,
mode 0600). The app waits for the database’s healthcheck before starting. The password is
applied by the postgres image on first volume initialization only — re-running the
installer never rotates it; to truly reset, docker compose down -v (this destroys the data).
Existing server
Section titled “Existing server”curl -fsSL https://nugetkeep.com/install | bash -s -- --db external-postgres \ --db-connection 'Host=pg.example.com;Port=5432;Database=nugetkeep;Username=nugetkeep;Password=…'The connection string uses the Npgsql keyword form; a postgres://user:pass@host:port/db
URI is also accepted and converted. The installer validates the connection (a real
SELECT 1, not just a port probe) before writing anything, with specific errors for DNS,
refused connections, failed authentication, a missing database, and pg_hba.conf/SSL
rejections (--skip-db-check bypasses it).
The database must already exist — NuGetKeep creates its schema (EF Core migrations run at startup), but never the database itself:
CREATE DATABASE nugetkeep OWNER nugetkeep;A Postgres on the same machine as Docker is reached via host.docker.internal, not
localhost (inside the container, localhost is the container).
Outside the installer, the same two settings drive everything (e.g. Kubernetes):
NUGETKEEP_DB_PROVIDER=PostgresNUGETKEEP_DB_CONNECTION='Host=…;Port=5432;Database=nugetkeep;Username=…;Password=…'Backup
Section titled “Backup”| Mode | What to back up |
|---|---|
| SQLite | The nugetkeep-data volume. One volume, one backup — database, packages, and keys together. |
| Bundled Postgres | The nugetkeep-data volume (packages/keys) and the database: docker compose exec postgres pg_dump -U nugetkeep nugetkeep > nugetkeep.sql |
| External Postgres | The nugetkeep-data volume, plus whatever backup story your database server already has. |
When upgrading a bundled Postgres across a major version (17 → 18), dump and restore — the data directory format is not compatible across majors.
Switching providers
Section titled “Switching providers”There is no automatic data migration between SQLite and PostgreSQL (in either direction). Switching providers means starting with a fresh database — packages would need to be re-pushed or re-mirrored. The installer warns loudly if you ask it to switch an existing stack; the old SQLite file / postgres volume is left untouched. If you anticipate needing PostgreSQL, start on it.