sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
servidor: el crawler de Meta queda vetado del todo, a pedido del usuario
1// Config DESPLEGADA de `saywa` en la caja `takana` (2.29.29.217) — el servidor de borde que
2// reemplazó a caddy el 2026-10-20. Esto es una COPIA de /etc/saywa/saywa.ron, versionada acá
3// porque antes vivía SÓLO en /etc del anfitrión: si la caja se rehace, se pierde. Mismo criterio
4// que `cortafuegos-entrada.ron`, al lado.
5//
6// saywa check --config scripts/servidor/saywa.ron # valida sin arrancar
7// saywa explain --config scripts/servidor/saywa.ron URL # qué contestaría, y por qué
8// # desplegar: copiar a /etc/saywa/saywa.ron y `saywa ctl reload` (en caliente, sin cortar)
9//
10// ⚠ `explain` es la herramienta que hay que usar ANTES de tocar esto: dice qué ruta coincide y
11// qué se responde, leyendo un fichero cualquiera. Evita probar en producción.
12//
13// ══ EL FRENO ANTI-RASTREO (2026-10-21) ════════════════════════════════════════════════════════
14// Los dos frentes de gitea (git.gioser.net y git.tawasuyu.net) llevan una ruta que corta con 403
15// las vistas "por commit" para visitantes ANÓNIMOS. Medido, no preventivo:
16//
17// · 1.179.729 peticiones/día desde 8.945 IPs distintas ⇒ bloquear por IP es inútil
18// · el 99,5 % del coste estaba en /src|commits|blame|raw /commit/<sha>/... y en /compare:
19// son ficheros × commits y refs × refs — espacio de rastreo INFINITO por construcción
20// · las URL "por rama", que es lo que usa una persona, eran el 0,4 %
21// · load 14,78 en 4 cores; gitea forkeaba un `git cat-file` y un `git check-attr` por vista
22// · tras el freno: 35,4 → 0,98 cores de coste medio, y CERO hijos `git` colgando
23//
24// El robots.txt YA prohibía esas rutas y los bots la ignoran (incluido meta-webindexer, que pedía
25// /blame/commit estando explícitamente prohibido) ⇒ la capa educada estaba agotada y había que
26// hacer cumplir la norma. La cookie de sesión EXIME, así que quien entra con usuario conserva los
27// permalinks; clonar y empujar no pasan por esas rutas y están verificados intactos.
28//
29// ⚠ Y la trampa del recargado en caliente, que casi me hizo diagnosticar mal: tras `ctl reload`
30// las conexiones HTTP/2 ya abiertas SIGUEN con la tabla de rutas vieja. Se ve en el log por el
31// campo `saywa.ruta` (el índice del proxy se corre al insertar una ruta): 707 peticiones por la
32// ruta vieja en el minuto 0, 649 en el 1, 2 en el 2, 0 en el 3. Se drena solo en ~3 minutos, pero
33// medir antes de eso dice que la regla NO funciona cuando sí funciona.
34// saywa en takana: la config de caddy (/etc/caddy/Caddyfile) absorbida con
35// `saywa import caddyfile` el 2026-10-20, más lo que ya servía saywa
36// (repo.gioser.net desde /srv/repo). Los registros siguen en los mismos
37// archivos de caddy, con la misma forma JSON y la misma rotación: lo que los
38// lee no cambia. Volver a caddy: ver /root/saywa-cambio/VOLVER.
39// saywa en takana: la config de caddy (/etc/caddy/Caddyfile) absorbida con
40// `saywa import caddyfile` el 2026-10-20, más lo que ya servía saywa
41// (repo.gioser.net desde /srv/repo). Los registros siguen en los mismos
42// archivos de caddy, con la misma forma JSON y la misma rotación: lo que los
43// lee no cambia. Volver a caddy: ver /root/saywa-cambio/VOLVER.
44(
45 listen: [
46 (
47 address: "[::]:80",
48 tls: false,
49 egress: false,
50 ),
51 (
52 address: "[::]:443",
53 tls: true,
54 egress: false,
55 // HTTP/3 por UDP en el mismo puerto (SDD §17); el cortafuegos lo deja pasar.
56 http3: true,
57 ),
58 ],
59 sites: [
60 (
61 names: [
62 "gitea.gioser.net",
63 ],
64 tls: Auto,
65 log: Some("requests"),
66 routes: [
67 (
68 actions: [
69 Redirect(
70 to: "https://git.gioser.net{uri}",
71 status: 301,
72 ),
73 ],
74 ),
75 ],
76 ),
77 (
78 names: [
79 "git.takana-os.net",
80 ],
81 tls: Auto,
82 log: Some("requests"),
83 routes: [
84 (
85 actions: [
86 Redirect(
87 to: "https://git.gioser.net{uri}",
88 status: 301,
89 ),
90 ],
91 ),
92 ],
93 ),
94 (
95 names: [
96 "git.gioser.net",
97 ],
98 tls: Auto,
99 log: Some("requests"),
100 routes: [
101 (
102 match: (
103 header: [
104 ("User-Agent", "*meta-externalagent*"),
105 ("User-Agent", "*FacebookBot*"),
106 // 2026-10-21, a pedido explícito del usuario: el crawler de Meta FUERA
107 // del todo, no sólo de las vistas caras. Medido en el log: 22.641
108 // peticiones desde 48 IPs, y pedía /blame/commit estando PROHIBIDO en
109 // el robots.txt — o sea que no lo lee. Fue el 33,6 % del coste de la
110 // máquina él solo cuando el load estaba en 14,78.
111 ("User-Agent", "*meta-webindexer*"),
112 ("User-Agent", "*meta-externalfetcher*"),
113 // ⚠ `facebookexternalhit` NO se veta a propósito: no es un crawler,
114 // es el que busca la vista previa cuando una PERSONA comparte el
115 // enlace — y lo usa WhatsApp también. Vetarlo rompe las previsualiza-
116 // ciones de los enlaces propios. Eran 45 peticiones, coste ~0.
117 ("User-Agent", "*GPTBot*"),
118 ("User-Agent", "*OAI-SearchBot*"),
119 ("User-Agent", "*ChatGPT*"),
120 ("User-Agent", "*Amazonbot*"),
121 ("User-Agent", "*ClaudeBot*"),
122 ("User-Agent", "*anthropic-ai*"),
123 ("User-Agent", "*Claude-Web*"),
124 ("User-Agent", "*Bytespider*"),
125 ("User-Agent", "*CCBot*"),
126 ("User-Agent", "*Google-Extended*"),
127 ("User-Agent", "*Applebot-Extended*"),
128 ("User-Agent", "*PerplexityBot*"),
129 ("User-Agent", "*Diffbot*"),
130 ("User-Agent", "*Omgilibot*"),
131 ("User-Agent", "*DataForSeoBot*"),
132 ],
133 ),
134 actions: [
135 Respond(
136 status: 403,
137 body: None,
138 type: None,
139 ),
140 ],
141 ),
142 (
143 // ⚠ FRENO ANTI-RASTREO — puesto 2026-10-21, medido, no preventivo.
144 // El log de saywa daba 1.179.729 peticiones/día de 8.945 IPs distintas, y
145 // el 99,5 % del coste estaba en las URL "por commit": /src|commits|blame|raw
146 // /commit/<sha>/..., que son ficheros × commits = espacio INFINITO. Las URL
147 // "por rama" —lo que usa una persona— eran el 0,4 %. Load 14,78 en 4 cores.
148 // El robots.txt YA prohibía estas rutas y lo ignoran: la capa educada está
149 // agotada, así que acá se hace cumplir. La cookie de sesión exime, o sea que
150 // quien entra con usuario conserva los permalinks; clonar y empujar no pasan
151 // por acá (van por /info/refs y /git-upload-pack) y no se tocan.
152 match: (
153 path: [
154 "/*/*/src/commit/*",
155 "/*/*/commits/commit/*",
156 "/*/*/blame/commit/*",
157 "/*/*/raw/commit/*",
158 "/*/*/commit/*",
159 // 2ª tanda, misma medición: con lo de arriba ya cortado, /compare se
160 // quedó con el 96 % del coste restante (5,2 s de media por peticion).
161 // Es refs × refs — la misma trampa combinatoria que /commit, y los
162 // bots la recorren igual. /activity y /lastcommit son agregados caros
163 // (vi un /activity/monthly de 42 s en UNA peticion).
164 "/*/*/compare/*",
165 "/*/*/activity",
166 "/*/*/activity/*",
167 "/*/*/lastcommit/*",
168 ],
169 not: [
170 (
171 header: [
172 ("Cookie", "*i_like_gitea*"),
173 ],
174 ),
175 ],
176 ),
177 actions: [
178 Respond(
179 status: 403,
180 body: Some("Esta vista por commit esta cerrada a visitantes anonimos: un rastreo la convierte en ficheros x commits y se come la maquina. Navega por rama (/src/branch/...), o entra con tu usuario. Clonar funciona siempre: git clone https://git.gioser.net/<dueno>/<repo>.git\n"),
181 type: Some("text/plain; charset=utf-8"),
182 ),
183 ],
184 ),
185 (
186 match: (
187 path: [
188 "/robots.txt",
189 ],
190 ),
191 actions: [
192 Files(
193 root: "/var/www/git-robots",
194 try: [],
195 browse: false,
196 index: [
197 "index.html",
198 ],
199 on_missing: NotFound,
200 hidden: false,
201 ),
202 ],
203 ),
204 (
205 match: (
206 not: [
207 (
208 path: [
209 "/robots.txt",
210 ],
211 ),
212 ],
213 ),
214 actions: [
215 Proxy(
216 to: [
217 "127.0.0.1:3002",
218 ],
219 policy: First,
220 ),
221 ],
222 ),
223 ],
224 ),
225 (
226 names: [
227 "git.tawasuyu.net",
228 ],
229 tls: Auto,
230 log: Some("requests"),
231 routes: [
232 (
233 match: (
234 header: [
235 ("User-Agent", "*meta-externalagent*"),
236 ("User-Agent", "*FacebookBot*"),
237 // 2026-10-21, a pedido explícito del usuario: el crawler de Meta FUERA
238 // del todo, no sólo de las vistas caras. Medido en el log: 22.641
239 // peticiones desde 48 IPs, y pedía /blame/commit estando PROHIBIDO en
240 // el robots.txt — o sea que no lo lee. Fue el 33,6 % del coste de la
241 // máquina él solo cuando el load estaba en 14,78.
242 ("User-Agent", "*meta-webindexer*"),
243 ("User-Agent", "*meta-externalfetcher*"),
244 // ⚠ `facebookexternalhit` NO se veta a propósito: no es un crawler,
245 // es el que busca la vista previa cuando una PERSONA comparte el
246 // enlace — y lo usa WhatsApp también. Vetarlo rompe las previsualiza-
247 // ciones de los enlaces propios. Eran 45 peticiones, coste ~0.
248 ("User-Agent", "*GPTBot*"),
249 ("User-Agent", "*OAI-SearchBot*"),
250 ("User-Agent", "*ChatGPT*"),
251 ("User-Agent", "*Amazonbot*"),
252 ("User-Agent", "*ClaudeBot*"),
253 ("User-Agent", "*anthropic-ai*"),
254 ("User-Agent", "*Claude-Web*"),
255 ("User-Agent", "*Bytespider*"),
256 ("User-Agent", "*CCBot*"),
257 ("User-Agent", "*Google-Extended*"),
258 ("User-Agent", "*Applebot-Extended*"),
259 ("User-Agent", "*PerplexityBot*"),
260 ("User-Agent", "*Diffbot*"),
261 ("User-Agent", "*Omgilibot*"),
262 ("User-Agent", "*DataForSeoBot*"),
263 ],
264 ),
265 actions: [
266 Respond(
267 status: 403,
268 body: None,
269 type: None,
270 ),
271 ],
272 ),
273 (
274 // ⚠ FRENO ANTI-RASTREO — puesto 2026-10-21, medido, no preventivo.
275 // El log de saywa daba 1.179.729 peticiones/día de 8.945 IPs distintas, y
276 // el 99,5 % del coste estaba en las URL "por commit": /src|commits|blame|raw
277 // /commit/<sha>/..., que son ficheros × commits = espacio INFINITO. Las URL
278 // "por rama" —lo que usa una persona— eran el 0,4 %. Load 14,78 en 4 cores.
279 // El robots.txt YA prohibía estas rutas y lo ignoran: la capa educada está
280 // agotada, así que acá se hace cumplir. La cookie de sesión exime, o sea que
281 // quien entra con usuario conserva los permalinks; clonar y empujar no pasan
282 // por acá (van por /info/refs y /git-upload-pack) y no se tocan.
283 match: (
284 path: [
285 "/*/*/src/commit/*",
286 "/*/*/commits/commit/*",
287 "/*/*/blame/commit/*",
288 "/*/*/raw/commit/*",
289 "/*/*/commit/*",
290 // 2ª tanda, misma medición: con lo de arriba ya cortado, /compare se
291 // quedó con el 96 % del coste restante (5,2 s de media por peticion).
292 // Es refs × refs — la misma trampa combinatoria que /commit, y los
293 // bots la recorren igual. /activity y /lastcommit son agregados caros
294 // (vi un /activity/monthly de 42 s en UNA peticion).
295 "/*/*/compare/*",
296 "/*/*/activity",
297 "/*/*/activity/*",
298 "/*/*/lastcommit/*",
299 ],
300 not: [
301 (
302 header: [
303 ("Cookie", "*i_like_gitea*"),
304 ],
305 ),
306 ],
307 ),
308 actions: [
309 Respond(
310 status: 403,
311 body: Some("Esta vista por commit esta cerrada a visitantes anonimos: un rastreo la convierte en ficheros x commits y se come la maquina. Navega por rama (/src/branch/...), o entra con tu usuario. Clonar funciona siempre: git clone https://git.gioser.net/<dueno>/<repo>.git\n"),
312 type: Some("text/plain; charset=utf-8"),
313 ),
314 ],
315 ),
316 (
317 match: (
318 path: [
319 "/robots.txt",
320 ],
321 ),
322 actions: [
323 Files(
324 root: "/var/www/git-robots",
325 try: [],
326 browse: false,
327 index: [
328 "index.html",
329 ],
330 on_missing: NotFound,
331 hidden: false,
332 ),
333 ],
334 ),
335 (
336 match: (
337 not: [
338 (
339 path: [
340 "/robots.txt",
341 ],
342 ),
343 ],
344 ),
345 actions: [
346 Proxy(
347 to: [
348 "127.0.0.1:3002",
349 ],
350 policy: First,
351 ),
352 ],
353 ),
354 ],
355 ),
356 (
357 names: [
358 "takana.gioser.net",
359 ],
360 tls: Auto,
361 log: Some("requests"),
362 routes: [
363 (
364 actions: [
365 Redirect(
366 to: "https://takana-os.net{uri}",
367 status: 301,
368 ),
369 ],
370 ),
371 ],
372 ),
373 (
374 names: [
375 "hifas.gioser.net",
376 ],
377 tls: Auto,
378 log: Some("sitios"),
379 routes: [
380 (
381 match: (
382 not: [
383 (
384 path: [
385 "*.*",
386 ],
387 ),
388 ],
389 ),
390 actions: [
391 Header(
392 name: "Cache-Control",
393 value: Some("no-cache"),
394 phase: Response,
395 ),
396 ],
397 ),
398 (
399 match: (
400 path: [
401 "*.html",
402 "*.json",
403 "*.css",
404 "*.js",
405 "*.xml",
406 ],
407 ),
408 actions: [
409 Header(
410 name: "Cache-Control",
411 value: Some("no-cache"),
412 phase: Response,
413 ),
414 ],
415 ),
416 (
417 match: (
418 file: Some((
419 root: Dir("/work/sergio/gioser-web/hifas"),
420 try: [
421 "{path}",
422 ],
423 )),
424 ),
425 actions: [
426 Rewrite(
427 to: "{path}",
428 ),
429 ],
430 ),
431 (
432 match: (
433 not: [
434 (
435 file: Some((
436 root: Dir("/work/sergio/gioser-web/hifas"),
437 try: [
438 "{path}",
439 ],
440 )),
441 ),
442 ],
443 all: [
444 (
445 file: Some((
446 root: Dir("/work/sergio/gioser-web/hifas"),
447 try: [
448 "{path}/",
449 ],
450 )),
451 ),
452 ],
453 ),
454 actions: [
455 Rewrite(
456 to: "{path}/",
457 ),
458 ],
459 ),
460 (
461 match: (
462 not: [
463 (
464 file: Some((
465 root: Dir("/work/sergio/gioser-web/hifas"),
466 try: [
467 "{path}",
468 ],
469 )),
470 ),
471 (
472 file: Some((
473 root: Dir("/work/sergio/gioser-web/hifas"),
474 try: [
475 "{path}/",
476 ],
477 )),
478 ),
479 ],
480 all: [
481 (
482 file: Some((
483 root: Dir("/work/sergio/gioser-web/hifas"),
484 try: [
485 "/index.html",
486 ],
487 )),
488 ),
489 ],
490 ),
491 actions: [
492 Rewrite(
493 to: "/index.html",
494 ),
495 ],
496 ),
497 (
498 actions: [
499 Encode(
500 with: [
501 Gzip,
502 Zstd,
503 ],
504 ),
505 ],
506 ),
507 (
508 actions: [
509 Files(
510 root: "/work/sergio/gioser-web/hifas",
511 try: [],
512 browse: false,
513 index: [
514 "index.html",
515 ],
516 on_missing: NotFound,
517 hidden: false,
518 ),
519 ],
520 ),
521 ],
522 ),
523 (
524 names: [
525 "api.sergio.gioser.net",
526 ],
527 tls: Auto,
528 log: Some("requests"),
529 routes: [
530 (
531 actions: [
532 Proxy(
533 to: [
534 "127.0.0.1:8771",
535 ],
536 policy: First,
537 ),
538 ],
539 ),
540 ],
541 ),
542 (
543 names: [
544 "tawasuyu.net",
545 "www.tawasuyu.net",
546 ],
547 tls: Auto,
548 log: Some("sitios"),
549 routes: [
550 (
551 match: (
552 path: [
553 "/pkg/*.wasm",
554 ],
555 ),
556 actions: [
557 Header(
558 name: "Content-Type",
559 value: Some("application/wasm"),
560 phase: Response,
561 ),
562 ],
563 ),
564 (
565 match: (
566 path: [
567 "*.webm",
568 ],
569 ),
570 actions: [
571 Header(
572 name: "Content-Type",
573 value: Some("video/webm"),
574 phase: Response,
575 ),
576 ],
577 ),
578 (
579 match: (
580 not: [
581 (
582 path: [
583 "*.*",
584 ],
585 ),
586 ],
587 ),
588 actions: [
589 Header(
590 name: "Cache-Control",
591 value: Some("no-cache"),
592 phase: Response,
593 ),
594 ],
595 ),
596 (
597 match: (
598 path: [
599 "*.html",
600 "*.json",
601 "*.css",
602 "*.js",
603 ],
604 ),
605 actions: [
606 Header(
607 name: "Cache-Control",
608 value: Some("no-cache"),
609 phase: Response,
610 ),
611 ],
612 ),
613 (
614 match: (
615 path: [
616 "/index.html",
617 ],
618 ),
619 actions: [
620 Rewrite(
621 to: "/web/tawasuyu-web/index.html",
622 ),
623 ],
624 ),
625 (
626 match: (
627 not: [
628 (
629 path: [
630 "/index.html",
631 ],
632 ),
633 ],
634 all: [
635 (
636 path: [
637 "/styles.css",
638 ],
639 ),
640 ],
641 ),
642 actions: [
643 Rewrite(
644 to: "/web/tawasuyu-web/styles.css",
645 ),
646 ],
647 ),
648 (
649 match: (
650 not: [
651 (
652 path: [
653 "/index.html",
654 ],
655 ),
656 (
657 path: [
658 "/styles.css",
659 ],
660 ),
661 ],
662 all: [
663 (
664 path: [
665 "/escritorio",
666 ],
667 ),
668 ],
669 ),
670 actions: [
671 Rewrite(
672 to: "/web/tawasuyu-web/escritorio.html",
673 ),
674 ],
675 ),
676 (
677 match: (
678 not: [
679 (
680 path: [
681 "/index.html",
682 ],
683 ),
684 (
685 path: [
686 "/styles.css",
687 ],
688 ),
689 (
690 path: [
691 "/escritorio",
692 ],
693 ),
694 ],
695 all: [
696 (
697 path: [
698 "/galeria",
699 ],
700 ),
701 ],
702 ),
703 actions: [
704 Rewrite(
705 to: "/web/tawasuyu-web/galeria.html",
706 ),
707 ],
708 ),
709 (
710 match: (
711 not: [
712 (
713 path: [
714 "/index.html",
715 ],
716 ),
717 (
718 path: [
719 "/styles.css",
720 ],
721 ),
722 (
723 path: [
724 "/escritorio",
725 ],
726 ),
727 (
728 path: [
729 "/galeria",
730 ],
731 ),
732 ],
733 all: [
734 (
735 path: [
736 "/pkg/*",
737 ],
738 ),
739 ],
740 ),
741 actions: [
742 Rewrite(
743 to: "/web/tawasuyu-web{path}",
744 ),
745 ],
746 ),
747 (
748 match: (
749 not: [
750 (
751 path: [
752 "/index.html",
753 ],
754 ),
755 (
756 path: [
757 "/styles.css",
758 ],
759 ),
760 (
761 path: [
762 "/escritorio",
763 ],
764 ),
765 (
766 path: [
767 "/galeria",
768 ],
769 ),
770 (
771 path: [
772 "/pkg/*",
773 ],
774 ),
775 ],
776 all: [
777 (
778 path: [
779 "/",
780 ],
781 ),
782 ],
783 ),
784 actions: [
785 Rewrite(
786 to: "/web/tawasuyu-web/index.html",
787 ),
788 ],
789 ),
790 (
791 match: (
792 not: [
793 (
794 path: [
795 "/index.html",
796 ],
797 ),
798 (
799 path: [
800 "/styles.css",
801 ],
802 ),
803 (
804 path: [
805 "/escritorio",
806 ],
807 ),
808 (
809 path: [
810 "/galeria",
811 ],
812 ),
813 (
814 path: [
815 "/pkg/*",
816 ],
817 ),
818 (
819 path: [
820 "/",
821 ],
822 ),
823 ],
824 all: [
825 (
826 not: [
827 (
828 path: [
829 "*.*",
830 ],
831 ),
832 (
833 path: [
834 "/",
835 ],
836 ),
837 (
838 path: [
839 "/visto",
840 ],
841 ),
842 (
843 file: Some((
844 root: Dir("/work/sergio/tawasuyu"),
845 try: [
846 "{path}",
847 "{path}/index.html",
848 ],
849 )),
850 ),
851 ],
852 ),
853 ],
854 ),
855 actions: [
856 Rewrite(
857 to: "/web/tawasuyu-web/index.html",
858 ),
859 ],
860 ),
861 (
862 actions: [
863 Encode(
864 with: [
865 Gzip,
866 Zstd,
867 ],
868 ),
869 ],
870 ),
871 (
872 match: (
873 path: [
874 "/visto",
875 ],
876 ),
877 actions: [
878 Respond(
879 status: 204,
880 body: None,
881 type: None,
882 ),
883 ],
884 ),
885 (
886 match: (
887 path: [
888 "/.*",
889 "*/.*",
890 ],
891 ),
892 actions: [
893 Respond(
894 status: 404,
895 body: None,
896 type: None,
897 ),
898 ],
899 ),
900 (
901 actions: [
902 Files(
903 root: "/work/sergio/tawasuyu",
904 try: [],
905 browse: false,
906 index: [
907 "index.html",
908 ],
909 on_missing: NotFound,
910 hidden: false,
911 ),
912 ],
913 ),
914 ],
915 ),
916 (
917 names: [
918 "gioser.net",
919 "www.gioser.net",
920 ],
921 tls: Auto,
922 log: Some("sitios"),
923 routes: [
924 (
925 match: (
926 not: [
927 (
928 path: [
929 "*.*",
930 ],
931 ),
932 ],
933 ),
934 actions: [
935 Header(
936 name: "Cache-Control",
937 value: Some("no-cache"),
938 phase: Response,
939 ),
940 ],
941 ),
942 (
943 match: (
944 path: [
945 "*.html",
946 "*.json",
947 "*.css",
948 "*.js",
949 "*.xml",
950 ],
951 ),
952 actions: [
953 Header(
954 name: "Cache-Control",
955 value: Some("no-cache"),
956 phase: Response,
957 ),
958 ],
959 ),
960 (
961 match: (
962 path: [
963 "/reencuentro/*",
964 ],
965 ),
966 strip_prefix: Some("/reencuentro"),
967 actions: [
968 Header(
969 name: "X-Robots-Tag",
970 value: Some("noindex, nofollow, noarchive, noimageindex"),
971 phase: Response,
972 ),
973 ],
974 ),
975 (
976 match: (
977 path: [
978 "/reencuentro/*",
979 ],
980 ),
981 strip_prefix: Some("/reencuentro"),
982 actions: [
983 Encode(
984 with: [
985 Gzip,
986 Zstd,
987 ],
988 ),
989 ],
990 ),
991 (
992 match: (
993 path: [
994 "/reencuentro/*",
995 ],
996 ),
997 strip_prefix: Some("/reencuentro"),
998 actions: [
999 FastCgi(
1000 to: "127.0.0.1:9000",
1001 root: "/work/www/gioser-web/reencuentro",
1002 index: "index.php",
1003 ),
1004 ],
1005 ),
1006 (
1007 match: (
1008 path: [
1009 "/reencuentro/*",
1010 ],
1011 ),
1012 strip_prefix: Some("/reencuentro"),
1013 actions: [
1014 Files(
1015 root: "/work/www/gioser-web/reencuentro",
1016 try: [],
1017 browse: false,
1018 index: [
1019 "index.html",
1020 ],
1021 on_missing: NotFound,
1022 hidden: false,
1023 ),
1024 ],
1025 ),
1026 (
1027 match: (
1028 not: [
1029 (
1030 path: [
1031 "/reencuentro/*",
1032 ],
1033 ),
1034 ],
1035 all: [
1036 (
1037 path: [
1038 "/humanoid/*",
1039 ],
1040 ),
1041 ],
1042 ),
1043 strip_prefix: Some("/humanoid"),
1044 actions: [
1045 Encode(
1046 with: [
1047 Gzip,
1048 ],
1049 ),
1050 ],
1051 ),
1052 (
1053 match: (
1054 not: [
1055 (
1056 path: [
1057 "/reencuentro/*",
1058 ],
1059 ),
1060 ],
1061 all: [
1062 (
1063 path: [
1064 "/humanoid/*",
1065 ],
1066 ),
1067 ],
1068 ),
1069 strip_prefix: Some("/humanoid"),
1070 actions: [
1071 Files(
1072 root: "/work/www/gioser-web/humanoid",
1073 try: [],
1074 browse: false,
1075 index: [
1076 "index.html",
1077 ],
1078 on_missing: NotFound,
1079 hidden: false,
1080 ),
1081 ],
1082 ),
1083 (
1084 match: (
1085 not: [
1086 (
1087 path: [
1088 "/reencuentro/*",
1089 ],
1090 ),
1091 (
1092 path: [
1093 "/humanoid/*",
1094 ],
1095 ),
1096 ],
1097 all: [
1098 (
1099 path: [
1100 "/muestras/*",
1101 ],
1102 ),
1103 ],
1104 ),
1105 strip_prefix: Some("/muestras"),
1106 actions: [
1107 Encode(
1108 with: [
1109 Gzip,
1110 ],
1111 ),
1112 ],
1113 ),
1114 (
1115 match: (
1116 not: [
1117 (
1118 path: [
1119 "/reencuentro/*",
1120 ],
1121 ),
1122 (
1123 path: [
1124 "/humanoid/*",
1125 ],
1126 ),
1127 ],
1128 all: [
1129 (
1130 path: [
1131 "/muestras/*",
1132 ],
1133 ),
1134 ],
1135 ),
1136 strip_prefix: Some("/muestras"),
1137 actions: [
1138 Files(
1139 root: "/work/www/gioser-web/muestras",
1140 try: [],
1141 browse: true,
1142 index: [
1143 "index.html",
1144 ],
1145 on_missing: NotFound,
1146 hidden: false,
1147 ),
1148 ],
1149 ),
1150 (
1151 match: (
1152 not: [
1153 (
1154 path: [
1155 "/reencuentro/*",
1156 ],
1157 ),
1158 (
1159 path: [
1160 "/humanoid/*",
1161 ],
1162 ),
1163 (
1164 path: [
1165 "/muestras/*",
1166 ],
1167 ),
1168 ],
1169 all: [
1170 (
1171 path: [
1172 "/vivo/*",
1173 ],
1174 ),
1175 ],
1176 ),
1177 strip_prefix: Some("/vivo"),
1178 actions: [
1179 Encode(
1180 with: [
1181 Gzip,
1182 ],
1183 ),
1184 ],
1185 ),
1186 (
1187 match: (
1188 not: [
1189 (
1190 path: [
1191 "/reencuentro/*",
1192 ],
1193 ),
1194 (
1195 path: [
1196 "/humanoid/*",
1197 ],
1198 ),
1199 (
1200 path: [
1201 "/muestras/*",
1202 ],
1203 ),
1204 ],
1205 all: [
1206 (
1207 path: [
1208 "/vivo/*",
1209 ],
1210 ),
1211 ],
1212 ),
1213 strip_prefix: Some("/vivo"),
1214 actions: [
1215 Files(
1216 root: "/work/www/gioser-web/vivo",
1217 try: [],
1218 browse: true,
1219 index: [
1220 "index.html",
1221 ],
1222 on_missing: NotFound,
1223 hidden: false,
1224 ),
1225 ],
1226 ),
1227 (
1228 match: (
1229 not: [
1230 (
1231 path: [
1232 "/reencuentro/*",
1233 ],
1234 ),
1235 (
1236 path: [
1237 "/humanoid/*",
1238 ],
1239 ),
1240 (
1241 path: [
1242 "/muestras/*",
1243 ],
1244 ),
1245 (
1246 path: [
1247 "/vivo/*",
1248 ],
1249 ),
1250 ],
1251 all: [
1252 (
1253 path: [
1254 "/ende/*",
1255 ],
1256 ),
1257 ],
1258 ),
1259 strip_prefix: Some("/ende"),
1260 actions: [
1261 Encode(
1262 with: [
1263 Gzip,
1264 Zstd,
1265 ],
1266 ),
1267 ],
1268 ),
1269 (
1270 match: (
1271 not: [
1272 (
1273 path: [
1274 "/reencuentro/*",
1275 ],
1276 ),
1277 (
1278 path: [
1279 "/humanoid/*",
1280 ],
1281 ),
1282 (
1283 path: [
1284 "/muestras/*",
1285 ],
1286 ),
1287 (
1288 path: [
1289 "/vivo/*",
1290 ],
1291 ),
1292 ],
1293 all: [
1294 (
1295 path: [
1296 "/ende/*",
1297 ],
1298 ),
1299 ],
1300 ),
1301 strip_prefix: Some("/ende"),
1302 actions: [
1303 Files(
1304 root: "/work/www/gioser-web/ende",
1305 try: [],
1306 browse: true,
1307 index: [
1308 "index.html",
1309 ],
1310 on_missing: NotFound,
1311 hidden: false,
1312 ),
1313 ],
1314 ),
1315 (
1316 match: (
1317 not: [
1318 (
1319 path: [
1320 "/reencuentro/*",
1321 ],
1322 ),
1323 (
1324 path: [
1325 "/humanoid/*",
1326 ],
1327 ),
1328 (
1329 path: [
1330 "/muestras/*",
1331 ],
1332 ),
1333 (
1334 path: [
1335 "/vivo/*",
1336 ],
1337 ),
1338 (
1339 path: [
1340 "/ende/*",
1341 ],
1342 ),
1343 ],
1344 all: [
1345 (
1346 path: [
1347 "/visto",
1348 ],
1349 ),
1350 ],
1351 ),
1352 actions: [
1353 Respond(
1354 status: 204,
1355 body: None,
1356 type: None,
1357 ),
1358 ],
1359 ),
1360 (
1361 match: (
1362 not: [
1363 (
1364 path: [
1365 "/reencuentro/*",
1366 ],
1367 ),
1368 (
1369 path: [
1370 "/humanoid/*",
1371 ],
1372 ),
1373 (
1374 path: [
1375 "/muestras/*",
1376 ],
1377 ),
1378 (
1379 path: [
1380 "/vivo/*",
1381 ],
1382 ),
1383 (
1384 path: [
1385 "/ende/*",
1386 ],
1387 ),
1388 (
1389 path: [
1390 "/visto",
1391 ],
1392 ),
1393 ],
1394 all: [
1395 (
1396 path: [
1397 "/scripts",
1398 "/scripts/*",
1399 "/.*",
1400 "/.*/*",
1401 ],
1402 ),
1403 ],
1404 ),
1405 actions: [
1406 Respond(
1407 status: 404,
1408 body: None,
1409 type: None,
1410 ),
1411 ],
1412 ),
1413 (
1414 match: (
1415 not: [
1416 (
1417 path: [
1418 "/reencuentro/*",
1419 ],
1420 ),
1421 (
1422 path: [
1423 "/humanoid/*",
1424 ],
1425 ),
1426 (
1427 path: [
1428 "/muestras/*",
1429 ],
1430 ),
1431 (
1432 path: [
1433 "/vivo/*",
1434 ],
1435 ),
1436 (
1437 path: [
1438 "/ende/*",
1439 ],
1440 ),
1441 (
1442 path: [
1443 "/visto",
1444 ],
1445 ),
1446 (
1447 path: [
1448 "/scripts",
1449 "/scripts/*",
1450 "/.*",
1451 "/.*/*",
1452 ],
1453 ),
1454 ],
1455 ),
1456 actions: [
1457 Encode(
1458 with: [
1459 Gzip,
1460 Zstd,
1461 ],
1462 ),
1463 ],
1464 ),
1465 (
1466 match: (
1467 not: [
1468 (
1469 path: [
1470 "/reencuentro/*",
1471 ],
1472 ),
1473 (
1474 path: [
1475 "/humanoid/*",
1476 ],
1477 ),
1478 (
1479 path: [
1480 "/muestras/*",
1481 ],
1482 ),
1483 (
1484 path: [
1485 "/vivo/*",
1486 ],
1487 ),
1488 (
1489 path: [
1490 "/ende/*",
1491 ],
1492 ),
1493 (
1494 path: [
1495 "/visto",
1496 ],
1497 ),
1498 (
1499 path: [
1500 "/scripts",
1501 "/scripts/*",
1502 "/.*",
1503 "/.*/*",
1504 ],
1505 ),
1506 ],
1507 ),
1508 actions: [
1509 Files(
1510 root: "/work/sergio/gioser-web/",
1511 try: [],
1512 browse: false,
1513 index: [
1514 "index.html",
1515 ],
1516 on_missing: NotFound,
1517 hidden: false,
1518 ),
1519 ],
1520 ),
1521 ],
1522 ),
1523 (
1524 names: [
1525 "sergio.gioser.net",
1526 ],
1527 tls: Auto,
1528 log: Some("requests"),
1529 routes: [
1530 (
1531 match: (
1532 path: [
1533 "/shuma/*",
1534 ],
1535 ),
1536 strip_prefix: Some("/shuma"),
1537 actions: [
1538 Proxy(
1539 to: [
1540 "127.0.0.1:7378",
1541 ],
1542 policy: First,
1543 ),
1544 ],
1545 ),
1546 (
1547 match: (
1548 all: [
1549 (
1550 not: [
1551 (
1552 path: [
1553 "/shuma/*",
1554 ],
1555 ),
1556 ],
1557 ),
1558 (
1559 file: Some((
1560 root: Dir("/work/www/sergioh"),
1561 try: [
1562 "{path}",
1563 ],
1564 )),
1565 ),
1566 ],
1567 ),
1568 actions: [
1569 Rewrite(
1570 to: "{path}",
1571 ),
1572 ],
1573 ),
1574 (
1575 match: (
1576 not: [
1577 (
1578 file: Some((
1579 root: Dir("/work/www/sergioh"),
1580 try: [
1581 "{path}",
1582 ],
1583 )),
1584 ),
1585 ],
1586 all: [
1587 (
1588 all: [
1589 (
1590 not: [
1591 (
1592 path: [
1593 "/shuma/*",
1594 ],
1595 ),
1596 ],
1597 ),
1598 (
1599 file: Some((
1600 root: Dir("/work/www/sergioh"),
1601 try: [
1602 "{path}/",
1603 ],
1604 )),
1605 ),
1606 ],
1607 ),
1608 ],
1609 ),
1610 actions: [
1611 Rewrite(
1612 to: "{path}/",
1613 ),
1614 ],
1615 ),
1616 (
1617 match: (
1618 not: [
1619 (
1620 file: Some((
1621 root: Dir("/work/www/sergioh"),
1622 try: [
1623 "{path}",
1624 ],
1625 )),
1626 ),
1627 (
1628 file: Some((
1629 root: Dir("/work/www/sergioh"),
1630 try: [
1631 "{path}/",
1632 ],
1633 )),
1634 ),
1635 ],
1636 all: [
1637 (
1638 all: [
1639 (
1640 not: [
1641 (
1642 path: [
1643 "/shuma/*",
1644 ],
1645 ),
1646 ],
1647 ),
1648 (
1649 file: Some((
1650 root: Dir("/work/www/sergioh"),
1651 try: [
1652 "/index.html",
1653 ],
1654 )),
1655 ),
1656 ],
1657 ),
1658 ],
1659 ),
1660 actions: [
1661 Rewrite(
1662 to: "/index.html",
1663 ),
1664 ],
1665 ),
1666 (
1667 match: (
1668 not: [
1669 (
1670 path: [
1671 "/shuma/*",
1672 ],
1673 ),
1674 ],
1675 ),
1676 actions: [
1677 Encode(
1678 with: [
1679 Gzip,
1680 ],
1681 ),
1682 ],
1683 ),
1684 (
1685 match: (
1686 not: [
1687 (
1688 path: [
1689 "/shuma/*",
1690 ],
1691 ),
1692 ],
1693 ),
1694 actions: [
1695 Files(
1696 root: "/work/www/sergioh",
1697 try: [],
1698 browse: false,
1699 index: [
1700 "index.html",
1701 ],
1702 on_missing: NotFound,
1703 hidden: false,
1704 ),
1705 ],
1706 ),
1707 ],
1708 ),
1709 (
1710 names: [
1711 "repo.gioser.net",
1712 ],
1713 tls: Auto,
1714 log: Some("repo"),
1715 routes: [
1716 (actions: [Files(root: "/srv/repo", browse: true)]),
1717 ],
1718 ),
1719 (
1720 names: [
1721 "takana-os.net",
1722 "www.takana-os.net",
1723 ],
1724 tls: Auto,
1725 log: Some("sitios"),
1726 routes: [
1727 (
1728 match: (
1729 not: [
1730 (
1731 path: [
1732 "*.*",
1733 ],
1734 ),
1735 ],
1736 ),
1737 actions: [
1738 Header(
1739 name: "Cache-Control",
1740 value: Some("no-cache"),
1741 phase: Response,
1742 ),
1743 ],
1744 ),
1745 (
1746 match: (
1747 path: [
1748 "*.html",
1749 "*.json",
1750 "*.css",
1751 "*.js",
1752 "*.xml",
1753 ],
1754 ),
1755 actions: [
1756 Header(
1757 name: "Cache-Control",
1758 value: Some("no-cache"),
1759 phase: Response,
1760 ),
1761 ],
1762 ),
1763 (
1764 match: (
1765 path: [
1766 "/descargas",
1767 ],
1768 ),
1769 actions: [
1770 Redirect(
1771 to: "/descargas/",
1772 status: 301,
1773 ),
1774 ],
1775 ),
1776 (
1777 match: (
1778 path: [
1779 "/repo",
1780 ],
1781 ),
1782 actions: [
1783 Redirect(
1784 to: "/repo/",
1785 status: 301,
1786 ),
1787 ],
1788 ),
1789 (
1790 match: (
1791 not: [
1792 (
1793 path: [
1794 "/descargas/*",
1795 ],
1796 ),
1797 ],
1798 ),
1799 actions: [
1800 Encode(
1801 with: [
1802 Gzip,
1803 Zstd,
1804 ],
1805 ),
1806 ],
1807 ),
1808 (
1809 match: (
1810 path: [
1811 "/descargas/*",
1812 ],
1813 ),
1814 strip_prefix: Some("/descargas"),
1815 actions: [
1816 Header(
1817 name: "Content-Disposition",
1818 value: Some("attachment"),
1819 phase: Response,
1820 ),
1821 ],
1822 ),
1823 (
1824 match: (
1825 path: [
1826 "/descargas/*",
1827 ],
1828 ),
1829 strip_prefix: Some("/descargas"),
1830 actions: [
1831 Files(
1832 root: "/work/sergio/descargas",
1833 try: [],
1834 browse: true,
1835 index: [
1836 "index.html",
1837 ],
1838 on_missing: NotFound,
1839 hidden: false,
1840 ),
1841 ],
1842 ),
1843 (
1844 match: (
1845 not: [
1846 (
1847 path: [
1848 "/descargas/*",
1849 ],
1850 ),
1851 ],
1852 all: [
1853 (
1854 path: [
1855 "/repo/*",
1856 ],
1857 ),
1858 ],
1859 ),
1860 strip_prefix: Some("/repo"),
1861 actions: [
1862 Files(
1863 root: "/srv/repo",
1864 try: [],
1865 browse: true,
1866 index: [
1867 "index.html",
1868 ],
1869 on_missing: NotFound,
1870 hidden: false,
1871 ),
1872 ],
1873 ),
1874 (
1875 match: (
1876 not: [
1877 (
1878 path: [
1879 "/descargas/*",
1880 ],
1881 ),
1882 (
1883 path: [
1884 "/repo/*",
1885 ],
1886 ),
1887 ],
1888 all: [
1889 (
1890 path: [
1891 "/visto",
1892 ],
1893 ),
1894 ],
1895 ),
1896 actions: [
1897 Respond(
1898 status: 204,
1899 body: None,
1900 type: None,
1901 ),
1902 ],
1903 ),
1904 (
1905 match: (
1906 all: [
1907 (
1908 not: [
1909 (
1910 path: [
1911 "/descargas/*",
1912 ],
1913 ),
1914 (
1915 path: [
1916 "/repo/*",
1917 ],
1918 ),
1919 (
1920 path: [
1921 "/visto",
1922 ],
1923 ),
1924 ],
1925 ),
1926 (
1927 path: [
1928 "/.*",
1929 "*/.*",
1930 "/README.md",
1931 ],
1932 ),
1933 ],
1934 ),
1935 actions: [
1936 Respond(
1937 status: 404,
1938 body: None,
1939 type: None,
1940 ),
1941 ],
1942 ),
1943 (
1944 match: (
1945 not: [
1946 (
1947 path: [
1948 "/descargas/*",
1949 ],
1950 ),
1951 (
1952 path: [
1953 "/repo/*",
1954 ],
1955 ),
1956 (
1957 path: [
1958 "/visto",
1959 ],
1960 ),
1961 ],
1962 ),
1963 actions: [
1964 Files(
1965 root: "/work/sergio/takana/web/takana-os.net",
1966 try: [],
1967 browse: false,
1968 index: [
1969 "index.html",
1970 ],
1971 on_missing: NotFound,
1972 hidden: false,
1973 ),
1974 ],
1975 ),
1976 ],
1977 ),
1978 ],
1979 snippets: {},
1980 egress: None,
1981 tls: (
1982 state_dir: "/var/lib/saywa",
1983 acme_directory: "https://acme-v02.api.letsencrypt.org/directory",
1984 email: None,
1985 renew_days: 30,
1986 challenge: Http01,
1987 ),
1988 logs: [
1989 (name: "repo", file: "/var/log/saywa/repo.json", ip: Truncated),
1990 (
1991 name: "requests",
1992 file: "/var/log/caddy/requests.json",
1993 ip: Full,
1994 roll_mb: 50,
1995 roll_keep: 14,
1996 roll_keep_days: 30,
1997 format: Json,
1998 ),
1999 (
2000 name: "sitios",
2001 file: "/var/log/caddy/sitios.json",
2002 ip: Full,
2003 roll_mb: 20,
2004 roll_keep: 60,
2005 roll_keep_days: 90,
2006 format: Json,
2007 ),
2008 ],
2009 limits: (
2010 max_header_bytes: 65536,
2011 max_body_bytes: 10485760,
2012 header_timeout: 10,
2013 idle_timeout: 120,
2014 max_conns_per_ip: 256,
2015 max_h2_streams: 128,
2016 drain_timeout: 30,
2017 rate_per_ip: 0,
2018 body_timeout: 20,
2019 min_body_rate: 500,
2020 max_inflight: 4096,
2021 ban_after: 200,
2022 ban_secs: 600,
2023 ban_file: Some("/var/lib/saywa/castigo.txt"),
2024 ),
2025 trusted_proxies: [],
2026 store: None,
2027 trees: {},
2028 functions: None,
2029)