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

feature: support running under windows service #293

Closed
kardianos opened this issue Oct 28, 2015 · 20 comments
Closed

feature: support running under windows service #293

kardianos opened this issue Oct 28, 2015 · 20 comments
Labels
feature ⚙️ New feature or request plugin 🔌 A feature outside this repo

Comments

@kardianos
Copy link

Would you be open to a PR that under windows on load
a. detects if running as a windows service
b. if so, uses the windows service start, stop callbacks that enable running under windows services.

Could use either:
https://godoc.org/golang.org/x/sys/windows/svc
or https://godoc.org/github.com/kardianos/service

@Makpoc
Copy link

Makpoc commented Oct 29, 2015

The idea sounds interesting. Could you please explain a little bit more how do you propose to register the service. From what I understood a) and b) rely on an already installed service to detect and manage it.

@kardianos
Copy link
Author

The final goal of this would be to enable running caddy directly as a windows service which requires some callbacks and a control loop. Secondary items to address are making it easy to install and auto-sense when it is being run as a service or in cmd.

The kardianos/service package wraps the x/sys/windows/svc package on windows and exposes a uniform API for all platforms. A decision on if this change should be windows specific or not would need to be made.

An example of the service in action may be found here: https://github.com/kardianos/service/blob/master/example/logging/main.go
The following code is an excerpt from the above link and contains the code that installs, starts, stops, restarts, and removes the services:

    if len(*svcFlag) != 0 {
        err := service.Control(s, *svcFlag)
        if err != nil {
            log.Printf("Valid actions: %q\n", service.ControlAction)
            log.Fatal(err)
        }
        return
    }
    err = s.Run()

If there isn't a control flag, then it simply runs the service. The Run() method does a detection if it is running under a service manager or not which determines how it runs the executable (on windows, if it should use the service callbacks or now).

Even if you don't include or use the code to control the service, windows ships with a command called "sc" users could use to install, start, stop remove services, though most windows users who aren't sysadmins know of it.

You may wish to integrate a control flag to enforce the user to provide a Caddyfile location as the CWD is not settable for windows services.

The delta for this pull request that used the kardianos/service package would be:

  • Add a flag called something like "-instance-name", optional to identify different caddy service instances. (this flag could be omitted).
  • Add a flag called something like "-service", used to install, start, restart, stop, uninstall services.
  • In the main, probably replace app.Wg.Wait() with serviceInstance.Run() (still wait in a separate goroutine and signal stop when done). Care would need to be taken to not get in the way of something like graceful restarts or similar, if that is a goal.
  • In the main func, define the service. The service name could be "Caddy{{if instance name}}${{.InstanceName}}{{end}}". And populate the arguments for the Caddyfile location when installing the service.

@mholt mholt added the feature ⚙️ New feature or request label Oct 29, 2015
@mholt
Copy link
Member

mholt commented Oct 29, 2015

I do like the idea of "caddy as a service" -- but hold out on any implementation details, since the letsencrypt branch is going to land in master soon, which completely refactors the entire core -- making it very easy to start, stop, and restart the listeners, making it very service-friendly.

So I like where this is going. Keep an eye on master to see when letsencrypt gets merged into it. After the next release, would be a good time to start working on this.

@kardianos
Copy link
Author

@mholt Sounds good.

@mholt
Copy link
Member

mholt commented Nov 7, 2015

@kardianos The merge is completed, and I don't anticipate any huge changes for the next little while, if you wanted to start looking into the service feature.

@kardianos
Copy link
Author

@mholt Would you prefer this in the form of windows only support that enables manually installing and running as a web service, or would you like to see two additional flags that allow cross platform installing and controlling as a service?

@mholt
Copy link
Member

mholt commented Dec 3, 2015

I just saw your repo at https://github.com/kardianos/minwinsvc - I haven't given it a once-over yet and I still need to figure out the answers to your questions. 😄 But we'll get around to it!

@oliverjanik
Copy link

In the mean time,
if anyone is looking how to get Caddy setup as windows service. I recommend NSSM. It wraps CLI applications and manages their execution.

@mholt mholt added the plugin 🔌 A feature outside this repo label Jun 5, 2016
@mholt
Copy link
Member

mholt commented Jun 5, 2016

Hey @kardianos and others in this issue - thanks for your comments! There is a lot of good stuff here, so I have linked to this issue from a thread in our community forum where we are aggregating ideas/requests for Caddy plugins. It's quite possible, with Caddy 0.9, that maybe this kind of feature could be implemented as a plugin. I remember your pull request #588, kardianos, and it's totally possible, I think, to make it a plugin. And it would be as easy as your PR.

If you want to continue discussing this, feel free to start a new topic on the forum or re-open the issue. 👍 Again, not closing because I don't want this, just trying to get through my backlog, since this'll probably be a better plugin than built into Caddy core.

@mholt mholt closed this as completed Jun 5, 2016
@kardianos
Copy link
Author

kardianos commented Jun 7, 2016

yes, you could add a plugin that does one thing, import github.com/kardianos/minwinsvc and that's all. On non-windows compiles it would do nothing. On windows compiles it would allow registering as a windows service.

Or if you want you could import minwinsvc directly. It would do nothing for non-windows boxes, yet make it an option to run caddy as a windows service directly in windows. Either would work.

Neither would make a UI within caddy for easily setting up the service. Which is fine.

@infogulch
Copy link

What would a plugin look like here? It would call RegisterPlugin() of course, but how would it get access to the *Instance to call ShutdownCallbacks() and Stop()?

I don't see where plugins have access to initiate a shutdown (as opposed to just reacting to a shutdown).

@Echsecutor
Copy link

Echsecutor commented Sep 14, 2016

Registering/unregistering the service should only be triggered once, hence through a command line argument rather than a Caddyfile directive. Can plugins acces the args and prevent the server from starting if caddy.exe is only used as a cli to register/unregister the service?

Maybe it would be better to have a separate caddy_cli.exe than a caddy plugin? (Like e.g. postgres)

@infogulch
Copy link

@Echsecutor this issue is limited in scope to enabling a compiled caddy.exe to be used as a service, and explicitly not about the process of registering it as a service. To do that you would use an external program, for example, sc create among others.

@mholt
Copy link
Member

mholt commented Sep 14, 2016

Plugins can register their own command line flags, yes.

@infogulch
Copy link

@mholt So how would a plugin that decided that caddy should shutdown communicate that up to caddy? E.g. how would it call executeShutdownCallbacks()? Windows service messages are basically a different kind of signal and handling them should hook into the standard shutdown system.

@mholt
Copy link
Member

mholt commented Oct 1, 2016

Still working on those details...

@infogulch
Copy link

@mholt any progress here on the plugin api?

@mholt
Copy link
Member

mholt commented Apr 9, 2017

@infogulch Yes, @hacdias will have some news regarding this on April 20, or after he gets back from his trip.

@infogulch
Copy link

Awesome. Eagerly awaiting the live event! I'll certainly try to join via livestream. :)

@mholt
Copy link
Member

mholt commented Apr 28, 2017

FWIW, @hacdias helped work on this plugin which is now available: https://caddyserver.com/docs/hook.service

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature ⚙️ New feature or request plugin 🔌 A feature outside this repo
Projects
None yet
Development

No branches or pull requests

6 participants