# How CasaOS Handles Systemd SdNotifyReady Notifications

> Learn how CasaOS manages systemd SdNotifyReady signals using go-systemd for startup initialization. Discover automatic detection and graceful fallback for non-systemd systems.

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

---

**CasaOS uses the go-systemd library to send READY=1 messages to systemd's notification socket after completing startup initialization, with automatic detection and graceful fallback for non-systemd environments.**

CasaOS is an open-source home server operating system that integrates closely with Linux init systems to manage service dependencies. When running under systemd, the application must explicitly signal readiness after initializing its HTTP server and configuration to ensure proper service startup ordering.

## Systemd Notification Implementation in main/main.go

The notification logic resides in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go) of the CasaOS repository. After completing the startup sequence—initializing configuration, creating the address file, executing `start.d` scripts, and opening the HTTP listener—the application calls the notification function at approximately lines 204-210.

### The SdNotify Function Call

According to the CasaOS source code, the implementation uses `daemon.SdNotify` from the `github.com/coreos/go-systemd/v22/daemon` package:

```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.")
}

```

This call sends the **READY=1** message to systemd's notification socket. The `false` parameter indicates the notification does not unset the environment variable, allowing subsequent notifications if needed.

## Dependency Configuration

The systemd integration requires the `go-systemd` library, declared in `go.mod` as `github.com/coreos/go-systemd/v22`. The daemon package provides the binding to systemd's service notification protocol.

While [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) exists in the repository for CasaOS's internal notification service, it is unrelated to the systemd notification mechanism implemented in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go).

## Error Handling and Runtime Detection

The CasaOS implementation handles three distinct execution states:

- **Error state**: When `SdNotify` returns an error, the application logs a failure message using structured logging but continues operation
- **Systemd mode**: When the `supported` boolean is true, confirming systemd management, the application logs successful readiness notification
- **Standalone mode**: When `supported` is false, indicating manual execution or alternative init systems, the application logs this status and proceeds normally

This robust design ensures CasaOS functions correctly whether launched via systemd service units or executed directly for development and debugging.

## Practical Implementation Example

For developers implementing similar systemd integration in Go applications:

```go
import (
    "github.com/coreos/go-systemd/v22/daemon"
    "go.uber.org/zap"
)

func notifyReady(logger *zap.Logger) {
    if ok, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
        logger.Error("systemd notification error", zap.Error(err))
    } else if ok {
        logger.Info("systemd READY notification sent")
    } else {
        logger.Info("not running under systemd")
    }
}

```

## Summary

- CasaOS implements systemd notifications in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go) using the `go-systemd` library at approximately lines 204-210
- The `daemon.SdNotify(false, daemon.SdNotifyReady)` call transmits READY=1 after HTTP server initialization and startup script execution
- Boolean detection via the `supported` return value allows the application to distinguish between systemd and non-systemd execution contexts
- Error handling ensures startup continues even if the notification socket is unavailable or inaccessible

## Frequently Asked Questions

### What is SdNotifyReady in CasaOS?

SdNotifyReady is the constant used by CasaOS to send the READY=1 message to systemd's notification socket. This signal indicates that the CasaOS main service has completed initialization—including configuration loading, address file creation, and HTTP listener startup—and is ready to accept connections.

### Where is the systemd notification code located in CasaOS?

The notification logic is implemented in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go) immediately following the HTTP server startup sequence. The specific implementation appears at approximately lines 204-210, where the application calls `daemon.SdNotify` after executing startup scripts and opening network listeners.

### Does CasaOS require systemd to run?

No. CasaOS checks whether it is running under systemd using the `supported` boolean returned by `daemon.SdNotify`. If the process is not started by systemd, the function returns `false` and CasaOS logs that it is not running as a systemd service, continuing normal operation without the notification.

### Which library does CasaOS use for systemd integration?

CasaOS uses the `github.com/coreos/go-systemd/v22/daemon` package, a Go library maintained by CoreOS that provides bindings for systemd's notification socket and service manager functions.