initial commit
This commit is contained in:
commit
6f50de798b
24 changed files with 1082 additions and 0 deletions
8
roles/baseline/handlers/main.yml
Normal file
8
roles/baseline/handlers/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
- name: Restart firewall
|
||||
ansible.builtin.command: /etc/network/if-pre-up.d/firewall
|
||||
changed_when: true
|
||||
|
||||
- name: Restart sshd
|
||||
ansible.builtin.systemd:
|
||||
name: ssh
|
||||
state: restarted
|
||||
16
roles/baseline/tasks/firewall.yml
Normal file
16
roles/baseline/tasks/firewall.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
- name: Directory for firewall parts
|
||||
ansible.builtin.file:
|
||||
group: root
|
||||
owner: root
|
||||
name: /etc/firewall.d/
|
||||
mode: "0700"
|
||||
state: directory
|
||||
|
||||
- name: Firewall template
|
||||
ansible.builtin.template:
|
||||
dest: /etc/network/if-pre-up.d/firewall
|
||||
group: root
|
||||
owner: root
|
||||
mode: "0755"
|
||||
src: firewall.j2
|
||||
notify: Restart firewall
|
||||
11
roles/baseline/tasks/main.yml
Normal file
11
roles/baseline/tasks/main.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
- name: Manage apt packages
|
||||
ansible.builtin.import_tasks: packages.yml
|
||||
|
||||
- name: Manage global firewall
|
||||
ansible.builtin.import_tasks: firewall.yml
|
||||
|
||||
- name: Manage root user
|
||||
ansible.builtin.import_tasks: rootuser.yml
|
||||
|
||||
- name: Ensure handlers have ran
|
||||
ansible.builtin.meta: flush_handlers
|
||||
47
roles/baseline/tasks/packages.yml
Normal file
47
roles/baseline/tasks/packages.yml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
- name: Keep apt repository list uptodate
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
# Even if we "changed it", it's merely a cache, so ignore
|
||||
changed_when: false
|
||||
|
||||
- name: Update system packages to lates
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
|
||||
- name: Remove unused packages
|
||||
ansible.builtin.apt:
|
||||
autoremove: true
|
||||
|
||||
# The following is a list of utilities that I personally use
|
||||
# to make my life easier. It is opiniated and not needed...
|
||||
- name: Install utilities to make life easier
|
||||
ansible.builtin.apt:
|
||||
pkg:
|
||||
- apt-dater
|
||||
- mosh
|
||||
- mc
|
||||
- vim
|
||||
- curl
|
||||
- jq
|
||||
- host
|
||||
- telnet
|
||||
- screen
|
||||
- tmux
|
||||
- tcpdump
|
||||
- sqlite3
|
||||
- bash-completion
|
||||
- mtr-tiny
|
||||
- iotop
|
||||
- iftop
|
||||
- htop
|
||||
- ncdu
|
||||
|
||||
- name: Firewall for mosh
|
||||
ansible.builtin.template:
|
||||
dest: /etc/firewall.d/mosh
|
||||
group: root
|
||||
owner: root
|
||||
mode: "0755"
|
||||
src: mosh.j2
|
||||
notify: Restart firewall
|
||||
27
roles/baseline/tasks/rootuser.yml
Normal file
27
roles/baseline/tasks/rootuser.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
- name: Set root password
|
||||
ansible.builtin.user:
|
||||
name: root
|
||||
password: "{{ root_password }}"
|
||||
|
||||
- name: Ensure ssh directory for root
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
path: /root/.ssh
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Set authorized keys for root
|
||||
ansible.builtin.copy:
|
||||
content: "{{ root_sshkeys | join('\n') }}"
|
||||
dest: /root/.ssh/authorized_keys
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
|
||||
- name: Only allow root ssh
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/ssh/sshd_config
|
||||
line: "PermitRootLogin prohibit-password"
|
||||
regexp: "^PermitRootLogin "
|
||||
notify: Restart sshd
|
||||
78
roles/baseline/templates/firewall.j2
Normal file
78
roles/baseline/templates/firewall.j2
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/bash
|
||||
# {{ ansible_managed }}
|
||||
|
||||
# IPv4:
|
||||
iptables -F
|
||||
iptables -X
|
||||
iptables -t mangle -F
|
||||
iptables -t mangle -X
|
||||
iptables -t nat -F
|
||||
iptables -t nat -X
|
||||
|
||||
iptables -P INPUT ACCEPT
|
||||
iptables -P OUTPUT ACCEPT
|
||||
iptables -P FORWARD ACCEPT
|
||||
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
iptables -A INPUT -m state --state INVALID -j DROP
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A INPUT -m limit --limit 1/s --limit-burst 2 -p icmp --icmp-type echo-request -j ACCEPT
|
||||
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
|
||||
iptables -A INPUT -p icmp -j ACCEPT
|
||||
|
||||
{% for range in firewall_ssh_ranges %}
|
||||
{%if range.type=="ipv4" %}
|
||||
iptables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
||||
{%endif%}
|
||||
{%endfor%}
|
||||
|
||||
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
iptables -A OUTPUT -m state --state INVALID -j DROP
|
||||
|
||||
# IPv6:
|
||||
ip6tables -F
|
||||
ip6tables -X
|
||||
ip6tables -t mangle -F
|
||||
ip6tables -t mangle -X
|
||||
ip6tables -t nat -F
|
||||
ip6tables -t nat -X
|
||||
|
||||
ip6tables -P INPUT ACCEPT
|
||||
ip6tables -P OUTPUT ACCEPT
|
||||
ip6tables -P FORWARD ACCEPT
|
||||
|
||||
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
ip6tables -A INPUT -m state --state INVALID -j DROP
|
||||
ip6tables -A INPUT -i lo -j ACCEPT
|
||||
ip6tables -A INPUT -m limit --limit 1/s --limit-burst 2 -p icmpv6 --icmpv6-type echo-request -j ACCEPT
|
||||
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP
|
||||
ip6tables -A INPUT -p icmpv6 -j ACCEPT
|
||||
|
||||
{% for range in firewall_ssh_ranges %}
|
||||
{%if range.type=="ipv6" %}
|
||||
ip6tables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
||||
{%endif%}
|
||||
{%endfor%}
|
||||
|
||||
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
ip6tables -A OUTPUT -m state --state INVALID -j DROP
|
||||
|
||||
|
||||
# Disable all forwarding
|
||||
echo 0 > /proc/sys/net/ipv4/ip_forward
|
||||
echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
|
||||
|
||||
# Customisation:
|
||||
{# we use run-parts as it guarantees order and ignores backups etc. We use --list as it would otherwise run them concurently, causing iptables to exit with EAGAIN as changing the firewall is not possible by 2 prococesses #}
|
||||
for i in $(run-parts --list /etc/firewall.d/)
|
||||
do
|
||||
$i
|
||||
done
|
||||
|
||||
# Finish off with a block
|
||||
iptables -A INPUT -j REJECT
|
||||
ip6tables -A INPUT -j REJECT
|
||||
iptables -A FORWARD -j REJECT
|
||||
ip6tables -A FORWARD -j REJECT
|
||||
|
||||
# {{ansible_managed}}
|
||||
6
roles/baseline/templates/mosh.j2
Normal file
6
roles/baseline/templates/mosh.j2
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
# {{ansible_managed}}
|
||||
# Firewall to allow mosh sessions
|
||||
|
||||
ip6tables -A INPUT -p udp --match multiport --dports 60001:60020 -j ACCEPT
|
||||
iptables -A INPUT -p udp --match multiport --dports 60001:60020 -j ACCEPT
|
||||
3
roles/ppm/handlers/main.yml
Normal file
3
roles/ppm/handlers/main.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
- name: Restart firewall
|
||||
ansible.builtin.command: /etc/network/if-pre-up.d/firewall
|
||||
changed_when: true
|
||||
43
roles/ppm/tasks/copyappdef.yml
Normal file
43
roles/ppm/tasks/copyappdef.yml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# The chicken-egg should not be used. I use ppm to setup ppm.pfoe.be
|
||||
# so I cannot clone the appdefinition using git. So this chicken-egg
|
||||
# makes it possible to install apps when I'm still installing ppm.pfoe.be
|
||||
# However, it's easier to just git clone directly from the source.
|
||||
# You will need a local copy of the git repository to use this
|
||||
|
||||
- name: Create temporary build directory
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
suffix: build
|
||||
register: temp_dir
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: Create a .tar.gz archive from the chicken-egg directory
|
||||
community.general.archive:
|
||||
dest: "{{ temp_dir.path }}/appdef.tar.gz"
|
||||
path: "{{ ppm_app.chicken_egg_appdefinition }}"
|
||||
mode: "0600"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: Create directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ ppm_app_user.home }}/appdefinition"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: "{{ ppm_app_user.name }}"
|
||||
group: "{{ ppm_app_user.group }}"
|
||||
|
||||
- name: Unzip the files to server
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ temp_dir.path }}/appdef.tar.gz"
|
||||
dest: "{{ ppm_app_user.home }}/appdefinition"
|
||||
owner: "{{ ppm_app_user.name }}"
|
||||
group: "{{ ppm_app_user.group }}"
|
||||
|
||||
- name: Remove temp dir
|
||||
ansible.builtin.file:
|
||||
path: "{{ temp_dir.path }}"
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
19
roles/ppm/tasks/main.yml
Normal file
19
roles/ppm/tasks/main.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
- name: Install PPM program as root
|
||||
ansible.builtin.import_tasks: ppminstall.yml
|
||||
|
||||
- name: Go over all projects for this server
|
||||
ansible.builtin.include_tasks: oneapp.yml
|
||||
loop: "{{ ppm_apps }}"
|
||||
loop_control:
|
||||
loop_var: ppm_app
|
||||
label: "{{ ppm_app.user }}"
|
||||
when: ppm_app.on_server == inventory_hostname
|
||||
|
||||
- name: Configure firewall options
|
||||
ansible.builtin.template:
|
||||
dest: /etc/firewall.d/ppmfirewall
|
||||
group: root
|
||||
owner: root
|
||||
mode: "0755"
|
||||
src: ppmfirewall.j2
|
||||
notify: Restart firewall
|
||||
36
roles/ppm/tasks/oneapp.yml
Normal file
36
roles/ppm/tasks/oneapp.yml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
- name: "Create user ({{ ppm_app.user }})"
|
||||
ansible.builtin.user:
|
||||
name: "{{ ppm_app.user }}"
|
||||
shell: /bin/bash
|
||||
register: ppm_app_user
|
||||
|
||||
# Enabling linger will make systemd start the user-systemd for this user at bootup time
|
||||
# Enabling this will allow us to run programs automatically and independently of any user login
|
||||
- name: "Linger user ({{ ppm_app.user }})"
|
||||
ansible.builtin.command:
|
||||
cmd: "loginctl enable-linger {{ ppm_app_user.name }}"
|
||||
creates: "/var/lib/systemd/linger/{{ ppm_app_user.name }}"
|
||||
|
||||
- name: "Ensure we have a XDG_RUNTIME_DIR variable ({{ ppm_app.user }})"
|
||||
ansible.builtin.lineinfile:
|
||||
dest: "{{ ppm_app_user.home }}/.bashrc"
|
||||
state: present
|
||||
line: "export XDG_RUNTIME_DIR=/run/user/$(id -u)"
|
||||
regexp: ^export XDG_RUNTIME_DIR=
|
||||
|
||||
- name: "Place configuration ({{ ppm_app.user }})"
|
||||
ansible.builtin.copy:
|
||||
content: "{{ ppm_app.appconfig | dict2items | selectattr('key', 'ne', 'code') | items2dict | to_nice_yaml }}"
|
||||
dest: "{{ ppm_app_user.home }}/config.yml"
|
||||
owner: "{{ ppm_app_user.name }}"
|
||||
group: "{{ ppm_app_user.group }}"
|
||||
mode: "0600"
|
||||
|
||||
- name: "See if app definition exists ({{ ppm_app.user }})"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ ppm_app_user.home }}/appdefinition"
|
||||
register: appdefinition
|
||||
|
||||
- name: "Bootstrap the app definition ({{ ppm_app.user }})"
|
||||
ansible.builtin.include_tasks: copyappdef.yml
|
||||
when: ppm_app.chicken_egg_appdefinition is defined and not appdefinition.stat.exists
|
||||
37
roles/ppm/tasks/ppminstall.yml
Normal file
37
roles/ppm/tasks/ppminstall.yml
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
- name: Install ppm dependencies
|
||||
ansible.builtin.apt:
|
||||
pkg:
|
||||
# We hard depend on podman, as this is the workhorse of most apps
|
||||
# We also depend on podman unshare in ppm itself
|
||||
- podman
|
||||
# Required for rootless operation
|
||||
- uidmap
|
||||
# Use the newer network backend instead of the default CNI backend
|
||||
- netavark
|
||||
# Required for rootless networking
|
||||
- slirp4netns
|
||||
# podman-compose is also used in many apps we can install
|
||||
- podman-compose
|
||||
# Restic is currently the only supported backup system
|
||||
- restic
|
||||
# The python dependencies of ppm are baked in. However, jsonschema is
|
||||
# not pure python, so it must be installed from system package
|
||||
- python3-jsonschema
|
||||
# Git is required for checking out the app definitions
|
||||
- git
|
||||
|
||||
- name: Create state directory
|
||||
ansible.builtin.file:
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "1777"
|
||||
path: /home/.ppmstate
|
||||
|
||||
- name: Copy ppm
|
||||
ansible.builtin.copy:
|
||||
src: "{{ ppm_binary }}"
|
||||
dest: /usr/local/bin/ppm
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
15
roles/ppm/templates/ppmfirewall.j2
Normal file
15
roles/ppm/templates/ppmfirewall.j2
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
# PPM Firewal, written by ansible
|
||||
|
||||
{% for ppm_app in ppm_apps %}
|
||||
# Firewall for {{ ppm_app.user }}
|
||||
{% for redirect in ppm_app.firewall_redirect | default([]) %}
|
||||
# Redirect {{ redirect.from }} to {{ redirect.to }}
|
||||
iptables -A INPUT -p tcp --dport {{ redirect.from }} -j ACCEPT
|
||||
ip6tables -A INPUT -p tcp --dport {{ redirect.from }} -j ACCEPT
|
||||
iptables -t nat -A PREROUTING -p tcp --dport {{ redirect.to }} -j REDIRECT --to-ports {{ redirect.from }}
|
||||
ip6tables -t nat -A PREROUTING -p tcp --dport {{ redirect.to }} -j REDIRECT --to-ports {{ redirect.from }}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue