Compare commits

...

7 commits

Author SHA1 Message Date
c34b3c1d0f add passt as dependency 2025-08-15 22:58:22 +02:00
4d8c4e5f48 Cleanup firewall + make it more strict
- Do not put too many empty newlines in rendered file
- Also write redirect rules in the output chain.  This will allow us to
use the port from the same machine.  Note that redirect does rewrite the
destination to localhost if used on the same machine, so your
application should also listen to localhost
- made the file a bit clearer with better comments
- Add the explicit device if we can for redirects
2025-08-15 22:52:03 +02:00
dc99b61ea8 the zabbix scripts I use use netcat 2025-08-15 22:49:10 +02:00
0a32383de3 add ssh key option for apps
This way we can push ssh keys that can pull/push to repositories.  This
is very handy if we wish to edit/maintain the appinfo repository right
on the server where it is hosted....
2025-08-15 22:48:55 +02:00
5fda82d0d3 when the setup changed something, show output in changed color 2025-08-15 22:48:14 +02:00
b021bb2620 allow defining the home directory
The idea here is that we can have a backup server that should run on a
slow huge disk, and that the rest should run on your very fast nvme's.
To differentiate, you can specify where the homedir should be
2025-08-15 22:47:51 +02:00
a55246263b implement "enabled" apps 2025-08-15 22:46:42 +02:00
4 changed files with 62 additions and 13 deletions

View file

@ -3,20 +3,45 @@
# PPM Firewall
{% for app in otherapps -%}
# App {{ app }}
{%- if "firewall" in otherapps[app]["imports"] -%}
{%- set oneapp = otherapps[app]["imports"]["firewall"] %}
{% for redirect in oneapp.redirect %}
{%- for redirect in oneapp.redirect %}
{%- if redirect.version == "ipv4" %}
{%- if redirect.ip is defined %}
# Redirect {{ redirect.ip }}:{{ redirect.from }} to {{ redirect.to }} ({{ redirect.proto | default('tcp') }}) for {{ app }}
inputinterface=$(ip -o -4 addr show | awk '$3 == "inet" && index($4,"{{ redirect.ip }}/")==1 {print "-i " $2}')
iptables -A INPUT -d {{ redirect.ip }} $inputinterface -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
iptables -t nat -A PREROUTING $inputinterface -d {{ redirect.ip }} -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
iptables -t nat -A OUTPUT -d {{ redirect.ip }} -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
{%- else %}
# Redirect {{ redirect.from }} to {{ redirect.to }} ({{ redirect.proto | default('tcp') }}) for {{ app }}
iptables -A INPUT -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
ip6tables -A INPUT -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
iptables -t nat -A PREROUTING -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
ip6tables -t nat -A PREROUTING -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
{% endfor %}
{% for openport in oneapp.open %}
iptables -A INPUT -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
iptables -t nat -A OUTPUT -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
{%- endif %}
{%- else %}{# ipv6 #}
{%- if redirect.ip is defined %}
# Redirect {{ redirect.ip }}:{{ redirect.from }} to {{ redirect.to }} ({{ redirect.proto | default('tcp') }}) for {{ app }}
inputinterface=$(ip -o -6 addr show | awk '$3 == "inet6" && index($4,"{{ redirect.ip }}/")==1 {print "-i " $2}')
ip6tables -A INPUT -d {{ redirect.ip }} $inputinterface -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
ip6tables -t nat -A PREROUTING -d {{ redirect.ip }} $inputinterface -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
ip6tables -t nat -A OUTPUT -d {{ redirect.ip }} -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
{%- else %}
# Redirect {{ redirect.from }} to {{ redirect.to }} ({{ redirect.proto | default('tcp') }}) for {{ app }}
ip6tables -A INPUT -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.to }} -j ACCEPT
ip6tables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
ip6tables -t nat -A OUTPUT -m addrtype --dst-type LOCAL -p {{ redirect.proto | default('tcp') }} --dport {{ redirect.from }} -j REDIRECT --to-ports {{ redirect.to }}
{%- endif %}
{%- endif %}
{%- endfor %}
{%- for openport in oneapp.open %}
# Open port {{ openport.port }}/{{ openport.proto | default('tcp') }} for app {{ app }}
iptables -A INPUT -p {{ openport.proto | default('tcp') }} --dport {{ openport.port }} -j ACCEPT
ip6tables -A INPUT -p {{ openport.proto | default('tcp') }} --dport {{ openport.port }} -j ACCEPT
{% endfor %}
{% endif %}
{%- if redirect.version == "ipv4" %}
iptables -A INPUT {% if firewall_bindservices_ipv4 is defined %}-s {{firewall_bindservices_ipv4 }}{% endif %} -p {{ openport.proto | default('tcp') }} --dport {{ openport.port }} -j ACCEPT
{%- else %}
ip6tables -A INPUT {% if firewall_bindservices_ipv6 is defined %}-s {{firewall_bindservices_ipv6 }}{% endif %} -p {{ openport.proto | default('tcp') }} --dport {{ openport.port }} -j ACCEPT
{%- endif %}
{%- endfor %}
{%- endif %}
{% endfor %}

View file

@ -7,7 +7,7 @@
loop_control:
loop_var: ppm_app
label: "{{ ppm_app.user }}"
when: ppm_app.on_server == inventory_hostname
when: ppm_app.on_server == inventory_hostname and ppm_app.enabled | default(true)
- name: Arrange firewall
ansible.builtin.import_tasks: firewall.yml

View file

@ -2,6 +2,7 @@
ansible.builtin.user:
name: "{{ ppm_app.user }}"
shell: /bin/bash
home: "{{ ppm_app.homedir | default(omit) }}"
register: ppm_app_user
# Enabling linger will make systemd start the user-systemd for this user at bootup time
@ -18,6 +19,23 @@
line: "export XDG_RUNTIME_DIR=/run/user/$(id -u)"
regexp: ^export XDG_RUNTIME_DIR=
- name: "Ensure ssh configuration directory for user {{ ppm_app.user }}"
ansible.builtin.file:
state: directory
mode: "0700"
path: "{{ ppm_app_user.home }}/.ssh"
owner: "{{ ppm_app_user.name }}"
group: "{{ ppm_app_user.group }}"
- name: "Place ssh key for user {{ ppm_app.user }}"
ansible.builtin.copy:
src: "{{ ppm_app.sshkey }}"
mode: "0600"
dest: "{{ ppm_app_user.home }}/.ssh/id_rsa"
owner: "{{ ppm_app_user.name }}"
group: "{{ ppm_app_user.group }}"
when: ppm_app.sshkey is defined
- name: "Place configuration ({{ ppm_app.user }})"
ansible.builtin.copy:
content: "{{ ppm_app.appconfig | dict2items | selectattr('key', 'ne', 'code') | items2dict | to_nice_yaml }}"
@ -56,3 +74,5 @@
- name: Show ppm output
ansible.builtin.debug:
var: ppm_setupstart
# Also mark it when the actual command changed, so it is easy to find...
changed_when: "'No changes have been made, everything was already ok' not in ppm_setupstart.stdout"

View file

@ -10,6 +10,8 @@
- netavark
# Required for rootless networking
- slirp4netns
# Required for rootless networking - for trixie and above
- passt
# podman-compose is also used in many apps we can install
- podman-compose
# Restic is currently the only supported backup system
@ -21,6 +23,8 @@
- git
# Yeah we should use nftables, patches welcome. For now, we install iptables
- iptables
# This is used in our zabbix scripts
- netcat-openbsd
- name: Create state directory
ansible.builtin.file: