aboutsummaryrefslogtreecommitdiffstats
path: root/whiterabbit.sh
diff options
context:
space:
mode:
authorFilip Wandzio <contact@philw.dev>2025-10-01 22:21:25 +0200
committerFilip Wandzio <contact@philw.dev>2025-10-01 22:21:25 +0200
commit37e65300245be45d4000797b3ada53c68022fc26 (patch)
treeae304da2869d2069b3359def36e36d29877fc7c8 /whiterabbit.sh
parent34fbb07af8de311a4d316325bcf574341f6be5dd (diff)
downloadwhiterabbit-37e65300245be45d4000797b3ada53c68022fc26.tar.gz
whiterabbit-37e65300245be45d4000797b3ada53c68022fc26.zip
Implement use flags for subcommants
Optimize synapse pipeline
Diffstat (limited to 'whiterabbit.sh')
-rwxr-xr-xwhiterabbit.sh417
1 files changed, 0 insertions, 417 deletions
diff --git a/whiterabbit.sh b/whiterabbit.sh
deleted file mode 100755
index f8eb350..0000000
--- a/whiterabbit.sh
+++ /dev/null
@@ -1,417 +0,0 @@
1#!/bin/sh
2set -eu
3
4BASE_DIR="/opt/matrix"
5
6# Detect docker compose binary
7DOCKER_COMPOSE=$(command -v docker-compose || command -v "docker" compose || true)
8if [ -z "$DOCKER_COMPOSE" ]; then
9 echo "[ERROR] docker-compose or docker compose not found" >&2
10 exit 1
11fi
12
13usage() {
14 cat <<'EOF'
15whiterabbit: auto-configure Matrix homeservers (Dendrite or Synapse)
16with a global Coturn instance and Nginx + Let's Encrypt proxy.
17
18Main actions:
19 turn Install or configure the global Coturn server
20 dendrite Add a new Matrix server (Dendrite)
21 synapse Add a new Matrix server (Synapse)
22 list Show all configured Matrix servers
23 remove Remove a Matrix server by domain
24
25Notes:
26 • Coturn should be installed only once using 'turn'.
27 • All Matrix servers share the same Coturn (TURN domain/secret).
28 • TLS certificates are issued automatically using Let's Encrypt.
29 • Requirements: docker, docker-compose, nginx, certbot, coturn.
30EOF
31 exit 1
32}
33
34require_nonempty() {
35 VAR_NAME="$1"
36 VAR_VALUE="$2"
37 if [ -z "$VAR_VALUE" ]; then
38 echo "[ERROR] $VAR_NAME cannot be empty" >&2
39 exit 1
40 fi
41}
42
43list_servers() {
44 echo "=== Installed servers ==="
45 ls -1 "$BASE_DIR" 2>/dev/null || echo "No servers installed"
46}
47
48install_turn() {
49 echo "=== Installing global Coturn ==="
50 printf "TURN domain (eg. turn.example.com): "
51 read -r TURN_DOMAIN
52 require_nonempty TURN_DOMAIN "$TURN_DOMAIN"
53
54 printf "TURN IP (eg. 127.0.0.1): "
55 read -r TURN_SERVER_IP
56 require_nonempty TURN_SERVER_IP "$TURN_SERVER_IP"
57
58 printf "Listening device (eg. eth0): "
59 read -r TURN_LISTENING_DEVICE
60 require_nonempty TURN_LISTENING_DEVICE "$TURN_LISTENING_DEVICE"
61
62 printf "TURN shared secret: "
63 read -r TURN_SECRET
64 require_nonempty TURN_SECRET "$TURN_SECRET"
65
66 mkdir -p /etc/turn
67 cat <<EOF > /etc/turn/turnserver.conf
68listening-device=$TURN_LISTENING_DEVICE
69listening-port=3478
70tls-listening-port=5349
71listening-ip=$TURN_SERVER_IP
72min-port=49152
73max-port=65535
74use-auth-secret
75static-auth-secret=$TURN_SECRET
76realm=$TURN_DOMAIN
77syslog
78no-rfc5780
79no-stun-backward-compatibility
80response-origin-only-with-rfc5780
81EOF
82
83 echo "$TURN_DOMAIN" > /etc/turn/domain
84 echo "$TURN_SECRET" > /etc/turn/secret
85
86 if command -v systemctl >/dev/null; then
87 systemctl enable --now coturn || true
88 else
89 service coturn start || true
90 fi
91
92 echo "[OK] Global Coturn configured ($TURN_DOMAIN)"
93}
94
95common_prompts() {
96 printf "Matrix domain (eg. matrix.example.com): "
97 read -r MATRIX_DOMAIN
98 require_nonempty MATRIX_DOMAIN "$MATRIX_DOMAIN"
99
100 printf "Let's Encrypt certificate email: "
101 read -r EMAIL
102 require_nonempty EMAIL "$EMAIL"
103
104 printf "Postgres secret: "
105 read -r DB_PASS
106 require_nonempty DB_PASS "$DB_PASS"
107
108 printf "registration_shared_secret: "
109 read -r REG_SECRET
110 require_nonempty REG_SECRET "$REG_SECRET"
111
112 printf "MATRIX server IP (eg. 127.0.0.1): "
113 read -r MATRIX_SERVER_IP
114 require_nonempty MATRIX_SERVER_IP "$MATRIX_SERVER_IP"
115
116 TURN_DOMAIN=$(cat /etc/turn/domain)
117 TURN_SECRET=$(cat /etc/turn/secret)
118
119 # Generate unique port numbers from hash of domain
120 HASH=$(printf "%s" "$MATRIX_DOMAIN" | cksum | cut -d ' ' -f1)
121 PORT_BASE=$(( (HASH % 1000) + 8000 ))
122 PORT_HTTP=$PORT_BASE
123 PORT_HTTPS=$((PORT_BASE+1))
124}
125
126configure_nginx() {
127 DOMAIN="$1"
128 SERVICE_PORT="$2"
129
130 mkdir -p /etc/nginx/sites-available
131 mkdir -p /etc/nginx/sites-enabled
132
133 cat <<EOF > "/etc/nginx/sites-available/$DOMAIN"
134server {
135 listen 80;
136 server_name $DOMAIN;
137
138 location /.well-known/matrix/server {
139 default_type application/json;
140 return 200 '{ "m.server": "$DOMAIN:443" }';
141 }
142
143 location /.well-known/matrix/client {
144 default_type application/json;
145 return 200 '{
146 "m.homeserver": { "base_url": "https://$DOMAIN" },
147 "m.identity_server": { "base_url": "https://vector.im" }
148 }';
149 }
150
151 location / {
152 proxy_pass http://127.0.0.1:$SERVICE_PORT;
153 proxy_set_header Host \$host;
154 proxy_set_header X-Forwarded-For \$remote_addr;
155 }
156}
157EOF
158
159 ln -sf "/etc/nginx/sites-available/$DOMAIN" "/etc/nginx/sites-enabled/$DOMAIN"
160 nginx -t || { echo "[ERROR] Invalid nginx config"; exit 1; }
161 if command -v systemctl >/dev/null; then
162 systemctl reload nginx
163 else
164 nginx -s reload
165 fi
166
167 if command -v certbot >/dev/null; then
168 certbot --nginx --non-interactive --agree-tos -m "$EMAIL" -d "$DOMAIN" || {
169 echo "[WARN] Certbot failed for $DOMAIN"
170 }
171 else
172 echo "[WARN] Certbot not installed, skipping TLS setup"
173 fi
174
175 echo "[OK] Nginx and SSL certificate configured for $DOMAIN"
176}
177
178
179install_dendrite() {
180 echo "=== Installing Matrix Dendrite ==="
181 common_prompts
182
183 INSTALL_DIR="$BASE_DIR/$MATRIX_DOMAIN"
184 mkdir -p "$INSTALL_DIR/config"
185 cd "$INSTALL_DIR" || exit 1
186
187 cat <<EOF > .env
188POSTGRES_HOSTNAME=postgres
189POSTGRES_VERSION=15-alpine
190POSTGRES_USER=dendrite
191POSTGRES_PASSWORD=$DB_PASS
192POSTGRES_DB=dendrite
193
194MONOLITH_HOSTNAME=monolith
195MONOLITH_IMAGE=matrixdotorg/dendrite-monolith:latest
196MONOLITH_PORT_HTTP=$PORT_HTTP
197MONOLITH_PORT_HTTPS=$PORT_HTTPS
198EOF
199
200cat <<EOF > compose.yml
201services:
202 postgres:
203 hostname: \${POSTGRES_HOSTNAME:-postgres}
204 image: postgres:\${POSTGRES_VERSION:-15-alpine}
205 restart: always
206 volumes:
207 - ./dendrite_postgres_data:/var/lib/postgresql/data
208 environment:
209 POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-$DB_PASS}
210 POSTGRES_USER: \${POSTGRES_USER:-dendrite}
211 POSTGRES_DB: \${POSTGRES_DB:-dendrite}
212 healthcheck:
213 test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER:-dendrite}"]
214 interval: 5s
215 timeout: 5s
216 retries: 5
217 networks:
218 - internal
219
220 monolith:
221 hostname: \${MONOLITH_HOSTNAME:-monolith}
222 image: \${MONOLITH_IMAGE:-matrixdotorg/dendrite-monolith:latest}
223 ports:
224 - \${MONOLITH_PORT_HTTP:-8008}:8008
225 - \${MONOLITH_PORT_HTTPS:-8448}:8448
226 volumes:
227 - ./config:/etc/dendrite
228 - ./dendrite_media:/var/dendrite/media
229 - ./dendrite_jetstream:/var/dendrite/jetstream
230 - ./dendrite_search_index:/var/dendrite/searchindex
231 - ./:/mnt
232 depends_on:
233 postgres:
234 condition: service_healthy
235 networks:
236 - internal
237 restart: unless-stopped
238
239networks:
240 internal:
241 attachable: true
242volumes:
243 dendrite_postgres_data:
244 dendrite_media:
245 dendrite_jetstream:
246 dendrite_search_index:
247EOF
248
249 # --- Plik konfiguracji Dendrite ---
250
251cat <<EOF > config/dendrite.yaml
252version: 2
253global:
254 server_name: $MATRIX_DOMAIN
255 private_key: /mnt/matrix_key.pem
256 tls_cert: /mnt/server.crt
257 tls_key: /mnt/server.key
258 old_private_keys: []
259 key_validity_period: 168h0m0s
260 database:
261 connection_string: postgresql://dendrite:$DB_PASS@postgres/dendrite?sslmode=disable
262 max_open_conns: 90
263 max_idle_conns: 5
264 conn_max_lifetime: -1
265 well_known_server_name: "$MATRIX_DOMAIN:443"
266 well_known_client_name: "https://$MATRIX_DOMAIN"
267 cache:
268 max_size_estimated: 1gb
269 max_age: 1h
270 trusted_third_party_id_servers:
271 - matrix.org
272 - vector.im
273 disable_federation: false
274 report_stats:
275 enabled: false
276client_api:
277 registration_disabled: true
278 registration_shared_secret: "$REG_SECRET"
279 turn:
280 turn_user_lifetime: "5m"
281 turn_uris:
282 - turn:$TURN_DOMAIN?transport=udp
283 - turn:$TURN_DOMAIN?transport=tcp
284 turn_shared_secret: "$TURN_SECRET"
285federation_api:
286 send_max_retries: 16
287 disable_tls_validation: false
288media_api:
289 base_path: ./media_store
290 max_file_size_bytes: 10485760
291sync_api:
292 search:
293 enabled: false
294 index_path: "./searchindex"
295user_api:
296 auto_join_rooms:
297 - "#main:$MATRIX_DOMAIN"
298logging:
299 - type: std
300 level: info
301 - type: file
302 level: info
303 params:
304 path: ./logs
305jetstream:
306 addresses: []
307 disable_tls_validation: false
308 storage_path: ./
309 topic_prefix: Dendrite
310metrics:
311 enabled: false
312 basic_auth:
313 username: metrics
314 password: metrics
315dns_cache:
316 enabled: false
317 cache_size: 256
318 cache_lifetime: "5m"
319EOF
320
321 # Generate necessary project directory
322 $DOCKER_COMPOSE up -d
323
324 $DOCKER_COMPOSE down
325
326 # --- Generowanie kluczy Dendrite + TLS jeśli nie istnieją ---
327 echo "[INFO] Generating Dendrite keys..."
328
329docker run --rm --entrypoint="" -v $(pwd):/mnt matrixdotorg/dendrite-monolith:latest /usr/bin/generate-keys -private-key /mnt/matrix_key.pem -tls-cert /mnt/server.crt -tls-key /mnt/server.key
330 echo "[OK] Keys generated in $PWD"
331
332 # --- Start kontenerów ---
333 $DOCKER_COMPOSE up -d
334
335 # --- Konfiguracja Nginx + SSL/TLS ---
336 configure_nginx "$MATRIX_DOMAIN" "$PORT_HTTP"
337
338 echo "[OK] Dendrite server ($MATRIX_DOMAIN) is running."
339}
340
341install_synapse() {
342 echo "=== Installing Matrix Synapse ==="
343 common_prompts
344
345 INSTALL_DIR="$BASE_DIR/$MATRIX_DOMAIN"
346 mkdir -p "$INSTALL_DIR"
347 cd "$INSTALL_DIR" || exit 1
348
349 cat <<EOF > docker-compose.yml
350version: '3.4'
351services:
352 db:
353 image: postgres:15-alpine
354 environment:
355 POSTGRES_USER: synapse
356 POSTGRES_PASSWORD: $DB_PASS
357 POSTGRES_DB: synapse
358 volumes:
359 - ./db:/var/lib/postgresql/data
360
361 synapse:
362 image: matrixdotorg/synapse:latest
363 depends_on: [ db ]
364 environment:
365 SYNAPSE_SERVER_NAME: $MATRIX_DOMAIN
366 SYNAPSE_REPORT_STATS: "yes"
367 POSTGRES_PASSWORD: $DB_PASS
368 ports:
369 - $PORT_HTTP:8008
370 - $PORT_HTTPS:8448
371 volumes:
372 - ./data:/data
373EOF
374
375 $DOCKER_COMPOSE up -d
376
377 cat <<EOF > data/homeserver-extra.yaml
378turn_uris: [ "turn:$TURN_DOMAIN?transport=udp", "turn:$TURN_DOMAIN?transport=tcp" ]
379turn_shared_secret: "$TURN_SECRET"
380turn_user_lifetime: "5m"
381EOF
382
383 configure_nginx "$MATRIX_DOMAIN" "$PORT_HTTP"
384
385 echo "[OK] Synapse server ($MATRIX_DOMAIN) is running."
386}
387
388remove_server() {
389 DOMAIN="$1"
390 [ -z "$DOMAIN" ] && usage
391
392 SERVER_DIR="$BASE_DIR/$DOMAIN"
393 case "$DOMAIN" in
394 ""|"/"|".") echo "[ERROR] Refusing to delete dangerous path ($DOMAIN)"; exit 1 ;;
395 esac
396
397 if [ -d "$SERVER_DIR" ]; then
398 (cd "$SERVER_DIR" && $DOCKER_COMPOSE down -v) || true
399 rm -rf "$SERVER_DIR"
400 fi
401
402 rm -f "/etc/nginx/sites-available/$DOMAIN" "/etc/nginx/sites-enabled/$DOMAIN"
403 nginx -t && (systemctl reload nginx 2>/dev/null || nginx -s reload)
404 echo "[OK] Server $DOMAIN removed."
405}
406
407# --- CLI router ---
408CMD="${1:-}"
409
410case "$CMD" in
411 turn) install_turn ;;
412 dendrite) install_dendrite ;;
413 synapse) install_synapse ;;
414 list) list_servers ;;
415 remove) remove_server "${2:-}" ;;
416 *) usage ;;
417esac