{"id":19965922,"url":"https://github.com/stephen-fox/cyberdaemon","last_synced_at":"2026-05-12T18:09:51.662Z","repository":{"id":57551291,"uuid":"198102716","full_name":"stephen-fox/cyberdaemon","owner":"stephen-fox","description":"A Go library that provides tooling for creating and managing a platform-agnostic daemon.","archived":false,"fork":false,"pushed_at":"2021-05-25T00:42:06.000Z","size":127,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-23T12:29:59.812Z","etag":null,"topics":["daemon","daemonize","launchd","systemd","systemv","windows-service"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stephen-fox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-21T20:34:13.000Z","updated_at":"2024-01-14T14:29:26.000Z","dependencies_parsed_at":"2022-09-26T18:41:25.658Z","dependency_job_id":null,"html_url":"https://github.com/stephen-fox/cyberdaemon","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephen-fox%2Fcyberdaemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephen-fox%2Fcyberdaemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephen-fox%2Fcyberdaemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephen-fox%2Fcyberdaemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stephen-fox","download_url":"https://codeload.github.com/stephen-fox/cyberdaemon/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241397348,"owners_count":19956500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["daemon","daemonize","launchd","systemd","systemv","windows-service"],"created_at":"2024-11-13T02:32:18.268Z","updated_at":"2025-11-24T22:04:55.154Z","avatar_url":"https://github.com/stephen-fox.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cyberdaemon\nA Go library that provides tooling for creating and managing a\nplatform-agnostic daemon.\n\n## Use cases\nMy primary motivation for writing this library was to create and understand\nhow a Windows service works. I ended up thinking \"how difficult could it be\nto support other operating systems?\" Well, it was not easy. This library can\ncontrol the state of a daemon (start, stop, install, and uninstall) as well\nas turn your application code into a daemon.\n\n## Supported systems\n- Linux\n    - systemd\n    - System V (init.d) (if systemd is unavailable)\n- macOS\n    - launchd\n- Windows\n    - Windows service\n\n## API\n\n#### `cyberdaemon`\nThe top-level package provides the following interfaces:\n- `Daemonizer`\n- `Application`\n\nDaemonizer is used to turn your application into a daemon. Implementations\nof this interface use operating system specific calls and logic to properly\nrun your code as a daemon. This is facilitated by the Application interface.\nUsage of the 'control' subpackage is not required when using a Daemonizer.\nDevelopers may implement their own daemon management tooling while also\nleveraging the Daemonizer. Please review the 'Gotchas' documentation in the\nDaemonizer interface if you choose to use your own management tooling.\n\nThe Application interface is used by the Daemonizer to run your application\ncode as a daemon. Implement this interface in your application and use the\nDaemonizer to run your program.\n\n#### `control` subpackage\nThe control subpackage provides the following interface:\n- `Controller`\n\nThe Controller is used to control the state of a daemon. Implementations\ncommunicate with the operating system's daemon management software to\nquery a daemon's status, start or stop it, and install and uninstall it.\nA Controller is configured using the ControllerConfig struct. This struct\nprovides the necessary information about a daemon (such as its ID).\nIt also provides customization options, such as the start up type.\n\n#### Example\nThe [examples/filewriter](examples/filewriter/main.go) provides a basic example\nof an application that uses a Controller to control its daemon's state, and\nthe Daemonizer interface to daemonize the application code.\n\n## Design philosophies\nI made a few design decisions along the way that are non-obvious. This section\nwill explain my thoughts on these decisions.\n\n#### Why are there two packages / why is `control` a subpackage?\nIt is uncommon for conventional daemons to \"control\" themselves. In other\nwords, many daemon's are managed by an external piece of software with its own\ndistinctly separate configuration. Not all operating systems function this way\n(I am looking at you, Windows). However, I thought it was worth separating the\n\"how do I daemonize my app\" code from the \"how do I control my daemon\" code for\ncleanliness, and to highlight implementation intent. As shown in the\nexample(s), there is no reason why you cannot use both packages together.\nAnother reason I prefer this design is that it should stop me from making the\ndaemonization code depend on the control code (via go's circular dependency\ncompile check).\n\n#### Why do I need to implement an interface?\nOne of the most prominent decisions is requiring users to implement the\n`Application` interface. The reasoning behind this is mainly due to operating\nsystem limitations (System V daemons need to fork exec, for example).\nIn addition, I did not want to risk log output (e.g., `log.Println()`)\noccurring before the daemon can connect the logger to the operating system's\nlogging tool. Even if the OS just collects stderr - there could be a race\nbetween the daemon starting and the application code running.\n\n#### Why are there so many interfaces?\nThe use of interfaces is necessitated by the sheer number of operating systems.\nSeparating the concerns of \"how do I control the daemon?\", and \"how do I turn\nmy code into a daemon?\" seemed logical. I did not want to mix these two\nresponsibilities. Also, many people consider it weird for a daemon to change\nits own state.\n\n## Inspirations\nSpecial thanks and acknowledgement must be made for the following individuals.\nTheir work was both inspirational and helpful for problem-solving ideas while\nworking on this project:\n- [Igor \"takama\" Dolzhikov](https://github.com/takama) for his awesome work\non his [daemon](https://github.com/takama/daemon) project\n- [Daniel \"kardianos\" Theophanes](https://github.com/kardianos) for his excellent\nwork on his [service](https://github.com/kardianos/service) project\n- The [OpenSSH project](https://github.com/openssh/openssh-portable)\ncontributors and maintainers for their sshd init.d script, which I based this\nproject's init.d script on\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephen-fox%2Fcyberdaemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstephen-fox%2Fcyberdaemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephen-fox%2Fcyberdaemon/lists"}