Updating a production server is a controlled change, not just an apt command. Packages may restart services, a new kernel may need a reboot, and the application can fail even when the package manager reports success. A useful maintenance plan defines what must remain accessible, how you will verify it, and how you will recover.
This checklist targets Ubuntu 24.04 or 26.04 on a VPS you administer. It assumes sudo, provider-console access, known application services and a tested backup. Commands are syntax-checked examples, not a record of upgrading a live server for this article. First rehearse them on a staging machine with similar configuration.
The VPS learning path connects initial setup, deployment and ongoing operations.
Record a baseline and a recovery route
Before patching, decide the maintenance window and acceptable interruption. Confirm another person is not deploying, migrating a database or taking a conflicting backup. Open the provider console and verify you can actually use it; a bookmarked rescue page is not a recovery test.
hostname
date --iso-8601=seconds
cat /etc/os-release
uname -r
uptime
df -h / /boot
df -i /
systemctl --failed --no-pager
systemctl is-active nginx.service demo-api.service
curl --fail --max-time 10 https://example.com/healthUse your real service names and a non-sensitive health route. df -h checks bytes; df -i checks inodes. A full boot filesystem can obstruct a kernel update even when the root filesystem looks healthy. Record existing failed units so you can distinguish old issues from regressions.
Back up application data and required uploads; test restoration separately. A VM snapshot can complement backups, but a snapshot taken while a database writes may not represent an application-consistent restore point. Establish the rollback method before changing the host.
Refresh package information and review the proposal
sudo apt update
apt list --upgradable
apt-mark showhold
sudo apt-get --simulate upgradeapt update refreshes package metadata; it does not install all available updates. Stop on repository or signature failures rather than ignoring them. A held package needs an explanation, not automatic unholding. The simulation shows the package-manager proposal, but cannot prove that every maintainer script or application integration will behave correctly.
Review removals, new dependencies, kernel packages, database packages and configuration-file changes. Ubuntu's package-management guide describes the different operations. Interactive apt and scripted apt-get are related but not interchangeable in every detail; review the real operation's prompt too.
Avoid unreviewed commands that force every answer, run autoremove, or perform a distribution upgrade as part of an ordinary security patch. Moving to a new Ubuntu release is a separate compatibility project.
Apply the planned update
Run the agreed operation from a stable administrative session:
sudo apt upgradeRead the proposed package changes before accepting. Configuration-file prompts may require preserving local changes or merging vendor updates; neither “always keep” nor “always replace” is universally correct. Keep the session open and use the console if network access is interrupted.
A patch may restart daemons during installation, so “I will reboot later” does not mean the maintenance window has no service interruption. If another apt or dpkg process holds the package lock, identify it and wait for legitimate activity to finish. Do not remove lock files or kill an updater merely because it is inconvenient.
Record any reported failures. A successful shell prompt is not enough; inspect the package-manager exit status and output. If package configuration is interrupted, follow the specific error and Ubuntu recovery guidance before retrying an unrelated upgrade command.
Identify what still needs restarting
if test -f /var/run/reboot-required; then
cat /var/run/reboot-required
if test -f /var/run/reboot-required.pkgs; then
cat /var/run/reboot-required.pkgs
fi
fi
systemctl --failed --no-pager
sudo journalctl -p err --since "30 minutes ago" --no-pager
sudo nginx -tA reboot-required marker is a useful signal, not a complete inventory of every process holding old libraries. Follow the installed restart-checking tool's report and your service policy. Only restart services whose purpose and impact you understand. Database restarts and queue-worker restarts may require additional coordination.
Review logs privately; error output can contain request data or secrets. Test configuration before reloading a proxy. A successful nginx -t validates the files but does not itself apply them.
Reboot only with a verification plan
Before a reboot, confirm intended services are enabled and startup configuration is current. For PM2, use the named-process persistence guide; an interactive process list is not proof of boot recovery.
When the maintenance window and recovery console are ready:
sudo systemctl rebootThis interrupts the SSH connection and every application on the machine. Wait for the host to return, reconnect through your verified SSH identity, and run:
uptime
uname -r
systemctl --failed --no-pager
systemctl is-active nginx.service demo-api.service
sudo ss -ltnp
curl --fail --max-time 10 http://127.0.0.1:3001/health
curl --fail --max-time 10 https://example.com/healthConfirm the running kernel against the update plan, not merely that its version changed. Verify a representative user workflow, static assets, authentication and background jobs. Loopback health checks alone do not exercise DNS, TLS and the public reverse proxy.
Keep automatic maintenance observable
Automatic security updates can reduce delay, but their schedule, reboot policy and notifications should be understood. Inspect the actual timer names and logs on your installation rather than assuming every VPS image has identical defaults. Ubuntu documents unattended-upgrade configuration and testing.
If checks fail, preserve the evidence and use the recovery route you rehearsed. Booting a known-good kernel, restoring a compatible application release and restoring a database backup solve different failure classes. Do not blindly downgrade a database or restore an old VM snapshot over new customer writes.
Finish by recording what changed, test results, remaining follow-ups and the next review date. CodeKits development services can include this operational acceptance checklist alongside the app, so maintenance does not depend on remembering one successful terminal session.
