Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9428be9

Browse files
committed
chore: replace cloudflare dev tunnel with frp
1 parent 300c6d0 commit 9428be9

File tree

8 files changed

+222
-370
lines changed

8 files changed

+222
-370
lines changed

.goreleaser.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ before:
1717
builds:
1818
- id: coder-slim
1919
dir: cmd/coder
20-
ldflags: ["-s -w -X github.com/coder/coder/cli/buildinfo.tag={{ .Version }}"]
20+
flags: ["-tags=frp"]
21+
ldflags:
22+
["-s -w -X github.com/coder/coder/cli/buildinfo.tag={{ .Version }}"]
2123
env: [CGO_ENABLED=0]
2224
goos: [darwin, linux, windows]
2325
goarch: [amd64]
@@ -28,8 +30,9 @@ builds:
2830
2931
- id: coder
3032
dir: cmd/coder
31-
flags: [-tags=embed]
32-
ldflags: ["-s -w -X github.com/coder/coder/cli/buildinfo.tag={{ .Version }}"]
33+
flags: ["-tags=embed,frp"]
34+
ldflags:
35+
["-s -w -X github.com/coder/coder/cli/buildinfo.tag={{ .Version }}"]
3336
env: [CGO_ENABLED=0]
3437
goos: [darwin, linux, windows]
3538
goarch: [amd64, arm64]
@@ -61,4 +64,4 @@ release:
6164
ids: [coder, packages]
6265

6366
snapshot:
64-
name_template: '{{ .Version }}-devel+{{ .ShortCommit }}'
67+
name_template: "{{ .Version }}-devel+{{ .ShortCommit }}"

cli/start.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ import (
3232
"github.com/coder/coder/coderd"
3333
"github.com/coder/coder/coderd/database"
3434
"github.com/coder/coder/coderd/database/databasefake"
35+
"github.com/coder/coder/coderd/devtunnel"
3536
"github.com/coder/coder/coderd/gitsshkey"
36-
"github.com/coder/coder/coderd/tunnel"
3737
"github.com/coder/coder/codersdk"
3838
"github.com/coder/coder/provisioner/terraform"
3939
"github.com/coder/coder/provisionerd"
@@ -105,7 +105,13 @@ func start() *cobra.Command {
105105
// If an access URL is specified, always skip tunneling.
106106
skipTunnel = true
107107
}
108-
var tunnelErr <-chan error
108+
109+
var (
110+
tunnelErrChan <-chan error
111+
ctxTunnel, closeTunnel = context.WithCancel(cmd.Context())
112+
)
113+
defer closeTunnel()
114+
109115
// If we're attempting to tunnel in dev-mode, the access URL
110116
// needs to be changed to use the tunnel.
111117
if dev && !skipTunnel {
@@ -124,13 +130,14 @@ func start() *cobra.Command {
124130
return err
125131
}
126132
if err == nil {
127-
accessURL, tunnelErr, err = tunnel.New(cmd.Context(), localURL.String())
133+
accessURL, tunnelErrChan, err = devtunnel.New(ctxTunnel, localURL)
128134
if err != nil {
129135
return xerrors.Errorf("create tunnel: %w", err)
130136
}
131137
}
132138
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
133139
}
140+
134141
validator, err := idtoken.NewValidator(cmd.Context(), option.WithoutAuthentication())
135142
if err != nil {
136143
return err
@@ -263,8 +270,10 @@ func start() *cobra.Command {
263270
case <-cmd.Context().Done():
264271
closeCoderd()
265272
return cmd.Context().Err()
266-
case err := <-tunnelErr:
267-
return err
273+
case err := <-tunnelErrChan:
274+
if err != nil {
275+
return err
276+
}
268277
case err := <-errCh:
269278
closeCoderd()
270279
return err
@@ -328,6 +337,12 @@ func start() *cobra.Command {
328337
spin.Stop()
329338
}
330339

340+
if dev && !skipTunnel {
341+
_, _ = fmt.Fprintf(cmd.OutOrStdout(), cliui.Styles.Prompt.String()+"Waiting for dev tunnel to close...\n")
342+
closeTunnel()
343+
<-tunnelErrChan
344+
}
345+
331346
_, _ = fmt.Fprintf(cmd.OutOrStdout(), cliui.Styles.Prompt.String()+"Waiting for WebSocket connections to close...\n")
332347
shutdownConns()
333348
closeCoderd()

cmd/templater/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"github.com/coder/coder/coderd"
2121
"github.com/coder/coder/coderd/database"
2222
"github.com/coder/coder/coderd/database/databasefake"
23-
"github.com/coder/coder/coderd/tunnel"
23+
"github.com/coder/coder/coderd/devtunnel"
2424
"github.com/coder/coder/codersdk"
2525
"github.com/coder/coder/provisioner/terraform"
2626
"github.com/coder/coder/provisionerd"
@@ -63,7 +63,7 @@ func parse(cmd *cobra.Command, parameters []codersdk.CreateParameterRequest) err
6363
if err != nil {
6464
return err
6565
}
66-
accessURL, errCh, err := tunnel.New(cmd.Context(), srv.URL)
66+
accessURL, errCh, err := devtunnel.New(cmd.Context(), serverURL)
6767
if err != nil {
6868
return err
6969
}

coderd/devtunnel/tunnel.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package devtunnel
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
7+
"strconv"
8+
"strings"
9+
10+
frpclient "github.com/fatedier/frp/client"
11+
frpconfig "github.com/fatedier/frp/pkg/config"
12+
frpconsts "github.com/fatedier/frp/pkg/consts"
13+
frpcrypto "github.com/fatedier/golib/crypto"
14+
"github.com/google/uuid"
15+
"github.com/moby/moby/pkg/namesgenerator"
16+
"golang.org/x/xerrors"
17+
)
18+
19+
// New creates a new tunnel pointing at the URL provided.
20+
// Once created, it returns the external hostname that will resolve to it.
21+
//
22+
// The tunnel will exit when the context provided is canceled.
23+
//
24+
// Upstream connection occurs async through Cloudflare, so the error channel
25+
// will only be executed if the tunnel has failed after numerous attempts.
26+
func New(ctx context.Context, coderurl *url.URL) (string, <-chan error, error) {
27+
frpcrypto.DefaultSalt = "frp"
28+
29+
cfg := frpconfig.GetDefaultClientConf()
30+
cfg.ServerAddr = "34.133.27.233"
31+
cfg.ServerPort = 7000
32+
cfg.LogWay = "file"
33+
cfg.LogFile = "/dev/null"
34+
cfg.LogLevel = "warn"
35+
36+
var (
37+
id = uuid.NewString()
38+
subdomain = strings.ReplaceAll(namesgenerator.GetRandomName(1), "_", "-")
39+
portStr = coderurl.Port()
40+
)
41+
if portStr == "" {
42+
portStr = "80"
43+
}
44+
45+
port, err := strconv.ParseInt(portStr, 10, 64)
46+
if err != nil {
47+
return "", nil, xerrors.Errorf("parse port %q: %w", port, err)
48+
}
49+
50+
httpcfg := map[string]frpconfig.ProxyConf{
51+
id: &frpconfig.HTTPProxyConf{
52+
BaseProxyConf: frpconfig.BaseProxyConf{
53+
ProxyName: id,
54+
ProxyType: frpconsts.HTTPProxy,
55+
UseEncryption: false,
56+
UseCompression: false,
57+
LocalSvrConf: frpconfig.LocalSvrConf{
58+
LocalIP: coderurl.Hostname(),
59+
LocalPort: int(port),
60+
},
61+
},
62+
DomainConf: frpconfig.DomainConf{
63+
SubDomain: subdomain,
64+
},
65+
Locations: []string{""},
66+
},
67+
}
68+
69+
if err := httpcfg[id].CheckForCli(); err != nil {
70+
return "", nil, xerrors.Errorf("check for cli: %w", err)
71+
}
72+
73+
svc, err := frpclient.NewService(cfg, httpcfg, nil, "")
74+
if err != nil {
75+
return "", nil, xerrors.Errorf("create new proxy service: %w", err)
76+
}
77+
78+
ch := make(chan error, 1)
79+
go func() {
80+
err := svc.Run()
81+
ch <- err
82+
close(ch)
83+
}()
84+
go func() {
85+
select {
86+
case <-ctx.Done():
87+
svc.Close()
88+
}
89+
}()
90+
91+
return fmt.Sprintf("https://%s.tunnel.coder.app", subdomain), ch, nil
92+
}

coderd/tunnel/tunnel_test.go renamed to coderd/devtunnel/tunnel_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
package tunnel_test
1+
package devtunnel_test
22

33
import (
44
"context"
55
"net"
66
"net/http"
77
"net/http/httptest"
8+
"net/url"
89
"os"
910
"testing"
1011
"time"
1112

1213
"github.com/stretchr/testify/require"
1314
"golang.org/x/xerrors"
1415

15-
"github.com/coder/coder/coderd/tunnel"
16+
"github.com/coder/coder/coderd/devtunnel"
1617
)
1718

1819
// The tunnel leaks a few goroutines that aren't impactful to production scenarios.
@@ -36,12 +37,16 @@ func TestTunnel(t *testing.T) {
3637

3738
ctx, cancelFunc := context.WithCancel(context.Background())
3839
defer cancelFunc()
39-
url, _, err := tunnel.New(ctx, srv.URL)
40+
41+
srvURL, err := url.Parse(srv.URL)
42+
require.NoError(t, err)
43+
44+
tunURL, _, err := devtunnel.New(ctx, srvURL)
4045
require.NoError(t, err)
41-
t.Log(url)
46+
t.Log(tunURL)
4247

4348
require.Eventually(t, func() bool {
44-
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
49+
req, err := http.NewRequestWithContext(ctx, "GET", tunURL, nil)
4550
require.NoError(t, err)
4651
res, err := http.DefaultClient.Do(req)
4752
var dnsErr *net.DNSError

coderd/tunnel/tunnel.go

Lines changed: 0 additions & 117 deletions
This file was deleted.

0 commit comments

Comments
 (0)