Skip to main content
Back to notes

A safe checklist for deploying a static site on a shared server

Still Brewing UAPublished: Updated:

Adding a site to an empty server is easy. Adding one to a server that already runs other people’s working projects is a different job: the goal is not only that the new site works, but that nothing else changed. This is the checklist I follow.

Preflight before touching anything

Start read-only. Confirm the repository is on the expected branch, the working tree is clean, and the commit you are about to ship is the one already pushed. If any of that is off, stop and resolve it before the server is involved at all.

Then look at the server without changing it: operating system, uptime, free memory and disk, failed units, running services, listening ports, and whether the configuration currently parses.

Read-only server checks
systemctl --failed
sudo ss -lntp
sudo nginx -t
sudo ls -l /etc/nginx/sites-enabled/

Record a baseline you can compare against

Before any change, capture what "working" looks like for everything already on the server. Afterwards, "I did not break anything" becomes a comparison instead of an opinion.

  • a checksum of every configuration file you must not modify
  • the process id of each running service
  • the list of listening sockets
  • the status code, redirect target and content type of each existing site
  • the certificates that exist and when they expire

Process ids are the most useful of these. If a service was restarted when it should not have been, the id changes and you will see it immediately.

A separate virtual host, in a new file

The new site gets its own configuration file and its own symlink. Existing files are not edited. If the new site has to be removed, the change is one symlink and a reload, and nothing else was ever touched.

Give the new host a hostname of its own and never add the server’s bare IP address to it. The IP usually already belongs to whichever site was there first, and claiming it twice creates a conflict that resolves in load order rather than by intent.

Do not add `default_server`

The default server answers requests whose Host header matches nothing. On a shared server that role already belongs to an existing site, whether it was set deliberately or simply fell to whichever block loads first.

Adding `default_server` to a new virtual host silently takes that traffic away from the site that had it. Nothing errors, the configuration test passes, and the change only shows up as somebody else’s unexplained traffic drop. Leave it alone.

Back up before editing

Before changing a configuration file you own, copy it aside with a timestamp and verify the copy matches. It takes a moment and turns a bad edit into a one-command recovery.

Timestamped backup
sudo cp -p /etc/nginx/sites-available/example \
  /etc/nginx/sites-available/example.backup-$(date -u +%Y%m%d-%H%M%SZ)

Test, then reload — never restart

Always validate the configuration before applying it. A syntax error caught by the test is harmless; the same error applied to a running server takes every site on it down.

Validate, then apply
sudo nginx -t && sudo systemctl reload nginx

Reload replaces the worker processes while the master keeps running and connections are finished cleanly. Restart stops the server and starts it again, which is a visible outage for every site it hosts. Check afterwards that the master process id is unchanged — that is the proof it was a reload.

And if you only changed content, not configuration, do not reload at all. There is nothing to re-read.

A separate certificate for a separate hostname

Issue a new certificate for the new hostname instead of extending an existing one. Extending rewrites a certificate other sites depend on; a separate one can be renewed, replaced or removed without touching anything else.

Do a staging dry run first, confirm it succeeds, and only then request the real certificate. Afterwards, check that the existing certificate is untouched — comparing its serial number against the baseline settles it.

Avoid the standalone method on a shared server: it needs port 80 to itself and would stop the running web server to get it. Use the web server plugin, which validates through the server that is already running.

Verify the new site

Check both protocols and the failure cases, not just the happy path.

  • HTTP redirects to HTTPS on the same path
  • the certificate matches the hostname and verifies cleanly
  • the expected pages return 200 with sensible content types
  • following redirects ends somewhere, with no loop
  • an address that does not exist returns a real 404
  • no URL redirects to a different site on the same server

Verify the projects that were already there

This is the step that is easiest to skip and most valuable to keep. Repeat every baseline measurement and compare.

  • configuration checksums unchanged
  • service process ids unchanged
  • no new failed units
  • listening sockets unchanged
  • existing sites returning the same status codes and redirects
  • existing certificates unchanged, by serial number

Know the rollback before you need it

Write the exact rollback command down as part of the plan. For a configuration change it is restoring the backup, testing and reloading. For a content change it is pointing the symlink back at the previous release.

Rollback should never delete a certificate or a release directory. Undo the smallest thing that restores service, and leave the investigation for afterwards.

Do not touch what is not yours

The most useful rule on a shared server is the least technical one: change only what the task requires. Not the firewall, not DNS, not another project’s configuration, not the packages installed, not a certificate you did not create.

When something unexpected appears — a path that already exists, a service you did not expect, a configuration that differs from the last audit — stop and report it instead of adapting around it. An unexplained difference is information, and overwriting it destroys the only copy.

Want something like this built?

These notes come from work I have shipped. If you need the same done properly, tell me what you have in mind.