How CasaOS Handles systemd Daemon Notifications for Service Management

CasaOS uses the go-systemd library to emit a READY=1 notification via daemon.SdNotify() in main/main.go, signaling systemd that all internal services are initialized before the unit transitions to the active state.

CasaOS, the open-source home cloud system from IceWhaleTech, implements systemd daemon notifications for service management to ensure reliable service startup sequencing. By integrating with systemd's Type=notify protocol through the go-systemd library, CasaOS guarantees that the systemd unit remains in the activating state until all critical components—including the database, cache, background jobs, and HTTP router—are fully initialized.

The SdNotify Implementation in main.go

Signaling Readiness After Initialization

In main/main.go, CasaOS invokes the daemon.SdNotify function from github.com/coreos/go-systemd/daemon immediately after completing its startup sequence. The application passes false as the first argument to preserve the watchdog flag and daemon.SdNotifyReady (which expands to READY=1) as the second argument:

if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
    logger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
} else if supported {
    logger.Info("Notified systemd that casaos main service is ready")
} else {
    logger.Info("This process is not running as a systemd service.")
}

Handling Non-Systemd Environments

The function returns a boolean supported indicating whether the process is running under systemd. When supported is false—such as when running the binary manually—the application logs a benign informational message and continues execution without the systemd integration.

Systemd Integration and Service Lifecycle

Type=notify Service Integration

CasaOS expects to run as a Type=notify systemd service. In this mode, systemd waits for the READY=1 notification before marking the unit as active (running). This prevents systemd from considering the service started prematurely while background jobs and the HTTP server are still initializing.

The Notification Payload

The daemon.SdNotifyReady constant translates to the string READY=1. When systemd receives this notification through the notification socket, it transitions the service from the activating to the active state, enabling automatic restart policies and proper dependency management for downstream services.

Unit File Configuration and Dependencies

To leverage CasaOS's systemd daemon notifications for service management, the unit file must specify Type=notify:

[Unit]
Description=CasaOS service
After=network.target

[Service]
Type=notify
ExecStart=/usr/local/bin/casaos
Restart=on-failure

[Install]
WantedBy=multi-user.target

Project Dependencies

The notification capability relies on the github.com/coreos/go-systemd/daemon package, declared in go.mod. The core initialization logic that must complete before notification resides in the service/ directory, which handles the HTTP server, caching layer, and cron jobs.

Summary

  • CasaOS calls daemon.SdNotify(false, daemon.SdNotifyReady) in main/main.go after initializing all services.
  • The notification sends READY=1 to systemd, completing the startup sequence for Type=notify units.
  • The implementation gracefully handles non-systemd environments by checking the supported boolean return value.
  • This integration ensures systemd only considers CasaOS active after the database, cache, and HTTP router are ready.

Frequently Asked Questions

What happens if CasaOS runs without systemd?

When executed outside of systemd, the daemon.SdNotify function returns supported=false. CasaOS detects this condition and logs "This process is not running as a systemd service," continuing normal operation without attempting to communicate with the init system.

Why does CasaOS pass false as the first argument to SdNotify?

The first parameter controls whether to unset the WATCHDOG environment variable. CasaOS passes false because it does not utilize systemd's watchdog functionality, choosing only to signal readiness while preserving any existing watchdog state.

Which CasaOS components must be ready before the systemd notification is sent?

According to the source code in main/main.go and the service/ directory, CasaOS initializes its configuration, database connections, cache layer, background cron jobs, and HTTP router before emitting the READY=1 notification to systemd.

What version of the go-systemd library does CasaOS use?

CasaOS imports github.com/coreos/go-systemd/daemon as specified in go.mod, providing the SdNotify function and SdNotifyReady constant used to implement the sd-notify protocol.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →