Moving an in-place application onto releases
Move an application deployed in place onto releases, explicitly, and undone exactly if it fails.
Part of Releases.
An application deployed by 1.x keeps running and updating in place after the upgrade, exactly as before. Moving it onto releases is an explicit operation, one application at a time:
noust --dry-run app migrate shop.example.com # the plan, and a rehearsal that changes nothing
noust app migrate shop.example.com # asks for confirmation; -y to skip it
noust app migrate shop.example.com --persist storage --persist public/uploads--dry-run is a global option and goes before the command. The console offers the same
operation from the application's Settings tab; the API has GET /api/apps/{domain}/migrate/plan
(read only) and POST /api/apps/{domain}/migrate (needs sudo mode), which queues the migration
as a job and answers 202 with it.
What the migration does:
- The unit is stopped first, so nothing writes into the tree while it moves. The plan states this downtime; it lasts until the health gate passes, usually seconds.
- The live tree becomes the first release. It is moved, not copied: every change is a rename inside the application directory, or the creation of a directory or a link.
- The environment moves to
shared/..envand Noust's inventory of it (.noust) are moved toshared/and linked into the release. - What the application wrote for itself moves to
shared/. In a git checkout that is every untracked directory, ignored or not (git status --ignored), minus build output (node_modules,.next,dist,build,.venv,__pycache__and similar). Without git, Noust cannot tell uploads from code: it keeps whichever ofuploads,public/uploads,storageanddataexist, and warns you to name the rest.--persistreplaces detection entirely. SQLite databases are found by their file header wherever they are (outside build output) and always move toshared/, with their-wal,-shmand-journalfiles beside them; a--persistlist that leaves one out is refused. - The unit and the site are rewritten to run from
current, when they name the application directory. A proxied site only names a port and is left alone. - The file count is verified. Regular files and their bytes are counted before and after,
shared/included. Any difference fails the migration. - The application goes through the health gate. If it does not answer, every rename is reversed, the unit and site are put back byte for byte, and the application is restarted on the tree it had. Every undo step is attempted even when an earlier one fails; anything that could not be put back is listed in the error with where it is now.
Read the plan before confirming. Two warnings in it matter:
- Untracked files outside a persistent path stay in the first release only. The next
deploy will not have them. Name the directory that holds them with
--persist. - A tree that is not a git checkout gets only the usual upload directories. Anything else
the application writes must be named with
--persist.
The migration refuses an application that is already on releases, one whose type cannot use the
release layout (Docker Compose), and one whose directory is missing. After it, the first
noust update builds a second release from the recorded source through repo/.