Something went wrong. Try again.
forked from tailscale/tailscale
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254// Copyright (c) Tailscale Inc & contributors// SPDX-License-Identifier: BSD-3-Clause
package tsnet_test
import ( "flag" "fmt" "log" "net/http" "net/http/httputil" "net/url" "os" "path/filepath"
"tailscale.com/tsnet")
// ExampleServer shows you how to construct a ready-to-use tsnet instance.func ExampleServer() { srv := new(tsnet.Server) if err := srv.Start(); err != nil { log.Fatalf("can't start tsnet server: %v", err) } defer srv.Close()}
// ExampleServer_hostname shows you how to set a tsnet server's hostname.//// This setting lets you control the host name of your program on your// tailnet. By default this will be the name of your program (such as foo// for a program stored at /usr/local/bin/foo). You can also override this// by setting the Hostname field.func ExampleServer_hostname() { srv := &tsnet.Server{ Hostname: "kirito", }
// do something with srv _ = srv}
// ExampleServer_dir shows you how to configure the persistent directory for// a tsnet application. This is where the Tailscale node information is stored// so that your application can reconnect to your tailnet when the application// is restarted.//// By default, tsnet will store data in your user configuration directory based// on the name of the binary. Note that this folder must already exist or tsnet// calls will fail.func ExampleServer_dir() { dir := filepath.Join("/data", "tsnet")
if err := os.MkdirAll(dir, 0700); err != nil { log.Fatal(err) }
srv := &tsnet.Server{ Dir: dir, }
// do something with srv _ = srv}
// ExampleServer_multipleInstances shows you how to configure multiple instances// of tsnet per program. This allows you to have multiple Tailscale nodes in the// same process/container.func ExampleServer_multipleInstances() { baseDir := "/data" var servers []*tsnet.Server for _, hostname := range []string{"ichika", "nino", "miku", "yotsuba", "itsuki"} { os.MkdirAll(filepath.Join(baseDir, hostname), 0700) srv := &tsnet.Server{ Hostname: hostname, AuthKey: os.Getenv("TS_AUTHKEY"), Ephemeral: true, Dir: filepath.Join(baseDir, hostname), } if err := srv.Start(); err != nil { log.Fatalf("can't start tsnet server: %v", err) } servers = append(servers, srv) }
// When you're done, close the instances defer func() { for _, srv := range servers { srv.Close() } }()}
// ExampleServer_ignoreLogsSometimes shows you how to ignore all of the log messages// written by a tsnet instance, but allows you to opt-into them if a command-line// flag is set.func ExampleServer_ignoreLogsSometimes() { tsnetVerbose := flag.Bool("tsnet-verbose", false, "if set, verbosely log tsnet information") hostname := flag.String("tsnet-hostname", "hikari", "hostname to use on the tailnet")
srv := &tsnet.Server{ Hostname: *hostname, }
if *tsnetVerbose { srv.Logf = log.New(os.Stderr, fmt.Sprintf("[tsnet:%s] ", *hostname), log.LstdFlags).Printf }}
// ExampleServer_HTTPClient shows you how to make HTTP requests over your tailnet.//// If you want to make outgoing HTTP connections to resources on your tailnet, use// the HTTP client that the tsnet.Server exposes.func ExampleServer_HTTPClient() { srv := &tsnet.Server{} cli := srv.HTTPClient()
resp, err := cli.Get("https://hello.ts.net") if resp == nil { log.Fatal(err) } // do something with resp _ = resp}
// ExampleServer_Start demonstrates the Start method, which should be called if// you need to explicitly start it. Note that the Start method is implicitly// called if needed.func ExampleServer_Start() { srv := new(tsnet.Server)
if err := srv.Start(); err != nil { log.Fatal(err) }
// Be sure to close the server instance at some point. It will stay open until // either the OS process ends or the server is explicitly closed. defer srv.Close()}
// ExampleServer_Listen shows you how to create a TCP listener on your tailnet and// then makes an HTTP server on top of that.func ExampleServer_Listen() { srv := &tsnet.Server{ Hostname: "tadaima", }
ln, err := srv.Listen("tcp", ":80") if err != nil { log.Fatal(err) }
log.Fatal(http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi there! Welcome to the tailnet!") })))}
// ExampleServer_ListenTLS shows you how to create a TCP listener on your tailnet and// then makes an HTTPS server on top of that.func ExampleServer_ListenTLS() { srv := &tsnet.Server{ Hostname: "aegis", }
ln, err := srv.ListenTLS("tcp", ":443") if err != nil { log.Fatal(err) }
log.Fatal(http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi there! Welcome to the tailnet!") })))}
// ExampleServer_ListenFunnel shows you how to create an HTTPS service on both your tailnet// and the public internet via Funnel.func ExampleServer_ListenFunnel() { srv := &tsnet.Server{ Hostname: "ophion", }
ln, err := srv.ListenFunnel("tcp", ":443") if err != nil { log.Fatal(err) }
log.Fatal(http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi there! Welcome to the tailnet!") })))}
// ExampleServer_ListenFunnel_funnelOnly shows you how to create a funnel-only HTTPS service.func ExampleServer_ListenFunnel_funnelOnly() { srv := new(tsnet.Server) srv.Hostname = "ophion" ln, err := srv.ListenFunnel("tcp", ":443", tsnet.FunnelOnly()) if err != nil { log.Fatal(err) }
log.Fatal(http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hi there! Welcome to the tailnet!") })))}
// ExampleServer_ListenService demonstrates how to advertise an HTTPS Service.func ExampleServer_ListenService() { srv := &tsnet.Server{ Hostname: "atum", }
ln, err := srv.ListenService("svc:my-service", tsnet.ServiceModeHTTP{ HTTPS: true, Port: 443, }) if err != nil { log.Fatal(err) }
log.Printf("Listening on https://%v\n", ln.FQDN) log.Fatal(http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "<html><body><h1>Hello, tailnet!</h1>") })))}
// ExampleServer_ListenService_reverseProxy demonstrates how to advertise a// Service targeting a reverse proxy. This is useful when the backing server is// external to the tsnet application.func ExampleServer_ListenService_reverseProxy() { // targetAddress represents the address of the backing server. const targetAddress = "1.2.3.4:80"
// We will use a reverse proxy to direct traffic to the backing server. reverseProxy := httputil.NewSingleHostReverseProxy(&url.URL{ Scheme: "http", Host: targetAddress, })
srv := &tsnet.Server{ Hostname: "tefnut", }
ln, err := srv.ListenService("svc:my-service", tsnet.ServiceModeHTTP{ HTTPS: true, Port: 443, }) if err != nil { log.Fatal(err) }
log.Printf("Listening on https://%v\n", ln.FQDN) log.Fatal(http.Serve(ln, reverseProxy))}