1 Commits

Author SHA1 Message Date
2b9f6567c1 feat: restore gitea proxy functionality with conditional support
Recupera la funcionalidad de proxy para repositorios git (gitea) que se perdió
al integrar el proxy SSH con stream.conf. Los servicios ahora pueden habilitar
opcionalmente el acceso a gitea agregando el atributo gitea_port.

Cambios:
- Agregado soporte condicional de upstream y servidor gitea en stream.conf
- El puerto gitea se agrega dinámicamente a matrix_ports cuando está definido
- Usa el mismo server_name que SSH, diferenciado solo por puerto
- Respeta la configuración root para dominios raíz

Uso: Agregar gitea_port: 2222 a cualquier servicio en abyayala.yml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:19:49 -03:00
22 changed files with 106 additions and 95 deletions

View File

@ -60,7 +60,6 @@ matrix:
- kaasavi
- llavero
- deabajo
- testnet
- service_name: respaldos
domains:
@ -68,9 +67,11 @@ matrix:
nodo: respaldos.comun
force_https: yes
- nodo: marmite
- service_name: marmite
domains:
- marmite.abyaya.la
nodo: marmite.comun
force_https: yes
# Auto-deduced: domains: [marmite.abyaya.la], rap_dn: marmite.comun
- service_name: yanapak
domains:

View File

@ -1,6 +1,3 @@
host_ip: 5.161.236.18
main_zone: abyaya.la
vpn_name: comun
vpn_proxy: 10.13.12.1
proxy_scale: 2
domains_default_force_https: yes

View File

@ -1,5 +1 @@
host_ip: 157.180.114.62
main_zone: abyayala.red
vpn_name: comun
vpn_proxy: 10.13.12.159
proxy_scale: 1

View File

@ -1,10 +1,9 @@
- set_fact:
current_service: "{{ item }}"
# Deducir service_name: usar 'nodo' si existe, sino 'service_name' (retrocompatibilidad)
service_name: "{{ item.nodo | default(item.service_name) }}"
service_name: "{{ item.service_name }}"
service_roles: "{{ item.roles | default([]) }}"
- include_role:
- include_role:
name: "{{ current_role_name }}"
with_items: "{{ service_roles }}"
loop_control:

View File

@ -2,14 +2,12 @@
apt:
name: dnsmasq
state: present
- name: configuracion de red comun
template:
src: dnsmasq.conf
dest: "/etc/dnsmasq.conf"
notify:
- restart dnsmasq
- name: activar el servicio
systemd_service:
name: dnsmasq

View File

@ -74,8 +74,8 @@ resolv-file=/etc/resolv.local
# Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only.
local=/{{ vpn_name }}/
domain={{ vpn_name }}
local=/comun/
domain=comun
# Add domains which you want to force to an IP address here.
# The example below send any host in double-click.net to a local
@ -117,12 +117,12 @@ domain={{ vpn_name }}
# specified interfaces (and the loopback) give the name of the
# interface (eg eth0) here.
# Repeat the line for more than one interface.
interface={{ vpn_name }}
interface=comun
# Or you can specify which interface _not_ to listen on
except-interface=eth0
# Or which to listen on by address (remember to include 127.0.0.1 if
# you use this.)
listen-address={{ vpn_proxy }},127.0.0.1
listen-address=10.13.12.1,127.0.0.1
# If you want dnsmasq to provide only DNS service on an interface,
# configure it as shown above, and then use the following line to
# disable DHCP and TFTP on it.

View File

@ -6,7 +6,7 @@
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i {{ vpn_name }} -j ACCEPT
-A INPUT -i comun -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT

View File

@ -5,6 +5,6 @@ server {
client_max_body_size 4k;
location / {
proxy_pass http://{{ vpn_proxy }}:3000;
proxy_pass http://10.13.12.1:3000;
}
}

View File

@ -1,10 +1,10 @@
- set_fact:
is_abyayala_subdomain: "{{ domain.endswith('.' ~ main_zone) }}"
is_abyayala_subdomain: "{{ domain.endswith('.abyaya.la') }}"
- name: extract zone and hostname for main zone subdomains
- name: extract zone and hostname for abyaya.la subdomains
set_fact:
zone: "{{ main_zone ~ '.' }}"
hostname: "{{ domain | regex_replace('([a-z0-9-]+)\\.' ~ main_zone|regex_escape , '\\1') }}"
zone: "abyaya.la."
hostname: "{{ domain | regex_replace('([a-z0-9-]+)\\.abyaya\\.la', '\\1') }}"
when: is_abyayala_subdomain
- name: split domain into parts
@ -30,11 +30,6 @@
hostname: "{{ domain_parts[:-2] | join('.') if domain_parts | length > 2 else '@' }}"
when: not is_abyayala_subdomain and not uses_compound_tld
- name: Debug knsupdate for this domain
debug:
msg: "{{ lookup('template', 'templates/commands.j2') }}"
when: is_abyayala_subdomain
- name: knsupdate for this domain
shell: knsupdate
args:

View File

@ -10,18 +10,14 @@
include_role: name=certbot
tags: certbot
- name: set main_zone_regex from main_zone
set_fact:
main_zone_regex: "{{ '.' ~ main_zone | replace('.', '\\.') }}"
- name: configuration paths
file: path={{ abc }} state=directory
file: path={{ comun }} state=directory
with_items:
- "{{ stream_path }}"
- "{{ conf_path }}"
- "{{ certbot_webroot }}"
loop_control:
loop_var: abc
loop_var: comun
- name: virtual hosts path
file: path={{ vhosts_path }} state=directory
@ -41,15 +37,34 @@
loop_control:
loop_var: common
- name: neo stuff
- name: domains' stuff
block:
- name: normalize and build matrix_loop
include_tasks: normalize_node.yml
with_items: "{{ matrix }}"
when: "{{ (domino.domains is defined or domino.nodo is defined or domino.service_name is defined) }}"
- name: slice matrix with those having domains defined
set_fact:
matrix_loop: "{{ matrix_loop | default([]) | union([ domino ]) }}"
with_items: "{{ matrix }}"
when: "{{ domino.domains is defined and domino.nodo is defined }}"
loop_control:
loop_var: domino
- name: ensure abyaya.la subdomain is always first in domains list
set_fact:
matrix_loop_with_defaults: "{{ matrix_loop_with_defaults | default([]) | union([ item_with_default ]) }}"
vars:
existing_abyayala_domains: "{{ item.domains | select('match', '.*\\.abyaya\\.la$') | list }}"
has_abyayala_domain: "{{ existing_abyayala_domains | length > 0 }}"
default_domain: "{{ item.service_name }}.abyaya.la"
other_domains: "{{ item.domains | reject('match', '.*\\.abyaya\\.la$') | list }}"
abyayala_domain_to_use: "{{ existing_abyayala_domains[0] if has_abyayala_domain else default_domain }}"
domains_with_default: "{{ [abyayala_domain_to_use] + other_domains }}"
item_with_default: "{{ item | combine({'domains': domains_with_default}) }}"
with_items: "{{ matrix_loop | default([]) }}"
- name: update matrix_loop with defaults
set_fact:
matrix_loop: "{{ matrix_loop_with_defaults }}"
when: matrix_loop_with_defaults is defined
- name: certificates loop
include_tasks: ../../certbot/tasks/certbot.yml
with_items: "{{ matrix_loop | default([]) }}"
@ -63,7 +78,7 @@
with_items: "{{ matrix_loop }}"
loop_control:
loop_var: vhost
when: ((service is undefined) or (service is defined and service == vhost.service_name)) and not vhost.skip_vhost
when: (service is undefined) or (service is defined and service == vhost.service_name)
- name: streams loop
include_tasks: stream.yml
@ -79,6 +94,14 @@
when: (ma.ports is defined)
loop_control:
loop_var: ma
- name: add gitea port if any service has gitea_port defined
set_fact:
matrix_ports: "{{ matrix_ports | default([]) | union([ma.gitea_port]) }}"
with_items: "{{ matrix }}"
when: (ma.gitea_port is defined)
loop_control:
loop_var: ma
- include_tasks: ../../althost/tasks/compose.yml
vars: # forcing since this role is included statically

View File

@ -1,21 +0,0 @@
- set_fact:
_existing_abyayala_domains: "{{ (domino.domains | default([])) | select('match', '.*' ~ main_zone_regex ~ '$') | list }}"
_other_domains: "{{ (domino.domains | default([])) | reject('match', '.*' ~ main_zone_regex ~ '$') | list }}"
_node_name: "{{ domino.nodo | default(domino.service_name) }}"
_default_domain: "{{ (domino.nodo | default(domino.service_name)) ~ '.' ~ main_zone }}"
_default_rap_dn: "{{ (domino.nodo | default(domino.service_name)) ~ '.' ~ vpn_name }}"
- set_fact:
domino_normalized:
nodo: "{{ _node_name }}"
rap_dn: "{{ domino.rap_dn | default(_default_rap_dn) }}"
domains: "{{ [(_existing_abyayala_domains[0] if (_existing_abyayala_domains | length > 0) else _default_domain)] + _other_domains }}"
force_https: "{{ domino.force_https | default(domains_default_force_https) }}"
ports: "{{ domino.ports | default([]) }}"
enable_compression: "{{ domino.enable_compression | default(domains_default_enable_compression) }}"
roles: "{{ domino.roles | default([]) }}"
service_name: "{{ domino.service_name | default(_node_name) }}"
skip_vhost: "{{ (domino.roles is defined and (domino.roles | length > 0) and domino.domains is not defined) }}"
- set_fact:
matrix_loop: "{{ matrix_loop | default([]) | union([ domino_normalized ]) }}"

View File

@ -1,10 +1,10 @@
- set_fact:
vhost_dest: "{{ stream_path }}/{{ vhost.service_name }}.conf"
vhost_dest: "{{ stream_path }}/{{ vhost.domains[0] }}.conf"
- name: default stream for ssh
template:
src: "{{ default_stream }}"
dest: "{{ vhost_dest }}"
when: vhost.ports is defined and (vhost.ports | length > 0)
when: vhost.ports is defined
notify:
- reload proxy

View File

@ -1,12 +1,12 @@
- set_fact:
vhost_dest: "{{ vhosts_path }}/{{ vhost.domains[0] }}.conf"
- block:
- block:
- set_fact:
custom_vhost: "roles/{{ vhost.roles[0] }}/templates/vhost.conf"
- set_fact:
proxy_conf: "roles/{{ vhost.roles[0] }}/templates/proxy.conf"
when: vhost.roles is defined and (vhost.roles | length > 0)
when: vhost.roles is defined
- set_fact:
proxy_conf_look: "{{ lookup('template', proxy_conf) }}"
@ -16,7 +16,7 @@
template:
src: "{{ default_vhost }}"
dest: "{{ vhost_dest }}"
when: (vhost.roles is undefined or (vhost.roles | length == 0) or vhost.roles[0] == 'proxy') or (custom_vhost is undefined or custom_vhost is not is_file)
when: (vhost.roles is undefined or vhost.roles[0] == 'proxy') or (custom_vhost is undefined or custom_vhost is not is_file)
notify:
- reload proxy
@ -24,6 +24,6 @@
template:
src: "{{ custom_vhost }}"
dest: "{{ vhost_dest }}"
when: (vhost.roles is defined and (vhost.roles | length > 0) and vhost.roles[0] != 'proxy') and custom_vhost is defined and custom_vhost is is_file
when: (vhost.roles is defined and vhost.roles[0] != 'proxy') and custom_vhost is defined and custom_vhost is is_file
notify:
- reload proxy

View File

@ -19,7 +19,7 @@
proxy_ssl_server_name on;
proxy_ssl_name $ssl_server_name;
proxy_pass https://$comun_{{ vhost.rap_dn | replace(".", "") }};
proxy_pass https://$comun_{{ vhost.nodo | replace(".", "") }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

View File

@ -1,11 +1,35 @@
upstream ssh_{{ vhost.rap_dn | replace(".", "") }} {
server {{ vhost.rap_dn }}:22;
upstream ssh_{{ vhost.nodo | replace(".", "") }} {
server {{ vhost.nodo }}:22;
}
{% if vhost.gitea_port is defined %}
upstream gitea_{{ vhost.nodo | replace(".", "") }} {
server {{ vhost.nodo }}:{{ vhost.gitea_port }};
}
{% endif %}
server {
listen {{ vhost.ports[0] }};
server_name {{ vhost.service_name }}.{{ main_zone }};
{% if vhost.root | default(false) %}
server_name {{ vhost.domains | join(' ') }};
{% else %}
server_name .{{ vhost.domains | join(' .') }};
{% endif %}
proxy_pass ssh_{{ vhost.rap_dn | replace(".", "") }};
}
proxy_pass ssh_{{ vhost.nodo | replace(".", "") }};
}
{% if vhost.gitea_port is defined %}
server {
listen {{ vhost.gitea_port }};
{% if vhost.root | default(false) %}
server_name {{ vhost.domains | join(' ') }};
{% else %}
server_name .{{ vhost.domains | join(' .') }};
{% endif %}
proxy_pass gitea_{{ vhost.nodo | replace(".", "") }};
}
{% endif %}

View File

@ -1,10 +1,10 @@
map $http_host $comun_{{ vhost.rap_dn | replace(".", "") }} {
map $http_host $comun_{{ vhost.nodo | replace(".", "") }} {
hostnames;
{% for domain in vhost.domains %}
{% if vhost.root | default(false) %}
{{ domain }} {{ vhost.rap_dn }};
{{ domain }} {{ vhost.nodo }};
{% else %}
.{{ domain }} {{ vhost.rap_dn }};
.{{ domain }} {{ vhost.nodo }};
{% endif %}
{% endfor %}
}
@ -18,7 +18,7 @@ server {
listen 80;
resolver {{ vpn_proxy }} valid=300s;
resolver 10.13.12.1 valid=300s;
resolver_timeout 5s;
{% if vhost.root | default(false) %}

View File

@ -1,6 +1,5 @@
domains_default_ssl: no
domains_default_force_https: no
domains_default_enable_compression: no
# nginx
vhosts_path: "{{ compose_path }}/proxy/vhosts"

View File

@ -2,7 +2,7 @@
# https://serverfault.com/questions/1108989/isc-dhcp-client-dhclient-alternative
- name: instalar dependecias de la RAP
apt:
name: ['tinc', 'rsync', 'dhcpcd5']
name: ['tinc', 'rsync', 'dhcp5']
state: latest
# update_cache: yes
tags: installation
@ -11,13 +11,13 @@
- name: copiar el codigo fuente
synchronize:
src: ../roles/rap/code/rap/
src: ../roles/rap/code/rap
dest: "{{ rap_path }}"
perms: true
- name: hacer ejecutable el archivo rap
file:
path: "{{ rap_path }}/rap"
path: "{{ rap_path }}/rap/rap"
state: touch
mode: '774'
modification_time: preserve
@ -26,13 +26,13 @@
- name: inicializar el nodo
shell:
cmd: "./rap init -i {{ nodo }}"
chdir: "{{ rap_path }}"
chdir: "{{ rap_path }}/rap"
environment:
NETWORK: "{{ vpn_name }}"
NETWORK: comun
- name: instalar el nodo
shell:
cmd: "./rap install -v {{ nodo }}"
chdir: "{{ rap_path }}"
chdir: "{{ rap_path }}/rap"
environment:
NETWORK: "{{ vpn_name }}"
NETWORK: comun

View File

@ -24,9 +24,9 @@
cmd: "./rap add-host {{ althost }} {{ nod }}"
chdir: "{{ rap_path }}"
args:
creates: "{{ rap_path }}/networks/{{ vpn_name }}/abyayala/hosts/{{ nod }}"
creates: "{{ rap_path }}/networks/comun/abyayala/hosts/{{ nod }}"
environment:
NETWORK: "{{ vpn_name }}"
NETWORK: comun
with_items: "{{ item.nodos }}"
loop_control:
loop_var: nod
@ -36,4 +36,4 @@
cmd: "./rap install -v {{ althost }}"
chdir: "{{ rap_path }}"
environment:
NETWORK: "{{ vpn_name }}"
NETWORK: comun

View File

@ -1,6 +1,5 @@
# Instalacion de la RAP en maquina local
# ansible-playbook --become tasks/rap.yml -e "host=localhost nodo=chem" -i hosts.local
# ansible-playbook tasks/rap.yml -e "host=testing nodo=testnet"
---
- hosts: "{{ host }}"
tasks:

View File

@ -16,7 +16,8 @@ matrix:
nodos:
- qi
- nodo: qi
ports:
- 531
- service_name: qi
domains:
- qi.abyayala.red
nodo: qi.comun
# force_https: yes