| 
									
										
										
										
											2019-06-30 16:07:58 -06:00
										 |  |  | // Copyright 2015 Matthew Holt and The Caddy Authors | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | // You may obtain a copy of the License at | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and | 
					
						
							|  |  |  | // limitations under the License. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 11:58:28 -06:00
										 |  |  | package caddy | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"runtime" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 23:15:25 -07:00
										 |  |  | 	"github.com/caddyserver/certmagic" | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | 	"go.uber.org/zap" | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StorageConverter is a type that can convert itself | 
					
						
							| 
									
										
										
										
											2019-04-26 12:35:39 -06:00
										 |  |  | // to a valid, usable certmagic.Storage value. (The | 
					
						
							|  |  |  | // value might be short-lived.) This interface allows | 
					
						
							|  |  |  | // us to adapt any CertMagic storage implementation | 
					
						
							|  |  |  | // into a consistent API for Caddy configuration. | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | type StorageConverter interface { | 
					
						
							|  |  |  | 	CertMagicStorage() (certmagic.Storage, error) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | // HomeDir returns the best guess of the current user's home | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | // directory from environment variables. If unknown, "." (the | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | // current directory) is returned instead, except GOOS=android, | 
					
						
							|  |  |  | // which returns "/sdcard". | 
					
						
							|  |  |  | func HomeDir() string { | 
					
						
							|  |  |  | 	home := homeDirUnsafe() | 
					
						
							|  |  |  | 	if home == "" && runtime.GOOS == "android" { | 
					
						
							|  |  |  | 		home = "/sdcard" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if home == "" { | 
					
						
							|  |  |  | 		home = "." | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return home | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // homeDirUnsafe is a low-level function that returns | 
					
						
							|  |  |  | // the user's home directory from environment | 
					
						
							|  |  |  | // variables. Careful: if it cannot be determined, an | 
					
						
							|  |  |  | // empty string is returned. If not accounting for | 
					
						
							|  |  |  | // that case, use HomeDir() instead; otherwise you | 
					
						
							|  |  |  | // may end up using the root of the file system. | 
					
						
							|  |  |  | func homeDirUnsafe() string { | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | 	home := os.Getenv("HOME") | 
					
						
							|  |  |  | 	if home == "" && runtime.GOOS == "windows" { | 
					
						
							|  |  |  | 		drive := os.Getenv("HOMEDRIVE") | 
					
						
							|  |  |  | 		path := os.Getenv("HOMEPATH") | 
					
						
							|  |  |  | 		home = drive + path | 
					
						
							|  |  |  | 		if drive == "" || path == "" { | 
					
						
							|  |  |  | 			home = os.Getenv("USERPROFILE") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | 	if home == "" && runtime.GOOS == "plan9" { | 
					
						
							|  |  |  | 		home = os.Getenv("home") | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return home | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | // AppConfigDir returns the directory where to store user's config. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If XDG_CONFIG_HOME is set, it returns: $XDG_CONFIG_HOME/caddy. | 
					
						
							|  |  |  | // Otherwise, os.UserConfigDir() is used; if successful, it appends | 
					
						
							|  |  |  | // "Caddy" (Windows & Mac) or "caddy" (every other OS) to the path. | 
					
						
							|  |  |  | // If it returns an error, the fallback path "./caddy" is returned. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The config directory is not guaranteed to be different from | 
					
						
							|  |  |  | // AppDataDir(). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Unlike os.UserConfigDir(), this function prefers the | 
					
						
							|  |  |  | // XDG_CONFIG_HOME env var on all platforms, not just Unix. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Ref: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html | 
					
						
							|  |  |  | func AppConfigDir() string { | 
					
						
							| 
									
										
										
										
											2019-12-31 18:31:43 -07:00
										 |  |  | 	if basedir := os.Getenv("XDG_CONFIG_HOME"); basedir != "" { | 
					
						
							|  |  |  | 		return filepath.Join(basedir, "caddy") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	basedir, err := os.UserConfigDir() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		Log().Warn("unable to determine directory for user configuration; falling back to current directory", zap.Error(err)) | 
					
						
							|  |  |  | 		return "./caddy" | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	subdir := "caddy" | 
					
						
							|  |  |  | 	switch runtime.GOOS { | 
					
						
							|  |  |  | 	case "windows", "darwin": | 
					
						
							|  |  |  | 		subdir = "Caddy" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return filepath.Join(basedir, subdir) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AppDataDir returns a directory path that is suitable for storing | 
					
						
							|  |  |  | // application data on disk. It uses the environment for finding the | 
					
						
							|  |  |  | // best place to store data, and appends a "caddy" or "Caddy" (depending | 
					
						
							|  |  |  | // on OS and environment) subdirectory. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // For a base directory path: | 
					
						
							|  |  |  | // If XDG_DATA_HOME is set, it returns: $XDG_DATA_HOME/caddy; otherwise, | 
					
						
							|  |  |  | // on Windows it returns: %AppData%/Caddy, | 
					
						
							|  |  |  | // on Mac: $HOME/Library/Application Support/Caddy, | 
					
						
							|  |  |  | // on Plan9: $home/lib/caddy, | 
					
						
							|  |  |  | // on Android: $HOME/caddy, | 
					
						
							|  |  |  | // and on everything else: $HOME/.local/share/caddy. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If a data directory cannot be determined, it returns "./caddy" | 
					
						
							|  |  |  | // (this is not ideal, and the environment should be fixed). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The data directory is not guaranteed to be different from AppConfigDir(). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Ref: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html | 
					
						
							|  |  |  | func AppDataDir() string { | 
					
						
							|  |  |  | 	if basedir := os.Getenv("XDG_DATA_HOME"); basedir != "" { | 
					
						
							|  |  |  | 		return filepath.Join(basedir, "caddy") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch runtime.GOOS { | 
					
						
							|  |  |  | 	case "windows": | 
					
						
							|  |  |  | 		appData := os.Getenv("AppData") | 
					
						
							|  |  |  | 		if appData != "" { | 
					
						
							|  |  |  | 			return filepath.Join(appData, "Caddy") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case "darwin": | 
					
						
							|  |  |  | 		home := homeDirUnsafe() | 
					
						
							|  |  |  | 		if home != "" { | 
					
						
							|  |  |  | 			return filepath.Join(home, "Library", "Application Support", "Caddy") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case "plan9": | 
					
						
							|  |  |  | 		home := homeDirUnsafe() | 
					
						
							|  |  |  | 		if home != "" { | 
					
						
							|  |  |  | 			return filepath.Join(home, "lib", "caddy") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case "android": | 
					
						
							|  |  |  | 		home := homeDirUnsafe() | 
					
						
							|  |  |  | 		if home != "" { | 
					
						
							|  |  |  | 			return filepath.Join(home, "caddy") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		home := homeDirUnsafe() | 
					
						
							|  |  |  | 		if home != "" { | 
					
						
							|  |  |  | 			return filepath.Join(home, ".local", "share", "caddy") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | 	return "./caddy" | 
					
						
							| 
									
										
										
										
											2019-04-25 13:54:48 -06:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-10 15:38:30 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-31 16:47:35 -07:00
										 |  |  | // ConfigAutosavePath is the default path to which the last config will be persisted. | 
					
						
							|  |  |  | var ConfigAutosavePath = filepath.Join(AppConfigDir(), "autosave.json") | 
					
						
							| 
									
										
										
										
											2020-03-31 17:56:36 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | // DefaultStorage is Caddy's default storage module. | 
					
						
							|  |  |  | var DefaultStorage = &certmagic.FileStorage{Path: AppDataDir()} |