// Blacktip is the edge: run it on a public server that owns the IP addresses. package main import ( "context" "flag" "log" "os" "os/signal" "strings" "git.veillax.com/Veillax/blacktip" "git.veillax.com/Veillax/reef/dotenv" "git.veillax.com/Veillax/reef/selfupdate" ) // version is set at build time (deploy/build.sh). var version = "dev" func env(k, def string) string { if v := os.Getenv(k); v != "" { return v } return def } func main() { // secrets (tokens, DNS-provider credentials) can live in a .env file instead of the command line envFile := dotenv.ArgPath(os.Args[1:], ".env") if _, err := dotenv.Load(envFile); err != nil { log.Fatalf("read %s: %v", envFile, err) } hh := flag.String("hammerhead", env("BLACKTIP_HAMMERHEAD", ""), "URL of hammerhead, e.g. http://10.0.0.5:8080") token := flag.String("token", env("BLACKTIP_TOKEN", ""), "edge token from the hammerhead UI") tun := flag.String("tunnel", env("BLACKTIP_TUNNEL", ":51820"), "UDP listen address for the WireGuard tunnel (open this UDP port in your firewall)") data := flag.String("data", env("BLACKTIP_DATA", "./blacktip-data"), "directory for the WireGuard key and certificates") dockerOn := flag.Bool("docker", os.Getenv("BLACKTIP_DOCKER") == "1", "report local Docker containers so they can be picked as targets in the UI") traefikPath := flag.String("traefik", os.Getenv("BLACKTIP_TRAEFIK"), "path to a Traefik binary: serve http/https resources with Traefik instead of the built-in proxy") acmeDNS := flag.String("acme-dns", os.Getenv("BLACKTIP_ACME_DNS"), "with -traefik: DNS-challenge provider (e.g. cloudflare) for wildcard certificates; its credentials go in this process's environment") noACME := flag.Bool("no-acme", false, "with -traefik: serve Traefik's self-signed certificate instead of requesting Let's Encrypt ones") flag.String("env", ".env", "file to read secrets and settings from") autoUpdate := flag.Bool("auto-update", os.Getenv("BLACKTIP_AUTO_UPDATE") == "1", "check for new releases every few hours and update and restart by itself (Linux and macOS)") showVersion := flag.Bool("version", false, "print the version and exit") flag.Parse() if *showVersion { os.Stdout.WriteString("blacktip " + version + "\n") return } if *hh == "" || *token == "" { flag.Usage() os.Exit(2) } upd := selfupdate.Config{Server: "https://git.veillax.com", Repo: "Veillax/blacktip", App: "blacktip", Current: version, Logf: log.Printf} b, err := blacktip.New(blacktip.Config{ Hammerhead: strings.TrimRight(*hh, "/"), Token: *token, TunnelAddr: *tun, DataDir: *data, Docker: *dockerOn, Traefik: blacktip.TraefikConfig{Path: *traefikPath, ACMEDNS: *acmeDNS, NoACME: *noACME}, Version: version, AutoUpdate: *autoUpdate, UpdateNow: func(ctx context.Context) (string, error) { return selfupdate.CheckOnce(ctx, upd) }, }) if err != nil { log.Fatal(err) } log.Printf("blacktip %s starting", version) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() if *autoUpdate { go selfupdate.Run(ctx, upd) } if err := b.Run(ctx); err != nil { log.Fatal(err) } }