Skip to content

Systemd Units

Infrastructure Banner


Systemd Services#

micipsa-hardware.service#

Runs a one-shot script that validates the presence and accessibility of all required hardware peripherals (cameras and serial devices) before the rest of the stack is allowed to start. Uses RemainAfterExit=yes so that micipsa-hardware.target and micipsa-compose-stack.service can safely declare dependencies on it even after the script has exited.

[Unit]
Description=Micipsa hardware devices check
DefaultDependencies=no
After=systemd-udev-settle.service
Wants=systemd-udev-settle.service

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/micipsa_devices_check.sh
RemainAfterExit=yes
StandardOutput=journal
StandardError=journal
SyslogIdentifier=micipsa-hardware-check

[Install]
WantedBy=micipsa-hardware.target

Key design decisions:

  • DefaultDependencies=no disables the default ordering constraints (e.g. against shutdown.target) that are inappropriate for early-boot hardware checks.
  • Wants=systemd-udev-settle.service (rather than Requires) the udev settle service is a soft dependency. If it is unavailable or fails, the hardware check will still attempt to run rather than being blocked entirely.
  • Type=oneshot with RemainAfterExit=yes the service is considered active as long as the check passed, even after the script process has exited. Downstream units that use After=micipsa-hardware.service will not start until the script completes successfully.

micipsa-hardware.target#

A passive synchronisation point that represents the "hardware layer is ready" state. It does not start any process itself. Other units declare WantedBy=micipsa-hardware.target or Requires=micipsa-hardware.target to hook into or depend on this layer.

[Unit]
Description=Micipsa Hardware Layer
Requires=micipsa-hardware.service
After=micipsa-hardware.service

[Install]
WantedBy=multi-user.target

Key design decisions:

  • Requires + After on micipsa-hardware.service the target only becomes active once the hardware check service has completed successfully, and fails immediately if the service fails.

micipsa-compose-stack.service#

Starts the full robot software stack via the micipsa_compose wrapper, which resolves the Docker Compose configuration from the specified config directory and brings up all containers. On stop, it brings the stack down cleanly.

[Unit]
Description=Micipsa Docker Compose Stack
Documentation=https://gitlab.com/yousriouartsi-group/micipsa/micipsa

After=micipsa-hardware.target
Requires=micipsa-hardware.target

After=docker.service
Requires=docker.service

[Service]
Type=simple
User=root
Environment=PYTHONPATH=/usr/local/lib/micipsa # to find utils files/libs

# Force-clear any leftover state from an unclean shutdown before bringing
# the stack up. The leading "-" tells systemd not to fail the unit if this
# step itself errors (e.g. nothing was running, or a container was already
# gone) it's cleanup, not a hard precondition.
ExecStartPre=-/usr/local/bin/compose_launcher down \
    --docker-compose-files-dir /etc/micipsa/infra/docker/

ExecStart=/usr/local/bin/compose_launcher up \
    --mode deploy \
    --bringup-config-dir /etc/micipsa/micipsa_robot/micipsa_bringup/config/ \
    --maps-dir /etc/micipsa/micipsa_robot/micipsa_maps/maps/ \
    --dds-dir /etc/micipsa/infra/dds/ \
    --bringup-config-name bringup_config.yaml \
    --docker-compose-files-dir /etc/micipsa/infra/docker/

ExecStop=/usr/local/bin/compose_launcher down \
    --docker-compose-files-dir /etc/micipsa/infra/docker/

Restart=on-failure
RestartSec=10s
TimeoutStartSec=120s
TimeoutStopSec=120s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=micipsa-docker

[Install]
WantedBy=multi-user.target

Key design decisions:

  • Requires=micipsa-hardware.target a hard dependency. If hardware validation failed at boot, systemd will not attempt to start this service.
  • Requires=docker.service ensures the Docker daemon is running before any docker compose command is issued.
  • Type=simple appropriate here because micipsa_compose up is a long-running foreground process. systemd considers it started as soon as the process is launched.
  • Restart=on-failure with RestartSec=10s the service will be restarted automatically if the compose process exits unexpectedly, but not on a clean stop (ExecStop).
  • TimeoutStartSec=120s / TimeoutStopSec=120s allows sufficient time for Docker images to be pulled and containers to initialise on first run, and for containers to shut down gracefully on stop.

Common Command#

# Check the status of a service
sudo systemctl status <service>

# Start a service
sudo systemctl start <service>

# Stop a service
sudo systemctl stop <service>

# Restart a service
sudo systemctl restart <service>

# Enable a service (start automatically at boot)
sudo systemctl enable <service>

# Disable a service (do not start at boot)
sudo systemctl disable <service>

# Reload systemd after modifying unit files
sudo systemctl daemon-reload