Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 850a5b90a5 |
@@ -64,7 +64,7 @@ To submit, press `CTRL+d` twice.
|
|||||||
|
|
||||||
## Copyrights and Licenses
|
## Copyrights and Licenses
|
||||||
|
|
||||||
Copyright (C) 2019, 2020, 2022, 2023, 2025, 2026 Free I.T. Athens
|
Copyright (C) 2019, 2020, 2022, 2023, 2025 Free I.T. Athens
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
- name: Install FRITA FOG Server
|
|
||||||
hosts: all
|
|
||||||
become: true
|
|
||||||
vars_files:
|
|
||||||
- vars/fog.yml
|
|
||||||
roles:
|
|
||||||
- common
|
|
||||||
- fog
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
###################
|
|
||||||
### common role ###
|
|
||||||
###################
|
|
||||||
|
|
||||||
firewalld:
|
|
||||||
# Turn 'drop' zone SSH access off after initial provision
|
|
||||||
# This example config defines an 'admin' zone for it instead
|
|
||||||
# drop_ssh: false
|
|
||||||
type: complex
|
|
||||||
zones:
|
|
||||||
admin:
|
|
||||||
source: 192.168.121.0/24
|
|
||||||
services:
|
|
||||||
- ssh
|
|
||||||
- cockpit
|
|
||||||
- http
|
|
||||||
fog:
|
|
||||||
interface: eth1
|
|
||||||
services:
|
|
||||||
- http
|
|
||||||
ports:
|
|
||||||
- 69/udp
|
|
||||||
- 111/tcp
|
|
||||||
- 111/udp
|
|
||||||
- 2049/tcp
|
|
||||||
- 2049/udp
|
|
||||||
|
|
||||||
################
|
|
||||||
### fog role ###
|
|
||||||
################
|
|
||||||
|
|
||||||
fog:
|
|
||||||
version: 1.5.10.1826 # defaults to stable
|
|
||||||
@@ -56,51 +56,33 @@
|
|||||||
state: present
|
state: present
|
||||||
update_cache: true
|
update_cache: true
|
||||||
|
|
||||||
- name: Assert valid firewalld config
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- firewalld is mapping
|
|
||||||
- firewalld.type is defined
|
|
||||||
- firewalld.type in ['simple', 'complex']
|
|
||||||
fail_msg: "firewalld.type must be 'simple' or 'complex'"
|
|
||||||
when: firewalld is defined
|
|
||||||
|
|
||||||
- name: Install firewalld
|
- name: Install firewalld
|
||||||
ansible.builtin.dnf:
|
ansible.builtin.dnf:
|
||||||
name: firewalld
|
name: firewalld
|
||||||
state: present
|
state: present
|
||||||
when: firewalld is defined
|
|
||||||
|
|
||||||
- name: Start and enable firewalld service
|
- name: Start and enable firewalld service
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: firewalld
|
name: firewalld
|
||||||
state: started
|
state: started
|
||||||
enabled: true
|
enabled: true
|
||||||
when: firewalld is defined
|
|
||||||
|
|
||||||
- name: Update SSH rule in firewalld drop zone
|
- name: Set default zone to drop (deny incoming by default)
|
||||||
|
ansible.posix.firewalld:
|
||||||
|
zone: drop
|
||||||
|
state: enabled
|
||||||
|
permanent: true
|
||||||
|
immediate: true
|
||||||
|
|
||||||
|
- name: Allow SSH in drop zone with rate limiting via rich rule
|
||||||
ansible.posix.firewalld:
|
ansible.posix.firewalld:
|
||||||
zone: drop
|
zone: drop
|
||||||
rich_rule: 'rule service name="ssh" accept limit value="10/m"'
|
rich_rule: 'rule service name="ssh" accept limit value="10/m"'
|
||||||
permanent: true
|
permanent: true
|
||||||
immediate: true
|
immediate: true
|
||||||
state: "{{ 'enabled' if (firewalld.drop_ssh | default(true)) else 'disabled' }}"
|
state: enabled
|
||||||
when: firewalld is defined
|
|
||||||
|
|
||||||
- name: Set drop as the default zone
|
- name: Set drop as the default zone
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
cmd: firewall-cmd --set-default-zone=drop
|
cmd: firewall-cmd --set-default-zone=drop
|
||||||
register: default_zone_result
|
changed_when: false
|
||||||
changed_when: "'ZONE_ALREADY_SET' not in default_zone_result.stderr"
|
|
||||||
when: firewalld is defined
|
|
||||||
|
|
||||||
- name: Install Cockpit
|
|
||||||
ansible.builtin.dnf:
|
|
||||||
name: cockpit
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Enable and start Cockpit socket
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: cockpit.socket
|
|
||||||
enabled: true
|
|
||||||
state: started
|
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
- name: Check if FOG is already installed
|
|
||||||
ansible.builtin.stat:
|
|
||||||
path: /opt/fog/.fogsettings
|
|
||||||
register: fog_installed
|
|
||||||
|
|
||||||
- name: Upgrade system before FOG server install
|
|
||||||
ansible.builtin.dnf:
|
|
||||||
name: "*"
|
|
||||||
state: latest # noqa: package-latest
|
|
||||||
when: not fog_installed.stat.exists
|
|
||||||
|
|
||||||
- name: Install git
|
|
||||||
ansible.builtin.dnf:
|
|
||||||
name: git
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Set SELinux to permissive and make it persistent
|
|
||||||
ansible.posix.selinux:
|
|
||||||
policy: targeted
|
|
||||||
state: permissive
|
|
||||||
|
|
||||||
- name: Ensure parent source directory exists
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: /usr/local/src
|
|
||||||
state: directory
|
|
||||||
mode: "0755"
|
|
||||||
|
|
||||||
- name: Clone FOG at specified version
|
|
||||||
ansible.builtin.git:
|
|
||||||
repo: https://github.com/FOGProject/fogproject.git
|
|
||||||
dest: /usr/local/src/fogproject
|
|
||||||
version: "{{ fog.version | default('stable') }}"
|
|
||||||
update: true
|
|
||||||
|
|
||||||
- name: Run FOG installer first time
|
|
||||||
ansible.builtin.command: ./installfog.sh -Y
|
|
||||||
args:
|
|
||||||
chdir: /usr/local/src/fogproject/bin
|
|
||||||
creates: /opt/fog/.fogsettings
|
|
||||||
|
|
||||||
- name: Create admin zone
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: admin
|
|
||||||
state: present
|
|
||||||
permanent: true
|
|
||||||
register: admin_zone
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Create fog zone
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: fog
|
|
||||||
state: present
|
|
||||||
permanent: true
|
|
||||||
register: fog_zone
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Reload firewalld if zones were created
|
|
||||||
ansible.builtin.command: firewall-cmd --reload
|
|
||||||
changed_when: true
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
- admin_zone.changed or fog_zone.changed
|
|
||||||
|
|
||||||
- name: Bind admin source to admin zone
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: admin
|
|
||||||
source: "{{ firewalld.zones.admin.source }}"
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
state: enabled
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Bind fog interface to fog zone
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: fog
|
|
||||||
interface: "{{ firewalld.zones.fog.interface }}"
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
state: enabled
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Allow admin services
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: admin
|
|
||||||
service: "{{ item }}"
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
state: enabled
|
|
||||||
loop: "{{ firewalld.zones.admin.services | default([]) }}"
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Allow fog services
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: fog
|
|
||||||
service: "{{ item }}"
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
state: enabled
|
|
||||||
loop: "{{ firewalld.zones.fog.services | default([]) }}"
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
|
|
||||||
- name: Allow fog ports
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
zone: fog
|
|
||||||
port: "{{ item }}"
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
state: enabled
|
|
||||||
loop: "{{ firewalld.zones.fog.ports | default([]) }}"
|
|
||||||
when:
|
|
||||||
- firewalld is defined
|
|
||||||
- firewalld.type == 'complex'
|
|
||||||
32
roles/nginx/files/nginx.conf
Normal file
32
roles/nginx/files/nginx.conf
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
user nginx;
|
||||||
|
worker_processes auto;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
|
include /usr/share/nginx/modules/*.conf;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
access_log /var/log/nginx/access.log combined;
|
||||||
|
|
||||||
|
server_tokens off;
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
server_names_hash_bucket_size 128;
|
||||||
|
|
||||||
|
# Mozilla intermediate config
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1;
|
||||||
|
ssl_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;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
ssl_session_cache shared:MozSSL:10m;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
117
roles/nginx/tasks/main.yml
Normal file
117
roles/nginx/tasks/main.yml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
- name: Install nginx
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: nginx
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install nginx base configuration
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: nginx.conf
|
||||||
|
dest: /etc/nginx/nginx.conf
|
||||||
|
mode: "644"
|
||||||
|
notify: reload_nginx
|
||||||
|
|
||||||
|
- name: Install nginx sites configuration
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: server.conf.j2
|
||||||
|
dest: "/etc/nginx/conf.d/{{ item.domain }}.conf"
|
||||||
|
mode: "644"
|
||||||
|
loop: "{{ proxy.servers }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.domain }}"
|
||||||
|
notify: reload_nginx
|
||||||
|
register: nginx_sites
|
||||||
|
|
||||||
|
- name: Generate self-signed certificate
|
||||||
|
ansible.builtin.command:
|
||||||
|
'openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes \
|
||||||
|
-subj "/C=US/ST=Local/L=Local/O=Org/OU=IT/CN=example.com" \
|
||||||
|
-keyout /etc/ssl/private/nginx-selfsigned.key \
|
||||||
|
-out /etc/ssl/certs/nginx-selfsigned.crt'
|
||||||
|
args:
|
||||||
|
creates: /etc/ssl/certs/nginx-selfsigned.crt
|
||||||
|
when: proxy.production is not defined or not proxy.production
|
||||||
|
notify: reload_nginx
|
||||||
|
|
||||||
|
- name: Install LE's certbot
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: ["certbot", "python3-certbot-dns-cloudflare"]
|
||||||
|
state: present
|
||||||
|
when: proxy.production is defined and proxy.production
|
||||||
|
|
||||||
|
- name: Grab Cloudflare API token for configuration
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: /etc/letsencrypt/cloudflare-api.key
|
||||||
|
register: cfapi
|
||||||
|
when: proxy.production is defined and proxy.production and proxy.dns_cloudflare is defined
|
||||||
|
|
||||||
|
- name: Install Cloudflare API token
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: cloudflare.ini.j2
|
||||||
|
dest: /etc/letsencrypt/cloudflare.ini
|
||||||
|
mode: "400"
|
||||||
|
diff: false
|
||||||
|
when: proxy.production is defined and proxy.production and proxy.dns_cloudflare is defined
|
||||||
|
|
||||||
|
- name: Create nginx post renewal hook directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/letsencrypt/renewal-hooks/post
|
||||||
|
state: directory
|
||||||
|
mode: "500"
|
||||||
|
when: proxy.production is defined and proxy.production
|
||||||
|
|
||||||
|
- name: Install nginx post renewal hook
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: reload-nginx.sh
|
||||||
|
dest: /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
|
||||||
|
mode: "0755"
|
||||||
|
when: proxy.production is defined and proxy.production
|
||||||
|
|
||||||
|
- name: Enable SELinux bool certbot_acmesh to allow sh access for DNS-01
|
||||||
|
ansible.posix.seboolean:
|
||||||
|
name: certbot_acmesh
|
||||||
|
state: true
|
||||||
|
persistent: true
|
||||||
|
when:
|
||||||
|
- selinux is defined
|
||||||
|
- selinux is not false
|
||||||
|
- proxy is defined
|
||||||
|
- proxy.production is defined
|
||||||
|
- proxy.production
|
||||||
|
- proxy.dns_cloudflare is defined
|
||||||
|
|
||||||
|
- name: Run Cloudflare DNS-01 challenges on wildcard domains
|
||||||
|
ansible.builtin.shell: '/usr/bin/certbot certonly \
|
||||||
|
--non-interactive \
|
||||||
|
--agree-tos \
|
||||||
|
--email "{{ proxy.dns_cloudflare.email }}" \
|
||||||
|
--dns-cloudflare \
|
||||||
|
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
|
||||||
|
-d "*.{{ item }}" \
|
||||||
|
-d "{{ item }}" \
|
||||||
|
{{ proxy.dns_cloudflare.opts | default("") }}
|
||||||
|
< /dev/null'
|
||||||
|
args:
|
||||||
|
creates: "/etc/letsencrypt/live/{{ item }}/fullchain.pem"
|
||||||
|
loop: "{{ proxy.dns_cloudflare.wildcard_domains }}"
|
||||||
|
when: proxy.production is defined and proxy.production and proxy.dns_cloudflare is defined
|
||||||
|
notify: reload_nginx
|
||||||
|
|
||||||
|
- name: Enable SELinux bool httpd_can_network_connect to give nginx networking
|
||||||
|
ansible.posix.seboolean:
|
||||||
|
name: httpd_can_network_connect
|
||||||
|
state: true
|
||||||
|
persistent: true
|
||||||
|
when:
|
||||||
|
- selinux is defined
|
||||||
|
- selinux is not false
|
||||||
|
- proxy is defined
|
||||||
|
|
||||||
|
- name: Add HTTP and HTTPS firewall rule
|
||||||
|
community.general.ufw:
|
||||||
|
rule: allow
|
||||||
|
port: "{{ item }}"
|
||||||
|
proto: tcp
|
||||||
|
loop:
|
||||||
|
- "80"
|
||||||
|
- "443"
|
||||||
0
roles/nginx/templates/server.conf.j2
Normal file
0
roles/nginx/templates/server.conf.j2
Normal file
Reference in New Issue
Block a user