# Deploy Agos VPN

These steps are for a **new Ubuntu 24.04 VPS**. Nothing in this project purchases a VPS or deploys to an external machine automatically. You need a public IPv4 address, SSH access, and a DNS name. The control room and first WireGuard node can share that VPS.

For **cPanel shared hosting at `rtube.site/vpn`**, follow [CPANEL.md](CPANEL.md) for the website, then return to steps 3–4 here on your separate WireGuard VPS. Create `/etc/agos` privately before writing the agent config.

## 1. Copy the project and install Node.js

Install Node.js 22 LTS from the official [Node.js download instructions](https://nodejs.org/en/download). Verify `node --version` reports at least 22.13 and note the path printed by `command -v node`.

Copy the project to `/opt/agos`, excluding the original IZPH XAPK, `node_modules`, local `server/data`, Android build output, and private local files. The API service expects `/usr/bin/node`; update `ExecStart` if your system-wide Node installation lives elsewhere. Do not use a Node installation beneath a user's home directory with the supplied `ProtectHome=true` service.

```sh
cd /opt/agos
npm ci --omit=dev
sudo useradd --system --home /var/lib/agos --shell /usr/sbin/nologin agos
sudo install -d -o agos -g agos -m 700 /var/lib/agos
sudo install -d -m 700 /etc/agos
sudo install -m 644 deploy/agos-api.service /etc/systemd/system/agos-api.service
sudo nano /etc/agos/api.env
```

Put the full public admin URL in that file, with no trailing slash:

```ini
PUBLIC_URL=https://vpn.example.com
```

Replace `vpn.example.com` with your real DNS name, then:

```sh
sudo chmod 600 /etc/agos/api.env
sudo systemctl daemon-reload
sudo systemctl enable --now agos-api
sudo cat /var/lib/agos/bootstrap-admin.txt
```

Save the generated password in your password manager. The runtime data directory contains the database and bootstrap password; do not serve it as public web content or commit it to source control. The service's 0077 umask makes SQLite companion files private as well.

## 2. Put HTTPS in front of the API

Point the DNS A record to your VPS. Install Caddy from its [official Debian/Ubuntu instructions](https://caddyserver.com/docs/install#debian-ubuntu-raspbian).

Use `deploy/Caddyfile` as the site configuration, replacing `vpn.example.com`. If the server already has other Caddy sites, merge this block rather than replacing the whole configuration. On a fresh VPS:

```sh
sudo cp /opt/agos/deploy/Caddyfile /etc/caddy/Caddyfile
sudo nano /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
```

Allow **TCP 80 and 443**, **UDP 51820**, and your SSH port in the provider's firewall and any host firewall. Keep SSH allowed before enabling a firewall. The API stays on loopback port 8787; do not expose that port publicly. Caddy obtains and renews the TLS certificate.

Open the HTTPS domain and sign in. `PUBLIC_URL` specifies the public domain and optional app path. Admin mutations compare the Origin header with the URL’s origin. For a subpath deployment, preserve the full request path through the proxy.

## 3. Prepare WireGuard

On the VPN VPS, run:

```sh
cd /opt/agos
sudo bash deploy/setup-wireguard.sh
```

The script:

- Installs WireGuard, iptables, and Python 3.
- Creates fresh private server keys in `/etc/wireguard/` with private permissions.
- Uses interface `wg-agos`, address `10.66.0.1/24`, and UDP port `51820`.
- Enables IPv4 forwarding and adds NAT for internet traffic.
- Blocks peers from the local VPS services, other peers, and common private/provider-metadata ranges.
- Refuses to replace an existing Agos WireGuard config.

It prints only the **public** key. Copy it into **Add server** in the admin website. Enter the VPS public IPv4 address or public hostname followed by `:51820`, a display name/location, and desired network labels. This version's endpoint form accepts IPv4 addresses or hostnames, not literal IPv6 addresses.

The setup script is meant for a dedicated VPS. Existing Docker/VPN/firewall deployments can require different routing and firewall rules; review the script before combining systems. It does not flush unrelated firewall rules.

## 4. Start the server agent

The admin website displays an **agent token once** after adding a server. On that same VPS:

```sh
sudo nano /etc/agos/agent.json
```

Enter:

```json
{
  "api_url": "https://vpn.example.com",
  "agent_token": "PASTE_THE_AGENT_TOKEN_FROM_THE_ADMIN_WEBSITE"
}
```

Then:

```sh
sudo chmod 600 /etc/agos/agent.json
sudo install -m 644 /opt/agos/deploy/agos-agent.service /etc/systemd/system/agos-agent.service
sudo systemctl daemon-reload
sudo systemctl enable --now agos-agent
sudo systemctl status agos-agent --no-pager
```

The agent requests desired public keys and IPs over verified HTTPS, verifies its local server key, applies the list with `wg syncconf`, and acknowledges the revision. It never sends the WireGuard private server key. Expect Online in the dashboard within about 15 seconds. Each extra VPS gets its own server record and agent token.

## 5. Enroll and test an Android phone

Install `artifacts/agos-vpn-debug.apk` for development. Create a device code in the admin website, enter the full HTTPS admin URL (including `/vpn` if used) and code in the app, choose a server, and connect. Codes expire after 24 hours and work once.

Test with an active data allowance or Wi-Fi first:

1. Accept the Android VPN prompt and allow the connection notification.
2. Confirm **Connected**, not merely **Waiting for handshake**.
3. Browse a site and confirm your visible public IPv4 matches the VPN VPS.
4. Disconnect and confirm normal browsing resumes.
5. Reconnect, revoke the device in the admin UI, and verify the agent removes its peer. Re-enroll using a new code after resetting app access.
6. Check the intended carrier/SIM separately. This project contains no tested no-load configuration.

The development build also permits HTTP **only for localhost/127.0.0.1/10.0.2.2 in the app URL validator** for emulator testing. Release builds require HTTPS. For an emulator on the same development Mac, use `http://10.0.2.2:8787`.

## Diagnostics and recovery

```sh
sudo journalctl -u agos-api -n 60 --no-pager
sudo journalctl -u agos-agent -n 60 --no-pager
sudo systemctl status wg-quick@wg-agos --no-pager
sudo wg show wg-agos
```

- **Awaiting agent:** inspect HTTPS reachability, token, server public-key match, and agent service logs. Agent log output omits tokens and private config contents.
- **Sync pending:** the desired peer list changed and is not acknowledged yet.
- **Waiting for handshake:** check endpoint DNS/IP, provider UDP firewall, host firewall, available mobile data, and agent sync. A WireGuard tunnel being open does not mean the server responded.
- **Connected but cannot browse:** check IPv4 forwarding/NAT and the provider's egress settings. The supplied DNS resolvers must be reachable through the tunnel.
- **Admin gets 403:** ensure the browser URL exactly matches `PUBLIC_URL` and restart the API after changing it.
- **Device reset:** revoke its old entry in the admin UI, generate another enrollment code, and pair again. Reinstalling the app generates a different device key.
- **Lost agent token:** back it up when issued. This starter has no token recovery endpoint. Preserve `/etc/agos/agent.json` securely; if rotating/replacing the node, use a new WireGuard key and server record, and pause the old one.

## Backups and release

Stop the API briefly before copying `/var/lib/agos` to a private encrypted backup, or use SQLite's online backup facilities. Back up the node's `/etc/wireguard/` and `/etc/agos/` separately. Those directories contain credentials; restrict access.

Use your own Android release signing key before distribution. Keep the signing key, passwords, server credentials, enrollment codes, and database out of public repositories. This starter has no billing, automatic node provisioning, account hierarchy, or automatic always-on reconnect.

## Removing the node

Pause it in the admin UI and confirm the agent has synced before stopping it:

```sh
sudo systemctl disable --now agos-agent
sudo systemctl disable --now wg-quick@wg-agos
```

Stopping WireGuard removes the associated Agos firewall rules. IP forwarding remains configured; remove `/etc/sysctl.d/70-agos-forward.conf` only after checking no other service needs forwarding. Keep keys/config backups until you deliberately retire the node.
