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