Skip to content

Commit 1c92d9d

Browse files
authored
feat: support server in daemon mode (#221)
Signed-off-by: Toma Puljak <[email protected]>
1 parent bfb0ef5 commit 1c92d9d

File tree

9 files changed

+176
-9
lines changed

9 files changed

+176
-9
lines changed

README.md

+15-6
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,13 @@ md -Force "$Env:APPDATA\daytona"; [System.Net.ServicePointManager]::SecurityProt
9191
### Start the Daytona server:
9292

9393
```bash
94-
95-
daytona server
94+
# Start the Daytona Server (omit -d if you want to run it in the foreground)
95+
daytona server -d
9696
```
9797

9898
### Create your first dev environment by opening a new terminal, and executing just this command:
9999

100100
```bash
101-
102101
daytona create
103102
```
104103

@@ -174,10 +173,10 @@ curl -sf -L https://download.daytona.io/daytona/get-server.sh | sudo bash
174173
### Initializing Daytona
175174
To initialize Daytona, follow these steps:
176175

177-
__1. Start the Daytona Service:__
178-
This initiates the Daytona service, which must always be running for Daytona to function. Use the command:
176+
__1. Start the Daytona Server:__
177+
This initiates the Daytona Server in daemon mode. Use the command:
179178
```bash
180-
daytona server
179+
daytona server -d
181180
```
182181
__2. Add Your Git Provider of Choice:__
183182
Daytona supports GitHub, GitLab, Bitbucket and Gitea. To add them to your profile, use the command:
@@ -221,6 +220,16 @@ daytona code
221220

222221
This command opens your development environment in your preferred IDE, allowing you to start coding instantly.
223222

223+
### Stopping the Daytona Server:
224+
```bash
225+
daytona server stop
226+
```
227+
228+
### Restarting the Daytona Server:
229+
```bash
230+
daytona server restart
231+
```
232+
224233
## How to Extend Daytona
225234

226235
Daytona offers flexibility for extension through the creation of plugins and providers.

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ require (
129129
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect
130130
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
131131
github.com/json-iterator/go v1.1.12 // indirect
132+
github.com/kardianos/service v1.2.2 // indirect
132133
github.com/klauspost/compress v1.17.4 // indirect
133134
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
134135
github.com/klauspost/reedsolomon v1.9.15 // indirect

go.sum

+3
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+
10851085
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
10861086
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
10871087
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
1088+
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
1089+
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
10881090
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
10891091
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
10901092
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
@@ -1664,6 +1666,7 @@ golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7w
16641666
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
16651667
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
16661668
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
1669+
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
16671670
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
16681671
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
16691672
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

pkg/cmd/server/daemon/daemon.go

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package daemon
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"runtime"
7+
"strings"
8+
9+
"github.com/kardianos/service"
10+
)
11+
12+
type program struct {
13+
service.Interface
14+
}
15+
16+
func Start() error {
17+
cfg, err := getServiceConfig()
18+
if err != nil {
19+
return err
20+
}
21+
s, err := service.New(program{}, cfg)
22+
if err != nil {
23+
return err
24+
}
25+
err = s.Install()
26+
if err != nil {
27+
return err
28+
}
29+
return s.Start()
30+
}
31+
32+
func Stop() error {
33+
cfg, err := getServiceConfig()
34+
if err != nil {
35+
return err
36+
}
37+
s, err := service.New(program{}, cfg)
38+
if err != nil {
39+
return err
40+
}
41+
42+
err = s.Stop()
43+
if err != nil {
44+
return err
45+
}
46+
47+
return s.Uninstall()
48+
}
49+
50+
func getServiceConfig() (*service.Config, error) {
51+
svcConfig := &service.Config{
52+
Name: "DaytonaServerDaemon",
53+
DisplayName: "Daytona Server",
54+
Description: "This is the Daytona Server daemon.",
55+
Arguments: []string{"server"},
56+
EnvVars: map[string]string{
57+
"LOG_LEVEL": "debug",
58+
},
59+
}
60+
61+
user := os.Getenv("USER")
62+
63+
switch runtime.GOOS {
64+
case "windows":
65+
return nil, fmt.Errorf("daemon mode not supported on Windows")
66+
case "linux":
67+
if !strings.HasSuffix(service.Platform(), "systemd") {
68+
return nil, fmt.Errorf("on Linux, `server -d` is only supported with systemd. %s detected", service.Platform())
69+
}
70+
fallthrough
71+
case "darwin":
72+
if user != "" && user != "root" {
73+
svcConfig.Option = service.KeyValue{"UserService": true}
74+
}
75+
}
76+
77+
return svcConfig, nil
78+
}

pkg/cmd/server/restart.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2024 Daytona Platforms Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package server
5+
6+
import (
7+
"fmt"
8+
9+
log "github.com/sirupsen/logrus"
10+
"github.com/spf13/cobra"
11+
12+
"github.com/daytonaio/daytona/pkg/cmd/server/daemon"
13+
)
14+
15+
var restartCmd = &cobra.Command{
16+
Use: "restart",
17+
Short: "Restarts the Daytona Server daemon",
18+
Run: func(cmd *cobra.Command, args []string) {
19+
fmt.Println("Stopping the Daytona Server daemon...")
20+
err := daemon.Stop()
21+
if err != nil {
22+
log.Fatal(err)
23+
}
24+
25+
fmt.Println("Starting the Daytona Server daemon...")
26+
err = daemon.Start()
27+
if err != nil {
28+
log.Fatal(err)
29+
}
30+
fmt.Println("Daytona Server daemon restarted successfully")
31+
},
32+
}

pkg/cmd/server/server.go

+16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"time"
99

10+
"github.com/daytonaio/daytona/pkg/cmd/server/daemon"
1011
"github.com/daytonaio/daytona/pkg/server"
1112
"github.com/daytonaio/daytona/pkg/server/config"
1213
"github.com/daytonaio/daytona/pkg/server/frpc"
@@ -16,6 +17,8 @@ import (
1617
"github.com/spf13/cobra"
1718
)
1819

20+
var runAsDaemon bool
21+
1922
var ServerCmd = &cobra.Command{
2023
Use: "server",
2124
Short: "Start the server process",
@@ -25,6 +28,16 @@ var ServerCmd = &cobra.Command{
2528
// for now, force the log level to info when running the server
2629
log.SetLevel(log.InfoLevel)
2730
}
31+
32+
if runAsDaemon {
33+
fmt.Println("Starting the Daytona Server daemon...")
34+
err := daemon.Start()
35+
if err != nil {
36+
log.Fatal(err)
37+
}
38+
return
39+
}
40+
2841
errCh := make(chan error)
2942

3043
err := server.Start(errCh)
@@ -53,7 +66,10 @@ var ServerCmd = &cobra.Command{
5366
}
5467

5568
func init() {
69+
ServerCmd.PersistentFlags().BoolVarP(&runAsDaemon, "daemon", "d", false, "Run the server as a daemon")
5670
ServerCmd.AddCommand(configureCmd)
5771
ServerCmd.AddCommand(configCmd)
5872
ServerCmd.AddCommand(logsCmd)
73+
ServerCmd.AddCommand(stopCmd)
74+
ServerCmd.AddCommand(restartCmd)
5975
}

pkg/cmd/server/stop.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2024 Daytona Platforms Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package server
5+
6+
import (
7+
"fmt"
8+
9+
log "github.com/sirupsen/logrus"
10+
"github.com/spf13/cobra"
11+
12+
"github.com/daytonaio/daytona/pkg/cmd/server/daemon"
13+
)
14+
15+
var stopCmd = &cobra.Command{
16+
Use: "stop",
17+
Short: "Stops the Daytona Server daemon",
18+
Run: func(cmd *cobra.Command, args []string) {
19+
fmt.Println("Stopping the Daytona Server daemon...")
20+
err := daemon.Stop()
21+
if err != nil {
22+
log.Fatal(err)
23+
}
24+
},
25+
}

pkg/server/config/config.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ package config
66
import (
77
"encoding/json"
88
"errors"
9-
"log"
109
"os"
1110
"path"
1211

1312
"github.com/daytonaio/daytona/pkg/types"
1413
"github.com/google/uuid"
14+
15+
log "github.com/sirupsen/logrus"
1516
)
1617

1718
func GetConfig() (*types.ServerConfig, error) {

pkg/server/logs/log_formater.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ func Init() error {
5151
}
5252

5353
logFormatter := &logFormatter{
54-
textFormater: new(log.TextFormatter),
55-
file: file,
54+
textFormater: &log.TextFormatter{
55+
ForceColors: true,
56+
},
57+
file: file,
5658
}
5759

5860
log.SetFormatter(logFormatter)

0 commit comments

Comments
 (0)