# Deploy SiteWatch on a Hostinger VPS

This guide deploys the current self-hosted SiteWatch build at a public HTTPS address so a WordPress site on Hostinger can send reports to it. It assumes the VPS is dedicated to SiteWatch and does not contain data you need to keep. A VPS is a paid Hostinger service; this guide does not buy or configure one for you.

**If hPanel has no VPS listed:** deployment cannot start yet. Provision a VPS in Hostinger first, or ask the account owner to do so. Keep any existing website hosting intact; SiteWatch needs its own server. Once hPanel shows the new VPS and its public IP, continue below. Do not reinstall an existing VPS unless you have verified it contains no data you need, because changing its operating system can erase it.

## Suggested starting size

For the lowest-cost private pilot, **KVM 1 (1 vCPU, 4 GB RAM, 50 GB NVMe)** is sufficient to begin a one-site test, but capacity has not been load-tested. Hostinger currently advertises it at **$6.49/month on a two-year term**, paid upfront (about **$155.76 before tax**), and renews at **$11.99/month**. Choose **KVM 2 (2 vCPU, 8 GB RAM, 100 GB NVMe)** if you want more room for scans and containers; the current page displays **$8.79/month** on its two-year offer, paid upfront (about **$210.96 before tax**), and renews at **$14.99/month**. Offers vary by account and date, so confirm the checkout total, renewal term, taxes, and add-ons before ordering. The lower rate trades flexibility for a long prepayment; DigitalOcean offers clearer monthly billing at a higher price. [Hostinger VPS plans](https://www.hostinger.com/vps-hosting)

Choose the Docker template for Ubuntu 24.04. Either size is only a private pilot, not a capacity promise for a paid multi-customer service: production scan concurrency, retained data, alert volume, and customer count have not been load-tested. Before enabling subscriptions, measure those workloads on the selected VPS and resize or separate services where the measurements require it. Plan prices and renewal terms change; verify them in hPanel before ordering. Hostinger VPS setup remains manual even though its dashboard includes Docker management; choosing a VPS does not make SiteWatch operations fully managed. [Hostinger VPS dashboard](https://www.hostinger.com/support/5726606-how-to-use-the-vps-dashboard-in-hostinger/)

## 1. Prepare the VPS and hostname

1. In Hostinger hPanel, open **VPS → Manage → OS & Panel → Operating System** and select Hostinger's Docker template for Ubuntu 24.04. The template installs Docker and Compose. Applying or changing an OS can erase the VPS, so use this only for a new or disposable server. [Hostinger Docker template guide](https://www.hostinger.com/support/8306612-how-to-use-the-docker-vps-template-at-hostinger/)
2. Copy the VPS public IPv4 address from hPanel. Keep SSH access restricted to your own IP where the firewall supports source restrictions.
3. Pick a domain you control, for example `monitor.example.com`. At the DNS provider for that domain, create an **A** record for `monitor` pointing to the VPS IPv4. Remove conflicting A records. Leave the AAAA record absent unless the VPS has working public IPv6 and its firewall permits the same web traffic. DNS changes can take time to become visible. [Hostinger A record guide](https://support.hostinger.com/en/articles/4468886-how-to-manage-a-records)
4. In **VPS → Security → Firewall**, activate a firewall group with inbound TCP 80 and 443 and UDP 443 allowed from anywhere. Restrict SSH to your own IP, using the SSH port shown in hPanel. Hostinger says the managed VPS firewall drops traffic by default until accept rules are added. [Hostinger firewall guide](https://www.hostinger.com/support/8172641-how-to-use-a-managed-vps-firewall-at-hostinger/)

## 2. Copy the tested SiteWatch source package

From PowerShell on the computer that has the SiteWatch checkout, copy the generated source archive to the VPS. Replace `VPS_IP` with the public IPv4 shown in hPanel:

```powershell
scp "C:\Users\alpha\OneDrive\Desktop\Clients\TaskLine\sitewatch\sitewatch-source.zip" root@VPS_IP:/root/sitewatch-source.zip
```

If Hostinger shows a different SSH account or port, use those values. On the VPS, unpack the archive into `/opt` so its top-level `sitewatch/` folder becomes `/opt/sitewatch`:

```bash
apt-get update
apt-get install -y unzip
mkdir -p /opt
unzip -q /root/sitewatch-source.zip -d /opt
cd /opt/sitewatch
```

The source archive includes the Docker files and application source but excludes `.env`, database files, owner keys, connector credentials, dependencies, and Git history. Keep the archive private because it contains unpublished source code.

## 3. Install the image scanner and configure HTTPS

Create a private environment file and keep new customer signup closed:

```bash
cp .env.example .env
chmod 600 .env
grep -nE '^(ALLOW_SIGNUP|PUBLIC_URL)=' .env
```

Confirm `ALLOW_SIGNUP=false`. Do not add payment, email, SMS, or AI credentials yet. Install Grype and Cosign using [Anchore's official installation guidance](https://github.com/anchore/grype#installation) and enable Grype's release-signature verification. Confirm `grype version` works for the deployment account. The deployment helper builds the SiteWatch image, refreshes Grype's vulnerability database, scans every image in the resolved Compose configuration with `--fail-on high`, and starts the stack only if all scans succeed. Missing scanner, scanner/database errors, and high/critical findings stop the deployment.

The helper builds a custom Caddy 2.11.7 image from pinned official builder/runtime images, verifies the compiled Go and `x/net` versions, and scans the final candidate before startup. The candidate has not been built or scanned on this Windows host; let the required Grype result decide whether deployment can proceed. Do not bypass a high/critical finding or scanner error.

After the scans pass, use the deployment helper to set the public URL, issue HTTPS certificates through Caddy, and verify the health endpoint and closed signup state:

```bash
./scripts/deploy-public.sh --url https://monitor.example.com
```

Replace the example hostname with the DNS name you configured. The command must run on the VPS after DNS points to it and ports 80/443 are reachable. It can take up to three minutes for the public HTTPS check. If it fails, inspect DNS, the Hostinger firewall, and `docker compose -f compose.yaml -f compose.public.yaml logs caddy sitewatch`. The script does not open firewall rules, configure DNS, or make real email/payment providers ready.

Open the new HTTPS address and sign in with the owner key. Retrieve it on the VPS and save it in a password manager:

```bash
cd /opt/sitewatch
docker compose -f compose.yaml -f compose.public.yaml exec sitewatch cat /data/owner-key
```

Do not paste the owner key, `.env`, SSH password, or private SSH key into chat, WordPress, or screenshots. WordPress receives only its per-site connector token.

## 4. Connect the Skyza WordPress site

1. In SiteWatch, add the exact public URL for the Skyza website and enable backend reporting. Save the generated Site ID and connector token somewhere private; the token is shown only once.
2. In the website's **Connectors** setup, download the WordPress ZIP and install it in WordPress. If the plugin is already installed, keep it and open **Settings → SiteWatch**.
3. Enter the dashboard URL, such as `https://monitor.example.com`, the Site ID, and that site's connector token. Save, then use **Send heartbeat now**.
4. Confirm the SiteWatch website changes from **Awaiting setup** and shows a received report. If it does not, check WordPress's connector status and verify that the VPS hostname resolves publicly from the WordPress host. Do not enter the owner's login key here.

## 5. Keep signup closed until launch checks pass

The deployment command only verifies public HTTPS health and disabled signup. Before inviting subscribers, complete the manual gates in the dashboard's readiness panel: test a real checkout and signed Stripe webhook lifecycle, receive real email and alert deliveries, test backup restoration, verify that the independent watchdog can alert during a dashboard outage, and finish security, privacy, support, and cancellation policies. Configure provider keys only through the private VPS `.env`; restart with `docker compose -f compose.yaml -f compose.public.yaml up -d` after changes.

Protect and back up the VPS data volume off-host. A backup stored only on this VPS cannot recover data after VPS loss. Monitor the public dashboard from a separate host and schedule operating-system, Docker image, and SiteWatch updates with a verified backup and rollback plan. See [backup and recovery](BACKUP_RECOVERY.md), [provider configuration](PROVIDERS.md), and [release status](RELEASE_STATUS.md).

This runbook has not been exercised against a live Hostinger VPS. Real DNS propagation, firewall behavior, certificate issuance, VPS sizing, restoration, and WordPress-to-VPS delivery remain external acceptance checks.
