gioser

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…

TOML 1576Shell 205Rust 111Markdown 993774 Definiciones

⎇ 0ea7ecc357158b7971485d277d8782138b25324f scripts/servidor/saywa.ron RON · 2002 líneas · 70.5 KB Historia crudo

servidor: freno anti-rastreo en gitea — de load 14,78 a 0,96 0ea7ecc35 · Sergio ·

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)