Skip to content

Commit ee7904d

Browse files
authored
Merge pull request #1 from chilleco/add-relay
Add Relay
2 parents 283beda + e5c0252 commit ee7904d

9 files changed

Lines changed: 157 additions & 7 deletions

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@ GRAFANA_PASS=
2727

2828
# Sentry
2929
SENTRY_PORT=9002
30+
SENTRY_RELAY_PORT=9003
3031
SENTRY_SECRET_KEY=
32+
SENTRY_RELAY_OPEN_REGISTRATION=true
3133
SENTRY_SINGLE_ORGANIZATION=1
3234
SENTRY_EVENT_RETENTION_DAYS=30
3335
SENTRY_DB_NAME=sentry
3436
SENTRY_DB_USER=sentry
3537
SENTRY_DB_PASS=
3638
SENTRY_SERVER_EMAIL=sentry@chill.services
39+
# Optional: required only for email notifications / password reset emails
3740
SENTRY_SMTP_HOST=
3841
SENTRY_SMTP_PORT=587
3942
SENTRY_SMTP_USER=

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ env/
1414

1515
# Data
1616
/data/
17+
18+
# Relay credentials (generated locally)
19+
infra/sentry/relay/credentials.json

AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
This repository manages the infrastructure stack for the `chill` ecosystem.
55

66
- `compose.yml`: main Docker Compose definition for MinIO, MongoDB, Prometheus, Loki, Alloy, Grafana, and Sentry.
7-
- `infra/`: service-level configuration (`nginx/`, `mongo/`, `prometheus/`, `loki/`, `alloy/`, `grafana/`).
7+
- `infra/`: service-level configuration (`nginx/`, `mongo/`, `prometheus/`, `loki/`, `alloy/`, `grafana/`, `sentry/`).
88
- `scripts/`: helper scripts (`scripts/main.py`, `scripts/lib/s3.py`).
99
- `.github/workflows/deploy.yml`: deploy pipeline for `main`.
1010
- `.env.example`: template for local environment variables.
1111

1212
## Build, Test, and Development Commands
1313
- `make up`: build and start all services in detached mode (`docker compose -p base up --build -d`).
14+
- `make sentry-init`: generate Relay credentials file for Sentry (`infra/sentry/relay/credentials.json`) if it does not exist.
1415
- `make down`: stop running stack containers.
1516
- `make status`: show container status and exposed ports.
1617
- `make mongo`: open `mongosh` inside the running MongoDB container.
@@ -22,6 +23,7 @@ This repository manages the infrastructure stack for the `chill` ecosystem.
2223
- YAML/Compose: 2-space indentation, lowercase service names (`base-mongo`, `base-grafana`).
2324
- Environment variables: uppercase with clear prefixes (`MONGO_*`, `GRAFANA_*`, `SENTRY_*`, ...) with entity suffix (`USER` for admin/user login, `PASS` for admin/user password/key, `ID` for account/user/application ID, `TOKEN` for account/user/application secret token, `PORT` for container port exporting, ...).
2425
- Keep config files service-scoped under `infra/<service>/` and avoid cross-service coupling in a single file.
26+
- Nginx routing: keep Sentry ingest routes (`/api/store/`, `/api/<project>/...`, `/api/0/relays/`) before the catch-all `/` route and proxy them to Relay.
2527

2628
## Testing Guidelines
2729
There is no formal automated test suite yet. Validate changes with infrastructure smoke checks:
@@ -43,4 +45,5 @@ There is no formal automated test suite yet. Validate changes with infrastructur
4345
- Never commit real secrets; copy `.env.example` to `.env` and keep credentials local.
4446
- Ensure `DATA_PATH` directories exist and are writable before `make up`.
4547
- Set strong local values for `SENTRY_SECRET_KEY` and `SENTRY_DB_PASS` before enabling Sentry.
48+
- Keep `infra/sentry/relay/credentials.json` local-only (generated on host and gitignored).
4649
- Treat `make set` and TLS changes as production-impacting operations; review host/domain variables first.

Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ set:
1010
sudo chmod -R a+w ~/data/
1111
sudo chmod 0700 ~/.ssh
1212
sudo chmod -R 0600 ~/.ssh/*
13-
export EXTERNAL_HOST=${EXTERNAL_HOST} DATA_PATH=${DATA_PATH} PROMETHEUS_PORT=${PROMETHEUS_PORT} GRAFANA_PORT=${GRAFANA_PORT} SENTRY_PORT=${SENTRY_PORT}; \
14-
envsubst '$${EXTERNAL_HOST} $${DATA_PATH} $${PROMETHEUS_PORT} $${GRAFANA_PORT} $${SENTRY_PORT}' < infra/nginx/prod.conf > /etc/nginx/sites-enabled/base.conf
13+
export EXTERNAL_HOST=${EXTERNAL_HOST} DATA_PATH=${DATA_PATH} PROMETHEUS_PORT=${PROMETHEUS_PORT} GRAFANA_PORT=${GRAFANA_PORT} SENTRY_PORT=${SENTRY_PORT} SENTRY_RELAY_PORT=${SENTRY_RELAY_PORT}; \
14+
envsubst '$${EXTERNAL_HOST} $${DATA_PATH} $${PROMETHEUS_PORT} $${GRAFANA_PORT} $${SENTRY_PORT} $${SENTRY_RELAY_PORT}' < infra/nginx/prod.conf > /etc/nginx/sites-enabled/base.conf
1515
sudo systemctl restart nginx
1616
sudo certbot --nginx
1717

@@ -21,11 +21,15 @@ certs:
2121
sudo systemctl restart nginx
2222
sudo certbot --nginx
2323

24+
.PHONY: sentry-init
25+
sentry-init:
26+
./scripts/ensure_sentry_relay_credentials.sh
27+
2428
# ============================================================================
2529
# Lifecycle
2630
# ============================================================================
2731

28-
up:
32+
up: sentry-init
2933
docker compose -p base up --build -d
3034

3135
down:

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A base of file storages and databases to support projects ecosystem
1111
sudo sysctl -w vm.max_map_count=262144
1212
```
1313

14-
4. Run `make run`
14+
4. Run `make up` (it auto-generates `infra/sentry/relay/credentials.json` on first run)
1515

1616
5. Set up domains `make set`
1717

@@ -23,3 +23,5 @@ sudo sysctl -w vm.max_map_count=262144
2323

2424
9. Create Sentry admin user after stack startup:
2525
`docker exec -it base-sentry-web sentry createuser --superuser --email <email>`
26+
27+
10. SMTP is optional for Sentry startup; leave `SENTRY_SMTP_*` empty if you do not need email notifications.

compose.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
version: "3.11"
21
x-sentry-env: &sentry_env
32
SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-change-me}
43
SENTRY_SINGLE_ORGANIZATION: ${SENTRY_SINGLE_ORGANIZATION:-1}
4+
SENTRY_RELAY_OPEN_REGISTRATION: ${SENTRY_RELAY_OPEN_REGISTRATION:-true}
55
SENTRY_EVENT_RETENTION_DAYS: ${SENTRY_EVENT_RETENTION_DAYS:-30}
66
SENTRY_POSTGRES_HOST: sentry-postgres
77
SENTRY_DB_NAME: ${SENTRY_DB_NAME:-sentry}
@@ -238,6 +238,24 @@ services:
238238
sentry-redis:
239239
condition: service_healthy
240240

241+
sentry-relay:
242+
image: getsentry/relay:latest
243+
container_name: base-sentry-relay
244+
restart: unless-stopped
245+
volumes:
246+
- ./infra/sentry/relay:/work/.relay
247+
command: run --config /work/.relay
248+
ports:
249+
- "${SENTRY_RELAY_PORT:-9003}:3000"
250+
healthcheck:
251+
test: ["CMD", "/bin/relay", "healthcheck"]
252+
interval: 15s
253+
timeout: 5s
254+
retries: 10
255+
depends_on:
256+
sentry-web:
257+
condition: service_started
258+
241259
sentry-worker:
242260
image: getsentry/sentry:latest
243261
container_name: base-sentry-worker

infra/nginx/prod.conf

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,35 @@ server {
9191

9292
root /;
9393

94+
location /api/store/ {
95+
proxy_pass http://0.0.0.0:${SENTRY_RELAY_PORT};
96+
proxy_set_header Host $host;
97+
proxy_set_header X-Real-IP $remote_addr;
98+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
99+
proxy_set_header X-Forwarded-Proto $scheme;
100+
proxy_http_version 1.1;
101+
}
102+
103+
location ~ ^/api/[1-9]\d*/ {
104+
proxy_pass http://0.0.0.0:${SENTRY_RELAY_PORT};
105+
proxy_set_header Host $host;
106+
proxy_set_header X-Real-IP $remote_addr;
107+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
108+
proxy_set_header X-Forwarded-Proto $scheme;
109+
proxy_http_version 1.1;
110+
}
111+
112+
location ^~ /api/0/relays/ {
113+
proxy_pass http://0.0.0.0:${SENTRY_RELAY_PORT};
114+
proxy_set_header Host $host;
115+
proxy_set_header X-Real-IP $remote_addr;
116+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
117+
proxy_set_header X-Forwarded-Proto $scheme;
118+
proxy_http_version 1.1;
119+
}
120+
94121
location / {
95-
proxy_pass http://0.0.0.0:${SENTRY_PORT}$request_uri;
122+
proxy_pass http://0.0.0.0:${SENTRY_PORT};
96123
proxy_set_header Host $host;
97124
proxy_set_header X-Real-IP $remote_addr;
98125
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

infra/sentry/relay/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
relay:
2+
mode: managed
3+
upstream: "http://sentry-web:9000/"
4+
host: 0.0.0.0
5+
port: 3000
6+
7+
logging:
8+
level: WARN
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env bash
2+
# chmod +x /root/base/scripts/ensure_sentry_relay_credentials.sh
3+
4+
set -euo pipefail
5+
6+
project="${1:-base}"
7+
relay_dir="infra/sentry/relay"
8+
relay_config="${relay_dir}/config.yml"
9+
relay_credentials="${relay_dir}/credentials.json"
10+
11+
is_valid_credentials() {
12+
local file_path="$1"
13+
grep -q '"public_key"' "${file_path}" && grep -q '"secret_key"' "${file_path}"
14+
}
15+
16+
ensure_relay_permissions() {
17+
chmod 755 "${relay_dir}" 2>/dev/null || true
18+
[[ -e "${relay_config}" ]] && chmod 644 "${relay_config}" 2>/dev/null || true
19+
[[ -e "${relay_credentials}" ]] && chmod 644 "${relay_credentials}" 2>/dev/null || true
20+
}
21+
22+
write_default_relay_config() {
23+
cat > "${relay_config}" <<'YAML'
24+
relay:
25+
mode: managed
26+
upstream: "http://sentry-web:9000/"
27+
host: 0.0.0.0
28+
port: 3000
29+
30+
logging:
31+
level: WARN
32+
YAML
33+
}
34+
35+
mkdir -p "${relay_dir}"
36+
ensure_relay_permissions
37+
38+
if [[ ! -s "${relay_config}" ]]; then
39+
write_default_relay_config
40+
fi
41+
ensure_relay_permissions
42+
43+
if grep -q '^[[:space:]]*processing:' "${relay_config}" && ! grep -q 'kafka_config' "${relay_config}"; then
44+
echo "Relay config has 'processing' enabled without 'kafka_config', resetting to default config."
45+
write_default_relay_config
46+
fi
47+
48+
if [[ -e "${relay_credentials}" && ! -s "${relay_credentials}" ]]; then
49+
echo "Relay credentials are empty, regenerating: ${relay_credentials}"
50+
rm -f "${relay_credentials}"
51+
fi
52+
53+
if [[ -s "${relay_credentials}" ]]; then
54+
if is_valid_credentials "${relay_credentials}"; then
55+
ensure_relay_permissions
56+
echo "Relay credentials already exist: ${relay_credentials}"
57+
exit 0
58+
fi
59+
60+
echo "Relay credentials are invalid, regenerating: ${relay_credentials}"
61+
rm -f "${relay_credentials}"
62+
fi
63+
64+
tmp_credentials="${relay_credentials}.tmp"
65+
rm -f "${tmp_credentials}"
66+
67+
# Pull first to avoid implicit pull output polluting generated JSON.
68+
docker compose -p "${project}" pull sentry-relay >/dev/null 2>&1 || true
69+
docker compose -p "${project}" run --rm --no-deps -T sentry-relay credentials generate --stdout > "${tmp_credentials}"
70+
71+
if ! is_valid_credentials "${tmp_credentials}"; then
72+
echo "Failed to generate valid relay credentials."
73+
echo "--- ${tmp_credentials} ---"
74+
cat "${tmp_credentials}" || true
75+
echo "--- end ---"
76+
rm -f "${tmp_credentials}"
77+
exit 1
78+
fi
79+
80+
mv "${tmp_credentials}" "${relay_credentials}"
81+
ensure_relay_permissions
82+
echo "Relay credentials written to ${relay_credentials}"

0 commit comments

Comments
 (0)