mirror of https://github.com/tailscale/tailscale/
ipn/ipnserver, paths, logpolicy: move Window config files out of %LocalAppData%
C:\WINDOWS\system32\config\systemprofile\AppData\Local\ is frequently cleared for almost any reason: Windows updates, System Restore, even various System Cleaner utilities. The server-state.conf file in AppData\Local could be deleted at any time, which would break login until the node is removed from the Admin Panel allowing it to create a new key. Carefully copy any AppData state to ProgramData at startup. If copying the state fails, continue to use AppData so at least there will be connectivity. If there is no state, use ProgramData. We also migrate the log.conf file. Very old versions of Tailscale named the EXE tailscale-ipn, so the log conf was tailscale-ipn.log.conf and more recent versions preserved this filename and cmdName in logs. In this migration we always update the filename to c:\ProgramData\Tailscale\tailscaled.log.conf Updates https://github.com/tailscale/tailscale/issues/2856 Signed-off-by: Denton Gentry <dgentry@tailscale.com>pull/2885/head
parent
aae622314e
commit
280c84e46a
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package paths
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TryConfigFileMigration carefully copies the contents of oldFile to
|
||||||
|
// newFile, returning the path which should be used to read the config.
|
||||||
|
// - if newFile already exists, don't modify it just return its path
|
||||||
|
// - if neither oldFile nor newFile exist, return newFile for a fresh
|
||||||
|
// default config to be written to.
|
||||||
|
// - if oldFile exists but copying to newFile fails, return oldFile so
|
||||||
|
// there will at least be some config to work with.
|
||||||
|
func TryConfigFileMigration(oldFile, newFile string) string {
|
||||||
|
_, err := os.Stat(newFile)
|
||||||
|
if err == nil {
|
||||||
|
// Common case for a system which has already been migrated.
|
||||||
|
return newFile
|
||||||
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
log.Printf("TryConfigFileMigration failed; new file: %v", err)
|
||||||
|
return newFile
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err := os.ReadFile(oldFile)
|
||||||
|
if err != nil {
|
||||||
|
// Common case for a new user.
|
||||||
|
return newFile
|
||||||
|
}
|
||||||
|
|
||||||
|
os.MkdirAll(filepath.Dir(newFile), 0700)
|
||||||
|
err = os.WriteFile(newFile, contents, 0600)
|
||||||
|
if err != nil {
|
||||||
|
removeErr := os.Remove(newFile)
|
||||||
|
if removeErr != nil {
|
||||||
|
log.Printf("TryConfigFileMigration failed; write newFile no cleanup: %v, remove err: %v",
|
||||||
|
err, removeErr)
|
||||||
|
return oldFile
|
||||||
|
}
|
||||||
|
log.Printf("TryConfigFileMigration failed; write newFile: %v", err)
|
||||||
|
return oldFile
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("TryConfigFileMigration: successfully migrated: from %v to %v",
|
||||||
|
oldFile, newFile)
|
||||||
|
|
||||||
|
return newFile
|
||||||
|
}
|
Loading…
Reference in New Issue