Compare commits

...

80 Commits

Author SHA1 Message Date
43dad7c261 roles: use ansible_facts["foo"] pattern
Instead of ansible_foo. Ansible recently started warning that this
is deprecated.
2025-12-02 20:42:58 +03:00
8439b674dd roles/nginx: git clone as nginx 2025-11-21 22:07:55 +03:00
c2c9f1b88d roles/nginx: fix syntax 2025-11-21 21:08:29 +03:00
3763ce80e1 roles/mariadb: rework to use Debian's mariadb
There are no MariaDB builds for Debian 13 (trixie) yet. This seems
to happen every new release. Surprisingly Debian's mariadb-server
is very new and we can simplify our tasks and templates a lot.
2025-11-20 08:47:27 +03:00
a8e4821ad0 roles/nginx: remove apt-key task 2025-11-20 08:47:27 +03:00
6ff4cf30f7 roles/mariadb: remove apt-key task
This is not longer present as of Debian 13, and the old MariaDB key
should not be present on any of my hosts anymore anyway.
2025-11-20 08:47:27 +03:00
8f57a5a974 roles/php_fpm: rework for Debian 13
We can use metapackages like php-fpm on each version as those pull
in the correct package. This allows us to use the same playbook lo-
gic for Debian 12 (PHP 8.2) and Debian 13 (PHP 8.4).
2025-11-20 08:47:26 +03:00
cac74c53ef roles/common: minor configuration of Debian 13 SSH
Tweak some of the new OpenSSH per-source penalty settings on Debian
13. For now only adjusting the source network masks and reusing the
list of IPs to exempt from fail2ban.

These being built in makes them easier to use, but I think I will
end up sticking with fail2ban for the heavy lifting because it per-
sists across restarts of the daemon, whereas OpenSSH's doesn't. I
will monitor OpenSSH on Debian 13 to see how to best use it along
side fail2ban.
2025-11-20 08:47:26 +03:00
078c5b36d8 roles/common: use 127.0.0.0/8 for fail2ban ignoreip
We can re-use our fail2ban ignoreip setting for Debian 13's OpenSSH
PerSourcePenaltyExemptList, but OpenSSH is more strict with regards
to masks not being applied to the host portion. I had never noticed
that fail2ban's default was applying the mask on the host portion!
2025-11-20 08:47:25 +03:00
a18c1e6a16 roles/common: sshd overrides for Debian 13 2025-11-20 08:47:25 +03:00
36cf98026b Pipfile.lock: run pipenv update 2025-11-20 08:46:41 +03:00
98746b3eb8 host_vars/web22: WordPress 6.8.3 2025-11-20 08:44:23 +03:00
afffd87201 roles/common: remove old firewall cleanup 2025-11-14 22:38:43 +03:00
d21f3d9371 roles/common: remove loops with one item 2025-11-14 22:38:17 +03:00
a6ef7a1c4e roles/common: don't notify fail2ban
We set the fail2ban service as "PartOf" the nftables service, so it
receives stop and restart events already.
2025-11-14 22:26:09 +03:00
602734acce roles: update ansible.builtin.systemd builtin
Use ansible.builtin.systemd_service instead.
2025-09-23 10:33:11 +03:00
0db7911b70 roles/common: remove sudoers.d
We are not using this.
2025-09-21 23:09:40 +03:00
ee4c62e5f9 roles: remove tests for Debian
We only run on Debian now.
2025-09-21 22:20:31 +03:00
a315db8a7c roles/common: use ansible_distribution_version
In most cases it is enough to use the full version (ie 12.12) since
we use Ansible's version comparison function. We rarely need to use
the major version (ie 12) directly.
2025-09-21 22:19:00 +03:00
5f00892df3 roles/common: adjust when in tasks 2025-09-21 22:04:25 +03:00
9357265d27 roles/common: use ansible.builtin.apt module 2025-09-21 22:00:39 +03:00
dd62266340 roles/common: update comment in ntp task 2025-09-21 21:58:11 +03:00
a1bec20824 roles/common: simplify when logic in ntp task 2025-09-21 21:57:34 +03:00
8e91c44529 roles/common: fix syntax error in npt when 2025-09-21 21:56:15 +03:00
02d4135c79 roles/common: adjust ntp task
On Debian 12 we need to explicitly remove ntp because it does not
conflict with other time daemons.
2025-09-21 21:55:09 +03:00
37e148d009 Re-work ansible_managed
This is no longer a configuration setting. Now we must set it like
any other template variabled.
2025-09-21 21:15:12 +03:00
73dbbd23b6 roles/common: adjust handlers
Should start with an upper case letter.
2025-09-21 20:22:58 +03:00
b84283aa38 roles/common: remove unneeded firewall packages
We don't need curl or libnet-ip-perl anymore.
2025-09-21 20:15:11 +03:00
1695fdf8d1 roles/common: syntax in firewall play 2025-09-21 20:11:46 +03:00
9f1f7b1c69 roles/nginx: more syntax fixes to tasks 2025-09-21 20:08:51 +03:00
7d725f2084 roles/nginx: adjust task syntax
Tasks should start with an upper case letter and we should not use
free form syntax anymore.
2025-09-21 20:04:53 +03:00
4c39b0d48c roles/php_fpm: adjust task syntax
All tasks need names, and we can use name, tags, when, block order
for task keys. Suggested by ansible-lint.
2025-09-21 20:02:46 +03:00
f4023d0b20 roles/php_fpm: rename handler
Suggested by ansible-lint.
2025-09-21 19:59:23 +03:00
6aaface4a2 Rename roles/php-fpm to roles/php_fpm
Suggested by ansible-lint.
2025-09-21 19:56:20 +03:00
333e1cbeb9 roles/mariadb/handlers/main.yml: update syntax 2025-09-21 17:32:57 +03:00
0c62f4bdf0 roles/common/tasks/packages.yml: improve task key order
Suggested by ansible-lint. Makes it easier to see the tags after the
very long block.
2025-09-21 17:30:54 +03:00
26f22c0447 roles/munin: update task syntax 2025-09-21 17:29:22 +03:00
05881e2585 roles: fix unquoted octal modes 2025-09-21 17:25:22 +03:00
d4d326c2f7 roles/common: use FQCN in handler 2025-09-21 17:09:45 +03:00
1d4a6f208b roles/common: update default fail2ban ignores 2025-09-21 17:06:48 +03:00
8b22076d4a roles/common: json spacing 2025-09-21 17:06:01 +03:00
38176cb34c roles/nginx: update task syntax for plays 2025-09-21 16:59:08 +03:00
da737b71f7 roles/mariadb: update task syntax for mariadb play 2025-09-21 16:54:19 +03:00
c28189a1a5 roles/common: update task syntax for fail2ban play 2025-09-21 16:54:03 +03:00
b600141e89 roles/common: update task syntax for sshd play 2025-09-21 16:51:23 +03:00
4be98d1a33 roles/common: update task syntax for ssh-keys play 2025-09-21 16:49:32 +03:00
2bb018a40c roles/common: rename firewall and packages task files
Don't use firewall_Debian.yml or packages_Debian.yml since I am not
deploying Ubuntu anymore there is no need to distinguish.
2025-09-21 16:45:51 +03:00
89a1e11b7a roles/common: update task syntax in main play 2025-09-21 16:40:37 +03:00
0c0cad9084 Remove Ubuntu logic
For a few years now I have only been deploying Debian for personal
use.
2025-09-21 16:34:57 +03:00
9dce701a19 roles/common: update task syntax in packages play 2025-09-21 16:23:10 +03:00
3e9ee44d5b roles/common: update task syntax in ntp play 2025-09-21 16:18:32 +03:00
599b5e5e83 Pipfile.lock: run pipenv update 2025-09-21 15:57:28 +03:00
bc700ea532 Pipfile.lock: pipenv update 2025-08-17 10:28:23 +03:00
8016701b57 host_vars/web22: WordPress 6.8.2 2025-08-17 10:26:43 +03:00
00558c7dea roles/common: re-work fail2ban and nftables
Re-work the fail2ban and nftables interaction. Use systemd's PartOf
to indicate that fail2ban is part of the nftables service, which
tells systemd to propogate stop/start signals to it. Then we tell
the firehol update script to restart nftables instead of reload.
The different between restart and reload is meaningless for nftables
but we want systemd to propagate the stop/start signals to fail2ban.
2025-07-08 10:39:17 +03:00
c927186837 roles/common: adjust update-firehol-nftables.service
This service does not actually depend on nftables, at least not in
the systemd sense of dependency. Furthermore, this hard dependency
was causing the service to fail when it restarts nftables at the
end, which causes systemd to start it again and again until it hits
a restarting too quickly error.
2025-07-08 10:37:39 +03:00
690774c862 host_vars/web22: WordPress 6.8.1 2025-07-08 10:34:34 +03:00
cc021bd14a Pipfile.lock: run pipenv update 2025-07-08 10:25:09 +03:00
73fd06fe3a roles/common: remove cron-apt
Use unattended-upgrades instead. It has sane defaults on Debian at
least (I haven't checked Ubuntu).
2025-04-07 09:51:09 +03:00
88cb3a370e Remove logic for Ubuntu 20.04 and Debian 11 2025-03-29 23:09:44 +03:00
027a43ddbe roles/caddy: use default for encode 2025-03-29 22:49:30 +03:00
bb30c3be20 host_vars/web22: update vhosts 2025-03-29 22:48:19 +03:00
d8d9790d21 roles/nginx: enable nginx ssl_session_tickets
This has apparently been supported since nginx 1.23.2 and is safe
to use the default (on) now.

See: https://github.com/mozilla/server-side-tls/issues/284
2025-03-29 22:35:56 +03:00
9a500ebc0d roles/nginx: disable nginx ssl_prefer_server_ciphers
This is apparently the default and recommended by Mozilla's server-
side SSL configurator also recommends. This lets the client choose
the ciphers best for them (and the ciphers in TLS 1.2 and 1.3 are
not currently known to be dangerous).
2025-03-29 22:34:41 +03:00
4bae942585 roles/nginx: add nginx ssl_ecdh_curve
This seems to be new since I last looked at the Mozilla server-side
SSL configurator.
2025-03-29 22:34:37 +03:00
99866c0c90 roles/nginx: use one day for nginx ssl_session_timeout
This is a new default since I last looked at the Mozilla server-side
SSL configurator.
2025-03-29 22:34:32 +03:00
0afb8a4493 roles/nginx: update nginx ssl_buffer_size
The old default has not been changed in eight years and I see that
there have been some discussions over the years about this. I will
change this from the slightly extreme 1400 bytes to 4k (nginx def-
ault is still 16k so this is more "optimal" for HTML/CSS content).

See: https://github.com/igrigorik/istlsfastyet.com/issues/63
2025-03-29 22:34:27 +03:00
506695da31 roles/nginx/defaults: update version comments 2025-03-29 22:24:49 +03:00
f67ed7762c roles/nginx: fix http2 syntax 2025-03-29 22:20:49 +03:00
014f4d9502 roles/nginx: add newline 2025-03-29 22:19:41 +03:00
22c16e1ed3 roles/caddy/templates: closer to supporting WordPress
I still wouldn't want to deploy WordPress on Caddy until it's more
obvious and standard to block paths that shouldn't be accessible.
It seems that this is still left as an exercise to the site admin.

This discussion has some tips, but it is four years old and hasn't
changed since I last looked.

See: https://caddy.community/t/using-caddy-to-harden-wordpress/13575
2025-03-29 22:09:37 +03:00
5aa6a33e51 roles/php-fpm: set user and group based on webserver
We use either caddy or nginx, which are conveniently named the same
as the Unix user and group.
2025-03-29 21:01:56 +03:00
7f9b06af9c roles/nginx: smarter setting of document root 2025-03-29 19:34:53 +03:00
84db337fea roles/caddy: smarter setting of document root 2025-03-29 19:33:02 +03:00
7b23f5f94f roles/caddy: add missing tag 2025-03-29 19:16:03 +03:00
9830338be3 Use one default root prefix for nginx and caddy 2025-03-29 19:15:56 +03:00
e3eed26765 roles/caddy: update vhost template 2025-03-29 18:37:28 +03:00
8b31c7e148 host_vars/web22: WordPress 6.7.2 2025-03-29 16:10:23 +03:00
3ff8043aaf Pipfile.lock: run pipenv update 2025-03-29 15:30:08 +03:00
cb79f7ef70 roles/common: minor change to firehol update script
They include bogons like 127.0.0.1 that should not be routed on the
public Internet, but this blocks local applications we proxy to.
2025-01-28 09:14:48 +03:00
70 changed files with 1589 additions and 2176 deletions

1120
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ Ansible playbook for base and initial configuration of the web server hosting my
## Assumptions ## Assumptions
Before you can run this, a few things are assumed: Before you can run this, a few things are assumed:
- You have a clean, minimal Ubuntu 20.04 or Debian 11/12 host up and running - You have a clean, minimal Debian 12 host up and running
- Python 3 is installed on the remote server (requirement of Ansible) - Python 3 is installed on the remote server (requirement of Ansible)
- You have a user account with password-less SSH access to the machine - You have a user account with password-less SSH access to the machine
- You have sudo privileges on the remote host - You have sudo privileges on the remote host

View File

@@ -13,12 +13,6 @@ interpreter_python=auto
# See: https://docs.ansible.com/ansible/latest/user_guide/connection_details.html#managing-host-key-checking # See: https://docs.ansible.com/ansible/latest/user_guide/connection_details.html#managing-host-key-checking
host_key_checking = False host_key_checking = False
ansible_managed = This file is managed by Ansible.%n
template: {file}
date: %Y-%m-%d %H:%M:%S
user: {uid}
host: {host}
[privilege_escalation] [privilege_escalation]
# instead of using -K # instead of using -K
become_ask_pass=True become_ask_pass=True

View File

@@ -3,4 +3,12 @@
tls_cipher_suite: "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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384" tls_cipher_suite: "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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
ansible_managed: |-
This file is managed by Ansible.
{{ 'template: ' + template_path }}
{{ 'date: ' + (template_mtime | string) }}
{{ 'user: ' + template_uid }}
{{ 'host: ' + template_host }}
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -8,4 +8,7 @@ webserver: nginx
extra_fail2ban_filters: extra_fail2ban_filters:
- nginx - nginx
# root prefix for all web servers
web_root_prefix: /var/www
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,138 +1,141 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
30323862646334626231363530353238333165653862356463386233326433393265643132353262 65636230346264393938656566653961393466306338353435333061356463363836616435333731
3561386632316261383561323831343334363532643566380a333961383133383838343333323937 3537316534663335343333643435383663303438333433650a666133633965643939306661383536
39303866616132383334663732393663386236393732386238376464373964373865653538353633 33626364316338306530393036653134373339653264616537623731323063646531383137333131
3863356261663430360a303131373063656136616166363065326563363462656634356666373661 6263363037613631360a343831393830646536326538363764643136613732636165316466316566
61663734303833306231393766633338316634383339356436666465313966643635623732643432 65346162383337626631663533626230643061633139663661656365333738353530316661313864
34393633393736353261316232393761613931313537356166646634626137353863353930366130 32373831396437386434313430666434363534656130613632643264393538663131336635653537
63323662653933383537643861623035326166306235343937393764316635613339663132633039 61613065336133343130353862646130386136333231393962353064666335363330623064626631
66643163653739333665396263333332313863616136613132393462346136666163663039333963 34333137363566313764343335646531326337616563366636316232633936333264373731653332
61396562633964653063333338643531373264323739353738346639623433323162356633353538 66366361643261626563633838663061303762386234336133366233356564343562323965663731
38633964363466303433663731303261656166626432366231373464353138383465616539623665 38326631333166643534313836323337663131313766306166333534336333613735643033326633
35666462653864346334316163656232363166303630333238613161646131316338663336323134 39396335613362363230333863396535343464346437366632316336626539623865313239353539
31363139306432653030613661623133626533653261376366633030643734633635396335323332 30643834633130333564666162623365323439396630333136616137633532363530623234376332
66363433613165333761323335333964326431616631343035633062643731616366623532643261 66353539306637633432353231326666643261386466633533313063353061643761313132623035
61376562323863353636643439666133643662336132663938653532323965613163346233356438 62653263636237666432336662633136653930323532623137386261333862623337326431336365
30613639616265633131656436323830353031653265323836303561306561363236613262363532 36663364386364346631393031326434326334636166663739366435616166363130623463633733
61666631663632353162336536323930353637643031353764633438613436393838363533663565 35383834326231363264623061303066326433613139333237656635643835393762313866356237
61386631343965626464623934363865303364363532303937383762393831373265306664626362 62616435613863616161376666333966323030326531323261646436633233613635383438373834
32306365643664363537623065643031666333363564303531613662653734336438343933613361 31343133326231636661353466396566656365396466343430613262316537623631376433633630
61336163646565303339336235366361653665616233396364373565666536313034343661393766 62336664346363393363306163333662323338343139646238633830326535313034613739616138
65313137663832356166626438643638653138303166393633373565633065393639363631316364 38313637333333383032316134316164363036396338306634633436633564306333336437393566
33623764613431646335326338386130626132643233333165323635346638613133383434383134 61656337343030393936353364386461643766636564333864396130343762323630393839393463
66363362363835376336616365376336383138643538666365383831653366393632336264643536 35343864393035333930313238663465663633633862623336663136626165666131383933626437
30346332336163306563303964393463306436643261326232653739313731656537326362386233 31323936653737646231363036383764333335313762356465333635303334663734636531343331
34306433396262633266646562313361666263353831393230393832313135303331393032656564 37386461643239363434373864373561353339343031346364383530663430393938333963333837
66313832643539653865663332613166383334303430376530343962656331633537633131646535 63303966366364626665303530356433643264343861346238353937386338383034356633623231
31666137353461643363353834306662643735303466626366396164393139663739666430386139 36663735386233396138306561326339626262326463336535646265666637383032396435333835
32316566626264663236633336303437626136333535316231633430656663623661306266613566 31363266666230366438313432356637663632333530646263663563373137313262663937636532
39383730636262333439376634313137333331303332633164636533333537366664626165393730 66633731333166386564386666363130633734643963653030386533393766623038383234646161
65366636366464653064666436343334363762303032393233656638356432356664313235353038 36343135663231323030306430623535373534353835623339333738376362663930343436343637
65613730323938393763653735353732643363663637633234343465393264313865373536313031 34383963306266623437323462356466336533643933653839366666393839626663353264326334
63666263326339623662323464346231383535333736333338336562396361633439343964616234 32663461663561396631363533383334363361373764363132643435373537333839613066396463
33373837646262333639393164366336666662343362336330373532306638353464363931303961 35386436326638353431363064626131306634363339653132396563356239653265303930333634
62363730333739346562333333376164663235316262363666396631323430303835636434313036 32376332643863376237383966623233323864393338346537393865363661616338333631383532
30376333383036373639343461666436643632653030623264393163643433333162626439393861 34373635316138663261633839333664353432666234306463306338653634633038373266646462
66333037363738343932323666393061653236376338643762393933366430323036636438333962 32336534356537306366656236356663616336333031306431653239343132336234626165333032
38396432366566343038303533353936363934313866646665313764336433656361363137613233 38303137666131363462363263333832356333616130346337663837376365346166306261373036
37393737663465336638623439373262313366623638336239373961356262653735643935613238 63383236323738303562623631633064363564663861336162356262373861383965623935343931
32343331316630646366306132663337373162363937323535323737313035326233303332316134 65663934623431363164356331353135633837616130363464353661663438323132363165343766
61313838346636353437666630653030316563626134626433306364313765613832343434663335 31393633306261303762613537343034316535373731363365666530623361623630633137326466
33336139303265336461396632633835366538663462393536383361656566393737383961653131 32326533313362333863383561343230626466303831623033613065363136396362373333306333
65393833313737383439356464653638393566646238636539393963313031373435663839613736 32336464356364663564626234653832323265313364343631646633396362373438666165353962
37346434336630366632306230393565363662353263643833613338623064646265313464346435 38396330333161356365626562383531323664636235643666613631636636323638376638396531
34663935353662393734313830316665663432303734313037373963363231636335313130363039 38646531666164653161353932643662363261323564373537343731666232666532633063353431
66383230633538323663333632633334636430393830666638373839633830393865363234626161 61386163363562313330393037656139303365396438313935306333656264373531373037303939
62366564386234623731643930656531353238633237666438623961656661613736333231656165 63373962356233346164383163323532373163376364623766323933623063653939346537306338
33336263386466393064633664613437336631313961633362613864366637376132363131393536 65353266656532636633326137356430666432333465626437633733356435363163626430303964
37373632326237623531636330666237363736643339396132333464643162373636346232366132 39343935623937616130326637323061373538616633393465653266656666376661393635333662
38303833623537393136643131323938623038353030626136373265303762373036653765656462 30363364653130356137393463613038663762396336306234363461396133306562323838336330
33636334623361313136633964346431666261616364643435323131643562333438626133646139 63303735646132353766313137303162366164613530303966383636393934393035306264626465
38373633393732333761633463646561613634313363623235323330323233386265393639383261 36613233376234633932663963623432663032656236323963353036356437383066373532323865
64343465373666306537383431353834386238633134366131376465363231366265383432383338 36643431373966613533646164303564653336396535343366303339303134613936656137653939
33366635363964336663623235316635353961393166313333343432363962636465356639643130 31333062623734613538333666636561386338306235633165386262383261333264623638383366
38336363626666613763336639346534373634323661656366393163653630323131313564643530 34313266333636376337393736343062363539366235393136663561303663386438333834613539
66643235313364376133323832313838363537353738313430396466343535663632396237313862 38623632656161653766363166653661336136653833336663616261663831656133666232633362
35313030376632333034323765316435636331303635386631343534373634376135643664393134 31373166306134653162313134333432323134623336666632613766386662653831643732326330
34366162303432323038376261346231313632356630633937333635343635663964613362343232 63643737333638626162646136373466613536653831663835616432343537323864343166316461
65643533643565383762656636623064346165323231313663636363323365303037636635326134 34393732353930343430356231626636373763636561343430616533663861346566326262313232
34663737316335373166343266303633663565616234613530613430323238303830663538353663 39623936366633363136353632346134643563383833376134363833336137613337326435613764
65663261653633346637656564643937323864393664633830356437353631656233306461306436 37653232613632333334316162383261383836613936376230393633343336346633386539356232
34313765313266336536626630383332343063303738316238626137376435656630663331663839 30316232373738363038356665366663623536626539376364303038643061386363636337386663
39393364613735313033633664616562636530366630306530386432356431663537643864363364 61383634336530666163346239343838326138373932383339396265653764313039653138643938
38633237646564306231653334633032393464653637316139356339316666343436633337613733 31613163653632656238376533363739346539623863623332653936643731623565613234663430
63346465316365366138306562336666333939663335623837326430363736396638333631376535 39363935306330386634363634363233376234613837353765353732646638663830323335616234
30663735306134653064633133326264336638313161623034356165656435626135393739633339 34366334636436633734333830306136333563666337623035653239313361626438316535313434
66623536373632323461343435636539313737313831366433393335396634396539663362356165 37343930643832383136343737313365316238373638323130653766646637343464653134616137
39653330663163323330616165346438393435366362353336316537613036323639613439623361 38313034383833626433326237633863313364353662326233636333333932633039396565356133
63343837303861613733353132373632313330333133316638303064316362316233366439316661 64376166383064343239633364363861616136643061646636323437376162313438396230393331
33326131656539393964643939353161626566666632306133393531313630356262646136613135 32633662323031666238643934646665303666383834336432363430363166356632353033336333
65336238386432336439306366636463373766646263613463373464663762396331303461326432 64383861663563653531643832656238643066323564656134633639666234363363363132623836
65666263373639626635623562343538636434663936666330333638333362333138376230333433 61386431643130333761376161646262346562363532353632633332343666393562313465303337
30666638343766656462366432373632306335393239663337646233653438393362663737613566 31333732626164363464323531323239333963303333626466623966346361383832353765346565
39626239643134623035336634316463313935646262663139643963636335663833386266616465 37303765363834376237636632386663373061346534643132636333623137366662646538306231
35306133383438633134356164633935663439336364373633326336346431353330373137626233 33353538623231636166653838333264396463616437396264353537633661313932353133316438
65663063373839333234663032666263633261346562373561633731343665333364303164306232 61323439363635383035316335363132383366613733383363306366356466333364633537393033
35333434343861666465623834653630396663363435336533336435613037623266623262343265 66636434623962633063306236303831633637656430376533353436613934636466363461333562
36313937363334363365613435633962613764366531626632613735306336613930633134383632 34613339373732343632343435333331353935303735633732656663643938663439656233613163
34366435313862373333396136363764643761646635663064336430636363316234613133643261 65356232633865656439643430636332386663333761376638323630373930663837653638363963
36353136343438646437613064333631626435613465356332346265363030323331343766366363 63656437323138633664613166353537306466666261353532326363346332343363343035386435
66656137346261343131653565356333326336363731393838613536333133643863363033383433 33326238333730303539363265383761663862313961383030326263353034303866626661623334
36663539366238333166303132633939313638656536653230626565646238666433373836353035 61623365373332366333376630626539343835663466666534636561643736646537646431386631
35613638393366373763643266626139316561313561353039613464353962353031643533646238 36366132663830336234613065626262336564316339383038333330323237363665373935326438
38303735663536623230383237653766323935343338393965306237363466653933393536303861 38646335346239316432636138633365373062663564326465643032633438306230363434323262
63366564373461366163373934323063366135633266373364396130376230383136666234616533 34313932653361346261623030623739313665356464373666346361663430336362383063666134
64343032336663646535333265616361656135326238666166353266393833366162333235363432 38323539653437623030333437373231646634333563306165393231653465313731633536323362
33373836373338323934626161613536363162363862396563643864613035643231383936616231 65613262633563653031306139383436663834616339316164393365336437653730393331636464
32386339633436613231663765663366626236656261643033313237386135666138343561663566 32313537313164386164313832396566353137376239303663656130383336336634313235376363
38303163313565313462636363303337653061316335393038643161616539336235363736396435 63326530333339356432343938306465623636336161363133613864336339393635306234656263
34356530633739346661306662376236353336613932323331326164623432393231333863323362 34343437336461303831393562653934633439336562663366643066393439396531653663386531
64623264316161313938666635373235653139663561316462323238333534363332666431626239 65623061643064396534353364663633653331653535306133386466356236623239646432373066
32386630353832303830366331616462656432393362666633383233666439663730316532323765 61313261366466663866613162323939646534653561356335393237376138633930663364636236
61623832366161666166633334623462666531303865313065396638646434396231363739366338 36613834303338646530663565303438363831663865323531386635303239646464343936303832
33616433613866376265333564336266626337616233636265386438313362366439336633306434 31323531363263333830623838666437636262306164386236643032356165323037656630383739
66363063376166663039366334666238333932386434653631313336366564366636363964366538 65666333656639333263346465666463616534353835656337353464336134303732323037393538
35346362353138613961313936306438326632656566613966663138613233356364383837373235 37366263656133643039373438636537343636663065646534616339303833666532396633616565
32313439636136313130313136333865653336383866626231636630316365313838636330376263 38353139323739656564623065613364346164633863343738633163383031663531663365616534
32623931313431373137343463626432393834353462333661656564333238646334323761333663 31663835323435643463666264623932396133336531626331303862356261306238326333366164
34653037366639393363383866626363663838643132663266346335656431303237653832663161 66306262386137363432376530366432356432653333393833376532623333373337393830316263
39653633626139343130393735393539393864356336636163363231633332303232323165646466 30326531613662313430663130613734663937613663353936346134356537393761373238393433
31383831333963393866343937643635376135303835353730656436333432373266303830613661 37356136393731626561303430626339386531386333386536656465646232633934393630613339
35636134333561626133333335323131373031616636373439393337316338656331316564303039 61333163613862346564316336353766346461626639303661353464633835626663313462613666
37343265393030633931346131313730303463383165303933323038363062343030363637646261 33343561613662303036643937656431393432333831383461323631393262346464393539353537
64366661663064643761666539623632333036393631656634333062313535663864376361333639 33633364383261663535323136393138333739356439663731636136393530323864333566323361
39323136656461323163663161643863626336306334343230326236343539633462363533343863 62643961323264336662316661303630636430323838633535343036303437393439656637326566
63313331393838343934643734373937366537626138336439653364346630323530323264336233 34363832366434316639393939313965633037653931323462363465643262653539623063326432
61643637393166316633323139326535366337623666386631316532333735363664353730376462 36616434366432303235663062663138623336336165373734353838333662363239333762323932
34333538323236643063623661333537393837373761636562323661366432373137393732363034 65393765326232373230666437656433373930643638386131363339343630636634636434326464
37323237633563353162653330666162613232376363623238383463376461313662346261323934 39366339326263666239646237326534383665376536313536303263373265306537316161663262
36623163393330303037626566373239643164626634383162646562313533343836653461303238 31346635346436313261626366333738333966643333313230623133313434373530366462653435
62356363666439306438373766633335376362636533333063656335333539343963356631616131 33353434643635383833643736653461373765326537313430353164306566323733653237343632
39303362383532386339663938313534353635633438626437343166376662343731316539316334 66346133656333303538306133313563393363313230323664303836323861346466343230343264
31666133623638376163396161623636373363303436353064336136366634613437396232643836 36613934643662626365653036636136623630333638373565316437646232316263663433313762
35303939316135646361393136366430626435613830656264393832316566303563366163313038 39353234333131623731643662303130626465386338353833393533646564646565623736343039
30613636343062393938373765313063363437383238346132396261376135366531336561303836 38356635393461353166653565336535626366396532633961393334343234353764303431303663
66303034646266383332316161613635366338313835363764376564323530376466633263396161 61666533633731663666346132383037646433336463643062396465383034346631346165323939
32373061303062393564636264616234383336373839616330306531363638356362666664306137 33313937343338383737373164363930336236326432346465646166363430653932333932343236
30393737653061643932346561306239303335646533353432383734626566333331363763313934 38336235613034386533613665393666633635383164646538373035623862343737353463623730
30646465363332306439383635376635343831336435313663343066313963616532366632363832 33396233353331633463373538326365636231323535633737303562613262613730636237336632
64663662363236333035313865393638623534646336326433323034356637643965336430316337 38626230313637336436623661666438666538333838356632653034303864313232623337306333
64383566333663346334373461356138663066623864643430346538343964653838383066313039 66363464643061363337393732323065306335656531376337323438313733616539613538333837
39336164333139646264363366303362353135623633616134636633383865623336386163336230 34363033666366613933343563303537613564356462313931353533323938656362393536386334
37306136663032313430323765393631613036383634383735343837353735333931353666623862 38336237616335346334613534323130613861663239356363366564623933303737306138613535
63306336383137353165343031313361613932323065623930626161373062303864333931623361 63643639323135663232336131643331343063363234336230653536623765323562393161663266
33366330306264636163373236636338353139363438353466326430373635616332336365346562 32663839613564613636343166396463366665666333306239386338616366363236393931313439
65356163366266663636623935343330366161353562633234303661633663343361643764313264 30386238316261323630633464386265353464333735336435646663656638316130333762666531
38666265316138613761353732386230353661643834646364326139373063646362366465333236 38626463316165373434613436343335303633643965633230326534323761616365376630363039
33643765663730646332616463383931363738656636313932666163623733343363393736646562 30336661313737383535343934366466353231396430353030653762383934666235646161653832
63393134613465396134333836656333383763353031383633636336656164316533343735663664 31613565643031353535353234386665373636356362653337366563316630343838626231646462
34363465353832386632323036643935366662636631616261336637336361663864313432363564 34623262343761373831303861313661666435373565386465336166306631376666643631303863
66656633353061613137393861663930366532343730353230626530656430346562383964393964 37633934326262623737373266326631663932373863346466613133303961386466366336643235
63636166396337346636666630363537363332313663346135386138616135356135613131393130 39303933333236626637663636633739343761393432616232643238663738313636346137316430
39383036646563386562326461333037643162396537396637336537623035613734336539326137 34623238326430616134396166306339626261643032613661343763366138653830376463306461
66336130633732383439346262313732336139376633383266633834663130373138363064316564 62366564393364306139633837646264633130383064383730393862633561303538363232663366
33393831333736653236356537623134396532336463336232393463396361363439323731393266 30343633666632303530356637646337623339303236376164633962383839386265336666396436
38643539376531343266336330366263656266393337333139363761623163316238643466356339 38616238656336343066333063393833623862646237323238393465633662393362353161313963
32333837346166333332633738376563303132626130376361383530363165613266373039336332 63663539383630366536313933643565346162646363353035386666396363633635386564346666
63376137343966333264336135333636643231643464633836636433363831393066373466643338 64336362633033346461353133396363646237613433306366333064626563656637383863323361
6335 31386262346631343565653836333764636366313330633462303533616531316537353538313031
64366263666138356339373864383866303632366162633738383437323564313732373738373038
39643862336136663165343736613730306339643237313361333438613438323439373966396138
62323661383336396636

View File

@@ -2,7 +2,7 @@
# file: roles/caddy/defaults/main.yml # file: roles/caddy/defaults/main.yml
# parent directory of vhost document roots # parent directory of vhost document roots
caddy_root_prefix: /var/www caddy_root_prefix: "{{ web_root_prefix }}"
# Email address to use for the ACME account managing the site's certificates. # Email address to use for the ACME account managing the site's certificates.
# Not sure what Caddy does if this doesn't exist. # Not sure what Caddy does if this doesn't exist.

View File

@@ -3,7 +3,7 @@
# I'm currently not sure when we need to restart versus reload # I'm currently not sure when we need to restart versus reload
- name: reload caddy - name: reload caddy
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: caddy name: caddy
state: reloaded state: reloaded

View File

@@ -71,6 +71,7 @@
mode: "0755" mode: "0755"
owner: root owner: root
group: root group: root
tags: caddy
# TODO: the variable is still named nginx_vhosts # TODO: the variable is still named nginx_vhosts
- name: Configure Caddy virtual hosts - name: Configure Caddy virtual hosts

View File

@@ -8,6 +8,12 @@
{% set needs_php = item.needs_php | default(false) %} {% set needs_php = item.needs_php | default(false) %}
{% set has_gitea = item.has_gitea | default(false) %} {% set has_gitea = item.has_gitea | default(false) %}
{% set static_site = item.static_site | default(false) %} {% set static_site = item.static_site | default(false) %}
{# Allow sites to override the document root #}
{% if item.document_root is defined %}
{% set document_root = item.document_root %}
{% else %}
{% set document_root = (caddy_root_prefix, domain_name) | ansible.builtin.path_join %}
{% endif %}
{% if domain_aliases %} {% if domain_aliases %}
{# domain_aliases is a string, so we split on space #} {# domain_aliases is a string, so we split on space #}
@@ -21,15 +27,20 @@
{{ domain_name }} { {{ domain_name }} {
{% if has_gitea %} {% if has_gitea %}
reverse_proxy :3000 reverse_proxy :3000
{% endif %} {% elif static_site -%}
root * {{ document_root }}
{% if static_site -%} encode
root * {{ item.document_root }}
encode zstd gzip
file_server file_server
{% endif %} {% elif has_wordpress -%}
root * {{ document_root }}
encode
{% if ansible_facts["distribution_major_version"] is version('12', '==') -%}
php_fastcgi unix//run/php/php8.2-fpm-{{ domain_name }}.sock
{% endif -%}
file_server
{% endif -%}
import security-headers import security-headers
} }

View File

@@ -8,7 +8,7 @@ fail2ban_maxretry: 6
fail2ban_findtime: 3600 fail2ban_findtime: 3600
# 2 weeks in seconds # 2 weeks in seconds
fail2ban_bantime: 1209600 fail2ban_bantime: 1209600
fail2ban_ignoreip: 127.0.0.1/8 172.26.0.0/16 192.168.5.0/24 fail2ban_ignoreip: 127.0.0.0/8
# Disable SSH passwords. Must use SSH keys. This is OK because we add the keys # Disable SSH passwords. Must use SSH keys. This is OK because we add the keys
# before re-configuring the SSH daemon to disable passwords. # before re-configuring the SSH daemon to disable passwords.

View File

@@ -1,2 +0,0 @@
autoclean -y
upgrade -y -o APT::Get::Show-Upgraded=true

View File

@@ -1,5 +0,0 @@
# Configuration for cron-apt. For further information about the possible
# configuration settings see the README file.
MAILON="never"
OPTIONS="-o quiet=1 -o Dir::Etc::SourceList=/etc/apt/security.sources.list -o Dir::Etc::SourceParts=\"/dev/null\""

View File

@@ -1 +0,0 @@
provisioning ALL=(ALL) ALL

View File

@@ -1,10 +1,7 @@
[Unit] [Unit]
Description=Update FireHOL lists Description=Update FireHOL lists
# This service will fail if nftables is not running so we use Requires to make # Make sure the network is up
# sure that nftables is started. After=network-online.target
Requires=nftables.service
# Make sure the network is up and nftables is started
After=network-online.target nftables.service
Wants=network-online.target update-firehol-nftables.timer Wants=network-online.target update-firehol-nftables.timer
[Service] [Service]

View File

@@ -1,27 +1,27 @@
--- ---
# ansible.builtin.file: roles/common/handlers/main.yml # ansible.builtin.file: roles/common/handlers/main.yml
- name: reload sshd - name: Reload sshd
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: "{{ sshd_service_name }}" name: "{{ sshd_service_name }}"
state: reloaded state: reloaded
- name: reload sysctl - name: Reload sysctl
command: sysctl -p /etc/sysctl.conf ansible.builtin.command: sysctl -p /etc/sysctl.conf
- name: reload systemd - name: Reload systemd
ansible.builtin.systemd: ansible.builtin.systemd_service:
daemon_reload: true daemon_reload: true
- name: restart nftables - name: Restart nftables
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: nftables name: nftables
state: restarted state: restarted
# 2021-09-28: note to self to keep fail2ban at the end, as handlers are executed # 2021-09-28: note to self to keep fail2ban at the end, as handlers are executed
# in the order they are defined, not in the order they are listed in the task's # in the order they are defined, not in the order they are listed in the task's
# notify statement and we must restart fail2ban after updating the firewall. # notify statement and we must restart fail2ban after updating the firewall.
- name: restart fail2ban - name: Restart fail2ban
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: fail2ban name: fail2ban
state: restarted state: restarted

View File

@@ -1,11 +1,17 @@
--- ---
- name: Configure cron-apt (config) - name: Remove cron-apt
ansible.builtin.copy: src={{ item.src }} dest={{ item.dest }} mode={{ item.mode }} owner={{ item.owner }} group={{ item.group }} ansible.builtin.apt:
loop: name: cron-apt
- { src: etc/cron-apt/config, dest: /etc/cron-apt/config, mode: "0644", owner: root, group: root } state: absent
- { src: etc/cron-apt/3-download, dest: /etc/cron-apt/action.d/3-download, mode: "0644", owner: root, group: root } cache_valid_time: 3600
- name: Configure cron-apt (security) - name: Remove cron-apt configs
ansible.builtin.template: src=security.sources.list.j2 dest=/etc/apt/security.sources.list mode=0644 owner=root group=root ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /etc/cron-apt/config
- /etc/cron-apt/action.d/3-download
- /etc/apt/security.sources.list
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,8 +1,7 @@
--- ---
- name: Install fail2ban - name: Install fail2ban
when: when: ansible_facts["distribution_version"] is version('11', '>=')
- ansible_distribution_major_version is version('11', '>=') ansible.builtin.apt:
ansible.builtin.package:
name: name:
- fail2ban - fail2ban
- python3-systemd - python3-systemd
@@ -15,7 +14,7 @@
dest: /etc/fail2ban/jail.d/sshd.local dest: /etc/fail2ban/jail.d/sshd.local
owner: root owner: root
mode: "0644" mode: "0644"
notify: restart fail2ban notify: Restart fail2ban
- name: Configure fail2ban nginx filter - name: Configure fail2ban nginx filter
when: when:
@@ -27,7 +26,7 @@
dest: /etc/fail2ban/jail.d/nginx.local dest: /etc/fail2ban/jail.d/nginx.local
owner: root owner: root
mode: "0644" mode: "0644"
notify: restart fail2ban notify: Restart fail2ban
- name: Create fail2ban service override directory - name: Create fail2ban service override directory
ansible.builtin.file: ansible.builtin.file:
@@ -44,11 +43,11 @@
owner: root owner: root
mode: "0644" mode: "0644"
notify: notify:
- reload systemd - Reload systemd
- restart fail2ban - Restart fail2ban
- name: Start and enable fail2ban service - name: Start and enable fail2ban service
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: fail2ban name: fail2ban
state: started state: started
enabled: true enabled: true

View File

@@ -1,20 +1,25 @@
--- ---
- name: Configure firewall (Debian) # Debian 11+ will use nftables directly, with no firewalld.
when: ansible_distribution == 'Debian'
ansible.builtin.include_tasks:
file: firewall_Debian.yml
apply:
tags:
- firewall
tags: firewall
- name: Configure firewall (Ubuntu) - name: Install Debian firewall packages
when: ansible_distribution == 'Ubuntu' when: ansible_facts["distribution_version"] is version('11', '>=')
ansible.builtin.include_tasks: ansible.builtin.apt:
file: firewall_Ubuntu.yml name: nftables
apply: state: present
tags: cache_valid_time: 3600
- firewall
tags: firewall
- name: Remove iptables on newer Debian
when: ansible_facts["distribution_version"] is version('11', '>=')
ansible.builtin.apt:
pkg: iptables
state: absent
- name: Configure nftables
when: ansible_facts["distribution_version"] is version('11', '>=')
ansible.builtin.include_tasks: nftables.yml
- name: Configure fail2ban
when: ansible_facts["distribution_version"] is version('9', '>=')
ansible.builtin.include_tasks: fail2ban.yml
# vim: set sw=2 ts=2:

View File

@@ -1,28 +0,0 @@
---
# Debian 11+ will use nftables directly, with no firewalld.
- name: Install Debian firewall packages
when: ansible_distribution_major_version is version('11', '>=')
ansible.builtin.package:
name:
- libnet-ip-perl # for aggregate-cidr-addresses.pl
- nftables
- curl # for nftables update scripts
state: present
cache_valid_time: 3600
- name: Remove iptables on newer Debian
when: ansible_distribution_major_version is version('11', '>=')
ansible.builtin.apt:
pkg: iptables
state: absent
- name: Configure nftables
ansible.builtin.include_tasks: nftables.yml
when: ansible_distribution_version is version('11', '>=')
- ansible.builtin.include_tasks: fail2ban.yml
when:
- ansible_distribution_major_version is version('9', '>=')
# vim: set sw=2 ts=2:

View File

@@ -1,27 +0,0 @@
---
# Ubuntu 20.04 will use nftables directly, with no firewalld.
- name: Install Ubuntu firewall packages
when: ansible_distribution_version is version('20.04', '>=')
ansible.builtin.package:
name:
- libnet-ip-perl # for aggregate-cidr-addresses.pl
- nftables
- curl # for nftables update scripts
state: present
cache_valid_time: 3600
- name: Remove ufw
ansible.builtin.package:
name: ufw
state: absent
- name: Configure nftables
ansible.builtin.include_tasks: nftables.yml
when: ansible_distribution_version is version('20.04', '>=')
- ansible.builtin.include_tasks: fail2ban.yml
when:
- ansible_distribution_version is version('16.04', '>=')
# vim: set sw=2 ts=2:

View File

@@ -1,6 +1,6 @@
--- ---
- name: Import OS-specific variables - name: Import OS-specific variables
ansible.builtin.include_vars: vars/{{ ansible_distribution }}.yml ansible.builtin.include_vars: vars/{{ ansible_facts["distribution"] }}.yml
tags: always tags: always
- name: Configure network time - name: Configure network time
@@ -8,13 +8,7 @@
tags: ntp tags: ntp
- name: Install common packages - name: Install common packages
ansible.builtin.include_tasks: packages_Debian.yml ansible.builtin.include_tasks: packages.yml
when: ansible_distribution == 'Debian'
tags: packages
- name: Install common packages
ansible.builtin.include_tasks: packages_Ubuntu.yml
when: ansible_distribution == 'Ubuntu'
tags: packages tags: packages
- name: Configure firewall - name: Configure firewall
@@ -27,14 +21,24 @@
# containers identify as virtualization hosts, which makes this tricky, because we have actual Debian VM hosts! # containers identify as virtualization hosts, which makes this tricky, because we have actual Debian VM hosts!
- name: Reconfigure /etc/sysctl.conf - name: Reconfigure /etc/sysctl.conf
when: ansible_virtualization_role != 'host' when: ansible_facts["virtualization_role"] != 'host'
ansible.builtin.template: src=sysctl_{{ ansible_distribution }}.j2 dest=/etc/sysctl.conf owner=root group=root mode=0644 ansible.builtin.template:
src: "sysctl_{{ ansible_facts['distribution'] }}.j2"
dest: /etc/sysctl.conf
owner: root
group: root
mode: "0644"
notify: notify:
- reload sysctl - Reload sysctl
tags: sysctl tags: sysctl
- name: Set I/O scheduler - name: Set I/O scheduler
ansible.builtin.template: src=etc/udev/rules.d/60-scheduler.rules.j2 dest=/etc/udev/rules.d/60-scheduler.rules owner=root group=root mode=0644 ansible.builtin.template:
src: etc/udev/rules.d/60-scheduler.rules.j2
dest: /etc/udev/rules.d/60-scheduler.rules
owner: root
group: root
mode: "0644"
tags: udev tags: udev
- name: Copy admin SSH keys - name: Copy admin SSH keys

View File

@@ -1,6 +1,5 @@
--- ---
# Common nftables tasks for Ubuntu 20.04, Ubuntu 22.04, Ubuntu 24.04, Debian 11, # Common nftables tasks for Debian 11 and Debian 12.
# and Debian 12.
- name: Copy nftables.conf - name: Copy nftables.conf
ansible.builtin.template: ansible.builtin.template:
@@ -9,8 +8,7 @@
owner: root owner: root
mode: "0644" mode: "0644"
notify: notify:
- restart nftables - Restart nftables
- restart fail2ban
- name: Create /etc/nftables extra config directory - name: Create /etc/nftables extra config directory
ansible.builtin.file: ansible.builtin.file:
@@ -21,17 +19,14 @@
- name: Copy extra nftables configuration files - name: Copy extra nftables configuration files
ansible.builtin.copy: ansible.builtin.copy:
src: "{{ item.src }}" src: firehol_level1-ipv4.nft
dest: /etc/nftables/{{ item.src }} dest: /etc/nftables/firehol_level1-ipv4.nft
owner: root owner: root
group: root group: root
mode: "0644" mode: "0644"
force: "{{ item.force }}" force: false
loop:
- { src: firehol_level1-ipv4.nft, force: false }
notify: notify:
- restart nftables - Restart nftables
- restart fail2ban
- name: Copy nftables update scripts - name: Copy nftables update scripts
ansible.builtin.template: ansible.builtin.template:
@@ -41,27 +36,6 @@
owner: root owner: root
group: root group: root
- name: Remove deprecated data and scripts
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- /etc/nftables/spamhaus-ipv4.nft
- /etc/nftables/spamhaus-ipv6.nft
- /etc/nftables/abuseipdb-ipv4.nft
- /etc/nftables/abuseipdb-ipv6.nft
- /etc/nftables/abusech-ipv4.nft
- /usr/local/bin/update-abusech-nftables.sh
- /usr/local/bin/update-spamhaus-nftables.sh
- /etc/systemd/system/update-abusech-nftables.service
- /etc/systemd/system/update-abusech-nftables.timer
- /etc/systemd/system/update-spamhaus-nftables.service
- /etc/systemd/system/update-spamhaus-nftables.timer
- /usr/local/bin/aggregate-cidr-addresses.pl
notify:
- restart nftables
- restart fail2ban
- name: Copy nftables systemd units - name: Copy nftables systemd units
ansible.builtin.copy: ansible.builtin.copy:
src: "{{ item }}" src: "{{ item }}"
@@ -76,20 +50,18 @@
# need to reload to pick up service/timer/environment changes # need to reload to pick up service/timer/environment changes
- name: Reload systemd daemon - name: Reload systemd daemon
ansible.builtin.systemd: # noqa no-handler
daemon_reload: true
when: nftables_systemd_units is changed when: nftables_systemd_units is changed
ansible.builtin.systemd_service: # noqa no-handler
daemon_reload: true
- name: Start and enable nftables update timers - name: Start and enable nftables update timers
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: "{{ item }}" name: update-firehol-nftables.timer
state: started state: started
enabled: true enabled: true
loop:
- update-firehol-nftables.timer
- name: Start and enable nftables - name: Start and enable nftables
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: nftables name: nftables
state: started state: started
enabled: true enabled: true

View File

@@ -1,30 +1,40 @@
--- ---
# Hosts running Ubuntu 16.04+ and Debian 9+ use systemd init system and should # Hosts running Debian 9+ use systemd init system and can use systemd-timesyncd
# use systemd-timesyncd as a network time client instead of the standalone ntp # as a network time client instead of the standalone ntp client.
# client.
- name: Set timezone - name: Set timezone
when: when:
- timezone is defined - timezone is defined
- ansible_service_mgr == 'systemd' - ansible_facts["service_mgr"] == 'systemd'
community.general.timezone: community.general.timezone:
name: "{{ timezone }}" name: "{{ timezone }}"
tags: timezone tags: timezone
# Apparently some cloud images don't have this installed by default. From what # Apparently some cloud images don't have this installed by default. From what
# I can see on existing servers, systemd-timesyncd is a standalone package on # I can see on existing servers, systemd-timesyncd is a standalone package on
# Ubuntu 20.04 and Debian 11. # Debian 11 and Debian 12.
- name: Install systemd-timesyncd - name: Install systemd-timesyncd
when: (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '==')) or (ansible_distribution == 'Debian' and ansible_distribution_version when: ansible_facts["distribution_version"] is version('11', '>=')
is version('11', '>=')) ansible.builtin.apt:
ansible.builtin.apt: name=systemd-timesyncd state=present cache_valid_time=3600 name: systemd-timesyncd
state: present
cache_valid_time: 3600
- name: Start and enable systemd's NTP client - name: Start and enable systemd's NTP client
when: ansible_service_mgr == 'systemd' when: ansible_facts["service_mgr"] == 'systemd'
ansible.builtin.systemd: name=systemd-timesyncd state=started enabled=true ansible.builtin.systemd_service:
name: systemd-timesyncd
state: started
enabled: true
- name: Uninstall ntp on modern Ubuntu/Debian # On Debian 12 ntp doesn't conflict with systemd-timesyncd so we should try to
ansible.builtin.apt: name=ntp state=absent # remove it to be sure.
when: ansible_service_mgr == 'systemd' - name: Uninstall ntp on Debian 12
when:
- ansible_facts["service_mgr"] == 'systemd'
- ansible_facts["distribution_major_version"] is version('12', '==')
ansible.builtin.apt:
name: ntp
state: absent
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,19 +1,7 @@
--- ---
- name: Configure Debian packages - name: Configure Debian packages
tags: packages
block: block:
# Create directory for third-party package signing keys. Required on distros
# older than Debian 12 / Ubuntu 22.04.
#
# See: https://wiki.debian.org/DebianRepository/UseThirdParty
- name: Create /etc/apt/keyrings
file:
path: /etc/apt/keyrings
mode: "0755"
owner: root
group: root
state: directory
when: ansible_distribution_major_version is version('12', '<')
# Scaleway seems to use a weird sources.list format as of Debian 12? # Scaleway seems to use a weird sources.list format as of Debian 12?
- name: Check for weird Debian sources - name: Check for weird Debian sources
ansible.builtin.stat: ansible.builtin.stat:
@@ -21,10 +9,15 @@
register: weird_debian_sources_stat register: weird_debian_sources_stat
- name: Configure apt mirror - name: Configure apt mirror
ansible.builtin.template: src=sources.list.j2 dest=/etc/apt/sources.list owner=root group=root mode=0644
when: when:
- ansible_architecture != 'armv7l' - ansible_facts["architecture"] != 'armv7l'
- not weird_debian_sources_stat - not weird_debian_sources_stat
ansible.builtin.template:
src: sources.list.j2
dest: /etc/apt/sources.list
owner: root
group: root
mode: "0644"
- name: Set fact for base packages - name: Set fact for base packages
ansible.builtin.set_fact: ansible.builtin.set_fact:
@@ -35,7 +28,6 @@
- iotop - iotop
- htop - htop
- strace - strace
- cron-apt
- safe-rm - safe-rm
- debian-goodies - debian-goodies
- mosh - mosh
@@ -47,16 +39,19 @@
- zstd - zstd
- rsync - rsync
- lsof - lsof
- unattended-upgrades
- name: Install base packages - name: Install base packages
ansible.builtin.apt: name={{ base_packages }} state=present cache_valid_time=3600 ansible.builtin.apt:
name: "{{ base_packages }}"
state: present
cache_valid_time: 3600
- name: Configure cron-apt - name: Remove cron-apt
ansible.builtin.import_tasks: cron-apt.yml
tags: cron-apt tags: cron-apt
ansible.builtin.import_tasks: cron-apt.yml
- name: Install tarsnap - name: Install tarsnap
ansible.builtin.import_tasks: tarsnap.yml ansible.builtin.import_tasks: tarsnap.yml
tags: packages
# vim: set sw=2 ts=2: # vim: set sw=2 ts=2:

View File

@@ -1,105 +0,0 @@
---
- name: Configure Ubuntu packages
block:
# Create directory for third-party package signing keys. Required on distros
# older than Debian 12 / Ubuntu 22.04.
#
# See: https://wiki.debian.org/DebianRepository/UseThirdParty
- name: Create /etc/apt/keyrings
file:
path: /etc/apt/keyrings
mode: "0755"
owner: root
group: root
state: directory
when: ansible_distribution_major_version is version('22.04', '<')
- name: Configure apt mirror
ansible.builtin.template: src=sources.list.j2 dest=/etc/apt/sources.list owner=root group=root mode=0644
when: ansible_architecture != 'armv7l'
- name: Upgrade base OS
ansible.builtin.apt: upgrade=dist cache_valid_time=3600
- name: Set Ubuntu base packages
ansible.builtin.set_fact:
ubuntu_base_packages:
- git
- git-lfs
- tmux
- iotop
- htop
- strace
- cron-apt
- safe-rm
- debian-goodies
- mosh
- python-pycurl # for ansible's apt_repository
- vim
- unzip
- apt-transport-https # for https support in apt
- zstd
- rsync
- lsof
- name: Install base packages
ansible.builtin.apt: pkg={{ ubuntu_base_packages }} state=present cache_valid_time=3600
# We have to remove snaps one by one in a specific order because some depend
# on others. Only after that can we remove the corresponding system packages.
- name: Remove lxd snap
community.general.snap: name=lxd state=absent
when: ansible_distribution_version is version('20.04', '==')
ignore_errors: true
- name: Remove core18 snap
community.general.snap: name=core18 state=absent
when: ansible_distribution_version is version('20.04', '==')
ignore_errors: true
- name: Remove snapd snap
community.general.snap: name=snapd state=absent
when: ansible_distribution_version is version('20.04', '==')
ignore_errors: true
- name: Set fact for packages to remove (Ubuntu 20.04)
ansible.builtin.set_fact:
ubuntu_annoying_packages:
- whoopsie # security (CIS 4.1)
- apport # security (CIS 4.1)
- command-not-found # annoying
- command-not-found-data # annoying
- python3-commandnotfound # annoying
- snapd # annoying (Ubuntu >= 16.04)
- lxd-agent-loader # annoying (Ubuntu 20.04)
when: ansible_distribution_version is version('20.04', '==')
- name: Remove packages
ansible.builtin.apt: name={{ ubuntu_annoying_packages }} state=absent purge=true
- name: Disable annoying Canonical spam in MOTD
ansible.builtin.file: path={{ item }} mode=0644 state=absent
loop:
- /etc/update-motd.d/99-esm # Ubuntu 14.04
- /etc/update-motd.d/10-help-text # Ubuntu 14.04+
- /etc/update-motd.d/50-motd-news # Ubuntu 18.04+
- /etc/update-motd.d/80-esm # Ubuntu 18.04+
- /etc/update-motd.d/80-livepatch # Ubuntu 18.04+
ignore_errors: true
- name: Disable annoying Canonical spam in MOTD
ansible.builtin.systemd: name={{ item }} state=stopped enabled=no
when: ansible_service_mgr == 'systemd'
loop:
- motd-news.service
- motd-news.timer
- name: Configure cron-apt
ansible.builtin.import_tasks: cron-apt.yml
tags: cron-apt
- name: Install tarsnap
ansible.builtin.import_tasks: tarsnap.yml
tags: packages
# vim: set sw=2 ts=2:

View File

@@ -1,9 +1,11 @@
--- ---
- name: Zero .ssh/authorized_keys for provisioning user - name: Zero .ssh/authorized_keys for provisioning user
ansible.builtin.file: dest={{ provisioning_user.home }}/.ssh/authorized_keys state=absent ansible.builtin.file:
dest: "{{ provisioning_user.home }}/.ssh/authorized_keys"
state: absent
- name: Add public keys to authorized_keys - name: Add public keys to authorized_keys
ansible.posix.authorized_key: { user: "{{ provisioning_user.name }}", key: "{{ lookup('file',item) }}" } ansible.posix.authorized_key: { user: "{{ provisioning_user.name }}", key: "{{ lookup('file', item) }}" }
with_fileglob: with_fileglob:
# use descriptive names for keys, like: aorth-mzito-rsa.pub # use descriptive names for keys, like: aorth-mzito-rsa.pub
- ssh-pub-keys/*.pub - ssh-pub-keys/*.pub

View File

@@ -1,17 +1,26 @@
--- ---
# SSH configs don't change in Debian minor versions # Only override the system sshd configuration on older Debian.
- name: Reconfigure /etc/ssh/sshd_config - name: Reconfigure /etc/ssh/sshd_config
ansible.builtin.template: src=sshd_config_{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.j2 dest=/etc/ssh/sshd_config owner=root group=root when: ansible_facts["distribution_version"] is version('12', '<=')
mode=0600 ansible.builtin.template:
when: ansible_distribution == 'Debian' src: "sshd_config_{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.j2"
notify: reload sshd dest: /etc/ssh/sshd_config
owner: root
group: root
mode: "0600"
notify: Reload sshd
# Ubuntu is the only distro we have where SSH version is very different from 14.04 -> 14.10, # Newer OpenSSH versions support including extra configuration. The includes
# ie with new ciphers supported etc. # happen at the beginning of the file and the first value to be read is used.
- name: Reconfigure /etc/ssh/sshd_config - name: Configure sshd_config.d overrides
ansible.builtin.template: src=sshd_config_{{ ansible_distribution }}-{{ ansible_distribution_version }}.j2 dest=/etc/ssh/sshd_config owner=root group=root mode=0600 when: ansible_facts["distribution_version"] is version('13', '>=')
when: ansible_distribution == 'Ubuntu' ansible.builtin.template:
notify: reload sshd src: etc/ssh/sshd_config.d/01-{{ ansible_facts["distribution"] }}-{{ ansible_facts["distribution_major_version"] }}.conf.j2
dest: /etc/ssh/sshd_config.d/01-custom.conf
owner: root
group: root
mode: "0600"
notify: Reload sshd
# See: WeakDH (2015): https://weakdh.org/sysadmin.html # See: WeakDH (2015): https://weakdh.org/sysadmin.html
- name: Remove small Diffie-Hellman SSH moduli - name: Remove small Diffie-Hellman SSH moduli
@@ -24,28 +33,30 @@
register: check_unsafe_moduli register: check_unsafe_moduli
- name: Extract safe Diffie-Hellman SSH moduli - name: Extract safe Diffie-Hellman SSH moduli
when: check_unsafe_moduli.stdout | length > 0
ansible.builtin.shell: ansible.builtin.shell:
cmd: awk '$5 >= 3071' moduli > moduli.safe cmd: awk '$5 >= 3071' moduli > moduli.safe
chdir: /etc/ssh chdir: /etc/ssh
creates: moduli.safe creates: moduli.safe
when: check_unsafe_moduli.stdout | length > 0
register: extract_safe_moduli register: extract_safe_moduli
- name: Replace unsafe Diffie-Hellman SSH moduli - name: Replace unsafe Diffie-Hellman SSH moduli
when: extract_safe_moduli is changed
ansible.builtin.command: ansible.builtin.command:
cmd: mv moduli.safe moduli cmd: mv moduli.safe moduli
chdir: /etc/ssh chdir: /etc/ssh
register: replace_small_moduli register: replace_small_moduli
when: extract_safe_moduli is changed notify: Reload sshd
notify: reload sshd
- name: Remove DSA and ECDSA host keys - name: Remove DSA and ECDSA host keys
ansible.builtin.file: name=/etc/ssh/{{ item }} state=absent ansible.builtin.file:
name: "/etc/ssh/{{ item }}"
state: absent
loop: loop:
- ssh_host_dsa_key - ssh_host_dsa_key
- ssh_host_dsa_key.pub - ssh_host_dsa_key.pub
- ssh_host_ecdsa_key - ssh_host_ecdsa_key
- ssh_host_ecdsa_key.pub - ssh_host_ecdsa_key.pub
notify: reload sshd notify: Reload sshd
# vim: set sw=2 ts=2: # vim: set sw=2 ts=2:

View File

@@ -5,6 +5,7 @@
register: tarsnap_signing_key_stat register: tarsnap_signing_key_stat
- name: Download tarsnap apt signing key - name: Download tarsnap apt signing key
when: not tarsnap_signing_key_stat.stat.exists
ansible.builtin.get_url: ansible.builtin.get_url:
url: https://pkg.tarsnap.com/tarsnap-deb-packaging-key.asc url: https://pkg.tarsnap.com/tarsnap-deb-packaging-key.asc
dest: /etc/apt/keyrings/tarsnap-deb-packaging-key.asc dest: /etc/apt/keyrings/tarsnap-deb-packaging-key.asc
@@ -12,9 +13,9 @@
group: root group: root
mode: "0644" mode: "0644"
register: download_tarsnap_signing_key register: download_tarsnap_signing_key
when: not tarsnap_signing_key_stat.stat.exists
- name: Add tarsnap.org repo - name: Add tarsnap.org repo
when: ansible_facts["architecture"] != 'armv7l'
ansible.builtin.template: ansible.builtin.template:
src: tarsnap_sources.list.j2 src: tarsnap_sources.list.j2
dest: /etc/apt/sources.list.d/tarsnap.list dest: /etc/apt/sources.list.d/tarsnap.list
@@ -22,12 +23,11 @@
group: root group: root
mode: "0644" mode: "0644"
register: add_tarsnap_apt_repository register: add_tarsnap_apt_repository
when: ansible_architecture != 'armv7l'
- name: Update apt cache - name: Update apt cache
when: (download_tarsnap_signing_key.status_code is defined and download_tarsnap_signing_key.status_code == 200) or add_tarsnap_apt_repository is changed
ansible.builtin.apt: # noqa no-handler ansible.builtin.apt: # noqa no-handler
update_cache: true update_cache: true
when: (download_tarsnap_signing_key.status_code is defined and download_tarsnap_signing_key.status_code == 200) or add_tarsnap_apt_repository is changed
- name: Install tarsnap - name: Install tarsnap
ansible.builtin.apt: ansible.builtin.apt:

View File

@@ -0,0 +1,40 @@
{{ ansible_managed | comment }}
HostKey /etc/ssh/ssh_host_ed25519_key
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear
# audit track of which key was using to log in.
LogLevel VERBOSE
MaxAuthTries 4
AuthorizedKeysFile .ssh/authorized_keys
# To disable tunneled clear text passwords, change to no here!
{% if ssh_password_authentication == 'disabled' %}
PasswordAuthentication no
{% else %}
PasswordAuthentication yes
{% endif %}
X11Forwarding no
# Based on the ssh-audit profile for Debian 13, but with but with all algos with
# less than 256 bits removed, as NSA's Suite B removed them years ago and the
# new (2018) CNSA suite is 256 bits and up.
#
# See: ssh-audit.py -P "Hardened Debian 13 (version 1)"
# See: https://en.wikipedia.org/wiki/Commercial_National_Security_Algorithm_Suite
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com
{% if ssh_allowed_users is defined and ssh_allowed_users %}
AllowUsers {{ ssh_allowed_users|join(" ") }} {{ provisioning_user.name }}
{% endif %}
PerSourcePenaltyExemptList {{ fail2ban_ignoreip | replace(" ", ",") }}
# Mask to use for IPv4 and IPv6 respectively when applying network penalties.
# The default is 32:128.
PerSourceNetBlockSize 24:56

View File

@@ -1,15 +1,19 @@
[Unit]
# If nftables is stopped or restarted, propagate to fail2ban as well
PartOf=nftables.service
[Service] [Service]
PrivateDevices=yes PrivateDevices=yes
PrivateTmp=yes PrivateTmp=yes
ProtectHome=read-only ProtectHome=read-only
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version is version('18','>=')) or (ansible_distribution == 'Debian' and ansible_distribution_major_version is version('11','>=')) %} {% if ansible_facts["distribution_version"] is version('11','>=') %}
ProtectSystem=strict ProtectSystem=strict
{% else %} {% else %}
{# Older systemd versions don't have ProtectSystem=strict #} {# Older systemd versions don't have ProtectSystem=strict #}
ProtectSystem=full ProtectSystem=full
{% endif %} {% endif %}
NoNewPrivileges=yes NoNewPrivileges=yes
{% if (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version is version('18','>=')) or (ansible_distribution == 'Debian' and ansible_distribution_major_version is version('11','>=')) %} {% if ansible_facts["distribution_version"] is version('11','>=') %}
ReadWritePaths=-/var/run/fail2ban ReadWritePaths=-/var/run/fail2ban
ReadWritePaths=-/var/lib/fail2ban ReadWritePaths=-/var/lib/fail2ban
ReadWritePaths=-/var/log/fail2ban.log ReadWritePaths=-/var/log/fail2ban.log

View File

@@ -1,5 +0,0 @@
{% if ansible_distribution == 'Ubuntu' %}
deb http://security.ubuntu.com/ubuntu {{ ansible_distribution_release }}-security main restricted universe multiverse
{% elif ansible_distribution == 'Debian' %}
deb http://security.debian.org/debian-security {{ ansible_distribution_release }}/updates main contrib non-free
{% endif %}

View File

@@ -1,16 +1,6 @@
{% if ansible_distribution == 'Ubuntu' %}
{% set apt_mirror = apt_mirror | default("ubuntu.mirror.ac.ke") %}
deb http://{{ apt_mirror }}/ubuntu/ {{ ansible_distribution_release }} main restricted universe multiverse
deb http://{{ apt_mirror }}/ubuntu/ {{ ansible_distribution_release }}-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu/ {{ ansible_distribution_release }}-security main restricted universe multiverse
{% else %}
{% set apt_mirror = apt_mirror | default('deb.debian.org') %} {% set apt_mirror = apt_mirror | default('deb.debian.org') %}
deb http://{{ apt_mirror }}/debian/ {{ ansible_distribution_release }} main contrib non-free deb http://{{ apt_mirror }}/debian/ {{ ansible_distribution_release }} main contrib non-free
deb http://security.debian.org/debian-security {{ ansible_distribution_release }}-security main contrib non-free deb http://security.debian.org/debian-security {{ ansible_distribution_release }}-security main contrib non-free
deb http://{{ apt_mirror }}/debian/ {{ ansible_distribution_release }}-updates main contrib non-free deb http://{{ apt_mirror }}/debian/ {{ ansible_distribution_release }}-updates main contrib non-free
{% endif %} {# ansible_distribution #}

View File

@@ -1,143 +0,0 @@
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Include /etc/ssh/sshd_config.d/*.conf
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Authentication:
#LoginGraceTime 2m
PermitRootLogin prohibit-password
#StrictModes yes
MaxAuthTries 4
#MaxSessions 10
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
{% if ssh_password_authentication == 'disabled' %}
PasswordAuthentication no
{% else %}
PasswordAuthentication yes
{% endif %}
#PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
# Originally from: https://stribika.github.io/2015/01/04/secure-secure-shell.html
# ... but with ciphers and MACs with < 256 bits removed, as NSA's Suite B now
# does away with these! See: https://www.nsa.gov/ia/programs/suiteb_cryptography/index.shtml
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
{% if ssh_allowed_users is defined and ssh_allowed_users %}
# Is there a list of allowed users?
# Is it populated? (An empty list is 'None', which evaluates as False in Python)
# merge the items of a list into one string using a space as a separator
# http://jinja.pocoo.org/docs/dev/templates/#join
AllowUsers {{ ssh_allowed_users|join(" ") }} {{ provisioning_user.name }}
{% endif %}

View File

@@ -90,7 +90,7 @@ net.ipv4.tcp_wmem = 4096 65536 16777216
# increase the length of the processor input queue # increase the length of the processor input queue
net.core.netdev_max_backlog = 30000 net.core.netdev_max_backlog = 30000
{# kernels after 2.6.32 don't have buggy cubic #} {# kernels after 2.6.32 don't have buggy cubic #}
{% if ansible_kernel < "2.6.33" %} {% if ansible_facts["kernel"] < "2.6.33" %}
# recommended default congestion control is htcp # recommended default congestion control is htcp
net.ipv4.tcp_congestion_control=htcp net.ipv4.tcp_congestion_control=htcp
{% endif %} {% endif %}
@@ -98,7 +98,7 @@ net.ipv4.tcp_congestion_control=htcp
#net.ipv4.tcp_mtu_probing=1 #net.ipv4.tcp_mtu_probing=1
{# disable iptables on bridge interfaces on VM hosts #} {# disable iptables on bridge interfaces on VM hosts #}
{% if ansible_virtualization_role == "host" %} {% if ansible_facts["virtualization_role"] == "host" %}
net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0 net.bridge.bridge-nf-call-arptables = 0

View File

@@ -1,100 +0,0 @@
#
# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables
# See sysctl.conf (5) for information.
#
#kernel.domainname = example.com
# Uncomment the following to stop low-level messages on console
#kernel.printk = 3 4 1 3
##############################################################3
# Functions previously found in netbase
#
# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks
#net.ipv4.conf.default.rp_filter=1
#net.ipv4.conf.all.rp_filter=1
# Uncomment the next line to enable TCP/IP SYN cookies
# See http://lwn.net/Articles/277146/
# Note: This may impact IPv6 TCP sessions too
#net.ipv4.tcp_syncookies=1
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
###################################################################
# Additional settings - these settings can improve the network
# security of the host and prevent against some network attacks
# including spoofing attacks and man in the middle attacks through
# redirection. Some network environments, however, require that these
# settings are disabled so review and enable them as needed.
#
# Do not accept ICMP redirects (prevent MITM attacks)
#net.ipv4.conf.all.accept_redirects = 0
#net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
# net.ipv4.conf.all.secure_redirects = 1
#
# Do not send ICMP redirects (we are not a router)
#net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
#net.ipv4.conf.all.accept_source_route = 0
#net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
#net.ipv4.conf.all.log_martians = 1
#
# CIS Benchmark Adjustments
# See: https://github.com/alanorth/securekickstarts
kernel.randomize_va_space = 2
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
# TCP stuff
# See: http://fasterdata.es.net/host-tuning/linux/
# increase TCP max buffer size settable using setsockopt()
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# increase Linux autotuning TCP buffer limit
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# increase the length of the processor input queue
net.core.netdev_max_backlog = 30000
# recommended for hosts with jumbo frames enabled
#net.ipv4.tcp_mtu_probing=1
# increase quadruplets (src ip, src port, dest ip, dest port)
# see: http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html
net.ipv4.ip_local_port_range = 10240 65535
# recommended for web servers, especially if running SPDY
# see: http://www.chromium.org/spdy/spdy-best-practices
net.ipv4.tcp_slow_start_after_idle = 0

View File

@@ -1 +1 @@
deb [arch=amd64 signed-by=/etc/apt/keyrings/tarsnap-deb-packaging-key.asc] https://pkg.tarsnap.com/deb/{{ ansible_distribution_release }} ./ deb [arch=amd64 signed-by=/etc/apt/keyrings/tarsnap-deb-packaging-key.asc] https://pkg.tarsnap.com/deb/{{ ansible_facts["distribution_release"] }} ./

View File

@@ -28,11 +28,14 @@ if [[ -f "firehol_level1.netset" ]]; then
firehol_level1_ipv4_list_temp=$(mktemp) firehol_level1_ipv4_list_temp=$(mktemp)
firehol_level1_ipv4_set_temp=$(mktemp) firehol_level1_ipv4_set_temp=$(mktemp)
# Filter blank lines and comments # Filter blank lines, comments, and bogons we use inside the LAN, DMZ, and
# for local services like systemd-resolved and others on localhost. Ideally
# these are blocked already at the WAN side by network administrators.
cat firehol_level1.netset \ cat firehol_level1.netset \
| sed \ | sed \
-e '/^$/d' \ -e '/^$/d' \
-e '/^#.*/d' \ -e '/^#.*/d' \
-e '/^127\.0\.0\.0\/8/d' \
> "$firehol_level1_ipv4_list_temp" > "$firehol_level1_ipv4_list_temp"
echo "Building firehol_level1-ipv4 set" echo "Building firehol_level1-ipv4 set"
@@ -55,13 +58,8 @@ NFT_HEAD
rm -f "$firehol_level1_ipv4_list_temp" "$firehol_level1_ipv4_set_temp" rm -f "$firehol_level1_ipv4_list_temp" "$firehol_level1_ipv4_set_temp"
fi fi
echo "Reloading nftables" echo "Restarting nftables"
{% if ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '<=') %}
{% set systemctl_bin = '/bin/systemctl' %}
{% else %}
{% set systemctl_bin = '/usr/bin/systemctl' %}
{% endif -%}
{{ systemctl_bin }} reload nftables.service /usr/bin/systemctl restart nftables.service
rm -v firehol_level1.netset rm -v firehol_level1.netset

View File

@@ -1,15 +1,4 @@
--- ---
# ansible.builtin.file: roles/mariadb/defaults/main.yml
#
# Based on my running of mysqltuner.pl on a host with three WordPress databases
#
# default is 128MB but is a waste because it seems only the mysql table uses it
key_buffer_size: 8M
# default is 128MB but is a waste because it seems only information_schema uses
# AriaDB, see: https://mariadb.com/kb/en/mariadb/aria-system-variables
aria_pagecache_buffer_size: 8M
# default is 128M, but set to at least the size of your InnoDB data # default is 128M, but set to at least the size of your InnoDB data
innodb_buffer_pool_size: 256M innodb_buffer_pool_size: 256M
@@ -22,10 +11,6 @@ mariadb_login_unix_socket: /run/mysqld/mysqld.sock
# default is 100 but the max I've seen used is 5, so let's reduce it # default is 100 but the max I've seen used is 5, so let's reduce it
max_connections: 33 max_connections: 33
# disable the query cache by default
query_cache_size: 0
query_cache_type: 0
# mysqltuner says we should use larger than 32M on our setup # mysqltuner says we should use larger than 32M on our setup
tmp_table_size: 64M tmp_table_size: 64M
max_heap_table_size: 64M max_heap_table_size: 64M

View File

@@ -1,5 +1,7 @@
--- ---
- name: restart mariadb - name: restart mariadb
ansible.builtin.systemd: name=mariadb state=restarted ansible.builtin.systemd_service:
name: mariadb
state: restarted
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,52 +1,4 @@
--- ---
- name: Remove MariaDB key from apt-key
ansible.builtin.apt_key:
id: "013577200103762554506315430003013705453362230723150730"
state: absent
tags:
- packages
- mariadb
- name: Check MariaDB package signing key
ansible.builtin.stat:
path: /etc/apt/keyrings/mariadb_release_signing_key.asc
register: mariadb_signing_key_stat
tags:
- packages
- mariadb
- name: Download MariaDB package signing key
ansible.builtin.get_url:
url: https://mariadb.org/mariadb_release_signing_key.asc
dest: /etc/apt/keyrings/mariadb_release_signing_key.asc
owner: root
group: root
mode: "0644"
register: download_mariadb_signing_key
when: not mariadb_signing_key_stat.stat.exists
tags:
- packages
- mariadb
- name: Add MariaDB 10.11 repo
ansible.builtin.apt_repository:
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/mariadb_release_signing_key.asc] https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/debian {{ ansible_distribution_release
}} main
filename: mariadb
state: present
register: add_mariadb_apt_repository
tags:
- packages
- mariadb
- name: Update apt cache
ansible.builtin.apt: # noqa no-handler
update_cache: true
when: (download_mariadb_signing_key.status_code is defined and download_mariadb_signing_key.status_code == 200) or add_mariadb_apt_repository is changed
tags:
- packages
- mariadb
- name: Install mariadb-server - name: Install mariadb-server
ansible.builtin.apt: ansible.builtin.apt:
name: [mariadb-server, python3-pymysql] name: [mariadb-server, python3-pymysql]
@@ -54,10 +6,10 @@
cache_valid_time: 3600 cache_valid_time: 3600
tags: mariadb, packages tags: mariadb, packages
- name: Create system my.cnf - name: Add MariaDB configuration overrides
ansible.builtin.template: ansible.builtin.template:
src: my.cnf.j2 src: 70-local.cnf.j2
dest: /etc/mysql/my.cnf dest: /etc/mysql/mariadb.conf.d/70-local.cnf
owner: root owner: root
group: root group: root
mode: "0644" mode: "0644"
@@ -87,16 +39,17 @@
# See: https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html # See: https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html
- name: Create MariaDB database(s) - name: Create MariaDB database(s)
when: mariadb_databases is defined
community.mysql.mysql_db: community.mysql.mysql_db:
db: "{{ item.name }}" db: "{{ item.name }}"
state: present state: present
encoding: utf8mb4 encoding: utf8mb4
login_unix_socket: "{{ mariadb_login_unix_socket }}" login_unix_socket: "{{ mariadb_login_unix_socket }}"
loop: "{{ mariadb_databases }}" loop: "{{ mariadb_databases }}"
when: mariadb_databases is defined
tags: mariadb tags: mariadb
- name: Create MariaDB user(s) - name: Create MariaDB user(s)
when: mariadb_databases is defined
community.mysql.mysql_user: community.mysql.mysql_user:
name: "{{ item.user }}" name: "{{ item.user }}"
password: "{{ item.pass }}" password: "{{ item.pass }}"
@@ -105,7 +58,6 @@
state: present state: present
login_unix_socket: "{{ mariadb_login_unix_socket }}" login_unix_socket: "{{ mariadb_login_unix_socket }}"
loop: "{{ mariadb_databases }}" loop: "{{ mariadb_databases }}"
when: mariadb_databases is defined
tags: mariadb tags: mariadb
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -0,0 +1,10 @@
{{ ansible_managed | comment }}
[mysqld]
# don't resolve connection IPs to hostnames (make sure user accounts are using
# IPs instead of "localhost")
skip-name-resolve=1
max_connections = {{ max_connections }}
tmp_table_size = {{ tmp_table_size }}
max_heap_table_size = {{ max_heap_table_size }}
innodb_buffer_pool_size = {{ innodb_buffer_pool_size }}

View File

@@ -1,196 +0,0 @@
{{ ansible_managed | comment }}
# MariaDB database server configuration file.
#
# You can copy this file to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port = 3306
socket = /run/mysqld/mysqld.sock
# Here is entries for some specific programs
# The following values assume you have at least 32M ram
# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket = /run/mysqld/mysqld.sock
nice = 0
[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /run/mysqld/mysqld.pid
socket = /run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc_messages_dir = /usr/share/mysql
lc_messages = en_US
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
# don't resolve connection IPs to hostnames (make sure user accounts are using
# IPs instead of "localhost")
skip-name-resolve=1
#
# * Fine Tuning
#
max_connections = {{ max_connections }}
connect_timeout = 5
wait_timeout = 600
max_allowed_packet = 16M
thread_cache_size = 128
sort_buffer_size = 4M
bulk_insert_buffer_size = 16M
tmp_table_size = {{ tmp_table_size }}
max_heap_table_size = {{ max_heap_table_size }}
#
# * MyISAM
#
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched. On error, make copy and try a repair.
myisam_recover_options = BACKUP
key_buffer_size = {{ key_buffer_size }}
#open-files-limit = 2000
table_open_cache = 400
myisam_sort_buffer_size = 512M
concurrent_insert = 2
read_buffer_size = 2M
read_rnd_buffer_size = 1M
#
# * Query Cache Configuration
#
query_cache_limit = 128K
query_cache_size = {{ query_cache_size }}
query_cache_type = {{ query_cache_type }}
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf.
#
# we do want to know about network errors and such
log_warnings = 2
#
# Enable the slow query log to see queries with especially long duration
#slow_query_log[={0|1}]
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time = 10
#log_slow_rate_limit = 1000
log_slow_verbosity = query_plan
#log-queries-not-using-indexes
#log_slow_admin_statements
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#server-id = 1
#report_host = master1
#auto_increment_increment = 2
#auto_increment_offset = 1
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
# not fab for performance, but safer
#sync_binlog = 1
expire_logs_days = 10
max_binlog_size = 100M
# slaves
#relay_log = /var/log/mysql/relay-bin
#relay_log_index = /var/log/mysql/relay-bin.index
#relay_log_info_file = /var/log/mysql/relay-bin.info
#log_slave_updates
#read_only
#
# If applications support it, this stricter sql_mode prevents some
# mistakes like inserting invalid dates etc.
#sql_mode = NO_ENGINE_SUBSTITUTION,TRADITIONAL
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
default_storage_engine = InnoDB
# you can't just change log file size, requires special procedure
#innodb_log_file_size = 50M
innodb_buffer_pool_size = {{ innodb_buffer_pool_size }}
innodb_log_buffer_size = 8M
innodb_file_per_table = 1
innodb_open_files = 400
innodb_io_capacity = 400
innodb_flush_method = O_DIRECT
aria_pagecache_buffer_size = {{ aria_pagecache_buffer_size }}
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem
#
# * Galera-related settings
#
[galera]
# Mandatory settings
#wsrep_on=ON
#wsrep_provider=
#wsrep_cluster_address=
#binlog_format=row
#default_storage_engine=InnoDB
#innodb_autoinc_lock_mode=2
#
# Allow server to accept connections on all interfaces.
#
#bind-address=0.0.0.0
#
# Optional setting
#wsrep_slave_threads=1
#innodb_flush_log_at_trx_commit=0
[mysqldump]
quick
quote-names
max_allowed_packet = 16M
[mysql]
#no-auto-rehash # faster start of mysql but no tab completion
[isamchk]
key_buffer = 16M
#
# * IMPORTANT: Additional settings that can override those from this file!
# The files must end with '.cnf', otherwise they'll be ignored.
#
!include /etc/mysql/mariadb.cnf
!includedir /etc/mysql/conf.d/

View File

@@ -1,4 +1,4 @@
--- ---
# ansible.builtin.file: roles/munin/handlers/main.yml # ansible.builtin.file: roles/munin/handlers/main.yml
- name: restart munin-node - name: restart munin-node
ansible.builtin.systemd: name=munin-node state=restarted ansible.builtin.systemd_service: name=munin-node state=restarted

View File

@@ -1,16 +1,22 @@
--- ---
- name: Install munin-node - name: Install munin-node
ansible.builtin.apt: name=munin-node state=present ansible.builtin.apt:
name: munin-node
state: present
tags: packages tags: packages
# some nice things to have for munin-node on Ubuntu # some nice things to have for munin-node on Ubuntu
# libwww-perl: for munin's nginx_status check # libwww-perl: for munin's nginx_status check
- name: Install munin-node deps - name: Install munin-node deps
ansible.builtin.apt: name=libwww-perl state=present ansible.builtin.apt:
name: libwww-perl
state: present
tags: packages tags: packages
- name: Create munin-node.conf - name: Create munin-node.conf
ansible.builtin.template: src=munin-node.conf.j2 dest=/etc/munin/munin-node.conf ansible.builtin.template:
src: munin-node.conf.j2
dest: /etc/munin/munin-node.conf
notify: notify:
- restart munin-node - restart munin-node
@@ -20,6 +26,9 @@
- restart munin-node - restart munin-node
- name: Start munin-node - name: Start munin-node
ansible.builtin.systemd: name=munin-node state=started enabled=true ansible.builtin.systemd_service:
name: munin-node
state: started
enabled: true
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,9 +1,16 @@
--- ---
- name: Install munin package - name: Install munin package
ansible.builtin.apt: name=munin state=present ansible.builtin.apt:
name: munin
state: present
tags: packages tags: packages
- name: Create munin configuration file - name: Create munin configuration file
ansible.builtin.template: src=munin.conf.j2 dest=/etc/munin/munin.conf owner=root group=root mode=0644 ansible.builtin.template:
src: munin.conf.j2
dest: /etc/munin/munin.conf
owner: root
group: root
mode: "0644"
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -5,16 +5,16 @@
nginx_confd_path: /etc/nginx/conf.d nginx_confd_path: /etc/nginx/conf.d
# parent directory of vhost roots # parent directory of vhost roots
nginx_root_prefix: /var/www nginx_root_prefix: "{{ web_root_prefix }}"
# 1 hour timeout # 1 day timeout
nginx_ssl_session_timeout: 1h nginx_ssl_session_timeout: 1d
# 10MB -> 40,000 sessions # 10MB -> 40,000 sessions
nginx_ssl_session_cache: shared:SSL:10m nginx_ssl_session_cache: shared:SSL:10m
# 1400 bytes to fit in one MTU (default is 16k!) nginx_ssl_buffer_size: 4k
nginx_ssl_buffer_size: 1400
nginx_ssl_dhparam: /etc/ssl/certs/dhparam.pem nginx_ssl_dhparam: /etc/ssl/certs/dhparam.pem
nginx_ssl_protocols: TLSv1.2 TLSv1.3 nginx_ssl_protocols: TLSv1.2 TLSv1.3
nginx_ssl_ecdh_curve: X25519:prime256v1:secp384r1
# DNS resolvers for OCSP stapling (default to Cloudflare public DNS) # DNS resolvers for OCSP stapling (default to Cloudflare public DNS)
# See: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling # See: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling
@@ -37,8 +37,8 @@ letsencrypt_root: /etc/ssl
letsencrypt_acme_script_temp: /root/acme.sh letsencrypt_acme_script_temp: /root/acme.sh
letsencrypt_acme_home: /root/.acme.sh letsencrypt_acme_home: /root/.acme.sh
# stable is 1.20.x # stable is 1.26.x
# mainline is 1.21.x # mainline is 1.27.x
nginx_version: mainline nginx_version: mainline
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,5 +1,7 @@
--- ---
- name: reload nginx - name: Reload nginx
ansible.builtin.systemd: name=nginx state=reloaded ansible.builtin.systemd_service:
name: nginx
state: reloaded
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,7 +1,12 @@
--- ---
# Use acme.sh instead of certbot because they only support installation via # Use acme.sh instead of certbot because they only support installation via
# snap now. # snap now.
- block: - name: Install and configure Let's Encrypt
tags: letsencrypt
when:
- ansible_facts["distribution"] == 'Debian'
- ansible_facts["distribution_version"] is version('11', '>=')
block:
- name: Remove certbot - name: Remove certbot
ansible.builtin.apt: ansible.builtin.apt:
name: certbot name: certbot
@@ -21,31 +26,31 @@
register: acme_home register: acme_home
- name: Download acme.sh - name: Download acme.sh
when: not acme_home.stat.exists
ansible.builtin.get_url: ansible.builtin.get_url:
url: https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh url: https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh
dest: "{{ letsencrypt_acme_script_temp }}" dest: "{{ letsencrypt_acme_script_temp }}"
mode: "0700" mode: "0700"
register: acme_download register: acme_download
when: not acme_home.stat.exists
# Run the "install" for acme.sh so it creates the .acme.sh dir (currently I # Run the "install" for acme.sh so it creates the .acme.sh dir (currently I
# have to chdir to the /root directory where the script exists or else it # have to chdir to the /root directory where the script exists or else it
# fails. Ansible runs it, but the script can't find itself...). # fails. Ansible runs it, but the script can't find itself...).
- name: Install acme.sh - name: Install acme.sh
when: acme_download is changed
ansible.builtin.command: ansible.builtin.command:
cmd: "{{ letsencrypt_acme_script_temp }} --install --no-profile --no-cron" cmd: "{{ letsencrypt_acme_script_temp }} --install --no-profile --no-cron"
creates: "{{ letsencrypt_acme_home }}/acme.sh" creates: "{{ letsencrypt_acme_home }}/acme.sh"
chdir: /root chdir: /root
register: acme_install register: acme_install
when: acme_download is changed
- name: Remove temporary acme.sh script - name: Remove temporary acme.sh script
ansible.builtin.file:
dest: "{{ letsencrypt_acme_script_temp }}"
state: absent
when: when:
- acme_install.rc is defined - acme_install.rc is defined
- acme_install.rc == 0 - acme_install.rc == 0
ansible.builtin.file:
dest: "{{ letsencrypt_acme_script_temp }}"
state: absent
- name: Set default certificate authority for acme.sh - name: Set default certificate authority for acme.sh
ansible.builtin.command: ansible.builtin.command:
@@ -77,14 +82,10 @@
# always issues daemon-reload just in case the service/timer changed # always issues daemon-reload just in case the service/timer changed
- name: Start and enable systemd timer to renew Let's Encrypt certs - name: Start and enable systemd timer to renew Let's Encrypt certs
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: renew-letsencrypt.timer name: renew-letsencrypt.timer
state: started state: started
enabled: true enabled: true
daemon_reload: true daemon_reload: true
when: (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '==')) or (ansible_distribution == 'Debian' and ansible_distribution_version
is version('11', '>='))
tags: letsencrypt
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,12 +1,4 @@
--- ---
- name: Remove nginx apt signing key from apt-key
ansible.builtin.apt_key:
id: "053473772654754373614404074646527257655730117366337542"
state: absent
tags:
- packages
- nginx
- name: Download nginx apt signing key - name: Download nginx apt signing key
ansible.builtin.get_url: ansible.builtin.get_url:
url: https://nginx.org/keys/nginx_signing.key url: https://nginx.org/keys/nginx_signing.key
@@ -33,9 +25,9 @@
- packages - packages
- name: Update apt cache - name: Update apt cache
when: (download_nginx_signing_key.status_code is defined and download_nginx_signing_key.status_code == 200) or add_nginx_apt_repository is changed
ansible.builtin.apt: # noqa no-handler ansible.builtin.apt: # noqa no-handler
update_cache: true update_cache: true
when: (download_nginx_signing_key.status_code is defined and download_nginx_signing_key.status_code == 200) or add_nginx_apt_repository is changed
- name: Install nginx - name: Install nginx
ansible.builtin.apt: ansible.builtin.apt:
@@ -54,7 +46,7 @@
owner: root owner: root
group: root group: root
notify: notify:
- reload nginx - Reload nginx
tags: nginx tags: nginx
- name: Copy extra nginx configs - name: Copy extra nginx configs
@@ -68,7 +60,7 @@
- extra-security.conf - extra-security.conf
- fastcgi_cache - fastcgi_cache
notify: notify:
- reload nginx - Reload nginx
tags: nginx tags: nginx
- name: Remove default nginx vhost - name: Remove default nginx vhost
@@ -87,13 +79,13 @@
tags: nginx tags: nginx
- name: Configure nginx virtual hosts - name: Configure nginx virtual hosts
ansible.builtin.include_tasks: vhosts.yml
when: nginx_vhosts is defined when: nginx_vhosts is defined
ansible.builtin.include_tasks: vhosts.yml
tags: nginx tags: nginx
- name: Configure WordPress - name: Configure WordPress
ansible.builtin.include_tasks: wordpress.yml
when: nginx_vhosts is defined when: nginx_vhosts is defined
ansible.builtin.include_tasks: wordpress.yml
tags: wordpress tags: wordpress
- name: Configure blank nginx vhost - name: Configure blank nginx vhost
@@ -104,7 +96,7 @@
owner: root owner: root
group: root group: root
notify: notify:
- reload nginx - Reload nginx
tags: nginx tags: nginx
- name: Configure munin vhost - name: Configure munin vhost
@@ -115,11 +107,11 @@
owner: root owner: root
group: root group: root
notify: notify:
- reload nginx - Reload nginx
tags: nginx tags: nginx
- name: Start and enable nginx service - name: Start and enable nginx service
ansible.builtin.systemd: ansible.builtin.systemd_service:
name: nginx name: nginx
state: started state: started
enabled: true enabled: true

View File

@@ -1,16 +1,23 @@
--- ---
- block: - name: Configure https vhosts
tags: nginx
block:
- name: Configure https vhosts - name: Configure https vhosts
ansible.builtin.template: src=vhost.conf.j2 dest={{ nginx_confd_path }}/{{ item.domain_name }}.conf mode=0644 owner=root group=root ansible.builtin.template:
src: vhost.conf.j2
dest: "{{ nginx_confd_path }}/{{ item.domain_name }}.conf"
mode: "0644"
owner: root
group: root
loop: "{{ nginx_vhosts }}" loop: "{{ nginx_vhosts }}"
notify: notify:
- reload nginx - Reload nginx
- name: Generate self-signed TLS cert - name: Generate self-signed TLS cert
ansible.builtin.command: openssl req -x509 -nodes -sha256 -days 365 -subj "/C=SO/ST=SO/L=snakeoil/O=snakeoil/CN=snakeoil" -newkey rsa:2048 -keyout /etc/ssl/private/nginx-snakeoil.key ansible.builtin.command: openssl req -x509 -nodes -sha256 -days 365 -subj "/C=SO/ST=SO/L=snakeoil/O=snakeoil/CN=snakeoil" -newkey rsa:2048 -keyout /etc/ssl/private/nginx-snakeoil.key
-out /etc/ssl/certs/nginx-snakeoil.crt -extensions v3_ca creates=/etc/ssl/certs/nginx-snakeoil.crt -out /etc/ssl/certs/nginx-snakeoil.crt -extensions v3_ca creates=/etc/ssl/certs/nginx-snakeoil.crt
notify: notify:
- reload nginx - Reload nginx
- name: Download 4096-bit RFC 7919 dhparams - name: Download 4096-bit RFC 7919 dhparams
ansible.builtin.get_url: ansible.builtin.get_url:
@@ -18,12 +25,16 @@
checksum: sha256:64852d6890ff9e62eecd1ee89c72af9af244dfef5b853bcedea3dfd7aade22b3 checksum: sha256:64852d6890ff9e62eecd1ee89c72af9af244dfef5b853bcedea3dfd7aade22b3
dest: "{{ nginx_ssl_dhparam }}" dest: "{{ nginx_ssl_dhparam }}"
notify: notify:
- reload nginx - Reload nginx
# TODO: this could break because we can override the document root in host vars # TODO: this could break because we can override the document root in host vars
- name: Create vhost document roots - name: Create vhost document roots
ansible.builtin.file: path={{ nginx_root_prefix }}/{{ item.domain_name }} state=directory mode=0755 owner=nginx group=nginx ansible.builtin.file:
path: "{{ nginx_root_prefix }}/{{ item.domain_name }}"
state: directory
mode: "0755"
owner: nginx
group: nginx
loop: "{{ nginx_vhosts }}" loop: "{{ nginx_vhosts }}"
tags: nginx
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -1,19 +1,31 @@
--- ---
- block: - name: Install and configure WordPress
tags: wordpress
block:
- name: Install WordPress - name: Install WordPress
ansible.builtin.git: repo=https://github.com/WordPress/WordPress.git dest={{ nginx_root_prefix }}/{{ item.domain_name }}/wordpress version={{ item.wordpress_version
}} depth=1 force=true
when: when:
- item.has_wordpress is defined - item.has_wordpress is defined
- item.has_wordpress - item.has_wordpress
ansible.builtin.git:
repo: https://github.com/WordPress/WordPress.git
dest: "{{ nginx_root_prefix }}/{{ item.domain_name }}/wordpress"
version: "{{ item.wordpress_version }}"
depth: 1
force: true
loop: "{{ nginx_vhosts }}" loop: "{{ nginx_vhosts }}"
become: true
become_user: nginx
- name: Fix WordPress directory permissions - name: Fix WordPress directory permissions
ansible.builtin.file: path={{ nginx_root_prefix }}/{{ item.domain_name }} state=directory owner=nginx group=nginx recurse=true
when: when:
- item.has_wordpress is defined - item.has_wordpress is defined
- item.has_wordpress - item.has_wordpress
ansible.builtin.file:
path: "{{ nginx_root_prefix }}/{{ item.domain_name }}"
state: directory
owner: nginx
group: nginx
recurse: true
loop: "{{ nginx_vhosts }}" loop: "{{ nginx_vhosts }}"
tags: wordpress
# vim: set ts=2 sw=2: # vim: set ts=2 sw=2:

View File

@@ -11,9 +11,11 @@ server {
return 444; return 444;
} }
server { server {
listen 443 ssl http2 default_server; listen 443 ssl default_server;
listen [::]:443 ssl http2 default_server; listen [::]:443 ssl default_server;
http2 on;
server_name _; server_name _;
# self-signed "snakeoil" certificate # self-signed "snakeoil" certificate

View File

@@ -27,8 +27,9 @@
ssl_dhparam {{ nginx_ssl_dhparam }}; ssl_dhparam {{ nginx_ssl_dhparam }};
ssl_protocols {{ nginx_ssl_protocols }}; ssl_protocols {{ nginx_ssl_protocols }};
ssl_ecdh_curve {{ nginx_ssl_ecdh_curve }};
ssl_ciphers "{{ tls_cipher_suite }}"; ssl_ciphers "{{ tls_cipher_suite }}";
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers off;
{# OSCP stapling only works with real certs #} {# OSCP stapling only works with real certs #}
{% if use_letsencrypt == true or item.tls_certificate_path %} {% if use_letsencrypt == true or item.tls_certificate_path %}
@@ -38,15 +39,6 @@
resolver {{ nginx_ssl_stapling_resolver }}; resolver {{ nginx_ssl_stapling_resolver }};
{% endif %} {# end: use_letsencrypt #} {% endif %} {# end: use_letsencrypt #}
# nginx does not auto-rotate session ticket keys: only a HUP / restart will do so and
# when a restart is performed the previous key is lost, which resets all previous
# sessions. The fix for this is to setup a manual rotation mechanism:
# http://trac.nginx.org/nginx/changeset/1356a3b9692441e163b4e78be4e9f5a46c7479e9/nginx
#
# Note that you'll have to define and rotate the keys securely by yourself. In absence
# of such infrastructure, consider turning off session tickets:
ssl_session_tickets off;
{% if enable_hsts == true %} {% if enable_hsts == true %}
# Enable this if you want HSTS (recommended, but be careful) # Enable this if you want HSTS (recommended, but be careful)
# Include all subdomains and indicate to Google that we want this pre-loaded in Chrome's HSTS store # Include all subdomains and indicate to Google that we want this pre-loaded in Chrome's HSTS store

View File

@@ -14,7 +14,6 @@ error_log /var/log/nginx/error.log warn;
# The file storing the process ID of the main process # The file storing the process ID of the main process
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
events { events {
# If you need more connections than this, you start optimizing your OS. # If you need more connections than this, you start optimizing your OS.
# That's probably the point at which you hire people who are smarter than you as this is *a lot* of requests. # That's probably the point at which you hire people who are smarter than you as this is *a lot* of requests.
@@ -23,6 +22,7 @@ events {
} }
http { http {
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
default_type application/octet-stream; default_type application/octet-stream;

View File

@@ -1,19 +1,7 @@
{{ ansible_managed | comment }} {{ ansible_managed | comment }}
{% if ansible_distribution == 'Ubuntu' %}
{% if nginx_version == "stable" %} {% if nginx_version == "stable" %}
deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/ubuntu/ {{ ansible_distribution_release }} nginx deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/debian/ {{ ansible_facts["distribution_release"] }} nginx
{% elif nginx_version == "mainline" %} {% elif nginx_version == "mainline" %}
deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/mainline/ubuntu/ {{ ansible_distribution_release }} nginx deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/mainline/debian/ {{ ansible_facts["distribution_release"] }} nginx
{% endif %}
{% elif ansible_distribution == 'Debian' %}
{% if nginx_version == "stable" %}
deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/debian/ {{ ansible_distribution_release }} nginx
{% elif nginx_version == "mainline" %}
deb [arch=amd64 signed-by=/usr/share/keyrings/nginx_signing.key] https://nginx.org/packages/mainline/debian/ {{ ansible_distribution_release }} nginx
{% endif %}
{% endif %} {% endif %}

View File

@@ -8,6 +8,12 @@
{% set has_wordpress = item.has_wordpress | default(false) %} {% set has_wordpress = item.has_wordpress | default(false) %}
{% set needs_php = item.needs_php | default(false) %} {% set needs_php = item.needs_php | default(false) %}
{% set has_gitea = item.has_gitea | default(false) %} {% set has_gitea = item.has_gitea | default(false) %}
{# Allow sites to override the document root #}
{% if item.document_root is defined %}
{% set document_root = item.document_root %}
{% else %}
{% set document_root = (nginx_root_prefix, domain_name) | ansible.builtin.path_join %}
{% endif %}
# http -> https vhost # http -> https vhost
server { server {
@@ -26,15 +32,11 @@ server {
} }
server { server {
listen 443 ssl http2; listen 443 ssl;
listen [::]:443 ssl http2; listen [::]:443 ssl;
http2 on;
{# Allow sites to override the nginx document root #} root {{ document_root }};
{% if item.document_root is defined %}
root {{ item.document_root }};
{% else %}
root {{ nginx_root_prefix }}/{{ domain_name }};
{% endif %}
{# will only work if the TLS cert covers the domain + aliases, like example.com and www.example.com #} {# will only work if the TLS cert covers the domain + aliases, like example.com and www.example.com #}
server_name {{ domain_name }} {{ domain_aliases }}; server_name {{ domain_name }} {{ domain_aliases }};
@@ -75,12 +77,8 @@ server {
# See: https://httpoxy.org/ # See: https://httpoxy.org/
fastcgi_param HTTP_PROXY ""; fastcgi_param HTTP_PROXY "";
{% if ansible_distribution == 'Debian' and ansible_distribution_major_version is version('12', '==') %} {% if ansible_facts["distribution_major_version"] is version('12', '==') %}
fastcgi_pass unix:/run/php/php8.2-fpm-{{ domain_name }}.sock; fastcgi_pass unix:/run/php/php8.2-fpm-{{ domain_name }}.sock;
{% elif (ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '==')) or (ansible_distribution == 'Debian' and ansible_distribution_major_version is version('11', '==')) %}
fastcgi_pass unix:/run/php/php7.4-fpm-{{ domain_name }}.sock;
{% else %}
fastcgi_pass unix:/var/run/php5-fpm-{{ domain_name }}.sock;
{% endif %} {% endif %}
fastcgi_index index.php; fastcgi_index index.php;
# set script path relative to document root in server block # set script path relative to document root in server block

View File

@@ -1,12 +0,0 @@
---
# For Ubuntu 20.04 and Debian 11
- name: reload php7.4-fpm
ansible.builtin.systemd: name=php7.4-fpm state=reloaded
# For Debian 12
- name: reload php8.2-fpm
ansible.builtin.systemd:
name: php8.2-fpm
state: reloaded
# vim: set ts=2 sw=2:

View File

@@ -1,50 +0,0 @@
---
- block:
- name: Set php-fpm packages
ansible.builtin.set_fact:
php_fpm_packages:
- php8.2-fpm
# for WordPress
- php8.2-mysql
- php8.2-gd
- php8.2-curl
- php8.2-xml
- name: Install php-fpm and deps
ansible.builtin.apt:
name: "{{ php_fpm_packages }}"
state: present
update_cache: true
# only copy php-fpm config for vhosts that need WordPress or PHP
- name: Copy php-fpm pool config
ansible.builtin.template:
src: php8.2-pool.conf.j2
dest: /etc/php/8.2/fpm/pool.d/{{ item.domain_name }}.conf
owner: root
group: root
mode: "0644"
loop: "{{ nginx_vhosts }}"
when: (item.has_wordpress is defined and item.has_wordpress) or (item.needs_php is defined and item.needs_php)
notify: reload php8.2-fpm
- name: Remove default www pool
ansible.builtin.file:
path: /etc/php/8.2/fpm/pool.d/www.conf
state: absent
notify: reload php8.2-fpm
# re-configure php.ini
- name: Update php.ini
ansible.builtin.template:
src: php8.2-php.ini.j2
dest: /etc/php/8.2/fpm/php.ini
owner: root
group: root
mode: "0644"
notify: reload php8.2-fpm
tags: php-fpm
when: install_php
# vim: set ts=2 sw=2:

View File

@@ -1,35 +0,0 @@
---
- block:
- name: Set php-fpm packages
ansible.builtin.set_fact:
php_fpm_packages:
- php7.4-fpm
# for WordPress
- php7.4-mysql
- php7.4-gd
- php7.4-curl
- php7.4-xml
- name: Install php-fpm and deps
ansible.builtin.apt: name={{ php_fpm_packages }} state=present update_cache=true
# only copy php-fpm config for vhosts that need WordPress or PHP
- name: Copy php-fpm pool config
ansible.builtin.template: src=php7.4-pool.conf.j2 dest=/etc/php/7.4/fpm/pool.d/{{ item.domain_name }}.conf owner=root group=root mode=0644
loop: "{{ nginx_vhosts }}"
when: (item.has_wordpress is defined and item.has_wordpress) or (item.needs_php is defined and item.needs_php)
notify: reload php7.4-fpm
- name: Remove default www pool
ansible.builtin.file: path=/etc/php/7.4/fpm/pool.d/www.conf state=absent
notify: reload php7.4-fpm
# re-configure php.ini
- name: Update php.ini
ansible.builtin.template: src=php7.4-php.ini.j2 dest=/etc/php/7.4/fpm/php.ini owner=root group=root mode=0644
notify: reload php7.4-fpm
tags: php-fpm
when: install_php
# vim: set ts=2 sw=2:

View File

@@ -1,53 +0,0 @@
---
# Ubuntu 20.04 uses PHP 7.4
# Debian 11 uses PHP 7.4
# Debian 12 uses PHP 8.2
# If any of the vhosts on this host need WordPress then we need to install PHP.
# This uses selectattr to filter the list of dicts in nginx_vhosts, selecting
# any that have has_wordpress defined, and has_wordpress set to true.
#
# See: https://stackoverflow.com/a/31896249
- name: Check if any vhost needs WordPress
ansible.builtin.set_fact:
install_php: true
when: nginx_vhosts | selectattr('has_wordpress', 'defined') | selectattr('has_wordpress', 'equalto', true) | list | length > 0
# Legacy, was only for Piwik, but leaving for now.
- name: Check if any vhost needs PHP
ansible.builtin.set_fact:
install_php: true
when: nginx_vhosts | selectattr('needs_php', 'defined') | selectattr('needs_php', 'equalto', true) | list | length > 0
# If install_php has not been set, then we assume no vhosts need PHP. This is
# a bit hacky, but it's the closest we come to an if/then/else.
- name: Set install_php to false
ansible.builtin.set_fact:
install_php: false
when: install_php is not defined
- name: Configure php-fpm on Ubuntu 20.04
ansible.builtin.include_tasks: Ubuntu_20.04.yml
when:
- ansible_distribution == 'Ubuntu'
- ansible_distribution_version is version('20.04', '==')
- install_php
tags: php-fpm
- name: Configure php-fpm on Debian 11
ansible.builtin.include_tasks: Ubuntu_20.04.yml
when:
- ansible_distribution == 'Debian'
- ansible_distribution_major_version is version('11', '==')
- install_php
tags: php-fpm
- name: Configure php-fpm on Debian 12
ansible.builtin.include_tasks: Debian_12.yml
when:
- ansible_distribution == 'Debian'
- ansible_distribution_major_version is version('12', '==')
- install_php
tags: php-fpm
# vim: set ts=2 sw=2:

View File

@@ -0,0 +1,14 @@
---
# For Debian 12
- name: Reload php8.2-fpm
ansible.builtin.systemd_service:
name: php8.2-fpm
state: reloaded
# For Debian 13
- name: Reload php8.4-fpm
ansible.builtin.systemd_service:
name: php8.4-fpm
state: reloaded
# vim: set ts=2 sw=2:

View File

@@ -0,0 +1,90 @@
---
# Debian 12 uses PHP 8.2
# Debian 13 uses PHP 8.4
# If any of the vhosts on this host need WordPress then we need to install PHP.
# This uses selectattr to filter the list of dicts in nginx_vhosts, selecting
# any that have has_wordpress defined, and has_wordpress set to true.
#
# See: https://stackoverflow.com/a/31896249
- name: Check if any vhost needs WordPress
ansible.builtin.set_fact:
install_php: true
when: nginx_vhosts | selectattr('has_wordpress', 'defined') | selectattr('has_wordpress', 'equalto', true) | list | length > 0
# Legacy, was only for Piwik, but leaving for now.
- name: Check if any vhost needs PHP
ansible.builtin.set_fact:
install_php: true
when: nginx_vhosts | selectattr('needs_php', 'defined') | selectattr('needs_php', 'equalto', true) | list | length > 0
# If install_php has not been set, then we assume no vhosts need PHP. This is
# a bit hacky, but it's the closest we come to an if/then/else.
- name: Set install_php to false
ansible.builtin.set_fact:
install_php: false
when: install_php is not defined
- name: Install and configure php-fpm
tags: php-fpm
when: install_php
block:
- name: Set php-fpm packages
ansible.builtin.set_fact:
php_fpm_packages:
- php-fpm
# for WordPress
- php-mysql
- php-gd
- php-curl
- php-xml
- name: Install php-fpm and deps
ansible.builtin.apt:
name: "{{ php_fpm_packages }}"
state: present
update_cache: true
- name: Set PHP version for Debian 12
when:
- ansible_facts["distribution"] == 'Debian'
- ansible_facts["distribution_major_version"] is version('12', '==')
ansible.builtin.set_fact:
php_version: 8.2
- name: Set PHP version for Debian 13
when:
- ansible_facts["distribution"] == 'Debian'
- ansible_facts["distribution_major_version"] is version('13', '==')
ansible.builtin.set_fact:
php_version: 8.4
# only copy php-fpm config for vhosts that need WordPress or PHP
- name: Copy php-fpm pool config
ansible.builtin.template:
src: php{{ php_version }}-pool.conf.j2
dest: /etc/php/{{ php_version }}/fpm/pool.d/{{ item.domain_name }}.conf
owner: root
group: root
mode: "0644"
loop: "{{ nginx_vhosts }}"
when: (item.has_wordpress is defined and item.has_wordpress) or (item.needs_php is defined and item.needs_php)
notify: Reload php{{ php_version }}-fpm
- name: Remove default www pool
ansible.builtin.file:
path: /etc/php/{{ php_version }}/fpm/pool.d/www.conf
state: absent
notify: Reload php{{ php_version }}-fpm
# re-configure php.ini
- name: Update php.ini
ansible.builtin.template:
src: php{{ php_version }}-php.ini.j2
dest: /etc/php/{{ php_version }}/fpm/php.ini
owner: root
group: root
mode: "0644"
notify: Reload php{{ php_version }}-fpm
# vim: set ts=2 sw=2:

View File

@@ -27,8 +27,8 @@
; --allow-to-run-as-root option to work. ; --allow-to-run-as-root option to work.
; Default Values: The user is set to master process running user by default. ; Default Values: The user is set to master process running user by default.
; If the group is not set, the user's group is used. ; If the group is not set, the user's group is used.
user = nginx user = {{ webserver }}
group = nginx group = {{ webserver }}
; The address on which to accept FastCGI requests. ; The address on which to accept FastCGI requests.
; Valid syntaxes are: ; Valid syntaxes are:
@@ -52,8 +52,8 @@ listen = /run/php/php8.2-fpm-{{ domain_name }}.sock
; and group can be specified either by name or by their numeric IDs. ; and group can be specified either by name or by their numeric IDs.
; Default Values: Owner is set to the master process running user. If the group ; Default Values: Owner is set to the master process running user. If the group
; is not set, the owner's group is used. Mode is set to 0660. ; is not set, the owner's group is used. Mode is set to 0660.
listen.owner = nginx listen.owner = {{ webserver }}
listen.group = nginx listen.group = {{ webserver }}
;listen.mode = 0660 ;listen.mode = 0660
; When POSIX Access Control Lists are supported you can set them using ; When POSIX Access Control Lists are supported you can set them using

View File

@@ -19,11 +19,16 @@
; Default Value: none ; Default Value: none
;prefix = /path/to/pools/$pool ;prefix = /path/to/pools/$pool
; Unix user/group of processes ; Unix user/group of the child processes. This can be used only if the master
; Note: The user is mandatory. If the group is not set, the default user's group ; process running user is root. It is set after the child process is created.
; will be used. ; The user and group can be specified either by their name or by their numeric
user = nginx ; IDs.
group = nginx ; Note: If the user is root, the executable needs to be started with
; --allow-to-run-as-root option to work.
; Default Values: The user is set to master process running user by default.
; If the group is not set, the user's group is used.
user = {{ webserver }}
group = {{ webserver }}
; The address on which to accept FastCGI requests. ; The address on which to accept FastCGI requests.
; Valid syntaxes are: ; Valid syntaxes are:
@@ -35,20 +40,22 @@ group = nginx
; (IPv6 and IPv4-mapped) on a specific port; ; (IPv6 and IPv4-mapped) on a specific port;
; '/path/to/unix/socket' - to listen on a unix socket. ; '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory. ; Note: This value is mandatory.
listen = /run/php/php7.4-fpm-{{ domain_name }}.sock listen = /run/php/php8.2-fpm-{{ domain_name }}.sock
; Set listen(2) backlog. ; Set listen(2) backlog.
; Default Value: 511 (-1 on FreeBSD and OpenBSD) ; Default Value: 511 (-1 on Linux, FreeBSD and OpenBSD)
;listen.backlog = 511 ;listen.backlog = 511
; Set permissions for unix socket, if one is used. In Linux, read/write ; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many ; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. ; BSD-derived systems allow connections regardless of permissions. The owner
; Default Values: user and group are set as the running user ; and group can be specified either by name or by their numeric IDs.
; mode is set to 0660 ; Default Values: Owner is set to the master process running user. If the group
listen.owner = nginx ; is not set, the owner's group is used. Mode is set to 0660.
listen.group = nginx listen.owner = {{ webserver }}
listen.group = {{ webserver }}
;listen.mode = 0660 ;listen.mode = 0660
; When POSIX Access Control Lists are supported you can set them using ; When POSIX Access Control Lists are supported you can set them using
; these options, value is a comma separated list of user/group names. ; these options, value is a comma separated list of user/group names.
; When set, listen.owner and listen.group are ignored ; When set, listen.owner and listen.group are ignored
@@ -63,6 +70,10 @@ listen.group = nginx
; Default Value: any ; Default Value: any
;listen.allowed_clients = 127.0.0.1 ;listen.allowed_clients = 127.0.0.1
; Set the associated the route table (FIB). FreeBSD only
; Default Value: -1
;listen.setfib = 1
; Specify the nice(2) priority to apply to the pool processes (only if set) ; Specify the nice(2) priority to apply to the pool processes (only if set)
; The value can vary from -19 (highest priority) to 20 (lower priority) ; The value can vary from -19 (highest priority) to 20 (lower priority)
; Note: - It will only work if the FPM master process is launched as root ; Note: - It will only work if the FPM master process is launched as root
@@ -71,8 +82,9 @@ listen.group = nginx
; Default Value: no set ; Default Value: no set
; process.priority = -19 ; process.priority = -19
; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user ; Set the process dumpable flag (PR_SET_DUMPABLE prctl for Linux or
; or group is differrent than the master process user. It allows to create process ; PROC_TRACE_CTL procctl for FreeBSD) even if the process user
; or group is different than the master process user. It allows to create process
; core dump and ptrace the process for the pool user. ; core dump and ptrace the process for the pool user.
; Default Value: no ; Default Value: no
; process.dumpable = yes ; process.dumpable = yes
@@ -94,6 +106,8 @@ listen.group = nginx
; state (waiting to process). If the number ; state (waiting to process). If the number
; of 'idle' processes is greater than this ; of 'idle' processes is greater than this
; number then some children will be killed. ; number then some children will be killed.
; pm.max_spawn_rate - the maximum number of rate to spawn child
; processes at once.
; ondemand - no children are created at startup. Children will be forked when ; ondemand - no children are created at startup. Children will be forked when
; new requests will connect. The following parameter are used: ; new requests will connect. The following parameter are used:
; pm.max_children - the maximum number of children that ; pm.max_children - the maximum number of children that
@@ -129,6 +143,12 @@ pm.min_spare_servers = 1
; Note: Mandatory when pm is set to 'dynamic' ; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 3 pm.max_spare_servers = 3
; The number of rate to spawn child processes at once.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
; Default Value: 32
;pm.max_spawn_rate = 32
; The number of seconds after which an idle process will be killed. ; The number of seconds after which an idle process will be killed.
; Note: Used only when pm is set to 'ondemand' ; Note: Used only when pm is set to 'ondemand'
; Default Value: 10s ; Default Value: 10s
@@ -141,7 +161,7 @@ pm.max_spare_servers = 3
;pm.max_requests = 500 ;pm.max_requests = 500
; The URI to view the FPM status page. If this value is not set, no URI will be ; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. It shows the following informations: ; recognized as a status page. It shows the following information:
; pool - the name of the pool; ; pool - the name of the pool;
; process manager - static, dynamic or ondemand; ; process manager - static, dynamic or ondemand;
; start time - the date and time FPM has started; ; start time - the date and time FPM has started;
@@ -211,8 +231,8 @@ pm.max_spare_servers = 3
; it's always 0 if the process is not in Idle state ; it's always 0 if the process is not in Idle state
; because memory calculation is done when the request ; because memory calculation is done when the request
; processing has terminated; ; processing has terminated;
; If the process is in Idle state, then informations are related to the ; If the process is in Idle state, then information is related to the
; last request the process has served. Otherwise informations are related to ; last request the process has served. Otherwise information is related to
; the current request being served. ; the current request being served.
; Example output: ; Example output:
; ************************ ; ************************
@@ -231,7 +251,7 @@ pm.max_spare_servers = 3
; last request memory: 0 ; last request memory: 0
; ;
; Note: There is a real-time FPM status monitoring sample web page available ; Note: There is a real-time FPM status monitoring sample web page available
; It's available in: /usr/share/php/7.4/fpm/status.html ; It's available in: /usr/share/php/8.4/fpm/status.html
; ;
; Note: The value must start with a leading slash (/). The value can be ; Note: The value must start with a leading slash (/). The value can be
; anything, but it may not be a good idea to use the .php extension or it ; anything, but it may not be a good idea to use the .php extension or it
@@ -239,6 +259,22 @@ pm.max_spare_servers = 3
; Default Value: not set ; Default Value: not set
;pm.status_path = /status ;pm.status_path = /status
; The address on which to accept FastCGI status request. This creates a new
; invisible pool that can handle requests independently. This is useful
; if the main pool is busy with long running requests because it is still possible
; to get the status before finishing the long running requests.
;
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
; a specific port;
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
; a specific port;
; 'port' - to listen on a TCP socket to all addresses
; (IPv6 and IPv4-mapped) on a specific port;
; '/path/to/unix/socket' - to listen on a unix socket.
; Default Value: value of the listen option
;pm.status_listen = 127.0.0.1:9001
; The ping URI to call the monitoring page of FPM. If this value is not set, no ; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside ; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to ; that FPM is alive and responding, or to
@@ -271,13 +307,13 @@ pm.max_spare_servers = 3
; %d: time taken to serve the request ; %d: time taken to serve the request
; it can accept the following format: ; it can accept the following format:
; - %{seconds}d (default) ; - %{seconds}d (default)
; - %{miliseconds}d ; - %{milliseconds}d
; - %{mili}d ; - %{milli}d
; - %{microseconds}d ; - %{microseconds}d
; - %{micro}d ; - %{micro}d
; %e: an environment variable (same as $_ENV or $_SERVER) ; %e: an environment variable (same as $_ENV or $_SERVER)
; it must be associated with embraces to specify the name of the env ; it must be associated with embraces to specify the name of the env
; variable. Some exemples: ; variable. Some examples:
; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e ; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e ; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
; %f: script filename ; %f: script filename
@@ -306,14 +342,30 @@ pm.max_spare_servers = 3
; %s: status (response code) ; %s: status (response code)
; %t: server time the request was received ; %t: server time the request was received
; it can accept a strftime(3) format: ; it can accept a strftime(3) format:
; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag ; The strftime(3) format must be encapsulated in a %{<strftime_format>}t tag
; %T: time the log has been written (the request has finished) ; %T: time the log has been written (the request has finished)
; it can accept a strftime(3) format: ; it can accept a strftime(3) format:
; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag ; The strftime(3) format must be encapsulated in a %{<strftime_format>}t tag
; %u: remote user ; %u: basic auth user if specified in Authorization header
; ;
; Default: "%R - %u %t \"%m %r\" %s" ; Default: "%R - %u %t \"%m %r\" %s"
;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" ;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%"
; A list of request_uri values which should be filtered from the access log.
;
; As a security precaution, this setting will be ignored if:
; - the request method is not GET or HEAD; or
; - there is a request body; or
; - there are query parameters; or
; - the response code is outwith the successful range of 200 to 299
;
; Note: The paths are matched against the output of the access.format tag "%r".
; On common configurations, this may look more like SCRIPT_NAME than the
; expected pre-rewrite URI.
;
; Default Value: not set
;access.suppress_path[] = /ping
;access.suppress_path[] = /health_check.php
; The log file for slow requests ; The log file for slow requests
; Default Value: not set ; Default Value: not set
@@ -372,7 +424,7 @@ pm.max_spare_servers = 3
; Redirect worker stdout and stderr into main error log. If not set, stdout and ; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs. ; stderr will be redirected to /dev/null according to FastCGI specs.
; Note: on highloaded environement, this can cause some delay in the page ; Note: on highloaded environment, this can cause some delay in the page
; process time (several ms). ; process time (several ms).
; Default Value: no ; Default Value: no
;catch_workers_output = yes ;catch_workers_output = yes

View File

@@ -1,10 +0,0 @@
---
# sshd service name is `ssh` on Debian/Ubuntu, but it's
# `sshd` on CentOS
sshd_service_name: ssh
# provisioning user vars
provisioning_user: { name: 'provisioning', home: '/home/provisioning' }
# vim: set ts=2 sw=2:

View File

@@ -9,7 +9,7 @@
- { role: mariadb, when: mariadb_databases is defined} - { role: mariadb, when: mariadb_databases is defined}
- { role: nginx, when: webserver is defined and webserver == 'nginx' } - { role: nginx, when: webserver is defined and webserver == 'nginx' }
- { role: caddy, when: webserver is defined and webserver == 'caddy' } - { role: caddy, when: webserver is defined and webserver == 'caddy' }
- php-fpm - php_fpm
- munin - munin
vars_files: vars_files:
- vars/ipsets.yml - vars/ipsets.yml