diff --git a/cmd/cloudflared/common_service.go b/cmd/cloudflared/common_service.go
new file mode 100644
index 00000000..db7338c0
--- /dev/null
+++ b/cmd/cloudflared/common_service.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+ "github.com/rs/zerolog"
+ "github.com/urfave/cli/v2"
+
+ "github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
+ "github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
+)
+
+func buildArgsForToken(c *cli.Context, log *zerolog.Logger) ([]string, error) {
+ token := c.Args().First()
+ if _, err := tunnel.ParseToken(token); err != nil {
+ return nil, cliutil.UsageError("Provided tunnel token is not valid (%s).", err)
+ }
+
+ return []string{
+ "tunnel", "run", "--token", token,
+ }, nil
+}
+
+func getServiceExtraArgsFromCliArgs(c *cli.Context, log *zerolog.Logger) ([]string, error) {
+ if c.NArg() > 0 {
+ // currently, we only support extra args for token
+ return buildArgsForToken(c, log)
+ } else {
+ // empty extra args
+ return make([]string, 0), nil
+ }
+}
diff --git a/cmd/cloudflared/linux_service.go b/cmd/cloudflared/linux_service.go
index 85d195fa..2d3060e7 100644
--- a/cmd/cloudflared/linux_service.go
+++ b/cmd/cloudflared/linux_service.go
@@ -6,7 +6,6 @@ package main
import (
"fmt"
"os"
- "path/filepath"
"github.com/rs/zerolog"
"github.com/urfave/cli/v2"
@@ -26,12 +25,6 @@ func runApp(app *cli.App, graceShutdownC chan struct{}) {
Name: "install",
Usage: "Install Cloudflare Tunnel as a system service",
Action: cliutil.ConfiguredAction(installLinuxService),
- Flags: []cli.Flag{
- &cli.BoolFlag{
- Name: "legacy",
- Usage: "Generate service file for non-named tunnels",
- },
- },
},
{
Name: "uninstall",
@@ -62,7 +55,7 @@ After=network.target
[Service]
TimeoutStartSec=0
Type=notify
-ExecStart={{ .Path }} --config /etc/cloudflared/config.yml --no-autoupdate{{ range .ExtraArgs }} {{ . }}{{ end }}
+ExecStart={{ .Path }} --no-autoupdate{{ range .ExtraArgs }} {{ . }}{{ end }}
Restart=on-failure
RestartSec=5s
@@ -112,7 +105,7 @@ var sysvTemplate = ServiceTemplate{
# Description: Cloudflare Tunnel agent
### END INIT INFO
name=$(basename $(readlink -f $0))
-cmd="{{.Path}} --config /etc/cloudflared/config.yml --pidfile /var/run/$name.pid --autoupdate-freq 24h0m0s{{ range .ExtraArgs }} {{ . }}{{ end }}"
+cmd="{{.Path}} --pidfile /var/run/$name.pid --autoupdate-freq 24h0m0s{{ range .ExtraArgs }} {{ . }}{{ end }}"
pid_file="/var/run/$name.pid"
stdout_log="/var/log/$name.log"
stderr_log="/var/log/$name.err"
@@ -191,27 +184,6 @@ func isSystemd() bool {
return false
}
-func copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile string, log *zerolog.Logger) error {
- srcCredentialPath := filepath.Join(userConfigDir, userCredentialFile)
- destCredentialPath := filepath.Join(serviceConfigDir, serviceCredentialFile)
- if srcCredentialPath != destCredentialPath {
- if err := copyCredential(srcCredentialPath, destCredentialPath); err != nil {
- return err
- }
- }
-
- srcConfigPath := filepath.Join(userConfigDir, userConfigFile)
- destConfigPath := filepath.Join(serviceConfigDir, serviceConfigFile)
- if srcConfigPath != destConfigPath {
- if err := copyConfig(srcConfigPath, destConfigPath); err != nil {
- return err
- }
- log.Info().Msgf("Copied %s to %s", srcConfigPath, destConfigPath)
- }
-
- return nil
-}
-
func installLinuxService(c *cli.Context) error {
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
@@ -223,52 +195,19 @@ func installLinuxService(c *cli.Context) error {
Path: etPath,
}
- if err := ensureConfigDirExists(serviceConfigDir); err != nil {
+ var extraArgsFunc func(c *cli.Context, log *zerolog.Logger) ([]string, error)
+ if c.NArg() == 0 {
+ extraArgsFunc = buildArgsForConfig
+ } else {
+ extraArgsFunc = buildArgsForToken
+ }
+
+ extraArgs, err := extraArgsFunc(c, log)
+ if err != nil {
return err
}
- if c.Bool("legacy") {
- userConfigDir := filepath.Dir(c.String("config"))
- userConfigFile := filepath.Base(c.String("config"))
- userCredentialFile := config.DefaultCredentialFile
- if err = copyUserConfiguration(userConfigDir, userConfigFile, userCredentialFile, log); err != nil {
- log.Err(err).Msgf("Failed to copy user configuration. Before running the service, ensure that %s contains two files, %s and %s",
- serviceConfigDir, serviceCredentialFile, serviceConfigFile)
- return err
- }
- templateArgs.ExtraArgs = []string{
- "--origincert", serviceConfigDir + "/" + serviceCredentialFile,
- }
- } else {
- src, _, err := config.ReadConfigFile(c, log)
- if err != nil {
- return err
- }
- // can't use context because this command doesn't define "credentials-file" flag
- configPresent := func(s string) bool {
- val, err := src.String(s)
- return err == nil && val != ""
- }
- if src.TunnelID == "" || !configPresent(tunnel.CredFileFlag) {
- return fmt.Errorf(`Configuration file %s must contain entries for the tunnel to run and its associated credentials:
-tunnel: TUNNEL-UUID
-credentials-file: CREDENTIALS-FILE
-`, src.Source())
- }
- if src.Source() != serviceConfigPath {
- if exists, err := config.FileExists(serviceConfigPath); err != nil || exists {
- return fmt.Errorf("Possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`", src.Source(), serviceConfigPath)
- }
-
- if err := copyFile(src.Source(), serviceConfigPath); err != nil {
- return fmt.Errorf("failed to copy %s to %s: %w", src.Source(), serviceConfigPath, err)
- }
- }
-
- templateArgs.ExtraArgs = []string{
- "tunnel", "run",
- }
- }
+ templateArgs.ExtraArgs = extraArgs
switch {
case isSystemd():
@@ -280,6 +219,42 @@ credentials-file: CREDENTIALS-FILE
}
}
+func buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, error) {
+ if err := ensureConfigDirExists(serviceConfigDir); err != nil {
+ return nil, err
+ }
+
+ src, _, err := config.ReadConfigFile(c, log)
+ if err != nil {
+ return nil, err
+ }
+
+ // can't use context because this command doesn't define "credentials-file" flag
+ configPresent := func(s string) bool {
+ val, err := src.String(s)
+ return err == nil && val != ""
+ }
+ if src.TunnelID == "" || !configPresent(tunnel.CredFileFlag) {
+ return nil, fmt.Errorf(`Configuration file %s must contain entries for the tunnel to run and its associated credentials:
+tunnel: TUNNEL-UUID
+credentials-file: CREDENTIALS-FILE
+`, src.Source())
+ }
+ if src.Source() != serviceConfigPath {
+ if exists, err := config.FileExists(serviceConfigPath); err != nil || exists {
+ return nil, fmt.Errorf("Possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`", src.Source(), serviceConfigPath)
+ }
+
+ if err := copyFile(src.Source(), serviceConfigPath); err != nil {
+ return nil, fmt.Errorf("failed to copy %s to %s: %w", src.Source(), serviceConfigPath, err)
+ }
+ }
+
+ return []string{
+ "--config", "/etc/cloudflared/config.yml", "tunnel", "run",
+ }, nil
+}
+
func installSystemd(templateArgs *ServiceTemplateArgs, log *zerolog.Logger) error {
for _, serviceTemplate := range systemdTemplates {
err := serviceTemplate.Generate(templateArgs)
diff --git a/cmd/cloudflared/macos_service.go b/cmd/cloudflared/macos_service.go
index e987df87..542b8849 100644
--- a/cmd/cloudflared/macos_service.go
+++ b/cmd/cloudflared/macos_service.go
@@ -50,6 +50,9 @@ func newLaunchdTemplate(installPath, stdoutPath, stderrPath string) *ServiceTemp
ProgramArguments
{{ .Path }}
+ {{- range $i, $item := .ExtraArgs}}
+ {{ $item }}
+ {{- end}}
RunAtLoad
@@ -129,6 +132,13 @@ func installLaunchd(c *cli.Context) error {
log.Err(err).Msg("Error determining install path")
return errors.Wrap(err, "Error determining install path")
}
+ extraArgs, err := getServiceExtraArgsFromCliArgs(c, log)
+ if err != nil {
+ errMsg := "Unable to determine extra arguments for launch daemon"
+ log.Err(err).Msg(errMsg)
+ return errors.Wrap(err, errMsg)
+ }
+
stdoutPath, err := stdoutPath()
if err != nil {
log.Err(err).Msg("error determining stdout path")
@@ -140,7 +150,7 @@ func installLaunchd(c *cli.Context) error {
return errors.Wrap(err, "error determining stderr path")
}
launchdTemplate := newLaunchdTemplate(installPath, stdoutPath, stderrPath)
- templateArgs := ServiceTemplateArgs{Path: etPath}
+ templateArgs := ServiceTemplateArgs{Path: etPath, ExtraArgs: extraArgs}
err = launchdTemplate.Generate(&templateArgs)
if err != nil {
log.Err(err).Msg("error generating launchd template")
diff --git a/cmd/cloudflared/tunnel/subcommands.go b/cmd/cloudflared/tunnel/subcommands.go
index 8362d8f8..905c8ad6 100644
--- a/cmd/cloudflared/tunnel/subcommands.go
+++ b/cmd/cloudflared/tunnel/subcommands.go
@@ -644,7 +644,7 @@ func runCommand(c *cli.Context) error {
// Check if token is provided and if not use default tunnelID flag method
if tokenStr := c.String(TunnelTokenFlag); tokenStr != "" {
- if token, err := parseToken(tokenStr); err == nil {
+ if token, err := ParseToken(tokenStr); err == nil {
return sc.runWithCredentials(token.Credentials())
}
@@ -663,7 +663,7 @@ func runCommand(c *cli.Context) error {
}
}
-func parseToken(tokenStr string) (*connection.TunnelToken, error) {
+func ParseToken(tokenStr string) (*connection.TunnelToken, error) {
content, err := base64.StdEncoding.DecodeString(tokenStr)
if err != nil {
return nil, err
diff --git a/cmd/cloudflared/tunnel/subcommands_test.go b/cmd/cloudflared/tunnel/subcommands_test.go
index 81f542c7..2016fe6d 100644
--- a/cmd/cloudflared/tunnel/subcommands_test.go
+++ b/cmd/cloudflared/tunnel/subcommands_test.go
@@ -183,7 +183,7 @@ func Test_validateHostname(t *testing.T) {
}
func Test_TunnelToken(t *testing.T) {
- token, err := parseToken("aabc")
+ token, err := ParseToken("aabc")
require.Error(t, err)
require.Nil(t, token)
@@ -198,7 +198,7 @@ func Test_TunnelToken(t *testing.T) {
token64 := base64.StdEncoding.EncodeToString(tokenJsonStr)
- token, err = parseToken(token64)
+ token, err = ParseToken(token64)
require.NoError(t, err)
require.Equal(t, token, expectedToken)
}
diff --git a/cmd/cloudflared/windows_service.go b/cmd/cloudflared/windows_service.go
index 2eba4780..6006c0b0 100644
--- a/cmd/cloudflared/windows_service.go
+++ b/cmd/cloudflared/windows_service.go
@@ -193,8 +193,15 @@ func installWindowsService(c *cli.Context) error {
s.Close()
return fmt.Errorf("Service %s already exists", windowsServiceName)
}
+ extraArgs, err := getServiceExtraArgsFromCliArgs(c, &log)
+ if err != nil {
+ errMsg := "Unable to determine extra arguments for windows service"
+ log.Err(err).Msg(errMsg)
+ return errors.Wrap(err, errMsg)
+ }
+
config := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}
- s, err = m.CreateService(windowsServiceName, exepath, config)
+ s, err = m.CreateService(windowsServiceName, exepath, config, extraArgs...)
if err != nil {
return errors.Wrap(err, "Cannot install service")
}