From 5779e898090b7182ad9307e3ddf1087ac913c770 Mon Sep 17 00:00:00 2001 From: TomSweeneyRedHat Date: Mon, 1 Jul 2019 14:35:13 -0400 Subject: Touch up XDG, add rootless links Touch up a number of formating issues for XDG_RUNTIME_DIRS in a number of man pages. Make use of the XDG_CONFIG_HOME environment variable in a rootless environment if available, or set it if not. Also added a number of links to the Rootless Podman config page and added the location of the auth.json files to that doc. Signed-off-by: TomSweeneyRedHat --- README.md | 5 +++++ cmd/podman/main.go | 2 +- cmd/podman/main_local.go | 1 + cmd/podman/main_remote.go | 17 +++++++++++--- cmd/podman/remoteclientconfig/config_linux.go | 9 ++++++-- docs/podman-container-runlabel.1.md | 2 +- docs/podman-login.1.md | 4 ++-- docs/podman-logout.1.md | 4 ++-- docs/podman-play-kube.1.md | 2 +- docs/podman-pull.1.md | 2 +- docs/podman-push.1.md | 2 +- docs/podman-run.1.md | 2 +- docs/podman-search.1.md | 2 +- docs/tutorials/README.md | 4 ++++ docs/tutorials/rootless_tutorial.md | 4 +++- libpod/runtime.go | 21 ++++++++++++++---- pkg/util/utils.go | 6 +++-- pkg/util/utils_supported.go | 32 +++++++++++++++++++++++++++ pkg/util/utils_windows.go | 5 +++++ vendor/modules.txt | 2 +- 20 files changed, 104 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e22c35d4f..f1d53cc11 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ If you run Podman as your user and mount in `/etc/passwd` from the host, you sti Almost all normal Podman functionality is available, though there are some [shortcomings](https://github.com/containers/libpod/blob/master/rootless.md). Any recent Podman release should be able to run rootless without any additional configuration, though your operating system may require some additional configuration detailed in the [install guide](https://github.com/containers/libpod/blob/master/install.md). +A little configuration by an administrator is required before rootless Podman can be used, the necessary setup is documented [here](https://github.com/containers/libpod/blob/master/docs/tutorials/rootless_tutorial.md). + ## Out of scope * Specializing in signing and pushing images to various storage backends. @@ -101,6 +103,9 @@ Tutorials on using Podman. **[Remote Client](remote_client.md)** A brief how-to on using the Podman remote-client. +**[Basic Setup and Use of Podman in a Rootless environment](https://github.com/containers/libpod/blob/master/docs/tutorials/rootless_tutorial.md) +A tutorial showing the setup and configuration necessary to run Rootless Podman. + **[Release Notes](RELEASE_NOTES.md)** Release notes for recent Podman versions diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 72d1754ac..f24c8c19c 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -101,7 +101,7 @@ func initConfig() { } func before(cmd *cobra.Command, args []string) error { - if err := libpod.SetXdgRuntimeDir(); err != nil { + if err := libpod.SetXdgDirs(); err != nil { logrus.Errorf(err.Error()) os.Exit(1) } diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index e4f521bc4..1e8cc1143 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -121,6 +121,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") { return nil } + podmanCmd := cliconfig.PodmanCommand{ Command: cmd, InputArgs: args, diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go index ecbb44d5a..d534f5bcb 100644 --- a/cmd/podman/main_remote.go +++ b/cmd/podman/main_remote.go @@ -8,7 +8,8 @@ import ( "os/user" "path/filepath" - "github.com/docker/docker/pkg/homedir" + "github.com/containers/libpod/pkg/util" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -31,9 +32,19 @@ func init() { } func setSyslog() error { + var err error + cfgHomeDir := os.Getenv("XDG_CONFIG_HOME") + if cfgHomeDir == "" { + if cfgHomeDir, err = util.GetRootlessConfigHomeDir(); err != nil { + return err + } + if err = os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { + return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME") + } + } + path := filepath.Join(cfgHomeDir, "containers") + // Log to file if not using syslog - homeDir := homedir.Get() - path := filepath.Join(homeDir, ".config", "containers") if _, err := os.Stat(path); os.IsNotExist(err) { if err := os.MkdirAll(path, 0750); err != nil { diff --git a/cmd/podman/remoteclientconfig/config_linux.go b/cmd/podman/remoteclientconfig/config_linux.go index b94941381..5d27f19f2 100644 --- a/cmd/podman/remoteclientconfig/config_linux.go +++ b/cmd/podman/remoteclientconfig/config_linux.go @@ -1,12 +1,17 @@ package remoteclientconfig import ( + "os" "path/filepath" "github.com/docker/docker/pkg/homedir" ) func getConfigFilePath() string { - homeDir := homedir.Get() - return filepath.Join(homeDir, ".config", "containers", remoteConfigFileName) + path := os.Getenv("XDG_CONFIG_HOME") + if path == "" { + homeDir := homedir.Get() + path = filepath.Join(homeDir, ".config") + } + return filepath.Join(path, "containers", remoteConfigFileName) } diff --git a/docs/podman-container-runlabel.1.md b/docs/podman-container-runlabel.1.md index aabeb092d..9b74a3410 100644 --- a/docs/podman-container-runlabel.1.md +++ b/docs/podman-container-runlabel.1.md @@ -45,7 +45,7 @@ Any additional arguments will be appended to the command. ## OPTIONS: **--authfile**=*path* -Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE diff --git a/docs/podman-login.1.md b/docs/podman-login.1.md index 9be67e5a4..9d368e9f2 100644 --- a/docs/podman-login.1.md +++ b/docs/podman-login.1.md @@ -11,7 +11,7 @@ podman\-login - Login to a container registry and password. **podman login** reads in the username and password from STDIN. The username and password can also be set using the **username** and **password** flags. The path of the authentication file can be specified by the user by setting the **authfile** -flag. The default path used is **${XDG\_RUNTIME_DIR}/containers/auth.json**. +flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**. **podman [GLOBAL OPTIONS]** @@ -35,7 +35,7 @@ Username for registry **--authfile**=*path* -Path of the authentication file. Default is ${XDG_\RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/podman-logout.1.md b/docs/podman-logout.1.md index 56d661309..01dc52ecd 100644 --- a/docs/podman-logout.1.md +++ b/docs/podman-logout.1.md @@ -9,7 +9,7 @@ podman\-logout - Logout of a container registry ## DESCRIPTION **podman logout** logs out of a specified registry server by deleting the cached credentials stored in the **auth.json** file. The path of the authentication file can be overridden by the user by setting the **authfile** flag. -The default path used is **${XDG\_RUNTIME_DIR}/containers/auth.json**. +The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**. All the cached credentials can be removed by setting the **all** flag. **podman [GLOBAL OPTIONS]** @@ -22,7 +22,7 @@ All the cached credentials can be removed by setting the **all** flag. **--authfile**=*path* -Path of the authentication file. Default is ${XDG_\RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md index 2fae09199..8b78c83d0 100644 --- a/docs/podman-play-kube.1.md +++ b/docs/podman-play-kube.1.md @@ -19,7 +19,7 @@ Note: HostPath volume types created by play kube will be given an SELinux privat **--authfile**=*path* -Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE diff --git a/docs/podman-pull.1.md b/docs/podman-pull.1.md index 2d6d42959..8774075e1 100644 --- a/docs/podman-pull.1.md +++ b/docs/podman-pull.1.md @@ -53,7 +53,7 @@ Note: When using the all-tags flag, Podman will not iterate over the search regi **--authfile**=*path* -Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE diff --git a/docs/podman-push.1.md b/docs/podman-push.1.md index 4ac901919..2058a432c 100644 --- a/docs/podman-push.1.md +++ b/docs/podman-push.1.md @@ -46,7 +46,7 @@ Image stored in local container/storage **--authfile**=*path* -Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index f5f44fad4..16c29168f 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -56,7 +56,7 @@ each of stdin, stdout, and stderr. **--authfile**[=*path*] -Path of the authentication file. Default is ${XDG_\RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/podman-search.1.md b/docs/podman-search.1.md index f0a696494..e50cc8c13 100644 --- a/docs/podman-search.1.md +++ b/docs/podman-search.1.md @@ -27,7 +27,7 @@ Note, searching without a search term will only work for registries that impleme **--authfile**=*path* -Path of the authentication file. Default is ${XDG_\RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) +Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json (Not available for remote commands) Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE environment variable. `export REGISTRY_AUTH_FILE=path` diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index ad0c5ae88..925cfb970 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -7,3 +7,7 @@ **[Introduction Tutorial](https://github.com/containers/libpod/tree/master/docs/tutorials/podman_tutorial.md)** Learn how to setup Podman and perform some basic commands with the utility. + +**[Basic Setup and Use of Podman in a Rootless environment.](https://github.com/containers/libpod/blob/master/docs/tutorials/rootless_tutorial.md). + +The steps required to setup rootless Podman are enumerated. diff --git a/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md index 553e8d297..9453e3855 100644 --- a/docs/tutorials/rootless_tutorial.md +++ b/docs/tutorials/rootless_tutorial.md @@ -76,7 +76,9 @@ Once the Administrator has completed the setup on the machine and then the confi ### User Configuration Files. -The Podman configuration files for root reside in /etc/containers. In the rootless environment they reside in ${HOME}/.config/containers and are owned by each individual user. The user can modify these files as they wish. +The Podman configuration files for root reside in /usr/share/containers with overrides in /etc/containers. In the rootless environment they reside in ${XDG\_CONFIG\_HOME}/containers and are owned by each individual user. The user can modify these files as they wish. + +The default authorization file used by the `podman login` and `podman logout` commands reside in ${XDG\_RUNTIME\_DIR}/containers/auth.json. ## More information diff --git a/libpod/runtime.go b/libpod/runtime.go index 28958e932..c900f2b8b 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -325,16 +325,19 @@ func defaultRuntimeConfig() (RuntimeConfig, error) { }, nil } -// SetXdgRuntimeDir ensures the XDG_RUNTIME_DIR env variable is set -// containers/image uses XDG_RUNTIME_DIR to locate the auth file. -// It internally calls EnableLinger() so that the user's processes are not +// SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set. +// containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is +// use for the libpod.conf configuration file. +// SetXdgDirs internally calls EnableLinger() so that the user's processes are not // killed once the session is terminated. EnableLinger() also attempts to // get the runtime directory when XDG_RUNTIME_DIR is not specified. -func SetXdgRuntimeDir() error { +// This function should only be called when running rootless. +func SetXdgDirs() error { if !rootless.IsRootless() { return nil } + // Setup XDG_RUNTIME_DIR runtimeDir := os.Getenv("XDG_RUNTIME_DIR") runtimeDirLinger, err := rootless.EnableLinger() @@ -362,6 +365,16 @@ func SetXdgRuntimeDir() error { if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil { return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") } + + // Setup XDG_CONFIG_HOME + if cfgHomeDir := os.Getenv("XDG_CONFIG_HOME"); cfgHomeDir == "" { + if cfgHomeDir, err = util.GetRootlessConfigHomeDir(); err != nil { + return err + } + if err = os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { + return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME") + } + } return nil } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index fba34a337..520e41438 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -239,8 +239,10 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin } var ( - rootlessRuntimeDirOnce sync.Once - rootlessRuntimeDir string + rootlessConfigHomeDirOnce sync.Once + rootlessConfigHomeDir string + rootlessRuntimeDirOnce sync.Once + rootlessRuntimeDir string ) type tomlOptionsConfig struct { diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index af55689a6..3eac58dc6 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -65,6 +65,38 @@ func GetRootlessRuntimeDir() (string, error) { return rootlessRuntimeDir, nil } +// GetRootlessConfigHomeDir returns the config home directory when running as non root +func GetRootlessConfigHomeDir() (string, error) { + var rootlessConfigHomeDirError error + + rootlessConfigHomeDirOnce.Do(func() { + cfgHomeDir := os.Getenv("XDG_CONFIG_HOME") + if cfgHomeDir == "" { + home := os.Getenv("HOME") + resolvedHome, err := filepath.EvalSymlinks(home) + if err != nil { + rootlessConfigHomeDirError = errors.Wrapf(err, "cannot resolve %s", home) + return + } + tmpDir := filepath.Join(resolvedHome, ".config") + if err := os.MkdirAll(tmpDir, 0755); err != nil { + logrus.Errorf("unable to make temp dir %s", tmpDir) + } + st, err := os.Stat(tmpDir) + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0755 { + cfgHomeDir = tmpDir + } + } + rootlessConfigHomeDir = cfgHomeDir + }) + + if rootlessConfigHomeDirError != nil { + return "", rootlessConfigHomeDirError + } + + return rootlessConfigHomeDir, nil +} + // GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for // the pause process func GetRootlessPauseProcessPidPath() (string, error) { diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go index 635558bf7..e7b2a272e 100644 --- a/pkg/util/utils_windows.go +++ b/pkg/util/utils_windows.go @@ -27,3 +27,8 @@ func GetRootlessPauseProcessPidPath() (string, error) { func GetRootlessRuntimeDir() (string, error) { return "", errors.New("this function is not implemented for windows") } + +// GetRootlessConfigHomeDir returns the config home directory when running as non root +func GetRootlessConfigHomeDir() (string, error) { + return "", errors.New("this function is not implemented for windows") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 17b11fd58..03946cd09 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -172,8 +172,8 @@ github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache/memory github.com/docker/distribution/metrics # github.com/docker/docker v0.7.3-0.20190309235953-33c3200e0d16 -github.com/docker/docker/pkg/homedir github.com/docker/docker/pkg/signal +github.com/docker/docker/pkg/homedir github.com/docker/docker/oci/caps github.com/docker/docker/pkg/namesgenerator github.com/docker/docker/pkg/term -- cgit v1.2.3-54-g00ecf