Skip to main content

Run PaGetto on Kubernetes

Every release publishes a Helm chart as an OCI artifact on GitHub Container Registry. The chart is built on the bjw-s common library, so every option of that library is available.

Install​

helm install pagetto oci://ghcr.io/letreset/charts/pagetto --version 1.0.0

The chart version always matches the PaGetto version, and the chart deploys the image letreset/pagetto with that same tag. See the releases page for the available versions.

To see every value with its default:

helm show values oci://ghcr.io/letreset/charts/pagetto --version 1.0.0

Configuration​

PaGetto's settings are environment variables in a ConfigMap, under configMaps.pagetto-env.data. The defaults use SQLite and file system storage on the persistent volume:

configMaps:
pagetto-env:
data:
Authentication__Mode: "Local"
Storage__Type: "FileSystem"
Storage__Path: "/data"
Database__Type: "Sqlite"
Database__ConnectionString: "Data Source=/data/pagetto.db"
warning

Change the default admin password right after the first start: sign in as admin / admin and PaGetto asks for a new one.

Any setting from Configuration can be added the same way, with __ as the section separator (for example Authentication__Mode: "Local").

Secrets​

Keep secrets such as database passwords and the Entra client secret in a Kubernetes Secret, and add it to the container's envFrom:

kubectl create secret generic pagetto-secrets \
--from-literal=Database__ConnectionString='Host=postgres;Database=pagetto;Username=pagetto;Password=...'
controllers:
pagetto:
containers:
pagetto:
envFrom:
- configMapRef:
name: pagetto-pagetto-env
- secretRef:
name: pagetto-secrets

envFrom replaces the default list, so keep the ConfigMap entry. Its name is <release name>-pagetto-env, so adjust it if your release isn't called pagetto. When a key is in both, the Secret wins because it is listed last.

Key values​

KeyDefaultDescription
configMaps.pagetto-env.dataSQLite and file system on /dataPaGetto settings as environment variables
controllers.pagetto.containers.pagetto.image.tagThe chart versionImage tag
controllers.pagetto.containers.pagetto.resources100m / 256Mi requested, 500m / 512Mi limitCPU and memory
controllers.pagetto.containers.pagetto.probes/livez liveness, /health readinessHealth probes
service.pagetto-srv.ports.http.port8080Service port
ingress.pagetto-ingress.enabledfalseCreate an Ingress
persistence.pagetto-data10Gi, ReadWriteOnce, mounted at /dataPackages, symbols, the SQLite database and Data Protection keys

Probes​

The liveness probe calls /livez, which only checks that the process responds. The readiness probe calls /health, which also checks the database (but not the package storage), so a pod that can't reach the database is taken out of the Service without being restarted. If you change HealthCheck__Path, change the readiness probe path too.

Ingress​

ingress:
pagetto-ingress:
enabled: true
className: nginx
annotations:
# Allow large packages (the default package limit is 8 GiB).
nginx.ingress.kubernetes.io/proxy-body-size: "0"
hosts:
- host: nuget.example.com
paths:
- path: /
service:
identifier: pagetto-srv
port: http
tls:
- secretName: nuget-example-com-tls
hosts:
- nuget.example.com

The ingress controller must forward X-Forwarded-Proto and X-Forwarded-Host (ingress-nginx does by default), so PaGetto returns https:// URLs in its service index.

Scaling out​

With the defaults (SQLite and a ReadWriteOnce volume) run one replica. To run more:

  • Use PostgreSQL, SQL Server or MySQL instead of SQLite.
  • Use shared storage: a ReadWriteMany volume, or cloud storage such as Azure Blob Storage or AWS S3.

The Data Protection keys live in the package storage, so every replica shares them and sign-in cookies work on all of them.

Upgrade​

helm upgrade pagetto oci://ghcr.io/letreset/charts/pagetto --version <new-version> --reuse-values

PaGetto runs database migrations on startup. Back up the database before upgrading across minor or major versions.