initial commit: Dawarich LXC role (CT 459 on pve02, .159)
Self-hosted location history. 4-container compose: Rails 8 app + Sidekiq + PostGIS 16-3.4 + Redis 7, plus watchtower. Authentik OIDC end-to-end. Image pinned at freikin/dawarich:1.7.11 (OIDC support requires >= 1.7.8). PostGIS DB lives in this LXC, not on the central DB VM (.172) — central image is postgres:16-alpine without postgis, swapping it carries broader blast radius than colocating here. Convention exception captured in homelab-docs project_dawarich memory. Roles: - dawarich: system + Docker + compose + weekly prune timer - alloy: logs+journald → Loki, node metrics → Prometheus Bring-up sequence proven 2026-06-01. README documents the 5-trap build chain (image version, entrypoint scripts, solid_cache SQLite bind mount, APPLICATION_HOSTS+localhost, force_ssl+healthcheck). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
---
|
||||
# ==============================================================================
|
||||
# Dawarich LXC — Self-hosted location history (Google Timeline alternative)
|
||||
# ==============================================================================
|
||||
# Rails app + Sidekiq worker + Redis + PostGIS, all on this LXC. PostGIS lives
|
||||
# here (not central DB VM .172) because the DB VM's postgres:16-alpine image
|
||||
# doesn't bundle the postgis extension — see memory project_dawarich for the
|
||||
# convention-exception rationale.
|
||||
#
|
||||
# Ingests: OwnTracks (HTTP, no MQTT broker needed), Dawarich's own iOS/Android
|
||||
# app, Google Takeout exports. Auth: Authentik OIDC end-to-end.
|
||||
# ==============================================================================
|
||||
|
||||
- name: Deploy Dawarich LXC
|
||||
hosts: all
|
||||
become: true
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
- vars/vault.yml
|
||||
|
||||
pre_tasks:
|
||||
- name: Deploy banner
|
||||
debug:
|
||||
msg: "===== {{ ansible_play_name }} → {{ inventory_hostname }} ({{ ansible_host }}) ====="
|
||||
|
||||
- name: Install infisicalsdk on controller
|
||||
pip:
|
||||
name: infisicalsdk
|
||||
state: present
|
||||
extra_args: --break-system-packages
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
- name: Authenticate with Infisical
|
||||
infisical.vault.login:
|
||||
url: "{{ infisical_url }}"
|
||||
auth_method: universal_auth
|
||||
universal_auth_client_id: "{{ infisical_client_id }}"
|
||||
universal_auth_client_secret: "{{ infisical_client_secret }}"
|
||||
register: infisical_login
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
- name: Read dawarich secrets
|
||||
infisical.vault.read_secrets:
|
||||
login_data: "{{ infisical_login.login_data }}"
|
||||
project_id: "{{ infisical_project_id }}"
|
||||
env_slug: "prod"
|
||||
path: "/dawarich"
|
||||
as_dict: true
|
||||
register: repo_secrets
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
# OIDC creds live in /oidc alongside every other Authentik client (the same
|
||||
# pair pi-auth pushes into Authentik). default('') keeps the play
|
||||
# idempotent before secrets exist / OIDC is flipped on.
|
||||
- name: Read oidc secrets
|
||||
infisical.vault.read_secrets:
|
||||
login_data: "{{ infisical_login.login_data }}"
|
||||
project_id: "{{ infisical_project_id }}"
|
||||
env_slug: "prod"
|
||||
path: "/oidc"
|
||||
as_dict: true
|
||||
register: oidc_secrets
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
- name: Read shared secrets
|
||||
infisical.vault.read_secrets:
|
||||
login_data: "{{ infisical_login.login_data }}"
|
||||
project_id: "{{ infisical_project_id }}"
|
||||
env_slug: "prod"
|
||||
path: "/shared"
|
||||
as_dict: true
|
||||
register: shared_secrets
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
run_once: true
|
||||
|
||||
- name: Map secrets to vars
|
||||
set_fact:
|
||||
dawarich_db_password: "{{ repo_secrets.secrets.vault_dawarich_db_password }}"
|
||||
dawarich_secret_key_base: "{{ repo_secrets.secrets.vault_dawarich_secret_key_base }}"
|
||||
# OTP encryption keys — Dawarich ships built-in defaults but rotating them
|
||||
# off the public defaults is a one-line hardening win. All three required.
|
||||
dawarich_otp_primary_key: "{{ repo_secrets.secrets.vault_dawarich_otp_primary_key }}"
|
||||
dawarich_otp_deterministic_key: "{{ repo_secrets.secrets.vault_dawarich_otp_deterministic_key }}"
|
||||
dawarich_otp_salt: "{{ repo_secrets.secrets.vault_dawarich_otp_salt }}"
|
||||
dawarich_oidc_client_id: "{{ oidc_secrets.secrets.vault_dawarich_oidc_client_id | default('') }}"
|
||||
dawarich_oidc_client_secret: "{{ oidc_secrets.secrets.vault_dawarich_oidc_client_secret | default('') }}"
|
||||
watchtower_gotify_url: "{{ shared_secrets.secrets.vault_watchtower_gotify_url }}"
|
||||
watchtower_api_token: "{{ shared_secrets.secrets.vault_watchtower_api_token }}"
|
||||
|
||||
roles:
|
||||
- dawarich
|
||||
- alloy
|
||||
Reference in New Issue
Block a user