Skip to content
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

Does tableflip work with systemd's socket activation? #14

Closed
matthewmueller opened this issue Dec 27, 2018 · 3 comments
Closed

Does tableflip work with systemd's socket activation? #14

matthewmueller opened this issue Dec 27, 2018 · 3 comments

Comments

@matthewmueller
Copy link
Contributor

matthewmueller commented Dec 27, 2018

Hi there, I'm wondering if this library can work alongside systemd's socket activation?

What I'm trying to do is basically use systemd's root access to listen on port 80 and pass that file descriptor into my Go application so my Go app doesn't have to use sudo.

Is this possible with tableflip? Does tableflip even make sense in this context? My thinking is that tableflip is would still be useful for doing the upgrade attempts.

Any feedback here would be greatly appreciated. Thanks!

@matthewmueller matthewmueller changed the title Does tableflip work with socket activation? Does tableflip work with systemd's socket activation? Dec 27, 2018
@lmb
Copy link
Contributor

lmb commented Jan 7, 2019

You should be able to achieve this by using Fds.Listener and Fds.AddListener.

Pseudo-code:

ln, _ := upg.Fds.Listener("systemd", "something")
if ln == nil {
  // Get ln from systemd, probably via os.NewFile / net.FileListener
  upg.Fds.AddListener("systemd", "something", ln)
}

@lmb
Copy link
Contributor

lmb commented Jan 11, 2019

@matthewmueller did you have any luck with the above?

@matthewmueller
Copy link
Contributor Author

matthewmueller commented Jan 11, 2019

@lmb, hey sorry for the late response! I want to say I tried this but wasn't able to get it working. I ended up sticking nginx in front for now.

I'll close this for now because I have something that's working, but I'll probably give this another shot at a later time because I just love that it's a single binary system.

If it's helpful to anyone else, here's my findings.

From the socket activation side it looks like this:

file := os.NewFile(uintptr(3), "socket")
ln, err := net.FileListener(file)
if err != nil {
	panic(err)
}

// serve, and somehow get it working with tableflip

And here's a test app that could simulate socket activation:

ln, err := net.Listen("tcp", ":8000")
if err != nil {
	panic(err)
}

file, err := ln.(*net.TCPListener).File()
if err != nil {
	panic(err)
}

cmd := exec.Command("go", "run", "main.go")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = append(cmd.ExtraFiles, file)

// serve from the other file
if err := cmd.Run(); err != nil {
	panic(err)
}

I think the ideal situation would be to say systemctl reload app and have it somehow do the upgrade, rolling back if there's been a failure. This might not make sense with socket activation in which case it might make more sense to just add capabilities to the systemd unit file for the protected port and call it the way godoc suggests.

Like I mentioned, I wasn't able to get this working nicely, but I'd love for someone else to take the lead!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants