Skip to main content

Run PaGetto on Docker

The image is letreset/pagetto on Docker Hub, built for linux/amd64 and linux/arm64.

Quick start​

docker run -d --name pagetto -p 5000:8080 -v pagetto-data:/data \
letreset/pagetto:latest

The image runs with local accounts (Authentication:Mode is Local). Open http://localhost:5000/ and sign in as admin with the password admin: PaGetto asks for a new password first. Then create a token under My Tokens and push a package with it:

dotnet nuget push -s http://localhost:5000/v3/index.json -k <token> MyPackage.1.0.0.nupkg
warning

Change the default admin password right after the first start, before others can reach the server.

To run without accounts, like BaGetter, set Authentication__Mode=Legacy and Authentication__ApiKeys__0__Key to a long random value. Without an API key, anyone who can reach the server can push packages.

Image tags​

TagMeaning
latestLatest stable release
1, 1.0Latest release in that major or minor line
1.0.0Exact version, never changes
1.1.0-rc.1Prerelease, never tagged latest

Pin an exact version (or at least a major version) in production, and upgrade on purpose. The releases page lists the changes in each version.

Build your own image​

Build the image from a clone of the repository:

docker build -t pagetto:local .

The build restores NuGet packages from https://api.nuget.org/v3/index.json. If the build machine can't reach nuget.org, point the restore at another feed (for example a mirror, or a PaGetto feed that mirrors nuget.org) with the NuGetSource build argument:

docker build -t pagetto:local --build-arg NuGetSource=https://nuget.example.com/v3/index.json .

That feed must serve every package the build needs. NuGetSource replaces the sources from nuget.config instead of adding to them.

The /data volume​

By default the image keeps all of its state in /data:

PathContents
/data/packages/…Packages, per feed
/data/symbols/…Symbol files, per feed
/data/db/pagetto.dbThe SQLite database
/data/dataprotection/keyring.xmlData Protection keys (sign-in cookies, forms)

Mount a named volume or a host folder there, or you lose everything when the container is recreated. These defaults come from environment variables in the image (Storage__Path=/data, Database__Type=Sqlite, Database__ConnectionString=Data Source=/data/db/pagetto.db, Search__Type=Database); override them to use another database or cloud storage.

Configure PaGetto​

Configure PaGetto with environment variables, using __ (two underscores) as the section separator, for example Database__Type for Database:Type. You can pass them with -e, with an --env-file, or in a compose file. For the full list, see Configuration.

Secrets can also be mounted as files under /run/secrets, one file per setting (see Load secrets from files).

Docker Compose​

A production-like setup with PostgreSQL:

services:
pagetto:
image: letreset/pagetto:2
restart: unless-stopped
ports:
- "5000:8080"
environment:
Database__Type: PostgreSql
Database__ConnectionString: Host=db;Database=pagetto;Username=pagetto;Password=${POSTGRES_PASSWORD}
Search__Type: Database
Authentication__Mode: Legacy
secrets:
- source: pagetto_api_key
target: Authentication__ApiKeys__0__Key
volumes:
- pagetto-data:/data
depends_on:
- db

db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: pagetto
POSTGRES_USER: pagetto
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data

volumes:
pagetto-data:
postgres-data:

secrets:
pagetto_api_key:
file: ./secrets/api-key.txt

Put POSTGRES_PASSWORD=… in a .env file next to compose.yaml, and the API key in secrets/api-key.txt, then run docker compose up -d. For user accounts and Entra ID sign-in, add the settings from Authentication.

Health checks​

EndpointChecks
/livezOnly that the process is up. Use it for liveness probes.
/healthThe database (not the package storage). Use it for readiness probes and monitoring. The path is set by HealthCheck:Path.

Restore packages​

Use this package source:

http://localhost:5000/v3/index.json

Other feeds are at http://localhost:5000/feeds/{slug}/v3/index.json. Some helpful guides:

Symbol server​

Publish a symbol package the same way as a package:

dotnet nuget push -s http://localhost:5000/v3/index.json -k change-me MyPackage.1.0.0.snupkg

Load symbols from this symbol location:

http://localhost:5000/api/download/symbols

For Visual Studio, see Configure symbol locations.

Running PaGetto behind a reverse proxy​

Run PaGetto behind a reverse proxy to add HTTPS and your own domain. For the API to return correct URLs, the proxy must forward the Host header (or X-Forwarded-Host) and X-Forwarded-Proto. For more information, see the ASP.NET Core documentation.

Consider binding the port to localhost only (-p 127.0.0.1:5000:8080), so unencrypted traffic never leaves the machine.

Apache 2 configuration​

<IfModule mod_ssl.c>
<VirtualHost *:443>

ServerName nuget.example.com

ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
RequestHeader set X-Forwarded-Proto https

SSLCertificateFile /etc/letsencrypt/live/nuget.example.com/fullchain.pem #managed by certbot
SSLCertificateKeyFile /etc/letsencrypt/live/nuget.example.com/privkey.pem #managed by certbot
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Content-Security-Policy upgrade-insecure-requests
</VirtualHost>
</IfModule>

To send HSTS from PaGetto itself instead of the proxy, see Security headers.