- name: Deploy LNBits with Poetry and configure Caddy reverse proxy hosts: vipy become: yes vars_files: - ../../infra_vars.yml - ../../services_config.yml - ../../infra_secrets.yml - ./lnbits_vars.yml vars: lnbits_subdomain: "{{ subdomains.lnbits }}" caddy_sites_dir: "{{ caddy_sites_dir }}" lnbits_domain: "{{ lnbits_subdomain }}.{{ root_domain }}" uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}" tasks: - name: Create lnbits directory file: path: "{{ lnbits_dir }}" state: directory owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: '0755' - name: Install required system packages apt: name: - python3 - python3-pip - python3-venv - python3-dev - git - curl - pkg-config - build-essential - libsecp256k1-dev - libffi-dev - libgmp-dev - libpq-dev - automake - autoconf - libtool - m4 - gawk state: present update_cache: yes - name: Install uv packaging tool shell: | curl -LsSf https://astral.sh/uv/install.sh | sh args: creates: "/home/{{ ansible_user }}/.local/bin/uv" become: yes become_user: "{{ ansible_user }}" environment: HOME: "/home/{{ ansible_user }}" - name: Clone LNBits repository git: repo: https://github.com/lnbits/lnbits.git dest: "{{ lnbits_dir }}/lnbits" version: "v1.3.1" accept_hostkey: yes - name: Change ownership of LNBits directory to user file: path: "{{ lnbits_dir }}/lnbits" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" recurse: yes - name: Install LNBits dependencies with uv (Python 3.12) command: /home/{{ ansible_user }}/.local/bin/uv sync --python 3.12 --all-extras --no-dev args: chdir: "{{ lnbits_dir }}/lnbits" become: yes become_user: "{{ ansible_user }}" environment: HOME: "/home/{{ ansible_user }}" PATH: "/home/{{ ansible_user }}/.local/bin:/usr/local/bin:/usr/bin:/bin" SECP_BUNDLED: "0" PKG_CONFIG_PATH: "/usr/lib/x86_64-linux-gnu/pkgconfig" ACLOCAL: "aclocal" AUTOMAKE: "automake" - name: Copy .env.example to .env copy: src: "{{ lnbits_dir }}/lnbits/.env.example" dest: "{{ lnbits_dir }}/lnbits/.env" remote_src: yes owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: '0644' - name: Configure LNBits environment variables lineinfile: path: "{{ lnbits_dir }}/lnbits/.env" regexp: "^{{ item.key }}=" line: "{{ item.key }}={{ item.value }}" state: present loop: - key: "LNBITS_BACKEND_WALLET_CLASS" value: "FakeWallet" - key: "LNBITS_ADMIN_UI" value: "true" - key: "HOST" value: "0.0.0.0" - key: "PORT" value: "{{ lnbits_port }}" - key: "LNBITS_DATA_FOLDER" value: "{{ lnbits_data_dir }}" - key: "LNBITS_EXTENSIONS_PATH" value: "{{ lnbits_data_dir }}/extensions" - name: Create systemd service file for LNBits copy: dest: /etc/systemd/system/lnbits.service content: | [Unit] Description=LNBits After=network.target [Service] Type=simple User={{ ansible_user }} WorkingDirectory={{ lnbits_dir }}/lnbits ExecStart=/home/{{ ansible_user }}/.local/bin/uv run --python 3.12 lnbits Restart=always RestartSec=30 Environment=PYTHONUNBUFFERED=1 Environment="PATH=/home/{{ ansible_user }}/.local/bin:/usr/local/bin:/usr/bin:/bin" Environment=SECP_BUNDLED=0 [Install] WantedBy=multi-user.target owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: '0644' - name: Reload systemd systemd: daemon_reload: yes - name: Enable and start LNBits service systemd: name: lnbits enabled: yes state: started - name: Ensure Caddy sites-enabled directory exists file: path: "{{ caddy_sites_dir }}" state: directory owner: root group: root mode: '0755' - name: Ensure Caddyfile includes import directive for sites-enabled lineinfile: path: /etc/caddy/Caddyfile line: 'import sites-enabled/*' insertafter: EOF state: present backup: yes create: yes mode: '0644' - name: Create Caddy reverse proxy configuration for lnbits copy: dest: "{{ caddy_sites_dir }}/lnbits.conf" content: | {{ lnbits_domain }} { reverse_proxy localhost:{{ lnbits_port }} { header_up X-Forwarded-Host {{ lnbits_domain }} } } owner: root group: root mode: '0644' - name: Reload Caddy to apply new config command: systemctl reload caddy - name: Create Uptime Kuma monitor setup script for LNBits delegate_to: localhost become: no copy: dest: /tmp/setup_lnbits_monitor.py content: | #!/usr/bin/env python3 import sys import yaml from uptime_kuma_api import UptimeKumaApi, MonitorType try: with open('/tmp/ansible_config.yml', 'r') as f: config = yaml.safe_load(f) url = config['uptime_kuma_url'] username = config['username'] password = config['password'] monitor_url = config['monitor_url'] monitor_name = config['monitor_name'] api = UptimeKumaApi(url, timeout=30) api.login(username, password) # Get all monitors monitors = api.get_monitors() # Find or create "services" group group = next((m for m in monitors if m.get('name') == 'services' and m.get('type') == 'group'), None) if not group: group_result = api.add_monitor(type='group', name='services') # Refresh to get the group with id monitors = api.get_monitors() group = next((m for m in monitors if m.get('name') == 'services' and m.get('type') == 'group'), None) # Check if monitor already exists existing_monitor = None for monitor in monitors: if monitor.get('name') == monitor_name: existing_monitor = monitor break # Get ntfy notification ID notifications = api.get_notifications() ntfy_notification_id = None for notif in notifications: if notif.get('type') == 'ntfy': ntfy_notification_id = notif.get('id') break if existing_monitor: print(f"Monitor '{monitor_name}' already exists (ID: {existing_monitor['id']})") print("Skipping - monitor already configured") else: print(f"Creating monitor '{monitor_name}'...") api.add_monitor( type=MonitorType.HTTP, name=monitor_name, url=monitor_url, parent=group['id'], interval=60, maxretries=3, retryInterval=60, notificationIDList={ntfy_notification_id: True} if ntfy_notification_id else {} ) api.disconnect() print("SUCCESS") except Exception as e: print(f"ERROR: {str(e)}", file=sys.stderr) sys.exit(1) mode: '0755' - name: Create temporary config for monitor setup delegate_to: localhost become: no copy: dest: /tmp/ansible_config.yml content: | uptime_kuma_url: "{{ uptime_kuma_api_url }}" username: "{{ uptime_kuma_username }}" password: "{{ uptime_kuma_password }}" monitor_url: "https://{{ lnbits_domain }}/api/v1/health" monitor_name: "LNBits" mode: '0644' - name: Run Uptime Kuma monitor setup command: python3 /tmp/setup_lnbits_monitor.py delegate_to: localhost become: no register: monitor_setup changed_when: "'SUCCESS' in monitor_setup.stdout" ignore_errors: yes - name: Clean up temporary files delegate_to: localhost become: no file: path: "{{ item }}" state: absent loop: - /tmp/setup_lnbits_monitor.py - /tmp/ansible_config.yml