Compare commits
No commits in common. "c36f52e4205fe5f8e3e4475c802126670065ba73" and "c34b3c1d0f3f911b35fbe4adbe3c81a7942ed7a2" have entirely different histories.
c36f52e420
...
c34b3c1d0f
18 changed files with 76 additions and 95 deletions
7
README.md
Normal file
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
This is how I set up ppm.pfoe.be
|
||||||
|
|
||||||
|
This repository is currently created to serve
|
||||||
|
as an inspiration for creating your own ansible playbook to set up ppm
|
||||||
|
|
||||||
|
At this moment it is not intended to be used as is/it is a work in progress
|
||||||
|
|
||||||
5
all.yml
Normal file
5
all.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
- name: Perform ppm server ansible playbook
|
||||||
|
hosts: all
|
||||||
|
roles:
|
||||||
|
- baseline
|
||||||
|
- ppm
|
||||||
9
ansible.cfg
Normal file
9
ansible.cfg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[defaults]
|
||||||
|
inventory=inventory
|
||||||
|
retry_files_enabled = False
|
||||||
|
remote_user = root
|
||||||
|
deperaction_warnings = True
|
||||||
|
display_skipped_hosts = True
|
||||||
|
|
||||||
|
result_format=yaml
|
||||||
|
|
||||||
33
group_vars/all/applications.yml
Normal file
33
group_vars/all/applications.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
ppm_apps:
|
||||||
|
- on_server: ppm.pfoe.be
|
||||||
|
user: git
|
||||||
|
chicken_egg_appdefinition: ../forgejo/
|
||||||
|
appconfig:
|
||||||
|
restic:
|
||||||
|
url: "{{ lookup('file', 'passwords/ppm-forgejo-url') }}"
|
||||||
|
password: "{{ lookup('file', 'passwords/ppm-forgejo-password') }}"
|
||||||
|
backupname: "{{ lookup('file', 'passwords/ppm-forgejo-name') }}"
|
||||||
|
appinfo:
|
||||||
|
url: https://ppm.pfoe.be/ppm/forgejo.git
|
||||||
|
config:
|
||||||
|
publicurl: ppm.pfoe.be
|
||||||
|
|
||||||
|
- on_server: ppm.pfoe.be
|
||||||
|
user: nginx
|
||||||
|
chicken_egg_appdefinition: ../nginx/
|
||||||
|
appconfig:
|
||||||
|
appinfo:
|
||||||
|
url: https://ppm.pfoe.be/ppm/nginx.git
|
||||||
|
code:
|
||||||
|
type: localfiles
|
||||||
|
directory: nginx
|
||||||
|
|
||||||
|
- on_server: ppm.pfoe.be
|
||||||
|
user: runner
|
||||||
|
chicken_egg_appdefinition: ../forgejo-runner/
|
||||||
|
appconfig:
|
||||||
|
appinfo:
|
||||||
|
url: https://ppm.pfoe.be/ppm/forgejo-runner.git
|
||||||
|
code:
|
||||||
|
type: localfiles
|
||||||
|
directory: forgejo-runner
|
||||||
7
group_vars/all/firewall.yml
Normal file
7
group_vars/all/firewall.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# I prefer not to share the list of admins in a public repo, so refer to passwords...
|
||||||
|
# The format for the ssh ranges is as follows:
|
||||||
|
# - name: The name that is in a comment in the generated file. Not used anywhere else
|
||||||
|
# type: ipv4 # or ipv6
|
||||||
|
# range: 10.10.10.10/32 # The range, MUST be a valid range, not an ip address, ie there must be a / and the netmask
|
||||||
|
|
||||||
|
firewall_ssh_ranges: "{{ lookup('file', 'passwords/firewall_ssh_ranges.yml') | from_yaml }}"
|
||||||
1
group_vars/all/ppm.yml
Normal file
1
group_vars/all/ppm.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ppm_binary: "{{ lookup('pipe', 'pwd') }}/../ppm/out/ppm"
|
||||||
3
group_vars/all/rootuser.yml
Normal file
3
group_vars/all/rootuser.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
root_password: "{{ lookup('file', 'passwords/root_password_hashed') }}"
|
||||||
|
# ssh keys are public, but I prefer not to share the list of admins in a public repo
|
||||||
|
root_sshkeys: "{{ lookup('file', 'passwords/root_sshkeys.yml') | from_yaml }}"
|
||||||
2
group_vars/all/zabbix.yml
Normal file
2
group_vars/all/zabbix.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
zabbix_server: "{{ lookup('file', 'passwords/zabbix_server') }}"
|
||||||
|
zabbix_psk: "{{ lookup('file', 'passwords/zabbix_psk') }}"
|
||||||
3
inventory
Normal file
3
inventory
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[ppmserver]
|
||||||
|
ppm.pfoe.be
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
# Even if we "changed it", it's merely a cache, so ignore
|
# Even if we "changed it", it's merely a cache, so ignore
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Update system packages to latest
|
- name: Update system packages to lates
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
upgrade: dist
|
upgrade: dist
|
||||||
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
pkg:
|
pkg:
|
||||||
- apt-dater
|
- apt-dater
|
||||||
- man
|
|
||||||
- mosh
|
- mosh
|
||||||
- mc
|
- mc
|
||||||
- vim
|
- vim
|
||||||
|
|
@ -37,9 +36,6 @@
|
||||||
- iftop
|
- iftop
|
||||||
- htop
|
- htop
|
||||||
- ncdu
|
- ncdu
|
||||||
- acl
|
|
||||||
- sudo
|
|
||||||
- ntpsec-ntpdate
|
|
||||||
|
|
||||||
- name: Firewall for mosh
|
- name: Firewall for mosh
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: root
|
name: root
|
||||||
password: "{{ root_password }}"
|
password: "{{ root_password }}"
|
||||||
when: root_password is defined
|
|
||||||
|
|
||||||
- name: Ensure ssh directory for root
|
- name: Ensure ssh directory for root
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|
@ -11,7 +10,6 @@
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: "0700"
|
mode: "0700"
|
||||||
when: root_sshkeys is defined
|
|
||||||
|
|
||||||
- name: Set authorized keys for root
|
- name: Set authorized keys for root
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
|
|
@ -20,7 +18,6 @@
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: "0600"
|
mode: "0600"
|
||||||
when: root_sshkeys is defined
|
|
||||||
|
|
||||||
- name: Only allow root ssh
|
- name: Only allow root ssh
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
|
|
@ -28,4 +25,3 @@
|
||||||
line: "PermitRootLogin prohibit-password"
|
line: "PermitRootLogin prohibit-password"
|
||||||
regexp: "^PermitRootLogin "
|
regexp: "^PermitRootLogin "
|
||||||
notify: Restart sshd
|
notify: Restart sshd
|
||||||
when: root_sshkeys is defined
|
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,11 @@ iptables -A INPUT -m limit --limit 1/s --limit-burst 2 -p icmp --icmp-type echo-
|
||||||
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
|
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
|
||||||
iptables -A INPUT -p icmp -j ACCEPT
|
iptables -A INPUT -p icmp -j ACCEPT
|
||||||
|
|
||||||
{% if firewall_ssh_ranges is defined %}
|
|
||||||
{% for range in firewall_ssh_ranges %}
|
{% for range in firewall_ssh_ranges %}
|
||||||
{%if range.type=="ipv4" %}
|
{%if range.type=="ipv4" %}
|
||||||
iptables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
iptables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
{% else %}
|
|
||||||
# This server has an open ssh policy
|
|
||||||
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
iptables -A OUTPUT -m state --state INVALID -j DROP
|
iptables -A OUTPUT -m state --state INVALID -j DROP
|
||||||
|
|
@ -53,16 +48,11 @@ ip6tables -A INPUT -m limit --limit 1/s --limit-burst 2 -p icmpv6 --icmpv6-type
|
||||||
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP
|
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP
|
||||||
ip6tables -A INPUT -p icmpv6 -j ACCEPT
|
ip6tables -A INPUT -p icmpv6 -j ACCEPT
|
||||||
|
|
||||||
{% if firewall_ssh_ranges is defined %}
|
|
||||||
{% for range in firewall_ssh_ranges %}
|
{% for range in firewall_ssh_ranges %}
|
||||||
{%if range.type=="ipv6" %}
|
{%if range.type=="ipv6" %}
|
||||||
ip6tables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
ip6tables -A INPUT -p tcp --dport 22 -s {{range.range}} -j ACCEPT # {{range.name}}
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{%endfor%}
|
{%endfor%}
|
||||||
{% else %}
|
|
||||||
# This server has an open ssh policy
|
|
||||||
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
ip6tables -A OUTPUT -m state --state INVALID -j DROP
|
ip6tables -A OUTPUT -m state --state INVALID -j DROP
|
||||||
|
|
@ -85,11 +75,4 @@ ip6tables -A INPUT -j REJECT
|
||||||
iptables -A FORWARD -j REJECT
|
iptables -A FORWARD -j REJECT
|
||||||
ip6tables -A FORWARD -j REJECT
|
ip6tables -A FORWARD -j REJECT
|
||||||
|
|
||||||
# Now *if* fail2ban has been installed, we would have destroyed it's setup.
|
|
||||||
# Restart it
|
|
||||||
if [ -e /etc/fail2ban/fail2ban.conf ]
|
|
||||||
then
|
|
||||||
systemctl restart fail2ban || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This file is managed by ansible, do not modify!
|
# This file is managed by ansible, do not modify!
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,6 @@
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
|
|
||||||
- name: delete appdefinition directory
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ ppm_app_user.home }}/appdefinition"
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Create directory
|
- name: Create directory
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ ppm_app_user.home }}/appdefinition"
|
path: "{{ ppm_app_user.home }}/appdefinition"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
dest: /home/.ppmfirewalltemplate
|
dest: /home/.ppmfirewalltemplate
|
||||||
group: root
|
group: root
|
||||||
owner: root
|
owner: root
|
||||||
mode: "0644"
|
mode: "0755"
|
||||||
src: ppmfirewall
|
src: ppmfirewall
|
||||||
|
|
||||||
- name: Render firewall
|
- name: Render firewall
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,6 @@
|
||||||
ansible.builtin.include_tasks: copyappdef.yml
|
ansible.builtin.include_tasks: copyappdef.yml
|
||||||
when: ppm_app.chicken_egg_appdefinition is defined and not appdefinition.stat.exists
|
when: ppm_app.chicken_egg_appdefinition is defined and not appdefinition.stat.exists
|
||||||
|
|
||||||
- name: "Update appdefinition ({{ ppm_app.user }})"
|
|
||||||
ansible.builtin.include_tasks: updateappdef.yml
|
|
||||||
when: ppm_app.chicken_egg_appdefinition is defined
|
|
||||||
|
|
||||||
- name: "Set up extra files for {{ ppm_app.user }}"
|
- name: "Set up extra files for {{ ppm_app.user }}"
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
src: "{{ item.from }}"
|
src: "{{ item.from }}"
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
- name: Check local working tree for uncommitted changes
|
|
||||||
command: git status --porcelain
|
|
||||||
args:
|
|
||||||
chdir: "{{ ppm_app.chicken_egg_appdefinition }}"
|
|
||||||
register: local_status
|
|
||||||
changed_when: false
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: Get local HEAD hash
|
|
||||||
command: git rev-parse HEAD
|
|
||||||
args:
|
|
||||||
chdir: "{{ ppm_app.chicken_egg_appdefinition }}"
|
|
||||||
register: local_hash
|
|
||||||
changed_when: false
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
|
|
||||||
- name: Check remote working tree for uncommitted changes
|
|
||||||
command: git status --porcelain
|
|
||||||
args:
|
|
||||||
chdir: "{{ ppm_app_user.home }}/appdefinition"
|
|
||||||
register: remote_status
|
|
||||||
changed_when: false
|
|
||||||
become: true
|
|
||||||
become_user: "{{ ppm_app_user.name }}"
|
|
||||||
|
|
||||||
- name: Get remote HEAD hash
|
|
||||||
command: git rev-parse HEAD
|
|
||||||
args:
|
|
||||||
chdir: "{{ ppm_app_user.home }}/appdefinition"
|
|
||||||
register: remote_hash
|
|
||||||
changed_when: false
|
|
||||||
become: true
|
|
||||||
become_user: "{{ ppm_app_user.name }}"
|
|
||||||
|
|
||||||
|
|
||||||
- name: Set helper facts
|
|
||||||
set_fact:
|
|
||||||
local_dirty: "{{ (local_status.stdout | default('')) != '' }}"
|
|
||||||
local_hash: "{{ local_hash.stdout }}"
|
|
||||||
remote_dirty: "{{ (remote_status.stdout | default('')) != '' }}"
|
|
||||||
remote_hash: "{{ remote_hash.stdout }}"
|
|
||||||
|
|
||||||
- name: Debug when remote is dirty (ignore remote dirty for sync decision)
|
|
||||||
debug:
|
|
||||||
msg: "Remote repository has uncommitted changes; ignoring for sync."
|
|
||||||
changed_when: true
|
|
||||||
when: remote_dirty
|
|
||||||
|
|
||||||
- name: Debug when local is dirty
|
|
||||||
debug:
|
|
||||||
msg: "Local repository has uncommitted changes; unconditional - non-idempotent sync."
|
|
||||||
changed_when: true
|
|
||||||
when: local_dirty and not remote_dirty
|
|
||||||
|
|
||||||
- name: Include copyappdef.yml when local dirty, hash retrieval failed, or hashes differ
|
|
||||||
include_tasks: copyappdef.yml
|
|
||||||
when: not remote_dirty and (local_hash!=remote_hash or local_dirty)
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
dest: /home/.zabbixagenttemplate
|
dest: /home/.zabbixagenttemplate
|
||||||
group: root
|
group: root
|
||||||
owner: root
|
owner: root
|
||||||
mode: "0644"
|
mode: "0755"
|
||||||
src: ppmzabbixagent
|
src: ppmzabbixagent
|
||||||
|
|
||||||
- name: Render zabbix template
|
- name: Render zabbix template
|
||||||
|
|
|
||||||
3
run
Executable file
3
run
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ansible-playbook --diff all.yml "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue