2 Commits
nginx ... main

Author SHA1 Message Date
4603ff67d9 Divide firewalld zones for FOG server 2026-04-25 19:14:26 -04:00
0aa62d6af9 Add FOG server role 2026-04-23 01:04:01 -04:00
8 changed files with 195 additions and 160 deletions

View File

@@ -64,7 +64,7 @@ To submit, press `CTRL+d` twice.
## Copyrights and Licenses
Copyright (C) 2019, 2020, 2022, 2023, 2025 Free I.T. Athens
Copyright (C) 2019, 2020, 2022, 2023, 2025, 2026 Free I.T. Athens
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

8
dev/fog.yml Normal file
View File

@@ -0,0 +1,8 @@
- name: Install FRITA FOG Server
hosts: all
become: true
vars_files:
- vars/fog.yml
roles:
- common
- fog

33
dev/vars/fog.yml Normal file
View File

@@ -0,0 +1,33 @@
###################
### 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

View File

@@ -56,33 +56,51 @@
state: present
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
ansible.builtin.dnf:
name: firewalld
state: present
when: firewalld is defined
- name: Start and enable firewalld service
ansible.builtin.systemd:
name: firewalld
state: started
enabled: true
when: firewalld is defined
- 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
- name: Update SSH rule in firewalld drop zone
ansible.posix.firewalld:
zone: drop
rich_rule: 'rule service name="ssh" accept limit value="10/m"'
permanent: true
immediate: true
state: enabled
state: "{{ 'enabled' if (firewalld.drop_ssh | default(true)) else 'disabled' }}"
when: firewalld is defined
- name: Set drop as the default zone
ansible.builtin.command:
cmd: firewall-cmd --set-default-zone=drop
changed_when: false
register: default_zone_result
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

125
roles/fog/tasks/main.yml Normal file
View File

@@ -0,0 +1,125 @@
- 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'

View File

@@ -1,32 +0,0 @@
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;
}

View File

@@ -1,117 +0,0 @@
- 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"