Add PostgreSQL and Miniflux services to tailnet #16

Merged
eblume merged 15 commits from feature/add-miniflux-postgresql into main 2026-01-16 12:30:21 -08:00

15 commits

Author SHA1 Message Date
b1c08af559 Remove XID gauge panel, keep only time series 2026-01-16 12:28:01 -08:00
a1341cdaa6 Fix trailing comma in PostgreSQL dashboard JSON 2026-01-16 12:24:34 -08:00
d56231d813 Bump PostgreSQL dashboard version to force reload 2026-01-16 12:20:55 -08:00
7dca29aea9 Add XID exhaustion tracking to PostgreSQL dashboard
- Add custom query for pg_database XID age monitoring
- Add gauge showing XID age with threshold warnings (yellow at 150M, red at 180M)
- Add time series chart for XID age trends
- URL-encode postgres password in alloy connection string

XID (transaction ID) exhaustion can cause PostgreSQL to shut down to prevent
wraparound. Default autovacuum_freeze_max_age is 200M, so warnings start well
before that threshold.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 12:15:45 -08:00
cce4c3776e Fix PostgreSQL metrics by URL-encoding password in alloy config
The password contained special characters (@, !, *) that broke the
connection string URL parsing. Added urlencode filter to the template.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 12:02:52 -08:00
88cf7fac7e Fix idempotency issues in playbook and tailscale_serve role
- Add tags to pre_tasks so they only run when relevant roles are included
- Make tailscale_serve idempotent by checking serve status JSON before
  configuring services (skips if already configured)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 11:59:54 -08:00
cdb8432691 Add ansible-managed borgmatic config with PostgreSQL backup
- Move borgmatic config.yaml from manual to ansible-managed template
- Add postgresql_databases backup for miniflux database
- Consolidate 1Password credential fetching to playbook pre_tasks
  to reduce auth prompts during full playbook runs
- Roles now check if credentials are already defined before fetching,
  so they still work when running with --tags

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 11:32:03 -08:00
02a2c9d6fb Fix psql commands to specify -d postgres database
Without specifying a database, psql defaults to connecting to a
database named after the current user, which doesn't exist on a
fresh install.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 10:39:40 -08:00
4e9c8c11f7 Add tag:blumeops as owner of service tags for IaC management
The OAuth client acts as tag:blumeops, so it needs to own all tags
it manages on devices. This enables Pulumi to set device tags
automatically instead of requiring manual Tailscale admin console
changes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 09:57:20 -08:00
544682e92e Restrict .pgpass to read-only borgmatic user only
Remove superuser from .pgpass since it's not needed for automated
operations. Only borgmatic (with pg_read_all_data role) needs
passwordless access for pg_dump backups.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 09:51:30 -08:00
f293b0e7e5 Add Pulumi DeviceTags for indri to manage device tags via IaC
Instead of manually applying tags to indri in Tailscale admin,
use tailscale.DeviceTags resource to manage them declaratively.
This includes all service tags (grafana, forge, kiwix, devpi, loki,
pg, feed) plus homelab and blumeops tags.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 09:47:05 -08:00
8b701bb5aa Add PostgreSQL metrics collection and Grafana dashboard
- Add 'alloy' PostgreSQL user with pg_monitor role (read-only)
- Configure Alloy prometheus.exporter.postgres for metrics collection
- Password fetched from 1Password with no_log protection
- Add PostgreSQL Grafana dashboard with:
  - Connection stats (active, total, by state)
  - Database sizes
  - Tuple operations rate
  - Transaction rate (commits/rollbacks)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:18:54 -08:00
f9757d71e3 Add note that zettelkasten uses Obsidian Sync, not git
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:11:10 -08:00
b7ccca87f3 Secure password management via 1Password CLI in ansible
- All passwords fetched from 1Password at runtime using `op` CLI
- pg_hba.conf uses scram-sha-256 everywhere (no trust mode)
- initdb uses --pwfile for secure superuser password bootstrap
- All password-handling tasks use no_log: true
- Add borgmatic user with pg_read_all_data for backup dumps
- Remove pg-setup mise task (no longer needed)
- Miniflux fetches password directly from 1Password

Requires: `op signin` before running ansible

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:06:29 -08:00
248e118102 Add PostgreSQL and Miniflux services to tailnet
- Add postgresql ansible role (postgresql@18 via homebrew)
  - Creates miniflux database and user
  - Configures pg_hba.conf for local scram-sha-256 auth
  - Exposed via Tailscale at pg.tail8d86e.ts.net:5432

- Add miniflux ansible role (RSS/Atom feed reader)
  - Depends on postgresql role
  - Configures via /opt/homebrew/etc/miniflux.conf
  - Reads DB password from ~/.miniflux-db-password
  - Supports first-run admin creation via miniflux_create_admin flag
  - Exposed via Tailscale at feed.tail8d86e.ts.net

- Update Pulumi ACL tags (tag:pg, tag:feed)
- Update tailscale_serve role with new service definitions
- Update Alloy log collection for both services
- Update indri.yml playbook with new roles

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 07:26:59 -08:00