# How CasaOS Handles systemd Daemon Notifications for Service Management

> Discover how CasaOS leverages systemd daemon notifications for robust service management. Learn about its use of go-systemd and SdNotify to ensure seamless initialization and active state transitions.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: internals
- Published: 2026-06-26

---

**CasaOS uses the go-systemd library to emit a `READY=1` notification via `daemon.SdNotify()` in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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:

```go
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`:

```ini
[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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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.