From 220e368bf388b59be7b123276f9fbc21d1cdf294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kaan=20Barmore-Gen=C3=A7?= Date: Sun, 18 Dec 2022 01:35:54 -0500 Subject: [PATCH] Use async sleep & document the repeat option (#70) * Use async sleep when long running Using an async sleep just seems more appropriate as we are in an async context, although the results are identical since gandi-live-dns only uses a single thread. * Document repeat option * Fix lints --- Readme.md | 32 ++++++++++++++++++++++++++++++-- src/main.rs | 11 +++++------ src/opts.rs | 9 +++++++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Readme.md b/Readme.md index 2701b4f..ae9d764 100644 --- a/Readme.md +++ b/Readme.md @@ -10,8 +10,8 @@ this creates a dynamic DNS system. If you want to host web services but you don't have a static IP address, this tool will allow you to keep your domains pointed at the right IP address. This program can update both IPv4 and IPv6 addresses for one or more domains and -subdomains. It's a one-shot tool that's meant to be managed with a systemd timer -or cron. +subdomains. It can be used as a one-shot tool managed with a systemd timer +or cron, or a long-running process that reschedules itself. ## Usage @@ -67,6 +67,34 @@ build it from source and you have a working rust install, you can use `cargo ins ## Automation +### By running as a background process + +`gandi-live-dns` can run as a daemon, a background process, periodically perform +the IP address updates. To do so, add the `--repeat=` command +line option. When given, this tool will not quit after updating your IP address +and instead will continue to perform periodic updates. + +If you are using Docker, you can add this option when starting it: + +```bash +# This will update your IP now, then repeat every 24 hours +docker run --rm -it -v $(pwd)/gandi.toml:/gandi.toml:ro seriousbug/gandi-live-dns-rust:latest --repeat=86400 +``` + +Or with a `docker-compose.yml` file, add it in the arguments: + +```yml + gandi-live-dns: + image: seriousbug/gandi-live-dns-rust:latest + restart: always + volumes: + - ./gandi.toml:/gandi.toml:ro + # Repeat the update every day + command: --repeat=86400 +``` + +### With a Systemd timer + The `Packaging` folder contains a Systemd service and timer, which you can use to automatically run this tool. By default it will update the IP addresses after every boot up, and at least once a day. You can adjust the timer to speed this diff --git a/src/main.rs b/src/main.rs index 4bdb20c..fd4fbf9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,8 @@ use config::IPSourceName; use ip_source::icanhazip::IPSourceIcanhazip; use reqwest::{header, Client, ClientBuilder, StatusCode}; use serde::Serialize; -use std::thread; use std::{num::NonZeroU32, sync::Arc, time::Duration}; -use tokio::{self, task::JoinHandle}; +use tokio::{self, task::JoinHandle, time::sleep}; mod config; mod gandi; mod ip_source; @@ -41,7 +40,7 @@ pub struct APIPayload { } async fn run(base_url: &str, conf: &Config) -> anyhow::Result<()> { - config::validate_config(&conf).die_with(|error| format!("Invalid config: {}", error)); + config::validate_config(conf).die_with(|error| format!("Invalid config: {}", error)); println!("Finding out the IP address..."); let ipv4_result = IP::get_ipv4().await; let ipv6_result = IP::get_ipv6().await; @@ -69,7 +68,7 @@ async fn run(base_url: &str, conf: &Config) -> anyhow::Result<()> for entry in &conf.entry { for entry_type in Config::types(entry) { - let fqdn = Config::fqdn(entry, &conf).to_string(); + let fqdn = Config::fqdn(entry, conf).to_string(); let url = GandiAPI { fqdn: &fqdn, rrset_name: &entry.name, @@ -84,7 +83,7 @@ async fn run(base_url: &str, conf: &Config) -> anyhow::Result<()> }; let payload = APIPayload { rrset_values: vec![ip.to_string()], - rrset_ttl: Config::ttl(entry, &conf), + rrset_ttl: Config::ttl(entry, conf), }; let req = client.put(url).json(&payload); let task_governor = governor.clone(); @@ -126,7 +125,7 @@ async fn main() -> anyhow::Result<()> { if let Some(delay) = opts.repeat { loop { run_dispatch(&conf).await.ok(); - thread::sleep(Duration::from_secs(delay)) + sleep(Duration::from_secs(delay)).await } } // otherwise run just once diff --git a/src/opts.rs b/src/opts.rs index 93fb62e..34d35c2 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -17,9 +17,14 @@ pub struct Opts { /// If enabled, any IPv6 (AAAA) records in the configuration file are ignored. #[clap(action, long)] pub skip_ipv6: bool, - /// Repeat after specified delay + /// Repeat after specified delay, in seconds. /// - /// If enabled waits for the given delay between updating DNS records + /// If enabled, this will continue to run and perform the updates + /// periodically. The first update will happen immediately, and later + /// updates will be delayed by this many seconds. + /// + /// This process will not fork, so you may need to use something like + /// `nohup` to keep it running in the background. #[clap(long)] pub repeat: Option, }