Commit Graph
100 Commits
Author SHA1 Message Date
Clément Désiles 5efc0b0d6e fix(nginx): make Let's Encrypt opt-in per service
certbot cannot issue for internal hostnames (*.nas.local), which made
nginx-enabled services with internal names fail on deploy.

Add a <service>_nginx_letsencrypt flag (default false) and computed
<service>_nginx_ssl_certificate/_key paths: when off the vhost uses the
shared self-signed cert (nginx_default_ssl_cert), when on it uses the
Let's Encrypt lineage. Gate the certbot include on the flag and apply the
pattern to all service roles (deluge, fdroid, gitea, grafana, immich,
metabase, ntfy, prowlarr, radarr, seerr, static_web, uptime_kuma).
2026-09-21 10:04:47 +02:00
Clément Désiles 61621715e0 fix(ansible): reference facts via ansible_facts to silence deprecation
INJECT_FACTS_AS_VARS auto-injection of top-level facts is deprecated and
removed in ansible-core 2.24. Use ansible_facts['architecture'] and
ansible_facts['date_time']['epoch'] instead.
2026-09-21 09:59:03 +02:00
Clément Désiles a73fb2aa29 feat(arr): add prowlarr, radarr and seerr roles 2026-09-18 18:53:43 +02:00
Clément Désiles 6ba208a455 docs(zfs): link pool capacity metric to Grafana alerts 2026-09-18 18:35:04 +02:00
Clément Désiles be73f3adfa feat(grafana): provision disk alerts to ntfy
Provision Grafana Unified Alerting as code: ntfy webhook contact point
(?template=grafana), notification policy tree, and cumulative disk tiers
for HDD temperature (48-60C, <20C) plus ZFS/filesystem capacity. Lower the
smartctl exporter interval to 30m for alert responsiveness.
2026-09-18 18:32:02 +02:00
Clément Désiles c127336321 feat(zfs): add capacity metrics and Grafana dashboard
Deploy an hourly systemd timer that writes pool and dataset capacity to
node_exporter's textfile collector, since --collector.zfs exposes only
ARC/I-O/state. Add a provisioned 'ZFS - Pools & Datasets' dashboard with
per-pool totals, per-dataset used/quota and daily growth panels.
2026-09-18 15:25:23 +02:00
Clément Désiles 501671770f add deluge role 2026-09-18 15:24:18 +02:00
Clément Désiles 30480f61d5 generalize zsh role to support darwin 2026-09-18 11:32:06 +02:00
Clément Désiles fd8c64aed1 add darwin support to install homebrew deps 2026-09-15 17:50:09 +02:00
Clément Désiles c88e90524b update doc 2026-09-15 17:49:33 +02:00
Clément Désiles f89a919022 add darwin support 2026-09-15 17:30:20 +02:00
Clément Désiles 923ffa4acd cleanup 2026-09-11 21:35:30 +02:00
Clément Désiles 94a1aa553a add ansible utils to enable wol 2026-09-11 21:33:16 +02:00
Clément Désiles 9fc28377d7 add wg prom exporter 2026-09-11 21:32:27 +02:00
Clément Désiles 20cbf01040 enhance dashboarding 2026-09-11 21:32:00 +02:00
Clément Désiles 9440d78cd9 add exa alias 2026-09-11 14:40:51 +02:00
Clément Désiles 281245ee32 Merge branch 'main' of gitlab.com-perso:cdesiles/ansible-playbooks 2026-09-10 21:26:00 +02:00
Clément Désiles 0ec6224941 feat(backup): per-job schedules, stale-lock recovery, service manifests
- Add per-job `schedule` (systemd OnCalendar) overrides and document the
  global `backup_schedule` / `backup_randomized_delay` knobs.
- Run `restic unlock` before backup/forget/check so a run killed mid-flight
  no longer wedges every later run on a stale exclusive lock.
- Publish backup manifests for fdroid, immich and unifi, so the inventory
  decides only where (repositories, retention, schedule).
- Document that `read_data_subset` re-reads on every job targeting the
  repository, so a large repository wants a small fraction.
2026-09-10 16:47:33 +02:00
Clément Désiles f6c4d36bbe feat(monitoring): add backup and systemd metrics, alerts, and dashboards
- backup role emits last-success/run metrics into node_exporter's textfile collector
- node_exporter enables systemd and textfile collectors
- prometheus deploys BackupStale/BackupTimerSilent/SystemdUnitFailed alert rules
- grafana gains Backups - Restic and Systemd dashboards
- fix prometheus.yml params rendering (quote values so {job=...} stays a string)
2026-09-09 12:07:50 +02:00
Clément Désiles 8756eb1183 feat(monitoring): add smartctl, fail2ban, wireguard exporters and dashboards
- smartctl_exporter (disks), fail2ban exporter, wireguard exporter
- grafana dashboards for each exporter
- prometheus: firewall source rules, honor_labels/params scrape config
- node_exporter: zfs collector
- wireguard: nftables dep, resolvconf wrapper, reload fix
- remove superseded monitoring role
2026-09-08 23:03:34 +02:00
Clément Désiles c29042fe1d feat(tooling): add nmap 2026-09-08 22:52:00 +02:00
Clément Désiles 56fe5304c5 feat(unbound): enable prefetch, prefetch-key, and deny-any 2026-09-08 22:49:50 +02:00
Clément Désiles e4d0812a69 fix(grafana): NUT dashboard instance variable ignores stale series
The variable used label_values() which lists all instances across full
retention, alphabetically sorting and auto-selecting the dead
127.0.0.1:9199 (relabeled to 'eaton' ~31h ago). Its stale series has no
samples in the visible window so every panel rendered empty. Replace with
query_result(count by (instance) (...)) which only surfaces live targets.
2026-09-06 23:51:22 +02:00
Clément Désiles 65fdb4face fix(monitoring): exporter auth and reload fixes
- postgres: use lib/pq conninfo DATA_SOURCE_NAME; the postgresql:// URL
  form broke on special chars in the password (net/url: invalid userinfo)
- nginx: flush handlers after deploying stub_status so nginx reloads
  before the exporter starts scraping
- valkey: drop invalid +arcount command from the exporter ACL set
  (Valkey aborted startup parsing the ACL file)
2026-09-06 23:47:13 +02:00
Clément Désiles ed5d0c68f1 feat(unbound): add prometheus exporter, dashboard, fix socket buffer sysctl 2026-09-06 23:44:05 +02:00
Clément Désiles 304a3fae12 feat(monitoring): add nginx, postgres, valkey dashboards 2026-09-06 23:43:50 +02:00
Clément Désiles aa78e238aa feat(monitoring): add nginx, postgres, valkey prometheus exporters
- nginx: nginx-prometheus-exporter gated by nginx_exporter_enabled,
  deploys loopback-only stub_status (8090), exporter on 9113
- postgres: postgres_exporter gated by postgres_exporter_enabled,
  creates postgres_exporter role with pg_monitor, exporter on 9187
- valkey: redis_exporter gated by valkey_exporter_enabled, adds
  read-only ACL user to users.acl, exporter on 9121

Each exporter follows the nut pattern (tasks/exporter.yml included from
main.yml, OS vars, 0600 secret env files, password asserts).
2026-09-06 09:37:36 +02:00
Clément Désiles 6f1f7f88f0 fix(metabase): bind host port 3400 instead of default 3000 2026-09-05 17:24:17 +02:00
Clément Désiles 5218fa2714 refactor(nut): merge prometheus exporter into nut role
- exporter gated by nut_prometheus_exporter_enabled
- env-file config (correct NUT_EXPORTER_* vars + --web.listen-address)
- remove standalone nut_exporter role
2026-09-05 17:24:12 +02:00
Clément Désiles 12b81919c3 feat(monitoring): add grafana, prometheus, node_exporter roles
- grafana: postgres backend, provisioning (prometheus datasource + node/NUT dashboards)
- prometheus: native service, scrape config via host_vars, localhost bind
- node_exporter: host metrics exporter (localhost:9100)
2026-09-05 17:24:08 +02:00
Clément Désiles b94743567f feat(sys_autoupdate): notify on pending kernel reboot
Detect drift between the running kernel and the newest installed one
(Arch: /usr/lib/modules vs uname -r; Debian: /var/run/reboot-required)
and push a weekly ntfy reminder until the host is rebooted.

Also bundles the in-flight ignore-packages feature and hostname
refactor in the autoupdate script.
2026-09-05 16:59:49 +02:00
Clément Désiles 24502f543f fix(fail2ban): pass blocktype via banaction to override the ufw action default
jail-level blocktype is ignored (action [Init] wins); it must be
passed as banaction = ufw[blocktype=deny].
2026-09-05 16:57:45 +02:00
Clément Désiles 6355a9aae5 fix(fail2ban): ban via ufw deny (DROP) instead of reject
REJECT needs the nft_reject kernel extension, which is unavailable on
this Arch kernel (iptables-nft reports 'Extension REJECT revision 0
not supported'), so every ban silently failed. DROP works everywhere
and is quieter toward attackers.
2026-09-05 16:45:12 +02:00
Clément Désiles 40cc0efcf8 fix(fail2ban): use ProtectSystem=full so ufw can create its lock file
strict makes /run read-only, which blocks ufw's /run/ufw.lock and
cannot be whitelisted via ReadWritePaths (the file does not exist).
full still protects /usr and /etc while leaving /run and /var writable,
so only /etc/ufw needs an explicit write path.
2026-09-05 16:28:55 +02:00
Clément Désiles 120615c38f fix(fail2ban): start under ProtectSystem=strict hardening
- log to journald via fail2ban.local (logtarget is a fail2ban.conf option,
  not jail.local) so the server can start without /var/log write access
- create the socket dir via RuntimeDirectory=fail2ban instead of a
  non-creating ReadWritePaths entry
- add ufw write paths so bans persist under the read-only namespace
- manage override.conf unconditionally and restart on change
2026-09-05 16:21:49 +02:00
Clément Désiles ceca06ff2e feat(backup): add restic backup role with encrypted incremental snapshots
Restic-backed backups using a many-to-many repository/job model.

- repository = destination: restic repository URL verbatim (s3, local,
  removable device), backend credentials via env passthrough, retention
  policy, and an optional per-repository ntfy notify channel
- job = source set: paths, sqlite and postgres dumps (consistent .backup /
  pg_dump instead of torn live-file copies), pushed to one or more repos
- systemd timer per job, per-repo + per-job flock serialisation, restic
  check with read_data_subset for rotating integrity verification

Service roles declare what to back up (ntfy_backup_*, uptime_kuma_backup_*);
the inventory declares where.
2026-09-01 22:20:27 +02:00
Clément Désiles 8a3c323059 fix(wireguard): reload tunnel via syncconf on config change
Config template changes were never applied to the running interface,
leaving a stale peer list after redeploy. Notify a syncconf reload so
peer edits apply without dropping active connections.
2026-08-27 10:14:23 +02:00
Clément Désiles 842374616b fix: add unzip to tooling role 2026-08-26 00:16:33 +02:00
Clément Désiles fb01dfbf67 doc: minor alias to help me switch to podman 2026-08-26 00:16:09 +02:00
Clément Désiles 59c0b93905 fix: prevent ansible from parsing JSON when establishing an ssh connection 2026-08-26 00:15:04 +02:00
Clément Désiles 4c4cb16f37 fix(wireguard): allow ufw forwarding for server_mode tunnels
ufw FORWARD policy drop overrode the nft/iptables forward rules,
blocking all VPN traffic through the tunnel. Add routed rules in
both directions between the tunnel and primary interface.
2026-08-25 23:47:34 +02:00
Clément Désiles 642a0f8ea4 fix(sshd): move login banner to zsh .zprofile
sshd Banner fires on every connection (scp, sftp, non-interactive), the wrong layer for a welcome banner. Move to .zprofile, interactive login shells only.
2026-08-25 22:58:03 +02:00
Clément Désiles 43b510e77f fix(podman): restore newuidmap/newgidmap file caps for rootless namespaces
pacman strips file capabilities, leaving rootless podman unable to set up
user namespaces (rc 125). Re-apply cap_setuid/cap_setgid on Arch.
2026-08-23 22:03:31 +02:00
Clément Désiles 174a96eefc security: always restore sudoers after makepkg, drop dead paru block
The archlinux and zfs roles temporarily write `%wheel ALL=(ALL) NOPASSWD: ALL`
to /etc/sudoers so makepkg/paru can run unattended, then restore it in a
following task. Since the restore was a plain sibling task, any failure in
between aborted the play and left the host with passwordless root for the
whole wheel group. Move the restore into `always:` so it runs on failure too,
and narrow the window in yay.yml to just the makepkg call (dependency install,
directory setup and git clone no longer run inside it).

This is not hypothetical: a provisioning run of omega failed on paru's git
clone and left the sudoers hack in place.

The clone failed because the deprecated compile-from-source paru block, which
was commented out in tree, had been re-enabled. It fed paru_git_repo into the
git module, but that variable now holds a GitHub owner/repo slug for the
releases API rather than a clone URL. Remove the block outright, along with
the orphaned paru_src_path default; paru is installed from the release binary.

Also fix the ansible-lint violations this surfaced so roles/archlinux passes
the production profile: explicit `become` next to `become_user`, a pinned
branch on the yay clone, and `changed_when` on the command/shell tasks.
2026-08-18 21:52:49 +02:00
Clément Désiles 1970564c8f refactor: drop shared-service meta dependencies from service roles
podman, postgres, valkey, and nginx are shared services deployed once
per host. Declaring them in meta/main.yml re-ran them on every service
deploy, adding significant time to targeted runs. Playbooks now list
shared services first (tagged 'infra') and every role entry carries a
group tag plus its own name, so '--tags <role>' deploys just that role.

Roles still fail fast when a shared service is missing (password
asserts, postgresql tasks). Prerequisites are documented in role
READMEs. CLAUDE.md updated to reflect the new convention.
2026-07-04 00:15:50 +02:00
Clément Désiles 7972fe09ad security: deploy pod manifests containing credentials with mode 0600
gitea.yaml, immich.yaml, and metabase.yaml embed database passwords in
env vars; per repo policy, rendered files containing secrets must not
be world-readable.
2026-07-04 00:06:29 +02:00
Clément Désiles 95a743ddeb fix(roles): detect new image on podman pull and restart services
Same bug as immich (556fae8): 'Writing manifest' goes to stderr, so
changed_when never matched and the restart handlers never fired after
image upgrades. Compare local image IDs before/after pull instead, and
notify the restart handler only on a genuinely new image.

Applies to fdroid, gitea, metabase, ntfy, unifi, uptime-kuma.
2026-07-04 00:06:13 +02:00
Clément Désiles 556fae86d9 fix(immich): detect new image on pull and restart service
'Writing manifest' is printed by podman pull on stderr (not stdout), so
changed_when never matched, the Restart Immich handler never fired, and
pods kept running the old image after upgrades. Matching on stderr would
be wrong too: podman prints that line even when the image is unchanged.

Compare the local image ID before/after pull instead, and notify the
restart handler only when the tag resolves to a new image.
2026-07-04 00:03:34 +02:00
Clément Désiles f48d68da9d doc: add readme to zsh 2026-07-03 00:11:52 +02:00
Clément Désiles 75d6aae668 Add UniFi Network Controller role 2026-07-03 00:09:02 +02:00
Clément DésilesandClaude Opus 4.8 501f4e1f87 feat(nut): report outage duration and battery % in ntfy
ONBATT records the epoch start time and appends current battery
charge; ONLINE appends battery charge and the total outage duration
(HH:mm:ss) computed from the recorded start, then clears the state.
State lives in /run so it self-clears on reboot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 23:50:48 +02:00
Clément Désiles 21f47196cf feat(net_config): support IPForward and IPMasquerade in network config 2026-06-19 23:55:02 +02:00
Clément Désiles e4ad6888b6 Introduce vault pass in the doc to push a good practice 2026-06-19 23:52:19 +02:00
Clément Désiles 4c57d28b4d Add new fdroid role to host custom apks 2026-06-19 23:50:56 +02:00
Clément Désiles 045c0b9bec refactor(zfs): inline dataset ownership, add absent cleanup
Drop separate dataset-ownership.yml task file. Use
extra_zfs_properties.mountpoint directly instead of zfs get.
Add rmdir cleanup for absent dataset mountpoints.
2026-06-19 23:46:33 +02:00
Clément Désiles 13b8aae769 Add support for NUT (EATON inverter) 2026-06-13 09:37:49 +02:00
Clément Désiles 25621a101c Merge branch 'main' of github.com:cdesiles/ansible-playbooks 2026-06-12 22:34:24 +02:00
Clément Désiles 0726e417d2 feat: add syncthing support 2026-06-03 23:28:26 +02:00
Clément Désiles 2f3eebd422 feat: add metabase role 2026-06-03 10:01:00 +02:00
Clément Désiles d976a9d701 fix: cleanup examples 2026-05-31 22:42:12 +02:00
Clément Désiles e74fffd5fc refacto: move inventory examples to a dedicated dir 2026-05-31 22:34:31 +02:00
Clément Désiles 30dfb9ee8b feat(immich): support read-only external libraries
Add immich_external_libraries variable to mount host paths into the
server container, intended for use with Immich's External Libraries
feature. Mounts are read-only; the in-container mount_path must be
used when registering the library in the Immich UI.
2026-05-30 23:39:17 +02:00
Clément Désiles b0324cf3fe refactor: hoist OS-specific package names to role defaults
- nfs_server: nfs_package_name (nfs-utils / nfs-kernel-server)
- wireguard: wireguard_package_name (wireguard-tools / wireguard)
- tooling:   tooling_dig_package, tooling_netcat_package

Also fix tooling role structure: move tooling.yml to tasks/main.yml so
the role is actually invokable via 'role: tooling' (defaults/main.yml
is auto-loaded), and collapse the 10 individual package tasks into a
single list-based install.
2026-05-30 21:57:20 +02:00
Clément Désiles a6ca97ca0e feat(samba_server): new role for SMB/CIFS shares
Mirrors the nfs_server design: standalone tdbsam server, per-share access
control (valid_users, write_list, force_user/group), optional guest fallback
(map to guest = Bad User), UFW rules for ports 445/139, testparm-validated
config, idempotent smbpasswd user creation.
2026-05-30 21:57:13 +02:00
Clément Désiles b2a66099aa fix(immich): prevent client SocketTimeoutException on large uploads
Add missing nginx directives recommended by Immich docs for mobile
photo backup over slow links:

- http2 on: multiplex parallel asset uploads from the mobile app
- client_body_timeout / send_timeout / keepalive_timeout 600s: cover
  the client<->nginx leg (default 60s matched the Android timeout)
- proxy_request_buffering off + proxy_buffering off: stream upload
  bytes to immich as they arrive instead of buffering the whole file,
  keeping the TCP connection active and avoiding idle-socket timeouts
- proxy_connect_timeout 600s: explicit upstream connect timeout
2026-05-30 17:18:05 +02:00
Clément Désiles 314fa715fd fix(nginx): prevent cert leak on IPv6 / unknown SNI
Two issues caused TLS to break on photos.carabosse.cloud over IPv6
(GrapheneOS + Immich app via Orange 5G NAT64):

1. Per-service vhosts only listened on IPv4 (listen 443 ssl). On IPv6,
   nginx fell back to the first vhost loaded alphabetically and served
   its certificate, breaking hostname verification on every other vhost.

2. /etc/letsencrypt/{live,archive} were 0700 root:root after certbot
   created them, so the nginx worker (user http on Arch) could not read
   the chained intermediates and served the leaf-only chain.

Changes:
- Add catch-all 00-default.conf default_server on :80 and :443 (v4+v6)
  with a self-signed cert and 'return 444'. ACME challenges still
  answered on :80.
- Add IPv6 listeners ([::]:80 and [::]:443 ssl) to immich, gitea, ntfy,
  uptime_kuma vhosts and to the temporary ACME provisioning vhost.
- Apply 0755 on /etc/letsencrypt/live and /etc/letsencrypt/archive on
  every run, not only at initial cert provisioning.
2026-05-30 17:06:10 +02:00
Clément Désiles 80026fac0b fix: pin ansible.posix >=2.2.0 to silence _text deprecation warning 2026-05-30 17:05:58 +02:00
Clément Désiles c9e2ff930c feat(net_config): safer ufw restart on NAT/forwarding changes
- Replace 'ufw disable && ufw --force enable' single-shot handler with a
  block that dry-runs the ruleset, disables, re-enables, then verifies
  ufw is active. No '&&' short-circuit, so failures are loud instead of
  leaving the host firewall-less.
- Rename handler to 'Restart ufw (ip-forwarding settings changed)' to
  reflect that this is a full restart (required to pick up
  /etc/default/ufw and /etc/ufw/before.rules changes per ufw(8)).
- Add NAT/masquerade tasks: enable ipv4 forwarding, set
  DEFAULT_FORWARD_POLICY=ACCEPT, and write a per-interface *nat block
  in /etc/ufw/before.rules.
- Declare requires_ansible >=2.15 in meta/runtime.yml (handler uses
  block:, supported since 2.12; 2.15 is a safe modern floor).
- README: document Ansible version requirement, port reservation
  rules, and Immich pgvector Q&A.
2026-05-29 22:24:16 +02:00
Clément Désiles 36d6baaecb fix: missing task in wg 2026-05-29 21:54:25 +02:00
Clément Désiles 5f2c82d296 fix: use ansible_facts['getent_passwd'] to silence INJECT_FACTS_AS_VARS deprecation 2026-05-29 21:54:03 +02:00
Clément Désiles dbc7ca203a fix: minor taks name typo 2026-05-29 21:50:39 +02:00
Clément Désiles a8545fc501 fix(podman): use Type=notify + service-container so systemd sees pod crashes
The previous Type=oneshot + RemainAfterExit=true pattern made systemd
freeze pod units in 'active (exited)' as soon as 'podman play kube'
returned, so crash-looping containers were invisible to
'systemctl --user --failed' and Restart=on-failure never fired.

For every podman-pod role (immich, fdroid, ntfy, gitea, qfieldcloud,
unifi, matrix, uptime_kuma):

- switch units to Type=notify + NotifyAccess=all
- run 'podman kube play --service-container=true' so the unit's main
  PID stays alive as long as the pod
- use 'podman kube down' for ExecStop
- add TimeoutStartSec=180 to cover slow first-boot image pulls

Pod manifests: flip every container's restartPolicy from Always to
Never. systemd is now the single owner of the restart loop: container
exits -> pod dies -> service container dies -> unit fails ->
Restart=on-failure restarts everything cleanly. With Always, podman
retried internally and hid the failure from systemd.

CLAUDE.md updated to document the new canonical template and the
'restartPolicy: Never' requirement.
2026-05-29 21:49:13 +02:00
Clément Désiles 29d9f27052 fix: ntfy probe without curl available 2026-05-29 21:41:04 +02:00
Clément Désiles b04939d3d0 fix: use ansible_facts['kernel'] to avoid deprecation warning 2026-05-29 21:35:54 +02:00
Clément Désiles ff3133f8e7 feat: wireguard role allow multiple endpoints 2026-05-29 21:32:08 +02:00
Clément Désiles 4ae7721070 fix: secure pg + fix old way of sharing podman network 2026-05-29 21:31:07 +02:00
Clément Désiles ffeff6556b fix: restart dhcpd on nas restart 2026-05-29 21:29:14 +02:00
Clément Désiles 436fba0d39 Merge branch 'main' of github.com:cdesiles/ansible-playbooks 2026-05-29 21:28:41 +02:00
Clément Désiles 92deb854d2 fix: enhance tooling 2026-05-29 21:27:25 +02:00
Clément Désiles 05e7ee3956 fix: tls for static web 2026-05-29 21:27:00 +02:00
Clément Désiles aea450dc9d feat: nginx certbot 2026-05-29 21:26:17 +02:00
Clément Désiles 1d00432061 fix: podman integration 2026-05-29 21:24:58 +02:00
Clément Désiles 7904275754 nfs: minor tweak 2026-05-22 00:07:24 +02:00
Clément Désiles 305b8324db feat: sys autoupdate 2026-05-08 23:47:21 +02:00
Clément Désiles ea0771a5ac fix: update wireguard example 2026-05-05 22:59:46 +02:00
Clément Désiles 48e87f7cb1 zsh: enhance configuration with alacritty 2026-05-05 22:58:56 +02:00
Clément Désiles 4ac40b9898 fix: nginx defaults override on archlinux 2026-05-05 22:56:08 +02:00
Clément Désiles 488be1280c fix: dhcpd startup dependency 2026-05-05 22:54:56 +02:00
Clément Désiles de165f5e1c fix: review archlinux install details 2026-04-11 22:55:03 +02:00
Clément Désiles f9397ad38c feat: allow sshd to bind on multiple networks 2026-04-11 22:54:35 +02:00
Clément Désiles ac40c23d06 feat: more base tools 2026-04-11 22:53:19 +02:00
Clément Désiles 6fc7879648 fix: uptime-kuma reverse proxy config 2026-04-11 22:53:06 +02:00
Clément Désiles c4136ba5d2 fix: ntfy 2026-04-11 22:52:29 +02:00
Clément Désiles 4d60c6ea34 fix: zshrc to take p10k theme 2026-04-11 22:51:28 +02:00
Clément Désiles ae33184aa0 fix: zsh role add fzf support and p10k settings tweaks 2026-04-11 22:41:10 +02:00
Clément Désiles 61c88045f7 feat: add more tooling 2026-03-17 23:13:02 +01:00
Clément Désiles 525868caaf fix: wireguard on archlinux 2026-03-17 23:10:08 +01:00
Clément Désiles 235881aba7 fix: commit bootstrap playbook 2026-03-17 23:09:47 +01:00
Clément Désiles a6878c0b7d fix: dhcpd ipv4 service 2026-03-17 23:09:29 +01:00
Clément Désiles e209a93a78 feat: BREAKING unbound configuration 2026-03-17 23:08:44 +01:00