Skip to content

pkg/machine: setup lingering for custom username and remove unnecessary sleep service #26177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pkg/machine/e2e/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
55 changes: 23 additions & 32 deletions pkg/machine/ignition/ignition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -304,15 +303,22 @@ func getDirs(usrName string) []Directory {
func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, _ bool, swap uint64) []File {
files := make([]File, 0)

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())
}
// 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),
},
})

containers := `[containers]
netns="bridge"
Expand All @@ -332,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{
Expand Down Expand Up @@ -589,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{
Expand Down
14 changes: 1 addition & 13 deletions pkg/machine/wsl/declares.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/[email protected]
rm -f /etc/systemd/system/multi-user.target.wants/systemd-resolved.service
Expand Down Expand Up @@ -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
Expand Down
17 changes: 4 additions & 13 deletions pkg/machine/wsl/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down