Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ansible/roles/ingressproxy/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
# Public TCP entry points on this host forwarded into the mesh. Entries:
# {name: mysql, bind: 203.0.113.7, port: 3306, backend: 10.10.0.4:3306}.
# Bind the public IP explicitly: the same port may already be taken on
# 127.0.0.1 (the local MySQL replica on russia-03).
ingressproxy_routes: []

# Idle timeout for both sides; long enough for slow analytics queries.
ingressproxy_timeout: 1h
5 changes: 5 additions & 0 deletions ansible/roles/ingressproxy/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Reload haproxy
ansible.builtin.service:
name: haproxy
state: reloaded
23 changes: 23 additions & 0 deletions ansible/roles/ingressproxy/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
- name: Install haproxy
ansible.builtin.apt:
name: haproxy
state: present
update_cache: true
cache_valid_time: 3600

- name: Deploy /etc/haproxy/haproxy.cfg
ansible.builtin.template:
src: haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
owner: root
group: root
mode: "0644"
validate: "haproxy -c -f %s"
notify: Reload haproxy

- name: Enable and start haproxy
ansible.builtin.service:
name: haproxy
state: started
enabled: true
25 changes: 25 additions & 0 deletions ansible/roles/ingressproxy/templates/haproxy.cfg.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Managed by ansible (roles/ingressproxy). Local edits will be overwritten.
global
log /dev/log local0 warning
maxconn 512
user haproxy
group haproxy
daemon

defaults
mode tcp
log global
option tcplog
timeout connect 5s
timeout client {{ ingressproxy_timeout }}
timeout server {{ ingressproxy_timeout }}

# No `check` on servers: a bare TCP probe counts as a connect error on MySQL,
# and max_connect_errors would then block this host's wg IP — the same address
# the local replica replicates from.
{% for route in ingressproxy_routes %}
listen {{ route.name }}
bind {{ route.bind }}:{{ route.port }}
server backend {{ route.backend }}

{% endfor %}
6 changes: 6 additions & 0 deletions ansible/site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@
- role: egressproxy
when: egressproxy_managed | default(false)
tags: [egressproxy]
# The reverse: public TCP entry in Russia forwarded into the mesh
# (ru.mysql.gistrec.cloud → finland-01 MySQL) for Yandex Cloud consumers
# whose packets stopped reaching finland-01 in 2026-10.
- role: ingressproxy
when: ingressproxy_routes | default([]) | length > 0
tags: [ingressproxy]
# Break-glass: rescue user whose keys live OUTSIDE any home dir
# (root-owned /etc/ssh/rescue_keys) — survives home wipes and login-user
# compromise. Opt-in per host; germany-02 runs it too (2026-07-18
Expand Down
Loading