Skip to main content

Migrating from BaGetter

PaGetto can take over an existing BaGetter installation in place: point PaGetto at your BaGetter database and package storage, and your packages and client URLs keep working. A few settings need a change first; see What has a new name. On the first start PaGetto migrates the database to its own schema.

Before you start​

Back up the database and the package storage. The migrations add the feed, user, group, permission and token tables, and move every existing package into the default feed. There is no way back to BaGetter once they have run.

If you use Azure Table Storage as the database (Database:Type = AzureTable), move to a SQL database first; see Azure Table Storage.

Step by step​

  1. Stop BaGetter and back up the database and storage.
  2. Replace the application:
    • Docker: change the image from bagetter/bagetter to letreset/pagetto and pin a version, for example letreset/pagetto:1.0.0. Keep mounting the same /data volume.
    • Zip / IIS: download pagetto-<version>.zip from the releases page, extract it into a new folder, copy your appsettings.json over, and run dotnet PaGetto.dll instead of dotnet BaGetter.dll.
    • Kubernetes: install the PaGetto chart and point it at your existing volume and database.
  3. Check the names that changed (next section). The one that most often matters is the SQLite file name.
  4. Start PaGetto and watch the log for migration errors and configuration warnings. If BaGetter mirrored nuget.org, add the mirror to the default feed on Admin > Feeds (see Mirrors move to the feed).
  5. Browse to the site, sign in again, and restore and push a package to confirm everything works.

What has a new name​

Most configuration keys (Database, Storage, Search, Retention, …) are the same as in BaGetter, so your appsettings.json and Section__Key environment variables keep working. These changed:

BaGetterPaGettoWhat to do
Image bagetter/bagetterletreset/pagettoChange the image
BaGetter.dllPaGetto.dllChange your start command, service or IIS site
Default SQLite file bagetter.db (Docker: /data/db/bagetter.db)pagetto.db (Docker: /data/db/pagetto.db)If you relied on the default, either rename the file or set Database__ConnectionString=Data Source=/data/db/bagetter.db
BAGET_CONFIG_ROOT environment variablePAGETTO_CONFIG_ROOTRename the variable if you use it
Sign-in cookiePaGetto.AuthNothing: everyone signs in again once
Authentication:Mode optionalAuthentication:Mode requiredSet "Mode": "Legacy" to keep BaGetter's behavior; see Authentication
ApiKeyAuthentication:ApiKeysMove the key to Authentication:ApiKeys:0:Key (Authentication__ApiKeys__0__Key). PaGetto doesn't start while ApiKey is set
MirrorA mirror per feedAdd it on Admin > Feeds; the Mirror section is ignored with a warning
MaxPackageSizeGiBMaxPackageSizeMiBOptional: the old key is still read and converted

Package storage paths are not renamed, so the files stay where they are.

Feeds and URLs​

Every package now belongs to a feed. On the first start PaGetto creates the default feed (slug default) and puts all your existing packages in it.

  • The default feed stays at the old URLs, for example https://your-server/v3/index.json. Existing nuget.config files and CI pipelines keep working.
  • New feeds live under /feeds/{slug}/, for example https://your-server/feeds/internal/v3/index.json.
  • New packages in the default feed are stored under packages/default/…. Packages pushed by BaGetter stay at their old path (packages/{id}/…) and are still found, so you don't need to move files.

Mirrors move to the feed​

PaGetto doesn't read the global Mirror section. Mirrors belong to a feed: after the first start, open Admin > Feeds, open the default feed's settings and add the mirror there (source, v2/v3, download timeout and upstream authentication). Until the section is removed, PaGetto logs a warning at startup.

A feed can have several mirrors. Mirrored feeds keep upstream version lists in memory for 5 minutes by default, so a version newly published upstream can take up to 5 minutes to appear; set UpstreamListingCacheSeconds to 0 to turn this off. See Upstream listing cache.

Feed settings override the global ones​

These settings can be set per feed. The values in configuration become the defaults for feeds that don't override them:

  • AllowPackageOverwrites
  • PackageDeletionBehavior
  • IsReadOnlyMode
  • MaxPackageSizeMiB (BaGetter's MaxPackageSizeGiB is still read and converted)
  • Retention (max major, minor, patch and prerelease versions)

Nothing changes until you override a setting on a feed. See Feed settings.

Retention now runs as soon as any of the four limits is set, not only MaxMajorVersions. If you set MaxMinorVersions, MaxPatchVersions or MaxPrereleaseVersions without MaxMajorVersions, the next push or mirror of each package deletes the versions outside the limits. Check your retention settings before you migrate.

Authentication​

Authentication:Mode selects how people sign in and must be set. Legacy works like BaGetter: Authentication:ApiKeys protect pushes and Credentials protect reads. Set "Mode": "Legacy" to keep authentication working as before (Config, the old name, is still accepted).

ModeUse it when
LegacyYou want BaGetter's behavior
LocalYou want user accounts, groups and per-feed permissions stored in PaGetto
EntraEveryone signs in with Microsoft Entra ID
HybridYou want Entra ID for people and local accounts for build agents or external users

Switching away from Legacy turns off anonymous access, ApiKeys and Credentials. Plan the switch before you make it; see Authentication. In the user modes, a valid account or token without the push or delete permission gets 403 Forbidden instead of 401 Unauthorized, or 404 Not Found when it has no permission on the feed at all.

Data Protection keys​

PaGetto keeps its ASP.NET Core Data Protection keys (which protect sign-in cookies and forms) in the configured package storage, at dataprotection/keyring.xml. With file system storage in Docker this is inside /data. If /data isn't a persistent volume, every restart signs everybody out, and several replicas can't share cookies.

Database changes​

The migrations run automatically on startup (RunMigrationsAtStartup, on by default). Some of them need attention on a large or older database:

  • Usernames and group names must be unique regardless of case. This only matters if you already have accounts; a BaGetter database has none, so the check passes.
  • MySQL moves to utf8mb4. BaGetter stored MySQL data as latin1, so package metadata with other characters (for example the author "Havlíček", or Polish or Turkish text) failed to push or mirror. A migration converts the database and every table to utf8mb4 with the utf8mb4_unicode_ci collation and keeps the data. It rewrites every table (one ALTER TABLE each), which can take a while and blocks writes to the table being converted, so plan a maintenance window. The tables use the DYNAMIC row format (the default on MySQL 5.7.9+, MySQL 8 and MariaDB 10.2+), and the nine long package columns become text.
  • PostgreSQL: package versions become case-insensitive. Some older databases still have Packages.Version as varchar(64) although the migration that should have made it citext is recorded as applied, so prerelease versions with capital letters can't be found or deleted. PaGetto repairs this on startup. If the log says Cannot convert "Packages"."Version" to citext, delete one version of each pair that only differs by case and start again.
  • Stored packages are read once. PaGetto fills the new Copyright, LicenseExpression and Size columns in the background after startup, 100 packages at a time, while it keeps serving requests. On cloud storage this means one read of every stored package.

Azure Table Storage isn't supported​

The AzureTable database type can't store feeds, users, groups, permissions or tokens, so PaGetto refuses to start with it. Before you migrate, move to one of the SQL databases (Sqlite, SqlServer, PostgreSql or MySql): start BaGetter with the new database and the same storage, and push your packages again (see Import packages from a local feed).

New settings you may want​

These are optional and off or safe by default. See Configuration.

  • RegistrationPageSize: registration index paging for packages with many versions (default 64).
  • Cors: allowed origins for browser clients.
  • SecurityHeaders: security headers (on by default) and optional HSTS.
  • RequestRateLimit: per-client request rate limiting (off by default).
  • Database:ServerVersion (MySQL): skips server version detection.
  • Database:JournalMode (SQLite): sets the journal mode, e.g. WAL.
  • Email and PatExpiryNotification: emails before personal access tokens expire.
  • The machine-wide config file: %ProgramData%\PaGetto\appsettings.json or /etc/pagetto/appsettings.json.