Fix docker user and write configuration to disk when setting user
This commit is contained in:
parent
6e2a442846
commit
94223bafec
|
@ -66,7 +66,14 @@ type SystemConfiguration struct {
|
||||||
Data string
|
Data string
|
||||||
|
|
||||||
// The user that should own all of the server files, and be used for containers.
|
// The user that should own all of the server files, and be used for containers.
|
||||||
User string
|
Username string
|
||||||
|
|
||||||
|
// Definitions for the user that gets created to ensure that we can quickly access
|
||||||
|
// this information without constantly having to do a system lookup.
|
||||||
|
User struct {
|
||||||
|
Uid int
|
||||||
|
Gid int
|
||||||
|
}
|
||||||
|
|
||||||
// The path to the system's timezone file that will be mounted into running Docker containers.
|
// The path to the system's timezone file that will be mounted into running Docker containers.
|
||||||
TimezonePath string `yaml:"timezone_path"`
|
TimezonePath string `yaml:"timezone_path"`
|
||||||
|
@ -133,6 +140,7 @@ type ApiConfiguration struct {
|
||||||
// a tedious thing to have to do.
|
// a tedious thing to have to do.
|
||||||
func (c *Configuration) SetDefaults() {
|
func (c *Configuration) SetDefaults() {
|
||||||
c.System = &SystemConfiguration{
|
c.System = &SystemConfiguration{
|
||||||
|
Username: "pterodactyl",
|
||||||
Data: "/srv/daemon-data",
|
Data: "/srv/daemon-data",
|
||||||
TimezonePath:"/etc/timezone",
|
TimezonePath:"/etc/timezone",
|
||||||
}
|
}
|
||||||
|
@ -198,12 +206,12 @@ func ReadConfiguration(path string) (*Configuration, error) {
|
||||||
// If files are not owned by this user there will be issues with permissions on Docker
|
// If files are not owned by this user there will be issues with permissions on Docker
|
||||||
// mount points.
|
// mount points.
|
||||||
func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
||||||
u, err := user.Lookup(c.System.User)
|
u, err := user.Lookup(c.System.Username)
|
||||||
|
|
||||||
// If an error is returned but it isn't the unknown user error just abort
|
// If an error is returned but it isn't the unknown user error just abort
|
||||||
// the process entirely. If we did find a user, return it immediately.
|
// the process entirely. If we did find a user, return it immediately.
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return u, nil
|
return u, c.setSystemUser(u)
|
||||||
} else if _, ok := err.(user.UnknownUserError); !ok {
|
} else if _, ok := err.(user.UnknownUserError); !ok {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -213,16 +221,16 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.User)
|
var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.Username)
|
||||||
|
|
||||||
// Alpine Linux is the only OS we currently support that doesn't work with the useradd command, so
|
// Alpine Linux is the only OS we currently support that doesn't work with the useradd command, so
|
||||||
// in those cases we just modify the command a bit to work as expected.
|
// in those cases we just modify the command a bit to work as expected.
|
||||||
if strings.HasPrefix(sysName, "Alpine") {
|
if strings.HasPrefix(sysName, "Alpine") {
|
||||||
command = fmt.Sprintf("adduser -S -D -H -G %[1]s -s /bin/false %[1]s", c.System.User)
|
command = fmt.Sprintf("adduser -S -D -H -G %[1]s -s /bin/false %[1]s", c.System.Username)
|
||||||
|
|
||||||
// We have to create the group first on Alpine, so do that here before continuing on
|
// We have to create the group first on Alpine, so do that here before continuing on
|
||||||
// to the user creation process.
|
// to the user creation process.
|
||||||
if _, err := exec.Command("addgroup", "-s", c.System.User).Output(); err != nil {
|
if _, err := exec.Command("addgroup", "-s", c.System.Username).Output(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +240,24 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return user.Lookup(c.System.User)
|
if u, err := user.Lookup(c.System.Username); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return u, c.setSystemUser(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the system user into the configuration and then write it to the disk so that
|
||||||
|
// it is persisted on boot.
|
||||||
|
func (c *Configuration) setSystemUser(u *user.User) error {
|
||||||
|
uid, _ := strconv.Atoi(u.Uid)
|
||||||
|
gid, _ := strconv.Atoi(u.Gid)
|
||||||
|
|
||||||
|
c.System.Username = u.Username
|
||||||
|
c.System.User.Uid = uid
|
||||||
|
c.System.User.Gid = gid
|
||||||
|
|
||||||
|
return c.WriteToDisk()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that the configured data directory has the correct permissions assigned to
|
// Ensures that the configured data directory has the correct permissions assigned to
|
||||||
|
@ -251,7 +276,7 @@ func (c *Configuration) EnsureFilePermissions() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
su, err := user.Lookup(c.System.User)
|
su, err := user.Lookup(c.System.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -287,6 +312,28 @@ func (c *Configuration) EnsureFilePermissions() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes the configuration to the disk as a blocking operation by obtaining an exclusive
|
||||||
|
// lock on the file. This prevents something else from writing at the exact same time and
|
||||||
|
// leading to bad data conditions.
|
||||||
|
func (c *Configuration) WriteToDisk() error {
|
||||||
|
f, err := os.OpenFile("config.yml", os.O_WRONLY, os.ModeExclusive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
b, err := yaml.Marshal(&c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := f.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the system release name.
|
// Gets the system release name.
|
||||||
func getSystemName() (string, error) {
|
func getSystemName() (string, error) {
|
||||||
cmd := exec.Command("lsb_release", "-is")
|
cmd := exec.Command("lsb_release", "-is")
|
||||||
|
|
|
@ -24,8 +24,8 @@ import (
|
||||||
type DockerEnvironment struct {
|
type DockerEnvironment struct {
|
||||||
Server *Server
|
Server *Server
|
||||||
|
|
||||||
// The user that containers should be running as.
|
// The user ID that containers should be running as.
|
||||||
User string
|
User int
|
||||||
|
|
||||||
// Defines the configuration for the Docker instance that will allow us to connect
|
// Defines the configuration for the Docker instance that will allow us to connect
|
||||||
// and create and modify containers.
|
// and create and modify containers.
|
||||||
|
@ -43,6 +43,7 @@ func NewDockerEnvironment(opts ...func(*DockerEnvironment)) (*DockerEnvironment,
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &DockerEnvironment{
|
env := &DockerEnvironment{
|
||||||
|
User: 1000,
|
||||||
Client: cli,
|
Client: cli,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ func (d *DockerEnvironment) Create() error {
|
||||||
|
|
||||||
conf := &container.Config{
|
conf := &container.Config{
|
||||||
Hostname: "container",
|
Hostname: "container",
|
||||||
User: d.User,
|
User: strconv.Itoa(d.User),
|
||||||
AttachStdin: true,
|
AttachStdin: true,
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
|
|
|
@ -171,7 +171,7 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, e
|
||||||
}
|
}
|
||||||
|
|
||||||
withConfiguration := func (e *DockerEnvironment) {
|
withConfiguration := func (e *DockerEnvironment) {
|
||||||
e.User = cfg.User
|
e.User = cfg.User.Uid
|
||||||
e.TimezonePath = cfg.TimezonePath
|
e.TimezonePath = cfg.TimezonePath
|
||||||
e.Server = s
|
e.Server = s
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user