Document deploy.sh and where the observability platform lives

phase-1: deploy via deploy.sh, correct the container count, and note
that stripped host ports leave no path for the Phase 5 scrape.
phase-2: explain why Grafana is not on the Ledgerline server and why
Cloudflare's proxy never forwards :3000 or the other platform ports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Movses Aslanyan
2026-10-12 11:01:49 +03:30
co-authored by Claude Opus 5.5
parent 79a41bf869
commit 34a11da848
2 changed files with 34 additions and 4 deletions
+15 -4
View File
@@ -13,8 +13,9 @@ just the config: the frontend loads, `/api/health/all` reports every service
- **Target:** the throwaway server `czy` (Ubuntu 24.04, 1 vCPU, 1 GB RAM), repo
at `/opt/apps/LedgerLine`. Docker 29.9 and Compose v5.6 installed from
Docker's apt repo. A 2 GB swapfile was added (persisted in `/etc/fstab`) —
nine containers do not fit in 1 GB of RAM without it, and steady state still
uses roughly 700 MB plus swap.
ten containers (nine Ledgerline + Traefik) do not fit in 1 GB of RAM without
it, and steady state still uses roughly 600–700 MB plus swap. There is no
headroom for the observability platform on this host.
- **How it's wired:** `docker-compose.traefik.yml` is an *override*, not an
edit of `docker-compose.yml`, so local development is unchanged. It adds
Traefik v3.6 on ports 80/443 (Docker provider, `exposedByDefault=false`,
@@ -25,8 +26,13 @@ just the config: the frontend loads, `/api/health/all` reports every service
- **No application or `tests/` changes.** The Dockerfile and base compose file
are untouched; schema applied and data seeded on the server with the same
steps as `make seed` (800 accounts, 250,000 transactions).
- **Deploy / redeploy command** (always both files — a bare `docker compose up`
would use the base file alone and publish every port):
- **Deploy / redeploy:** run `./deploy.sh` from your own machine. It SSHes to
`czy` (override with `DEPLOY_HOST` / `DEPLOY_DIR`), does `git pull --ff-only`
in `/opt/apps/LedgerLine`, and runs the compose command below. The server
pulls from the remote, so push first; the script warns about unpushed
commits. The underlying command, if run by hand on the server (always both
files — a bare `docker compose up` would use the base file alone and
publish every port):
```bash
docker compose -f docker-compose.yml -f docker-compose.traefik.yml up -d --build
@@ -46,6 +52,11 @@ just the config: the frontend loads, `/api/health/all` reports every service
server is disposable by design, and Traefik's state lives in the
`letsencrypt` volume, which is lost on an OS reinstall (a new certificate is
simply issued on the next run).
- **Consequence for later phases:** because `!reset` strips every service's
host port, nothing outside `czy` can reach a service's `/metrics` directly.
The Phase 5 scrape (Prometheus on the observability host →
`prometheus_extra_scrape_jobs`) needs a deliberate path in — e.g. a
firewalled port or a Traefik route — decided before Phase 5.
**Time-box:** 1 evening.
+19
View File
@@ -63,6 +63,25 @@ than abstract.
`ansible-playbook playbooks/grafana-stack.yml`. Verify every endpoint from the
README's table answers: Grafana 3000, Prometheus 9090, Alertmanager 9093,
Loki 3100, Tempo 3200, Alloy UI 12345, OTLP 4317/4318.
**Where the platform lives — not on the Ledgerline server.** Grafana (3000)
and the rest come from the Ansible stack, not from Ledgerline's compose
files, so `ledgerline.vione.cloud:3000` will never show Grafana. Three
reasons it belongs on its own host:
- `czy` has 1 GB RAM and Ledgerline already fills it; the platform README
recommends 2 vCPU / 4 GB for the Grafana stack.
- Phase 1's rule is that only 22/80/443 are open on `czy`; the platform
publishes seven more ports.
- `ledgerline.vione.cloud` is behind Cloudflare's proxy, which only forwards
ports 80, 8080, 8880, 2052, 2082, 2086, 2095 (HTTP) and 443, 2053, 2083,
2087, 2096, 8443 (HTTPS). Port 3000 (and 3100, 3200, 4318, 9090, 12345)
never reaches the origin through a proxied hostname.
So reach the platform by the obs host's IP, an SSH tunnel, or a separate
**DNS-only** (grey-cloud) record. The platform's ports are published on all
interfaces with little or no auth — firewall them to your own IP plus
`czy`'s IP (which needs 4318 for OTLP). `<obs-host>` below means that host,
reached from `czy` over the internet.
Then open the Alloy UI and **read the component graph** — it shows you the exact
pipeline, including the fact that the OTLP receiver has only a traces output.
Seeing that in the UI before you get bitten by it is worth ten minutes.