From 79a857e0a0465cc084d5dbae022d7b0146003b27 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 21 May 2025 17:38:39 +0200 Subject: [PATCH 1/2] pkg/machine: correctly enable lingering When a custom username is requested we must stil enable lingering for it. The linger setup in the coreos image with the hard coded core user doesn't really make sense as it doesn't work when another name is used. Signed-off-by: Paul Holzinger --- pkg/machine/e2e/init_test.go | 11 +++++++++++ pkg/machine/ignition/ignition.go | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go index 2e05f1a1e2..684e47e9d9 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go @@ -238,6 +238,17 @@ var _ = Describe("podman machine init", func() { Expect(testMachine.Resources.Memory).To(BeEquivalentTo(uint64(2048))) } Expect(testMachine.SSHConfig.RemoteUsername).To(Equal(remoteUsername)) + + s := new(startMachine) + session, err = mb.setCmd(s).run() + Expect(err).ToNot(HaveOccurred()) + Expect(session).To(Exit(0)) + + ssh := sshMachine{} + sshSession, err := mb.setName(mb.name).setCmd(ssh.withSSHCommand([]string{"loginctl -P Linger show-user " + remoteUsername})).run() + Expect(err).ToNot(HaveOccurred()) + Expect(sshSession).To(Exit(0)) + Expect(sshSession.outputToString()).To(ContainSubstring("yes")) }) It("machine init with cpus, disk size, memory, timezone", func() { diff --git a/pkg/machine/ignition/ignition.go b/pkg/machine/ignition/ignition.go index 2d7e63f3a4..e21eccf408 100644 --- a/pkg/machine/ignition/ignition.go +++ b/pkg/machine/ignition/ignition.go @@ -304,6 +304,23 @@ func getDirs(usrName string) []Directory { func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ bool, swap uint64) []File { files := make([]File, 0) + // enable linger mode for the user + files = append(files, File{ + Node: Node{ + Group: GetNodeGrp("root"), + Path: "/var/lib/systemd/linger/" + usrName, + User: GetNodeUsr("root"), + // the coreos image might already have this defined + Overwrite: BoolToPtr(true), + }, + FileEmbedded1: FileEmbedded1{ + Contents: Resource{ + Source: EncodeDataURLPtr(""), + }, + Mode: IntToPtr(0644), + }, + }) + lingerExample := parser.NewUnitFile() lingerExample.Add("Unit", "Description", "A systemd user unit demo") lingerExample.Add("Unit", "After", "network-online.target") From 5797c1dd27a6381b2ed69768262b71c4417dd74d Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 21 May 2025 18:18:04 +0200 Subject: [PATCH 2/2] pkg/machine: don't use dummy linger service There is no reason to deifne a dummy service to run sleep just to get the podman.socket enabled. Enabeling a service is just creating the symlink so we can do that for the user sessions as well. Signed-off-by: Paul Holzinger --- pkg/machine/ignition/ignition.go | 40 ++++++-------------------------- pkg/machine/wsl/declares.go | 14 +---------- pkg/machine/wsl/machine.go | 17 ++++---------- 3 files changed, 12 insertions(+), 59 deletions(-) diff --git a/pkg/machine/ignition/ignition.go b/pkg/machine/ignition/ignition.go index e21eccf408..9f3fcaf6e4 100644 --- a/pkg/machine/ignition/ignition.go +++ b/pkg/machine/ignition/ignition.go @@ -138,7 +138,7 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error { ignStorage := Storage{ Directories: getDirs(ign.Name), Files: getFiles(ign.Name, ign.UID, ign.Rootful, ign.VMType, ign.NetRecover, ign.Swap), - Links: getLinks(ign.Name), + Links: getLinks(), } // Add or set the time zone for the machine @@ -281,7 +281,6 @@ func getDirs(usrName string) []Directory { "/home/" + usrName + "/.config/containers", "/home/" + usrName + "/.config/systemd", "/home/" + usrName + "/.config/systemd/user", - "/home/" + usrName + "/.config/systemd/user/default.target.wants", } var ( dirs = make([]Directory, len(newDirs)) @@ -321,16 +320,6 @@ func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ boo }, }) - lingerExample := parser.NewUnitFile() - lingerExample.Add("Unit", "Description", "A systemd user unit demo") - lingerExample.Add("Unit", "After", "network-online.target") - lingerExample.Add("Unit", "Wants", "network-online.target podman.socket") - lingerExample.Add("Service", "ExecStart", "/usr/bin/sleep infinity") - lingerExampleFile, err := lingerExample.ToString() - if err != nil { - logrus.Warn(err.Error()) - } - containers := `[containers] netns="bridge" pids_limit=0 @@ -349,22 +338,6 @@ pids_limit=0 } etcSubUID := fmt.Sprintf(`%s:%d:%d`, usrName, subUID, subUIDs) - // Add a fake systemd service to get the user socket rolling - files = append(files, File{ - Node: Node{ - Group: GetNodeGrp(usrName), - Path: "/home/" + usrName + "/.config/systemd/user/linger-example.service", - User: GetNodeUsr(usrName), - }, - FileEmbedded1: FileEmbedded1{ - Append: nil, - Contents: Resource{ - Source: EncodeDataURLPtr(lingerExampleFile), - }, - Mode: IntToPtr(0744), - }, - }) - // Set containers.conf up for core user to use networks // by default files = append(files, File{ @@ -606,16 +579,17 @@ func getSSLFile(path, content string) File { } } -func getLinks(usrName string) []Link { +func getLinks() []Link { return []Link{{ Node: Node{ - Group: GetNodeGrp(usrName), - Path: "/home/" + usrName + "/.config/systemd/user/default.target.wants/linger-example.service", - User: GetNodeUsr(usrName), + Group: GetNodeGrp("root"), + Path: "/etc/systemd/user/sockets.target.wants/podman.socket", + User: GetNodeUsr("root"), + Overwrite: BoolToPtr(true), }, LinkEmbedded1: LinkEmbedded1{ Hard: BoolToPtr(false), - Target: "/home/" + usrName + "/.config/systemd/user/linger-example.service", + Target: "/usr/lib/systemd/user/podman.socket", }, }, { Node: Node{ diff --git a/pkg/machine/wsl/declares.go b/pkg/machine/wsl/declares.go index d801eb6f36..0145ae86bf 100644 --- a/pkg/machine/wsl/declares.go +++ b/pkg/machine/wsl/declares.go @@ -28,6 +28,7 @@ const changePort = `sed -E -i 's/^Port[[:space:]]+[0-9]+/Port %d/' /etc/ssh/sshd const configServices = `ln -fs /usr/lib/systemd/system/sshd.service /etc/systemd/system/multi-user.target.wants/sshd.service ln -fs /usr/lib/systemd/system/podman.socket /etc/systemd/system/sockets.target.wants/podman.socket +ln -fs /usr/lib/systemd/user/podman.socket /etc/systemd/user/sockets.target.wants/podman.socket rm -f /etc/systemd/system/getty.target.wants/console-getty.service rm -f /etc/systemd/system/getty.target.wants/getty@tty1.service rm -f /etc/systemd/system/multi-user.target.wants/systemd-resolved.service @@ -106,19 +107,6 @@ const overrideSysusers = `[Service] LoadCredential= ` -const lingerService = `[Unit] -Description=A systemd user unit demo -After=network-online.target -Wants=network-online.target podman.socket -[Service] -ExecStart=/usr/bin/sleep infinity -` - -const lingerSetup = `mkdir -p /home/[USER]/.config/systemd/user/default.target.wants -ln -fs /home/[USER]/.config/systemd/user/linger-example.service \ - /home/[USER]/.config/systemd/user/default.target.wants/linger-example.service -` - const bindMountSystemService = ` [Unit] Description=Bind mount for system podman sockets diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index d840ed3193..2c6ee39ac5 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -173,19 +173,10 @@ func configureSystem(mc *vmconfigs.MachineConfig, dist string, ansibleConfig *vm } } - lingerCmd := withUser("cat > /home/[USER]/.config/systemd/[USER]/linger-example.service", user) - if err := wslPipe(lingerService, dist, "sh", "-c", lingerCmd); err != nil { - return fmt.Errorf("could not generate linger service for guest OS: %w", err) - } - if err := enableUserLinger(mc, dist); err != nil { return err } - if err := wslPipe(withUser(lingerSetup, user), dist, "sh"); err != nil { - return fmt.Errorf("could not configure systemd settings for guest OS: %w", err) - } - if err := wslPipe(containersConf, dist, "sh", "-c", "cat > /etc/containers/containers.conf"); err != nil { return fmt.Errorf("could not create containers.conf for guest OS: %w", err) } @@ -214,6 +205,10 @@ func configureBindMounts(dist string, user string) error { return fmt.Errorf("could not create podman binding service file for guest OS: %w", err) } + if err := wslPipe(getConfigBindServicesScript(user), dist, "sh"); err != nil { + return fmt.Errorf("could not configure podman binding services for guest OS: %w", err) + } + catUserService := "cat > " + getUserUnitPath(user) if err := wslPipe(getBindMountUserService(dist), dist, "sh", "-c", catUserService); err != nil { return fmt.Errorf("could not create podman binding user service file for guest OS: %w", err) @@ -223,10 +218,6 @@ func configureBindMounts(dist string, user string) error { return fmt.Errorf("could not create podman binding fstab entry for guest OS: %w", err) } - if err := wslPipe(getConfigBindServicesScript(user), dist, "sh"); err != nil { - return fmt.Errorf("could not configure podman binding services for guest OS: %w", err) - } - catGroupDropin := fmt.Sprintf("cat > %s/%s", podmanSocketDropinPath, "10-group.conf") if err := wslPipe(overrideSocketGroup, dist, "sh", "-c", catGroupDropin); err != nil { return fmt.Errorf("could not configure podman socket group override: %w", err)