83 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			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)
 | |
| 		}
 | |
| 	}
 | |
| }
 |