diff --git a/changelog.md b/changelog.md
index bc8c45ed..8fb740db 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,11 @@
+## Version 0.17.6
+ - Can now chose between plain or formatted logs
+ - Added "force update" button in service mode
+ - Fixed issues related to fstab management
+
+## Version 0.17.5
+ - Fixed issue with TCP proxy timeouts
+
## Version 0.17.4
- Hide update button in container
- Fix issue with allowHTTPLocal and the TCP Proxy
diff --git a/client/src/api/index.jsx b/client/src/api/index.jsx
index c723d2e2..3b65d88d 100644
--- a/client/src/api/index.jsx
+++ b/client/src/api/index.jsx
@@ -230,6 +230,15 @@ function terminal(startCmd = "bash") {
return new WebSocket(protocol + window.location.host + '/cosmos/api/terminal/'+startCmd)
}
+function forceAutoUpdate() {
+ return wrap(fetch('/cosmos/api/force-server-update', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ }));
+}
+
const isDemo = import.meta.env.MODE === 'demo';
let auth = _auth;
@@ -281,5 +290,6 @@ export {
terminal,
cron,
rclone,
- restartServer
+ restartServer,
+ forceAutoUpdate
};
\ No newline at end of file
diff --git a/client/src/pages/config/users/configman.jsx b/client/src/pages/config/users/configman.jsx
index 272698b7..29ccea21 100644
--- a/client/src/pages/config/users/configman.jsx
+++ b/client/src/pages/config/users/configman.jsx
@@ -50,6 +50,7 @@ const ConfigManagement = () => {
const [saveLabel, setSaveLabel] = React.useState(t('global.saveAction'));
const {role} = useClientInfos();
const isAdmin = role === "2";
+ const [isCheckingUpdate, setIsCheckingUpdate] = React.useState(false);
function refresh() {
API.config.get().then((res) => {
@@ -295,6 +296,15 @@ const ConfigManagement = () => {
{status && !status.containerized && <>
+
+ {
+ setIsCheckingUpdate(true);
+ API.forceAutoUpdate().then(() => {
+ setIsCheckingUpdate(false);
+ })
+ }}>{t('mgmt.config.general.forceAutoUpdateButton')}
+
+
Thanks to the sponsors:
-
-
diff --git a/src/httpServer.go b/src/httpServer.go
index c0ad49b3..f60b4c4d 100644
--- a/src/httpServer.go
+++ b/src/httpServer.go
@@ -389,6 +389,7 @@ func InitServer() *mux.Router {
srapi.HandleFunc("/api/status", StatusRoute)
srapi.HandleFunc("/api/restart-server", restartHostMachineRoute)
srapi.HandleFunc("/_logs", LogsRoute)
+ srapi.HandleFunc("/api/force-server-update", ForceUpdateRoute)
srapi.HandleFunc("/api/can-send-email", CanSendEmail)
srapi.HandleFunc("/api/newInstall", NewInstallRoute)
srapi.HandleFunc("/api/logout", user.UserLogout)
diff --git a/src/storage/mergerFS.go b/src/storage/mergerFS.go
index e25d37c7..d48cd8fd 100644
--- a/src/storage/mergerFS.go
+++ b/src/storage/mergerFS.go
@@ -67,7 +67,7 @@ func MountMergerFS(paths []string, mountpoint string, opts string, permanent boo
}
// Format the fstab entry
- fstabEntry := fmt.Sprintf("%s %s mergerfs use_ino,cache.files=partial,dropcacheonclose=true,allow_other,category.create=mfs%s 0 0\n", strings.Join(paths, ":"), mountpoint, opts)
+ fstabEntry := fmt.Sprintf("\n%s %s mergerfs use_ino,cache.files=partial,dropcacheonclose=true,allow_other,category.create=mfs%s 0 0\n", strings.Join(paths, ":"), mountpoint, opts)
// Append to /etc/fstab
file, err := os.OpenFile("/etc/fstab", os.O_APPEND|os.O_WRONLY, 0644)
diff --git a/src/storage/mounts.go b/src/storage/mounts.go
index ba710fad..a1670bff 100644
--- a/src/storage/mounts.go
+++ b/src/storage/mounts.go
@@ -129,7 +129,7 @@ func Mount(path, mountpoint string, permanent bool, chown string) error {
}
// Format the fstab entry
- fstabEntry := fmt.Sprintf("%s %s auto defaults 0 0\n", path, mountpoint)
+ fstabEntry := fmt.Sprintf("\n%s %s auto defaults 0 0\n", path, mountpoint)
// Append to /etc/fstab
file, err := os.OpenFile("/etc/fstab", os.O_APPEND|os.O_WRONLY, 0644)
@@ -183,6 +183,8 @@ func Unmount(mountpoint string, permanent bool) error {
// isMountPointInFstab checks if the given mountpoint is already in /etc/fstab.
func isMountPointInFstab(mountpoint string) (bool, error) {
+ mountpoint = strings.Replace(mountpoint, "/var/mnt/", "/mnt/", 1)
+
file, err := os.Open("/etc/fstab")
if err != nil {
return false, err
@@ -191,7 +193,7 @@ func isMountPointInFstab(mountpoint string) (bool, error) {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
- if strings.Contains(scanner.Text(), mountpoint) {
+ if strings.Contains(scanner.Text(), " " + mountpoint + " ") {
return true, nil
}
}
@@ -205,6 +207,8 @@ func isMountPointInFstab(mountpoint string) (bool, error) {
// removeFstabEntry removes an entry for the specified mountpoint from /etc/fstab.
func removeFstabEntry(mountpoint string) error {
+ mountpoint = strings.Replace(mountpoint, "/var/mnt/", "/mnt/", 1)
+
file, err := os.Open("/etc/fstab")
if err != nil {
return err
@@ -215,7 +219,11 @@ func removeFstabEntry(mountpoint string) error {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
- if !strings.Contains(line, mountpoint) {
+
+ isComment := strings.HasPrefix(line, "#")
+ isEmpty := len(strings.TrimSpace(line)) == 0
+
+ if !isEmpty && (!strings.Contains(line, " " + mountpoint + " ") || isComment) {
lines = append(lines, line)
}
}
@@ -224,6 +232,8 @@ func removeFstabEntry(mountpoint string) error {
return err
}
+ utils.Debug("[STORAGE] Writing new /etc/fstab")
+
return os.WriteFile("/etc/fstab", []byte(strings.Join(lines, "\n")), 0644)
}
diff --git a/src/system.go b/src/system.go
index 93a045ea..c09558f0 100644
--- a/src/system.go
+++ b/src/system.go
@@ -144,8 +144,6 @@ func MemStatusRoute(w http.ResponseWriter, req *http.Request) {
}
if(req.Method == "GET") {
-
-
json.NewEncoder(w).Encode(map[string]interface{}{
"status": "OK",
"data": map[string]interface{}{
@@ -175,7 +173,7 @@ func LogsRoute(w http.ResponseWriter, req *http.Request) {
if(req.Method == "GET") {
// read log file
- logFile, err := os.Open(utils.CONFIGFOLDER + "cosmos.log")
+ logFile, err := os.Open(utils.CONFIGFOLDER + "cosmos.plain.log")
if err != nil {
utils.Error("Logs: Error reading log file", err)
@@ -205,6 +203,21 @@ func LogsRoute(w http.ResponseWriter, req *http.Request) {
}
}
+func ForceUpdateRoute(w http.ResponseWriter, req *http.Request) {
+ if utils.AdminOnly(w, req) != nil {
+ return
+ }
+
+ if(req.Method == "POST") {
+ utils.Log("API: Force update")
+ checkUpdatesAvailable()
+ } else {
+ utils.Error("Logs: Method not allowed" + req.Method, nil)
+ utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
+ return
+ }
+}
+
func restartHostMachineRoute(w http.ResponseWriter, req *http.Request) {
if utils.AdminOnly(w, req) != nil {
return
diff --git a/src/utils/log.go b/src/utils/log.go
index aaf7d34b..11e2130e 100644
--- a/src/utils/log.go
+++ b/src/utils/log.go
@@ -37,6 +37,9 @@ type LogLevel int
var (
logger *log.Logger
errorLogger *log.Logger
+
+ loggerPlain *log.Logger
+ errorLoggerPlain *log.Logger
)
func InitLogs() {
@@ -51,6 +54,14 @@ func InitLogs() {
Compress: true,
}
+ ljLoggerPlain := &lumberjack.Logger{
+ Filename: CONFIGFOLDER + "cosmos.plain.log",
+ MaxSize: 15, // megabytes
+ MaxBackups: 2,
+ MaxAge: 16, // days
+ Compress: true,
+ }
+
// Create a multi-writer to log to both file and stdout
// multiWriter := io.MultiWriter(ljLogger, os.Stdout)
@@ -60,6 +71,9 @@ func InitLogs() {
// Create loggers
logger = log.New(ljLogger, "", log.Ldate|log.Ltime)
errorLogger = log.New(ljLogger, "", log.Ldate|log.Ltime)
+
+ loggerPlain = log.New(ljLoggerPlain, "", log.Ldate|log.Ltime)
+ errorLoggerPlain = log.New(ljLoggerPlain, "", log.Ldate|log.Ltime)
}
func RawLogMessage(level LogLevel, prefix, prefixColor, color, message string) {
@@ -69,14 +83,16 @@ func RawLogMessage(level LogLevel, prefix, prefixColor, color, message string) {
log.Println(logString)
- if logger == nil || errorLogger == nil {
+ if logger == nil || errorLogger == nil || loggerPlain == nil || errorLoggerPlain == nil {
return
}
if level >= ERROR {
errorLogger.Println(logString)
+ errorLoggerPlain.Println(prefix + " " + message)
} else {
logger.Println(logString)
+ loggerPlain.Println(prefix + " " + message)
}
}
}