ts-docker-proxy/main.go

83 lines
1.6 KiB
Go

package main
import (
"context"
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/signal"
"strings"
"tailscale.com/tsnet"
)
func must[T any](t T, err error) T {
if err != nil {
panic(err)
}
return t
}
func main() {
var servers []*http.Server
upstreamsConfig := os.Getenv("UPSTREAMS")
hosts := strings.Split(upstreamsConfig, ",")
if upstreamsConfig == "" || len(hosts) == 0 {
log.Fatalf("set UPSTREAMS in environment like 'dockerhost:7400,otherdocker:80'")
}
for _, upstream := range hosts {
hostname, port, ok := strings.Cut(upstream, ":")
if hostname == "" {
// parsing error, just skip it
continue
}
if !ok || port == "" {
// default to 80
port = "80"
}
s := &tsnet.Server{
Dir: "/.config/" + hostname,
Hostname: hostname,
Logf: func(s string, a ...any) { // silence most tsnet logs
if strings.HasPrefix(s, "To start this tsnet server") {
log.Printf(s, a...)
}
},
}
defer s.Close()
ln, err := s.Listen("tcp", ":80")
if err != nil {
fmt.Printf("%+v\n", err)
return
}
defer ln.Close()
srv := &http.Server{
Handler: httputil.NewSingleHostReverseProxy(
must(url.Parse("http://" + hostname + ":" + port + "/")),
),
}
servers = append(servers, srv)
// start server
go func() {
err = srv.Serve(ln)
fmt.Printf("%+v\n", err)
}()
}
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)
<-sigint
for _, server := range servers {
if err := server.Shutdown(context.Background()); err != nil {
log.Printf("HTTP server Shutdown: %v", err)
}
}
}