Skip to content

Commit ffb43da

Browse files
committed
no longer need to reboot to start / stop tls service
1 parent 720c6f8 commit ffb43da

File tree

5 files changed

+112
-41
lines changed

5 files changed

+112
-41
lines changed

config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ func SaveConfig() error {
109109
configLock.Lock()
110110
defer configLock.Unlock()
111111

112+
logger.Tracef("Saving config to %s", configPath)
113+
112114
file, err := os.Create(configPath)
113115
if err != nil {
114116
return fmt.Errorf("failed to create config file: %w", err)

jsonrpc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ func rpcGetTLSState() TLSState {
405405
return getTLSState()
406406
}
407407

408-
func rpcSetTLSState(tlsState TLSState) error {
409-
err := setTLSState(tlsState)
408+
func rpcSetTLSState(state TLSState) error {
409+
err := setTLSState(state)
410410
if err != nil {
411411
return fmt.Errorf("failed to set TLS state: %w", err)
412412
}

main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,12 @@ func Main() {
7070
//go RunFuseServer()
7171
go RunWebServer()
7272

73+
go RunWebSecureServer()
74+
// Web secure server is started only if TLS mode is enabled
7375
if config.TLSMode != "" {
74-
initCertStore()
75-
go RunWebSecureServer()
76+
startWebSecureServer()
7677
}
78+
7779
// As websocket client already checks if the cloud token is set, we can start it here.
7880
go RunWebsocketClient()
7981

ui/src/routes/devices.$id.settings.access._index.tsx

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,12 @@ export default function SettingsAccessIndexRoute() {
161161
};
162162

163163
const handleTlsUpdate = useCallback(() => {
164-
send("setTLSState", { state: { mode: tlsMode, certificate: tlsCert, privateKey: tlsKey } as TLSState }, resp => {
164+
const state = { mode: tlsMode } as TLSState;
165+
if (tlsMode !== "disabled") {
166+
state.certificate = tlsCert;
167+
state.privateKey = tlsKey;
168+
}
169+
send("setTLSState", { state }, resp => {
165170
if ("error" in resp) {
166171
notifications.error(`Failed to update TLS settings: ${resp.error.data || "Unknown error"}`);
167172
return;
@@ -171,17 +176,6 @@ export default function SettingsAccessIndexRoute() {
171176
});
172177
}, [send, tlsMode, tlsCert, tlsKey]);
173178

174-
const handleReboot = useCallback(() => {
175-
send("reboot", { force: false }, resp => {
176-
if ("error" in resp) {
177-
notifications.error(`Failed to reboot: ${resp.error.data || "Unknown error"}`);
178-
return;
179-
}
180-
181-
notifications.success("Device will restart shortly, it might take a few seconds to boot up again.");
182-
});
183-
}, [send]);
184-
185179
// Fetch device ID and cloud state on component mount
186180
useEffect(() => {
187181
getCloudState();
@@ -211,8 +205,8 @@ export default function SettingsAccessIndexRoute() {
211205
<SettingsItem
212206
title="HTTPS/TLS Mode"
213207
description={<>
214-
Select the TLS mode for your device (beta)<br />
215-
<small>changing this setting might restart the device</small>
208+
Select the TLS mode for your device <sup>experimental</sup><br />
209+
<small>The feature might not work as expected, please report any issues if you encounter any.</small>
216210
</>}
217211
>
218212
<SelectMenuBasic
@@ -227,27 +221,6 @@ export default function SettingsAccessIndexRoute() {
227221
/>
228222
</SettingsItem>
229223

230-
<div className="space-y-4">
231-
<p className="text-xs text-slate-600 dark:text-slate-400">
232-
If TLS wasn't enabled before, you'll need to <strong>reboot</strong> the device to apply the changes.<br />
233-
</p>
234-
235-
<div className="flex items-center gap-x-2">
236-
<Button
237-
size="SM"
238-
theme="primary"
239-
text="Update TLS Settings"
240-
onClick={handleTlsUpdate}
241-
/>
242-
<Button
243-
size="SM"
244-
theme="danger"
245-
text="Reboot"
246-
onClick={handleReboot}
247-
/>
248-
</div>
249-
</div>
250-
251224
{tlsMode === "custom" && (
252225
<div className="mt-4 space-y-4">
253226
<div className="space-y-4">
@@ -282,6 +255,19 @@ export default function SettingsAccessIndexRoute() {
282255
</div>
283256
</div>
284257
)}
258+
259+
260+
<div className="space-y-4">
261+
<div className="flex items-center gap-x-2">
262+
<Button
263+
size="SM"
264+
theme="primary"
265+
text="Update TLS Settings"
266+
onClick={handleTlsUpdate}
267+
/>
268+
</div>
269+
</div>
270+
285271
<SettingsItem
286272
title="Authentication Mode"
287273
description={`Current mode: ${loaderData.authMode === "password" ? "Password protected" : "No password"}`}

web_tls.go

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package kvm
22

33
import (
4+
"context"
45
"crypto/tls"
56
"encoding/pem"
7+
"errors"
68
"fmt"
79
"net/http"
10+
"sync"
811

912
"github.com/jetkvm/kvm/internal/websecure"
1013
)
@@ -31,6 +34,10 @@ type TLSState struct {
3134
}
3235

3336
func initCertStore() {
37+
if certStore != nil {
38+
logger.Warnf("TLS store already initialized, it should not be initialized again")
39+
return
40+
}
3441
certStore = websecure.NewCertStore(tlsStorePath)
3542
certStore.LoadCertificates()
3643

@@ -87,10 +94,18 @@ func getTLSState() TLSState {
8794
}
8895

8996
func setTLSState(s TLSState) error {
97+
var isChanged = false
98+
9099
switch s.Mode {
91100
case "disabled":
101+
if config.TLSMode != "" {
102+
isChanged = true
103+
}
92104
config.TLSMode = ""
93105
case "custom":
106+
if config.TLSMode == "" {
107+
isChanged = true
108+
}
94109
// parse pem to cert and key
95110
err, _ := certStore.ValidateAndSaveCertificate(webSecureCustomCertificateName, s.Certificate, s.PrivateKey, true)
96111
// warn doesn't matter as ... we don't know the hostname yet
@@ -99,15 +114,47 @@ func setTLSState(s TLSState) error {
99114
}
100115
config.TLSMode = "custom"
101116
case "self-signed":
117+
if config.TLSMode == "" {
118+
isChanged = true
119+
}
102120
config.TLSMode = "self-signed"
103121
default:
104122
return fmt.Errorf("invalid TLS mode: %s", s.Mode)
105123
}
124+
125+
if !isChanged {
126+
logger.Tracef("TLS enabled state is not changed, not starting/stopping websecure server")
127+
return nil
128+
}
129+
130+
if config.TLSMode == "" {
131+
logger.Tracef("Stopping websecure server, as TLS mode is disabled")
132+
stopWebSecureServer()
133+
} else {
134+
logger.Tracef("Starting websecure server, as TLS mode is enabled")
135+
startWebSecureServer()
136+
}
137+
106138
return nil
107139
}
108140

141+
var (
142+
startTLS = make(chan struct{})
143+
stopTLS = make(chan struct{})
144+
tlsServiceLock = sync.Mutex{}
145+
tlsStarted = false
146+
)
147+
109148
// RunWebSecureServer runs a web server with TLS.
110-
func RunWebSecureServer() {
149+
func runWebSecureServer() {
150+
tlsServiceLock.Lock()
151+
defer tlsServiceLock.Unlock()
152+
153+
tlsStarted = true
154+
defer func() {
155+
tlsStarted = false
156+
}()
157+
111158
r := setupRouter()
112159

113160
server := &http.Server{
@@ -120,8 +167,42 @@ func RunWebSecureServer() {
120167
},
121168
}
122169
logger.Infof("Starting websecure server on %s", webSecureListen)
170+
171+
go func() {
172+
for _ = range stopTLS {
173+
logger.Infof("Shutting down websecure server")
174+
server.Shutdown(context.Background())
175+
}
176+
}()
177+
123178
err := server.ListenAndServeTLS("", "")
124-
if err != nil {
179+
if !errors.Is(err, http.ErrServerClosed) {
125180
panic(err)
126181
}
127182
}
183+
184+
func stopWebSecureServer() {
185+
if !tlsStarted {
186+
logger.Warnf("Websecure server is not running, not stopping it")
187+
return
188+
}
189+
stopTLS <- struct{}{}
190+
}
191+
192+
func startWebSecureServer() {
193+
if tlsStarted {
194+
logger.Warnf("Websecure server is already running, not starting it again")
195+
return
196+
}
197+
startTLS <- struct{}{}
198+
}
199+
200+
func RunWebSecureServer() {
201+
for _ = range startTLS {
202+
logger.Tracef("Starting websecure server, as we have received a start signal")
203+
if certStore == nil {
204+
initCertStore()
205+
}
206+
go runWebSecureServer()
207+
}
208+
}

0 commit comments

Comments
 (0)