feat: Cloudflare DNS-01 ACME + Docker hardening + sysctl
Some checks failed
CI/CD / syntax-check (push) Successful in 42s
CI/CD / deploy (push) Failing after 52s

Cloudflare DNS-01 ACME:
- Switch Traefik cert resolver from httpChallenge to dnsChallenge
  using Cloudflare provider (resolvers: 1.1.1.1, 1.0.0.1)
- Add CLOUDFLARE_DNS_API_TOKEN env to Traefik container
- Add CF_ZONE_ID + cloudflare_dns_api_token to all/main.yml
- Store API token in Ansible Vault

Docker daemon hardening:
- Add log-driver: json-file with max-size 10m / max-file 3
  (prevents disk fill from unbounded container logs)
- Add live-restore: true (containers survive Docker daemon restart)

Kernel hardening (sysctl):
- New roles/base/tasks/sysctl.yml via ansible.posix.sysctl
- IP spoofing protection (rp_filter)
- Disable ICMP redirects and broadcast pings
- SYN flood protection (syncookies, backlog)
- Disable IPv6 (not used)
- Restrict kernel pointers and dmesg to root
- Disable SysRq, suid core dumps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jack 2026-03-22 04:06:46 +07:00
parent e935c897c6
commit fccbd1a45a
11 changed files with 211 additions and 84 deletions

View file

@ -37,6 +37,8 @@ authelia_admin_password_hash: "{{ vault_authelia_admin_password_hash }}"
crowdsec_bouncer_key: "{{ vault_crowdsec_bouncer_key }}" crowdsec_bouncer_key: "{{ vault_crowdsec_bouncer_key }}"
s3_access_key: "{{ vault_s3_access_key }}" s3_access_key: "{{ vault_s3_access_key }}"
s3_secret_key: "{{ vault_s3_secret_key }}" s3_secret_key: "{{ vault_s3_secret_key }}"
cloudflare_dns_api_token: "{{ vault_cloudflare_dns_api_token }}"
cloudflare_zone_id: "0935215d596a24a10866a81409ed8332"
# CI/CD deploy key (public key — not a secret) # CI/CD deploy key (public key — not a secret)
ci_deploy_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHdr9mRSSUqt7Ym4wA5RpVyz76wEXSOtVfh2/yCSMIbg ci-deploy@forgejo-runner" ci_deploy_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHdr9mRSSUqt7Ym4wA5RpVyz76wEXSOtVfh2/yCSMIbg ci-deploy@forgejo-runner"

View file

@ -1,81 +1,86 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
63316565343636313366333436653062386233326239633136353033363861393962376563373538 61346166346534303931326332346432356137343133353337656364356530626562373464613939
6537376663323364316532303237666231373665613036370a653633333035336334333937313839 3233386137316337616638313738383030383534343161330a646337613536633961393064353538
34396166613565646561373237636331363039336539656136363031353466643437626535626235 30653634343031363063373866323634316638333233346231356465326339336337303266353637
3835373662616135660a316533373034626239393465366331633237336238366163633136376561 3235636435363631620a386337653334633132656430323166313436626565646662346165646366
39353333323932366464653363653063643037323861343163386331306337643266353762626665 33646439653033366334343330643235336531326333376230653435333430313733353164323564
64396366626333356135373161636239653434353939636365336235646533613336343438373939 62326665346162373265373462666332383366396534316466613935663531643661366464353137
37633037333035346134356664326135646531616266376439303965313432316638336138666161 64663430666237333930316630393637373239336533313364643034633335303963343661633438
64636234373839356362326363383437616265653934656665386231383662316136363164363631 65613630383436313761653738633831636333613962343535643966316164623931346337613338
38393163656639343561636334326133646336383733633966316536323933356236616336333465 31333638326630636430336266643238663665653332616536363535633966643836666434303464
38633365636363363237323232303064353232313030653132393439616462653736346665376165 38383366383232646434343333373836613934633964383362653134613466383932613264616632
64663139396664363561386536643862653766343066363565336261646338323935663564376261 37356130313363633438626238383463356431386539366465363965663332323462626530366166
35373833343563373731623136326666636165346564663133363763396231306665393536656566 65373838393436313633613333306639636165336633393533333063633539313538626436386535
37393431626565396632353931373161326139646537643865336333353462326438666131633636 33636630633366376138386532346664373535333932646335353638613364363433643034653733
38373463666539346230323437616135353166356331643962633537386364623265616239666235 36376136383833363236343538633464396438373862666238623536643366353632343363646130
62336337643562363738323133353339326435333262623563383939626463636434346435343862 66373635323437326530316432666236626239353963616364633266393432636264646466373261
35353366646635383738313561623366363736656465373665663663313632313132316665626635 62626433396133383335363163313136383238633663373336663562326331333933313963303432
35613134313738653165323536326330336539323964316463636630386637353565366464373861 38663365333830356534323532316431616565653638643261646139343662386436663334303234
33376364626633653937386137623936626663326638366235313637363561316265346632353633 33396136373539376238393837363536636565666535636333366430346633323638303962636431
66616334656665663032646663306364303461343163653966633335633039643332343365343630 65326633653161623462656261303036346433383837396436306430396234623964646662666166
32353837643930306534366233366234656436613730356632393466623636623263353139666664 61613432333330313563666133343664333965663465616232633735303032623462653639616461
39623835613935666665393235353234343962623531316633343865313331363337326630383932 30393465373339623664613264383239393538616233653061376434643332336539636135616432
66393263313031346634646335373032633762336462663037656139616531363265666535616135 64363134303865636535353738326466623264643034633734653731623731653531333834363861
36326234303434663036656638393361656365353837386536363834623134353366316135353864 35623739326134623332353762613732666233383466323661323464316464656231663038613161
33346338326534323335366331636338623931333561316466343733656333366632326131303536 38353830643832656538386665376630613465386437303838653566646438613935666363386335
31623662626265323133363635326235363334356537646263643737373661373265306632656538 65343130353864616563353161653938653466316533346234383265643534333231633235316630
38343061623235336537346463653634333837613162303930376532643539386132326539303336 39326339653939653163316633303964303166663039353464666337626235653133333431643262
39333166643864633065653834653365666230393633303866653535376339613533313236396537 32373939313835363236646564636237616232636333636238376265643530356566313864333966
62343136386637623439353061323531646365393733633339353364666633346634363264353166 30386631626437633361326436356630373330303761326665373962376639626363323163316261
62643432653165373663663561653339643066393361333265376236663132653134373465366364 33623334623336393230663232313032663434303330376163633265356130623639303431333333
38616364636337383438663737316630346632353635303430356463343066363766363662333632 32363735366138363435383964623933323062386661656566656238613933346636383737383939
33363633343165663631373064353661666430343266373032373238663466313438313539343139 62353939383235656136383062663164393135626539393966373939666561313334643266333466
34386131393337346364656632653831626561623763333063366166636439313030316664333861 37356164363861626565326364396531626536636266333735663238626234306139306465643733
63643033666639393963626234666334663062346530313237333361303161363564346438306263 65316631343963643666626335363036336263646138373562386662343735346134313836383765
66666365373061306464643836626635323439386565386437646238373064383861353038643335 35306465613831633330616261653537613730613564313635353535366138316332353736373964
65366165353130613762633231393934346562643739666666353865386537376431336333623936 63663366613666306533343331623939383866303864656134343437643665636565356432386432
39363563656432333961303033643365663963663239396330306333376634323139383762373736 34643364393864373935623230343661666238636564376664373830303666343332613436346537
32643630623731356664616336616634353630303731643037313039666339633864323231646530 65363062353338323832653338643063613964653933313231393732343466373138396265663566
61663735653034656137346635323331616130333761623830393137376665356639363963656465 63653835336331373462653638323038383463633733646266653137646264613531363130353232
61303434303466626465656432613230396631363434393839366631306466353030306436663139 31376664303635336565653939613933363539653161343637363131646362343265383131373339
31383461393733666465393733343231313737303833636231636136316530613538623535396230 66353432623266616139643264373832636665386235333839663833613661346632663461356232
36323463306233393138643333663161636461343436646463346165323333323135666131326435 39656463383431663164393564646338356638336530373937366266353264376165643335366335
34656161303664626135616134396266376234343139366561303765323530366632393736353762 32633639633138626633656633376639366432363761323538383731666336313639646566623933
66666639376362366435353639353439663835613463613739643861376666383036326339396537 36326232626333613630356163313731323336313237646363616530303832363233343364313164
35303161363763326439613834633564646161666135613935383739383838346563643961323864 65356137653363313564343062396461653134346335616637346164356539393731636566356265
34633031306664643266623262363065303965336337386332613262646464653933343836336230 65636639633839633835393061393837376634306630646435613066613361396134656465343332
63333934643763383566653762666638643565386264653132313333663130616537346366656463 31623837323830316336383835393037336338383264366138646334326530633331353638376138
63653730613238663365613132303136353965653433386563393836393737646132666237656333 39393534363130316331376636663234383435656666653235613131363862396336636434393736
34663330323437653761663235653565363632393332313630316433313436343539663366343638 64616334643366643330643661623238323063333864303963316166396463613637653764356435
65346534623063343739326166613530633165383266623637653238623133663637626634306337 31633235376363303265386536303032393036333838366237303966626533626466653634643933
36653937393234353136383933323661306263346466613362363739653733373938633332303132 37626266653461336366326430306266643132343137396634323363623562366632323763623934
37383562643630323362303733316664386339653166626338316332353131653531646136626362 31343861643834303864663831623239616266653335616562316463626365623365373162653863
61646263663162313964343939643834363931346462313862633339313866363562613330666163 34326432613230333431643334653165366632353463613465653963353166353334663039316535
66383835323461663133343333303833333662643331633265343364663238393331383634326338 35373230633962646562303065626431366139386339373065343264616639353336643339393162
36646337366638346537653533353038633031653134393831323766306261393232343532653139 65363339653164646435373064313665636262393833386664383064303463653437643633306234
61323139616363356639613664626439613463633564346163636361393339343636353031343165 32653935656530386534333537353966356461343537616338653164383465313830363032313235
37643264663366633034376534626430393431303133373563623132656239333139363764623430 30356339623530363766333963323636306635376238323664656365303661336134316163306165
61303161653930363862373265336432656162623437393239613562633363343337393161646333 38613638656132653463363162623334313636353433316330663733613865366138663165306665
39306338333566646565326631346534613863346236386363313063616462373831646430663738 39666661613365303461373464343233356239656631303536643461653036316435646633313037
30363865356161313931393130363361313663393238663935373834353564346131373866326237 63396165316562326531376266626566303734366434363066653662323131346237653231643931
39313939336435613234646230663835393166636463303030336262303337313339653164633436 37666465633461363735656135396537656637336532303235323433626539336433313835663964
61613931383632623065626161663531336263633263636131393334333337653464323836393266 62663532373461343933306466353331373461336630323038646238653063633562613164663939
38353437643334303434396463313063663564303431666336653636313338616334373836313161 39343039303563393363373165306133336638316633663532393538313834343136376265323038
65383061363736663134316432376136633966616533336365616566396635383666666464636564 39303332373164613836663738613466643637353030663466346437356535393661396236343834
37626465393466623666326565343265346662313938646639613737326534643664386132666336 38626461623238663936633431616637656264323636363763306464393534363134306235643133
31616561663063663739323862333366313130653239326163616631336464323936383638623464 37323131653961343565623433336635663263393436316233616231303431336531313634343565
36623963323837393662306436336261323934313664333634326538336334306133346666613139 64386462333166376261633430303664366630386235366333393662616261636636343562393266
36323735623861316337333666366336626639623933663038666134636136303264356136383231 32326235643737613437393037353330363931363861393134643231656133626162333230376431
64363262353434663263616536333662383331626130353931323034643336303931383166306139 62353530313036376239333137343435393061613332396638626266393065316431616537366562
39336662643162363034653737626564653935336561386439653765326631336636663238653934 30313834633730626463633263356134363635623835613232336366353864383661306363376536
38376162353533343964366232373066326432383362373834303331626161656234326663616135 63643761326437366138386235323839643034393931623961346638346663396532656532633338
62306661346135343665386535356537383362356232613337666433326537363937383530656261 38303266383765303731303935356239303166323633343432393035633531623835656535353637
64393662646639356161343439343035376161366632353136616136643230616135346561353932 31326163656662306435326265396137383163356333303465393437356462333761373732316437
38376462633035666437306636323832623765326366326166323966656635313332313366343832 38653532653332323263363933353264663334396238643232313662326231333935336433633031
38356666313164356437396638393530326136363465313966326430626662383032376337333438 62356462313665653637633630643133383930313665346631383932346135303963353964353662
38656536623966656261386139363734393437623531313935323236643733303661393232666463 65373165643266316638363935363733663533356639383863613333646331636131353464373666
36373933643736393765366131383666336338643465393162376538666663316365366636393532 38653163663265633932323465373238323963323062653165366432313665346666643035613836
34666234313364656536643530396662663832643437616136376439656562326135366530343833 35646363376165323964666439306666303635633865663039393437306139656161636261366363
35613066393034616235393462323038663966356130626666653735663938643332336236316238 66643462383466383434303939326464366339383064323138363131623162333962323766623233
30366536353566393063336137626162303461333332656237646235666533313361626633373931 66386436323934383137333365383264323634336533303162303965303935346666313231663961
39663862343635333162 61346632323531393539643134656363353434653538376164643066313537656633663330656364
30363163363665656230616537393132383735346637366337346634333635616664323566656466
30656439653630333464656564653963323831323566653037633539663065393532633866373765
65666138653731326639633864653264343737336334356332653032376639386661333939636434
63653536333536613639373235643636643066666465323166323835323137616266333935313531
6531

View file

@ -1,6 +1,7 @@
--- ---
- import_tasks: packages.yml - import_tasks: packages.yml
- import_tasks: swap.yml - import_tasks: swap.yml
- import_tasks: sysctl.yml
- import_tasks: users.yml - import_tasks: users.yml
- import_tasks: sshd.yml - import_tasks: sshd.yml
- import_tasks: firewall.yml - import_tasks: firewall.yml

View file

@ -0,0 +1,52 @@
---
# Kernel hardening via sysctl
# Applied permanently via /etc/sysctl.d/99-hardening.conf
- name: Apply kernel hardening parameters
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
sysctl_file: /etc/sysctl.d/99-hardening.conf
reload: true
loop:
# ── Network: IP Spoofing protection ───────────────────────────────────────
- { name: net.ipv4.conf.all.rp_filter, value: "1" }
- { name: net.ipv4.conf.default.rp_filter, value: "1" }
# ── Network: Ignore ICMP redirects ────────────────────────────────────────
- { name: net.ipv4.conf.all.accept_redirects, value: "0" }
- { name: net.ipv4.conf.default.accept_redirects, value: "0" }
- { name: net.ipv4.conf.all.send_redirects, value: "0" }
- { name: net.ipv4.conf.default.send_redirects, value: "0" }
- { name: net.ipv6.conf.all.accept_redirects, value: "0" }
- { name: net.ipv6.conf.default.accept_redirects, value: "0" }
# ── Network: Ignore broadcast pings ───────────────────────────────────────
- { name: net.ipv4.icmp_echo_ignore_broadcasts, value: "1" }
# ── Network: Ignore bogus error responses ────────────────────────────────
- { name: net.ipv4.icmp_ignore_bogus_error_responses, value: "1" }
# ── Network: SYN flood protection ────────────────────────────────────────
- { name: net.ipv4.tcp_syncookies, value: "1" }
- { name: net.ipv4.tcp_max_syn_backlog, value: "2048" }
- { name: net.ipv4.tcp_synack_retries, value: "2" }
- { name: net.ipv4.tcp_syn_retries, value: "5" }
# ── Network: Disable IPv6 if not needed ──────────────────────────────────
- { name: net.ipv6.conf.all.disable_ipv6, value: "1" }
- { name: net.ipv6.conf.default.disable_ipv6, value: "1" }
- { name: net.ipv6.conf.lo.disable_ipv6, value: "1" }
# ── Kernel: Restrict dmesg to root ───────────────────────────────────────
- { name: kernel.dmesg_restrict, value: "1" }
# ── Kernel: Hide kernel pointers ─────────────────────────────────────────
- { name: kernel.kptr_restrict, value: "2" }
# ── Kernel: Disable SysRq ────────────────────────────────────────────────
- { name: kernel.sysrq, value: "0" }
# ── Memory: Disable core dumps for suid programs ─────────────────────────
- { name: fs.suid_dumpable, value: "0" }

View file

@ -56,14 +56,20 @@
until: docker_install is succeeded until: docker_install is succeeded
notify: Restart Docker notify: Restart Docker
- name: Configure Docker daemon (registry mirrors) - name: Configure Docker daemon
ansible.builtin.copy: ansible.builtin.copy:
dest: /etc/docker/daemon.json dest: /etc/docker/daemon.json
content: | content: |
{ {
"registry-mirrors": [ "registry-mirrors": [
"https://dockerhub.timeweb.cloud" "https://dockerhub.timeweb.cloud"
] ],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true
} }
mode: "0644" mode: "0644"
notify: Restart Docker notify: Restart Docker

View file

@ -32,3 +32,4 @@ crowdsec_bouncer_image: "crowdsecurity/cs-firewall-bouncer:v0.0.31" # https://hu
authelia_image: "authelia/authelia:4.38" # https://hub.docker.com/r/authelia/authelia/tags authelia_image: "authelia/authelia:4.38" # https://hub.docker.com/r/authelia/authelia/tags
redis_image: "redis:7-alpine" # shared with plane-redis redis_image: "redis:7-alpine" # shared with plane-redis
authelia_admin_user: "admin" authelia_admin_user: "admin"
uptime_kuma_image: "louislam/uptime-kuma:1" # https://hub.docker.com/r/louislam/uptime-kuma/tags

View file

@ -46,6 +46,7 @@ volumes:
loki_data: loki_data:
crowdsec_data: crowdsec_data:
authelia_data: authelia_data:
uptime_kuma_data:
services: services:
@ -68,6 +69,13 @@ services:
- {{ services_root }}/traefik/dynamic:/etc/traefik/dynamic:ro - {{ services_root }}/traefik/dynamic:/etc/traefik/dynamic:ro
- {{ services_root }}/traefik/acme.json:/acme/acme.json - {{ services_root }}/traefik/acme.json:/acme/acme.json
- {{ services_root }}/traefik/logs:/var/log/traefik - {{ services_root }}/traefik/logs:/var/log/traefik
environment:
- CLOUDFLARE_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN}
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck: healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"] test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 30s interval: 30s
@ -618,3 +626,22 @@ services:
networks: networks:
- authelia-internal - authelia-internal
command: redis-server --appendonly yes --maxmemory 64mb --maxmemory-policy allkeys-lru command: redis-server --appendonly yes --maxmemory 64mb --maxmemory-policy allkeys-lru
# ── Uptime Kuma ────────────────────────────────────────────────────────────
# Мониторинг доступности сервисов + публичная статус-страница
# Доступен по адресу: https://{{ domain_status }}
uptime-kuma:
image: {{ uptime_kuma_image }}
container_name: uptime-kuma
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- backend
volumes:
- uptime_kuma_data:/app/data
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3001/"]
interval: 30s
timeout: 5s
retries: 3

View file

@ -16,3 +16,6 @@ AUTHELIA_JWT_SECRET={{ authelia_jwt_secret }}
AUTHELIA_SESSION_SECRET={{ authelia_session_secret }} AUTHELIA_SESSION_SECRET={{ authelia_session_secret }}
AUTHELIA_STORAGE_KEY={{ authelia_storage_key }} AUTHELIA_STORAGE_KEY={{ authelia_storage_key }}
CROWDSEC_BOUNCER_KEY={{ crowdsec_bouncer_key }} CROWDSEC_BOUNCER_KEY={{ crowdsec_bouncer_key }}
# Cloudflare DNS-01 ACME challenge
CLOUDFLARE_DNS_API_TOKEN={{ cloudflare_dns_api_token }}
CF_ZONE_ID={{ cloudflare_zone_id }}

View file

@ -0,0 +1,13 @@
# Generated by Ansible — do not edit manually
{{ services_root }}/traefik/logs/access.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 root root
postrotate
docker kill --signal=USR1 traefik 2>/dev/null || true
endscript
}

View file

@ -85,6 +85,14 @@ http:
service: authelia service: authelia
middlewares: [rate-limit-strict] middlewares: [rate-limit-strict]
uptime-kuma:
rule: "Host(`{{ domain_status }}`)"
entrypoints: [websecure]
tls:
certresolver: letsencrypt
service: uptime-kuma
middlewares: [rate-limit-default]
services: services:
vaultwarden: vaultwarden:
loadBalancer: loadBalancer:
@ -131,6 +139,11 @@ http:
servers: servers:
- url: "http://authelia:9091" - url: "http://authelia:9091"
uptime-kuma:
loadBalancer:
servers:
- url: "http://uptime-kuma:3001"
middlewares: middlewares:
# ── Security Headers (applied globally via entrypoint) ───────────────── # ── Security Headers (applied globally via entrypoint) ─────────────────
security-headers: security-headers:

View file

@ -93,8 +93,12 @@ certificatesResolvers:
acme: acme:
email: "{{ acme_email }}" email: "{{ acme_email }}"
storage: /acme/acme.json storage: /acme/acme.json
httpChallenge: dnsChallenge:
entryPoint: web provider: cloudflare
# Use Cloudflare DNS resolvers to avoid propagation delays
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
providers: providers:
file: file: