diff --git a/README.md b/README.md
index 8d691e1..de7d2d5 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,3 @@
# Home server configuration
Available at [comfycamp.space](https://comfycamp.space).
-
-## Ports
-
-| Number | Protocol | Service | Public URL |
-| --- | --- | --- | --- |
-| 3000 | | Mastodon | [m.comfycamp.space](https://m.comfycamp.space) |
-| 3001 | | Mastodon streaming | |
-| 3002 | | Vaultwarden | |
-| 3003 | | Minio console | |
-| 3004 | | Forgejo | [git.comfycamp.space](https://git.comfycamp.space) |
-| 3005 | | Synapse | |
-| 3006 | | Comfycamp | [comfycamp.space](https://comfycamp.space) |
-| 3478 | tcp/udp | Coturn | |
-| 8022 | | Forgejo SSH | |
-| 8448 | | Synapse/Haproxy | |
-| 9000 | | Minio | |
-| 49152 - 65535 | udp | Coturn | |
diff --git a/roles/comfycamp/tasks/main.yml b/roles/comfycamp/tasks/main.yml
index 758cf07..a5f08c6 100644
--- a/roles/comfycamp/tasks/main.yml
+++ b/roles/comfycamp/tasks/main.yml
@@ -22,6 +22,7 @@
env_file: /etc/comfycamp/.env
networks:
- name: postgresql
+ - name: haproxy
ports:
- 127.0.0.1:3006:4000
restart_policy: unless-stopped
diff --git a/roles/forgejo/tasks/forgejo.yml b/roles/forgejo/tasks/forgejo.yml
index de9a160..1e19cb1 100644
--- a/roles/forgejo/tasks/forgejo.yml
+++ b/roles/forgejo/tasks/forgejo.yml
@@ -26,6 +26,7 @@
- name: postgresql
- name: redis-forgejo
- name: minio
+ - name: haproxy
volumes:
- forgejo:/data
- /etc/timezone:/etc/timezone:ro
diff --git a/roles/haproxy/files/errors/400.http b/roles/haproxy/files/errors/400.http
new file mode 100644
index 0000000..3751ac4
--- /dev/null
+++ b/roles/haproxy/files/errors/400.http
@@ -0,0 +1,8 @@
+HTTP/1.0 400 Bad request
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+
400 Bad request
+Your browser sent an invalid request.
+
diff --git a/roles/haproxy/files/errors/403.http b/roles/haproxy/files/errors/403.http
new file mode 100644
index 0000000..55a1319
--- /dev/null
+++ b/roles/haproxy/files/errors/403.http
@@ -0,0 +1,8 @@
+HTTP/1.0 403 Forbidden
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+403 Forbidden
+Request forbidden by administrative rules.
+
diff --git a/roles/haproxy/files/errors/408.http b/roles/haproxy/files/errors/408.http
new file mode 100644
index 0000000..50aa9d4
--- /dev/null
+++ b/roles/haproxy/files/errors/408.http
@@ -0,0 +1,8 @@
+HTTP/1.0 408 Request Time-out
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+408 Request Time-out
+Your browser didn't send a complete request in time.
+
diff --git a/roles/haproxy/files/errors/500.http b/roles/haproxy/files/errors/500.http
new file mode 100644
index 0000000..bff85fa
--- /dev/null
+++ b/roles/haproxy/files/errors/500.http
@@ -0,0 +1,8 @@
+HTTP/1.0 500 Internal Server Error
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+500 Internal Server Error
+An internal server error occurred.
+
diff --git a/roles/haproxy/files/errors/502.http b/roles/haproxy/files/errors/502.http
new file mode 100644
index 0000000..d493d63
--- /dev/null
+++ b/roles/haproxy/files/errors/502.http
@@ -0,0 +1,8 @@
+HTTP/1.0 502 Bad Gateway
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+502 Bad Gateway
+The server returned an invalid or incomplete response.
+
diff --git a/roles/haproxy/files/errors/503.http b/roles/haproxy/files/errors/503.http
new file mode 100644
index 0000000..d1be36e
--- /dev/null
+++ b/roles/haproxy/files/errors/503.http
@@ -0,0 +1,8 @@
+HTTP/1.0 503 Service Unavailable
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+503 Service Unavailable
+No server is available to handle this request.
+
diff --git a/roles/haproxy/files/errors/504.http b/roles/haproxy/files/errors/504.http
new file mode 100644
index 0000000..555066b
--- /dev/null
+++ b/roles/haproxy/files/errors/504.http
@@ -0,0 +1,8 @@
+HTTP/1.0 504 Gateway Time-out
+Cache-Control: no-cache
+Connection: close
+Content-Type: text/html
+
+504 Gateway Time-out
+The server didn't respond in time.
+
diff --git a/roles/haproxy/files/haproxy.cfg b/roles/haproxy/files/haproxy.cfg
index 5a1248a..2a09d7a 100644
--- a/roles/haproxy/files/haproxy.cfg
+++ b/roles/haproxy/files/haproxy.cfg
@@ -1,16 +1,8 @@
global
- log /dev/log local0
- log /dev/log local1 notice
- chroot /var/lib/haproxy
- stats socket /run/haproxy/admin.sock mode 660 level admin
- stats timeout 30s
+ log /dev/stderr local0
+ log /dev/stderr local1 notice
user haproxy
group haproxy
- daemon
-
- # Default SSL material locations
- ca-base /etc/ssl/certs
- crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
@@ -25,18 +17,18 @@ defaults
timeout connect 5000
timeout client 50000
timeout server 50000
- errorfile 400 /etc/haproxy/errors/400.http
- errorfile 403 /etc/haproxy/errors/403.http
- errorfile 408 /etc/haproxy/errors/408.http
- errorfile 500 /etc/haproxy/errors/500.http
- errorfile 502 /etc/haproxy/errors/502.http
- errorfile 503 /etc/haproxy/errors/503.http
- errorfile 504 /etc/haproxy/errors/504.http
+ errorfile 400 /usr/local/etc/haproxy/errors/400.http
+ errorfile 403 /usr/local/etc/haproxy/errors/403.http
+ errorfile 408 /usr/local/etc/haproxy/errors/408.http
+ errorfile 500 /usr/local/etc/haproxy/errors/500.http
+ errorfile 502 /usr/local/etc/haproxy/errors/502.http
+ errorfile 503 /usr/local/etc/haproxy/errors/503.http
+ errorfile 504 /usr/local/etc/haproxy/errors/504.http
frontend www
mode http
bind :80
- bind :443 ssl crt /etc/haproxy/certs
+ bind :443 ssl crt /usr/local/etc/haproxy/certs
http-request redirect scheme https unless { ssl_fc }
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
@@ -62,7 +54,7 @@ frontend www
use_backend forgejo if acl_git
frontend matrix-federation
- bind *:8448 ssl crt /etc/haproxy/certs
+ bind *:8448 ssl crt /usr/local/etc/haproxy/certs
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
@@ -70,42 +62,42 @@ frontend matrix-federation
backend comfycamp
mode http
- server green 127.0.0.1:3006 check
+ server green comfycamp:4000 check
backend mastodon
mode http
option forwardfor
- server green 127.0.0.1:3000 check
+ server green mastodon-web:3000 check
backend mastodon_streaming
mode http
option forwardfor
option http-server-close
timeout tunnel 1h
- server green 127.0.0.1:3001 check
+ server green mastodon-streaming:4000 check
backend vaultwarden
mode http
option forwardfor
- server green 127.0.0.1:3002 check
+ server green vaultwarden:80 check
backend minio_console
mode http
option forwardfor
- server green 127.0.0.1:3003 check
+ server green minio:9001 check
backend minio
mode http
http-response set-header Access-Control-Allow-Origin https://m.comfycamp.space
option forwardfor
- server green 127.0.0.1:9000 check
+ server green minio:9000 check
backend forgejo
mode http
option forwardfor
- server green 127.0.0.1:3004 check
+ server green forgejo:3000 check
backend matrix
mode http
option forwardfor
- server matrix 127.0.0.1:3005
+ server matrix synapse:8008
diff --git a/roles/haproxy/tasks/main.yml b/roles/haproxy/tasks/main.yml
index 19812b2..5c40ca4 100644
--- a/roles/haproxy/tasks/main.yml
+++ b/roles/haproxy/tasks/main.yml
@@ -1,18 +1,69 @@
---
-- name: Install haproxy
+- name: Create haproxy docker network
become: true
- ansible.builtin.apt:
+ community.docker.docker_network:
name: haproxy
+- name: Create haproxy dirs
+ become: true
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: directory
+ mode: "1755"
+ owner: root
+ group: root
+ loop:
+ - /etc/haproxy
+ - /etc/haproxy/errors
+- name: Copy haproxy config to a temporary location
+ become: true
+ ansible.builtin.copy:
+ src: haproxy.cfg
+ dest: /tmp/haproxy.cfg
+- name: Validate haproxy config
+ become: true
+ community.docker.docker_container:
+ name: haproxy-config-test
+ image: "{{ haproxy_image }}"
+ command: haproxy -c -f /tmp/haproxy.cfg
+ networks:
+ - name: haproxy
+ volumes:
+ - /tmp/haproxy.cfg:/tmp/haproxy.cfg
+ - /etc/haproxy/certs:/usr/local/etc/haproxy/certs:ro
+ detach: no
+- name: Remove temporary container
+ become: true
+ community.docker.docker_container:
+ name: haproxy-config-test
+ state: absent
- name: Copy haproxy config
become: true
ansible.builtin.copy:
src: haproxy.cfg
dest: /etc/haproxy/haproxy.cfg
- validate: /usr/sbin/haproxy -f %s -c
register: haproxy
+- name: Copy errors
+ become: true
+ ansible.builtin.copy:
+ src: errors/{{ item }}.http
+ dest: /etc/haproxy/errors/{{ item }}.http
+ loop: [400, 403, 408, 500, 502, 503, 504]
+- name: Create haproxy container
+ become: true
+ community.docker.docker_container:
+ name: haproxy
+ image: "{{ haproxy_image }}"
+ networks:
+ - name: haproxy
+ volumes:
+ - /etc/haproxy:/usr/local/etc/haproxy:ro
+ sysctls:
+ net.ipv4.ip_unprivileged_port_start: 0
+ ports:
+ - 80:80
+ - 443:443
+ restart_policy: unless-stopped
- name: Reload haproxy
become: true
when: haproxy.changed
- ansible.builtin.systemd_service:
- name: haproxy
- state: reloaded
+ ansible.builtin.shell: docker kill -s HUP haproxy
diff --git a/roles/haproxy/vars/main.yml b/roles/haproxy/vars/main.yml
new file mode 100644
index 0000000..8f7b033
--- /dev/null
+++ b/roles/haproxy/vars/main.yml
@@ -0,0 +1 @@
+haproxy_image: haproxy:3.0-bookworm
diff --git a/roles/mastodon/tasks/mastodon.yml b/roles/mastodon/tasks/mastodon.yml
index 516fbad..415c8de 100644
--- a/roles/mastodon/tasks/mastodon.yml
+++ b/roles/mastodon/tasks/mastodon.yml
@@ -30,6 +30,7 @@
- name: redis-mastodon
- name: postgresql
- name: minio
+ - name: haproxy
ports:
- 127.0.0.1:3000:3000
volumes:
@@ -45,6 +46,7 @@
networks:
- name: redis-mastodon
- name: postgresql
+ - name: haproxy
ports:
- 127.0.0.1:3001:4000
restart_policy: unless-stopped
diff --git a/roles/minio/tasks/main.yml b/roles/minio/tasks/main.yml
index bc16b14..aedc85c 100644
--- a/roles/minio/tasks/main.yml
+++ b/roles/minio/tasks/main.yml
@@ -15,6 +15,7 @@
command: ["minio", "server", "--console-address", ":9001"]
networks:
- name: minio
+ - name: haproxy
volumes:
- minio:/data
ports:
diff --git a/roles/synapse/tasks/synapse.yml b/roles/synapse/tasks/synapse.yml
index e832032..f27fc24 100644
--- a/roles/synapse/tasks/synapse.yml
+++ b/roles/synapse/tasks/synapse.yml
@@ -41,6 +41,7 @@
SYNAPSE_CONFIG_PATH: /etc/synapse/homeserver.yaml
networks:
- name: postgresql
+ - name: haproxy
ports:
- 127.0.0.1:3005:8008/tcp
restart_policy: unless-stopped
diff --git a/roles/tls/tasks/main.yml b/roles/tls/tasks/main.yml
index fe5d333..6394cfb 100644
--- a/roles/tls/tasks/main.yml
+++ b/roles/tls/tasks/main.yml
@@ -32,7 +32,9 @@
ansible.builtin.file:
path: /etc/haproxy/certs
state: directory
- mode: '1750'
+ mode: '1700'
+ owner: "99"
+ group: "99"
- name: Combine certificate and private key
become: true
ansible.builtin.shell:
diff --git a/roles/vaultwarden/tasks/main.yml b/roles/vaultwarden/tasks/main.yml
index a289b05..2d3a1c2 100644
--- a/roles/vaultwarden/tasks/main.yml
+++ b/roles/vaultwarden/tasks/main.yml
@@ -14,6 +14,7 @@
DATABASE_URL: "{{ db_url }}"
networks:
- name: postgresql
+ - name: haproxy
ports:
- 127.0.0.1:3002:80
volumes: