Ahosting Logo

VPS Hosting

Setting Up Web Applications on VPS

A working order, and why the last two steps are in that orderSecure the serverbefore anything islisteningWeb server and runtimeand confirm each oneserves somethingtrivialDatabase, with a narrow userprivileges on onedatabase, not oneverythingDeploy the applicationand fix file ownershiplast, once paths aresettledA database user with global privileges and an application that runs as root are the two shortcuts that make everylater compromise total.

Installing a web application on a VPS is the same job as on any server: a web server, PHP or another runtime, a database, and a certificate. The difference is that all four are yours to configure, and the order you do them in decides how much doubling back is involved.

A working order

  1. Secure the server first: keys, firewall, updates. Not after.
  2. Install the web server and confirm it serves a plain page.
  3. Install the runtime and the database.
  4. Create the database and a user with access to it only.
  5. Deploy the application.
  6. Point DNS here.
  7. Issue the certificate, which can only work once DNS resolves here.

The last two are in that order for a reason. A certificate authority verifies you control the domain by reaching it, so requesting a certificate before DNS has moved fails every time, and retrying without fixing DNS fails identically.

Confirm each layer before adding the next

Serve a plain HTML file before installing PHP. Serve a page that reports the runtime version before connecting a database. Confirm the database accepts a connection before deploying the application.

Skipping this means a failure at the end could be any of four layers, and you debug all of them at once. Ten seconds of confirmation per layer removes that entirely.

Database users: one per application

Create a database, then a user with privileges on that database only.

Do not connect applications as the database administrator. A compromised application then reaches every database on the server rather than its own, and the difference between those two outcomes is the whole point of the practice.

Bind the database to localhost. A database port open to the internet is scanned and attacked within hours, and there is almost never a reason for it; the application connects locally.

File ownership

The web server user needs to read your files, and to write only where the application genuinely writes: an uploads directory, a cache directory.

Everything else should be readable and not writable. An application that can rewrite its own code is an application that can be made to rewrite its own code.

Never resolve a permissions problem with 777. It appears constantly in old forum advice and it makes the file writable by anyone on the server, converting an inconvenience into a compromise. The correct fix is nearly always ownership.

Certificates

Use an automated certificate client. It issues, installs and renews without anyone remembering, which removes the most common cause of certificate failure entirely.

Confirm renewal actually works rather than assuming. A renewal that has been failing silently surfaces as a browser warning on a live site, and the first person to notice is usually a visitor.

Then make it survive a reboot

The step people skip. Confirm every service starts automatically, then reboot deliberately and watch what comes back.

Doing that on purpose, while you are watching, is much better than discovering at 3am after an unplanned restart that one service was never enabled at boot.

Backups before traffic

Set them up before the site is live rather than afterwards. A backup arrangement created in response to a problem is created too late by definition. Backing up your VPS explains what to include and where it has to live.

For getting code onto the server repeatably rather than by hand, How to Deploy a Site with Git on a VPS goes into the arrangement.

Before changing a running application, a copy you can break is worth the hour. There is more on building one safely in How to Set Up a Staging Environment on a VPS.

An application started by hand stops when you log out and does not return after a reboot. How to Run an Application as a systemd Service explains handing it to the system instead.

Run the application as its own user

Installing everything as the administrative account is quick and it removes the boundary that limits the damage from any single mistake.

useradd -r -s /usr/sbin/nologin appuser
chown -R appuser:appuser /var/www/app
sudo -u appuser test -w /var/www/app/storage && echo "yazilabilir"

An application compromised while running as its own user reaches that user's files. The same application running as the administrator reaches everything on the machine, including every other application.

Give it write access only where it genuinely writes: uploads, cache, logs. Everything else should be readable and not writable, which also prevents the application modifying its own code, and that is what most web compromises attempt first.

Put a reverse proxy in front rather than exposing the application

An application server listening directly on the public port is doing work it was not designed for.

ss -tlnp | grep -E ':80|:443|:3000|:8000'
curl -sI http://127.0.0.1:3000/ | head -1

Bind the application to the local interface only, and let a web server in front handle the encryption, the static files, the compression and the request limits.

The check is the first command. An application port answering on the public address means it is exposed, and any protection configured in the web server is being bypassed by anyone who connects directly.

Confirm it recovers on its own

An application started by hand runs until something stops it, and the machine that has been up for a year has never proved it comes back.

systemctl is-enabled myapp 2>/dev/null
systemctl restart myapp && sleep 3 && curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/
journalctl -u myapp -n 20 --no-pager

Restart it deliberately and confirm it answers afterwards. Then reboot the machine at a time you choose and confirm the same thing.

Discovering that a service does not start automatically during an unplanned restart is the version of this that costs a night, and the test that prevents it takes two minutes on a quiet afternoon. Running an application as a systemd service covers the unit.