diff --git a/docker_install.v b/docker_install.v new file mode 100644 index 0000000..85f319f --- /dev/null +++ b/docker_install.v @@ -0,0 +1,138 @@ +module main + +import os + +// install_docker_stack generates a docker-compose.yml + config files in target_dir. +// When with_prometheus is true, also generates prometheus.yml and adds a prometheus service. +fn install_docker_stack(target_dir string, with_prometheus bool) ! { + os.mkdir_all(target_dir) or { return error('Cannot create ${target_dir}: ${err}') } + + // ntfy-bridge config + example_cfg := '# ntfy-bridge configuration +server: + port: 9090 + hmac_secret: "change-me-to-a-random-string" + +defaults: + priority: 3 + tags: ["bell"] + +sources: + generic: [] + gitea: [] + uptime_kuma: [] + docker: [] + http_poll: [] + cron: [] + +dedup: + enabled: false + +filters: + rules: [] + +outgoing: + webhooks: [] + +state: + file: "/data/state.json" +' + os.write_file('${target_dir}/ntfy-bridge.yaml', example_cfg) or { + return error('Failed to write config: ${err}') + } + println(' Wrote: ${target_dir}/ntfy-bridge.yaml') + + // Copy dashboard + if os.exists('dashboard.html') { + os.cp('dashboard.html', '${target_dir}/dashboard.html') or { + println(' Warning: could not copy dashboard.html') + } + println(' Wrote: ${target_dir}/dashboard.html') + } + + // docker-compose.yml + mut compose := 'services: + ntfy-bridge: + image: ghcr.io/bruno/ntfy-bridge:latest + container_name: ntfy-bridge + restart: unless-stopped + ports: + - "9090:9090" + volumes: + - ./ntfy-bridge.yaml:/etc/ntfy-bridge/ntfy-bridge.yaml:ro + - ./dashboard.html:/etc/ntfy-bridge/dashboard.html:ro + - ntfy-data:/data + environment: + - NTFY_TOKEN=\${NTFY_TOKEN:-} + - NTFY_HMAC_SECRET=\${NTFY_HMAC_SECRET:-} + healthcheck: + test: ["CMD", "wget", "--spider", "http://localhost:9090/health"] + interval: 30s + timeout: 5s + retries: 3 +' + + if with_prometheus { + compose += ' + prometheus: + image: prom/prometheus:latest + container_name: ntfy-prometheus + restart: unless-stopped + ports: + - "9091:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prom-data:/prometheus + command: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus" + +volumes: + ntfy-data: +' + + if with_prometheus { + compose += ' prom-data: +' + } + } else { + compose += ' +volumes: + ntfy-data: +' + } + + os.write_file('${target_dir}/docker-compose.yml', compose) or { + return error('Failed to write docker-compose.yml: ${err}') + } + println(' Wrote: ${target_dir}/docker-compose.yml') + + // Prometheus config + if with_prometheus { + prom_cfg := '# Prometheus configuration for ntfy-bridge monitoring +global: + scrape_interval: 15s + +scrape_configs: + - job_name: "ntfy-bridge" + metrics_path: /metrics + static_configs: + - targets: ["ntfy-bridge:9090"] +' + os.write_file('${target_dir}/prometheus.yml', prom_cfg) or { + return error('Failed to write prometheus.yml: ${err}') + } + println(' Wrote: ${target_dir}/prometheus.yml') + } + + println('') + println('Stack generated in ${target_dir}/') + println('') + println('Next steps:') + println(' 1. Edit ${target_dir}/ntfy-bridge.yaml to configure your sources') + println(' 2. cd ${target_dir} && docker compose up -d') + if with_prometheus { + println(' 3. Prometheus: http://localhost:9091/') + println(' 4. Add Prometheus as a Grafana data source') + } +} diff --git a/main.v b/main.v index 47e9092..42b6023 100644 --- a/main.v +++ b/main.v @@ -20,6 +20,8 @@ fn main() { install_svc := fp.bool('install-service', 0, false, 'Install as a system service (auto-detects OS)') uninstall_svc := fp.bool('uninstall-service', 0, false, 'Uninstall the system service') svc_status := fp.bool('service-status', 0, false, 'Check if the service is installed and running') + install_docker := fp.string('install-docker', 0, '', 'Generate docker-compose stack in