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 ## 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 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

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 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: Set default zone to drop (deny incoming by default) - name: Update SSH rule in firewalld drop zone
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 state: "{{ 'enabled' if (firewalld.drop_ssh | default(true)) else 'disabled' }}"
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
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"