Last active
April 19, 2022 17:22
-
-
Save bmizerany/f032a653cbfa47d0fd86f44a0b0f6940 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
"tailscale.com/client/tailscale" | |
"tailscale.com/tailcfg" | |
"tailscale.com/tsnet" | |
) | |
func main() { | |
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
user, err := getTailscaleUser(r.Context(), r.RemoteAddr) | |
if err != nil { | |
fmt.Fprintf(w, "Hey! You're not on Tailscale! You can only see public things.\n") | |
} else { | |
fmt.Fprintf(w, "Hello, %v! You can access internal routes.\n", user.LoginName) | |
} | |
}) | |
// Server internal VPN traffic. | |
go listenAndServeTailscaleTLS(h) | |
// Serve public traffic from Fly's edge. | |
log.Fatal(http.ListenAndServe(":8080", h)) | |
} | |
func getTailscaleUser(ctx context.Context, ipPort string) (*tailcfg.UserProfile, error) { | |
whois, err := tailscale.WhoIs(ctx, ipPort) | |
if err != nil { | |
return nil, fmt.Errorf("failed to identify remote host: %w", err) | |
} | |
if len(whois.Node.Tags) != 0 { | |
return nil, fmt.Errorf("tagged nodes are not users") | |
} | |
if whois.UserProfile == nil || whois.UserProfile.LoginName == "" { | |
return nil, fmt.Errorf("failed to identify remote user") | |
} | |
return whois.UserProfile, nil | |
} | |
// listenAndServeTailscaleTLS listens on the tailnet associated with TS_AUTHKEY | |
// on ports 443 and 80. Port 80 redirects all requests to 443. | |
func listenAndServeTailscaleTLS(h http.Handler) { | |
ts := &tsnet.Server{ | |
Ephemeral: true, | |
Hostname: "tierdemo", | |
} | |
go forceTLS(ts) | |
ln, err := ts.Listen("tcp", ":443") | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Fatal(http.Serve(ln, h)) | |
} | |
func forceTLS(ts *tsnet.Server) { | |
// wait for tailscale to start before trying to fetch cert names | |
for i := 0; i < 60; i++ { | |
st, err := tailscale.Status(context.Background()) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Printf("tailscale status: %v", st.BackendState) | |
if st.BackendState == "Running" { | |
break | |
} | |
time.Sleep(time.Second) | |
} | |
l80, err := ts.Listen("tcp", ":80") | |
if err != nil { | |
log.Fatal(err) | |
} | |
name, ok := tailscale.ExpandSNIName(context.Background(), ts.Hostname) | |
if !ok { | |
log.Fatalf("can't get hostname for https redirect") | |
} | |
if err := http.Serve(l80, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
http.Redirect(w, r, fmt.Sprintf("https://%s", name), http.StatusMovedPermanently) | |
})); err != nil { | |
log.Fatal(err) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set -x | |
set -e | |
GOOS=linux go build -o demo | |
flyctl deploy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM scratch | |
COPY demo / | |
CMD ["/demo"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fly.io.demo % ./deploy.sh | |
+ set -e | |
+ GOOS=linux | |
+ go build -o demo | |
+ flyctl deploy | |
==> Verifying app config | |
--> Verified app config | |
==> Building image | |
==> Creating build context | |
--> Creating build context done | |
==> Building image with Docker | |
--> docker host: 20.10.11 linux aarch64 | |
[+] Building 0.3s (0/1) | |
[+] Building 0.2s (5/5) FINISHED | |
=> [internal] load remote build context 0.0s | |
=> copy /context / 0.1s | |
=> CACHED copy /context / 0.0s | |
=> [1/1] COPY demo / 0.0s | |
=> exporting to image 0.0s | |
=> => exporting layers 0.0s | |
=> => writing image sha256:4616a340367b3af822b1d1d9a4aace67e84855c12c331e03b41b49bfe01b9322 0.0s | |
=> => naming to registry.fly.io/wandering-night-9237:deployment-1650388771 0.0s | |
--> Building image done | |
==> Pushing image to fly | |
The push refers to repository [registry.fly.io/wandering-night-9237] | |
8e88445fefd1: Pushed | |
deployment-1650388771: digest: sha256:bfc3ac6cab4ece6a827fa53e6d3ca9d0b6ea94cde20d56e713a6bc357a6949ae size: 527 | |
--> Pushing image done | |
image: registry.fly.io/wandering-night-9237:deployment-1650388771 | |
image size: 18 MB | |
==> Creating release | |
--> release v28 created | |
--> You can detach the terminal anytime without stopping the deployment | |
==> Monitoring deployment | |
1 desired, 1 placed, 0 healthy, 1 unhealthy [restarts: 2] [health checks: 1 total] | |
Failed Instances | |
Failure #1 | |
Instance | |
ID PROCESS VERSION REGION DESIRED STATUS HEALTH CHECKS RESTARTS CREATED | |
d60f3801 28 sjc run pending 1 total 2 26s ago | |
Recent Events | |
TIMESTAMP TYPE MESSAGE | |
2022-04-19T17:19:51Z Received Task received by client | |
2022-04-19T17:19:51Z Task Setup Building Task Directory | |
2022-04-19T17:19:57Z Started Task started by client | |
2022-04-19T17:20:01Z Terminated Exit Code: 1 | |
2022-04-19T17:20:01Z Restarting Task restarting in 1.180340653s | |
2022-04-19T17:20:08Z Started Task started by client | |
2022-04-19T17:20:12Z Terminated Exit Code: 1 | |
2022-04-19T17:20:12Z Restarting Task restarting in 1.187884191s | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 [v2] Routine: receive incoming v6 - started | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 [v2] Routine: receive incoming receiveDERP - started | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 [v1] got initial portlist info in 3ms | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: [v1] HostInfo: {"IPNVersion":"1.22.2-date.20220107","BackendLogID":"tslib-TODO","OS":"linux","OSVersion":"Other; kernel=5.12.2; env=fly","Hostname":"tierdemo","GoArch":"amd64","Services":[{"Proto":"tcp","Port":22,"Description":"hallpass"},{"Proto":"tcp","Port":8080,"Description":"demo"}]} | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 Backend: logs: be:tslib-TODO fe: | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 Switching ipn state NoState -> NeedsLogin (WantRunning=true, nm=false) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 blockEngineUpdates(true) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 wgengine: Reconfig: configuring userspace wireguard config (with 0/0 peers) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 wgengine: Reconfig: configuring router | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 [v1] warning: fakeRouter.Set: not implemented. | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 wgengine: Reconfig: configuring DNS | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 dns: Set: {DefaultResolvers:[] Routes:{} SearchDomains:[] Hosts:0} | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 dns: Resolvercfg: {Routes:{} Hosts:0 LocalDomains:[]} | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 dns: OScfg: {Nameservers:[] SearchDomains:[] MatchDomains:[]} | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 [v1] wgengine: Reconfig done | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 StartLoginInteractive: url=false | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: client.Login(false, 6) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: [v1] authRoutine: state:new; wantLoggedIn=true | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: [v1] direct.TryLogin(token=false, flags=6) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: LoginInteractive -> regen=true | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: doLogin(regen=true, hasUrl=false) | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 control: [v1] mapRoutine: state:authenticating | |
2022-04-19T17:20:20Z [info]2022/04/19 17:20:20 health("overall"): error: state=NeedsLogin, wantRunning=true | |
2022-04-19T17:20:21Z [info]2022/04/19 17:20:21 [v1] netmap packet filter: (not ready yet) | |
2022-04-19T17:20:21Z [info]2022/04/19 17:20:21 [v1] LinkChange: minor | |
2022-04-19T17:20:21Z [info]2022/04/19 17:20:21 [v1] magicsock: starting endpoint update (link-change-minor) | |
2022-04-19T17:20:21Z [info]2022/04/19 17:20:21 [v1] magicsock: ignoring pre-DERP map, STUN-less endpoint update: [{172.19.3.98:60020 local} {172.19.3.99:60020 local} {[2604:1380:45e1:3002:0:d60f:3801:1]:60020 local}] | |
2022-04-19T17:20:22Z [info]2022/04/19 17:20:22 Failed to connect to local Tailscale daemon for /localapi/v0/status; not running? Error: dial unix tailscaled.sock: connect: no such file or directory | |
2022-04-19T17:20:23Z [info]Main child exited normally with code: 1 | |
2022-04-19T17:20:23Z [info]Starting clean up. | |
--> v28 failed - Failed due to unhealthy allocations - rolling back to job version 27 and deploying as v29 | |
--> Troubleshooting guide at https://fly.io/docs/getting-started/troubleshooting/ | |
Error abort |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# fly.toml file generated for wandering-night-9237 on 2022-04-18T20:45:41-07:00 | |
app = "wandering-night-9237" | |
kill_signal = "SIGINT" | |
kill_timeout = 5 | |
processes = [] | |
[env] | |
TAILSCALE_USE_WIP_CODE = 1 | |
[experimental] | |
allowed_public_ports = [] | |
auto_rollback = true | |
[[services]] | |
http_checks = [] | |
internal_port = 8080 | |
processes = ["app"] | |
protocol = "tcp" | |
script_checks = [] | |
[services.concurrency] | |
hard_limit = 25 | |
soft_limit = 20 | |
type = "connections" | |
[[services.ports]] | |
force_https = true | |
handlers = ["http"] | |
port = 80 | |
[[services.ports]] | |
handlers = ["tls", "http"] | |
port = 443 | |
[[services.tcp_checks]] | |
grace_period = "1s" | |
interval = "15s" | |
restart_limit = 0 | |
timeout = "2s" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment