IoT 05.07.2026 3 min read by Ulrich Emmerich

Run your own server scripts from Home Assistant automations

Let Home Assistant start a job on a LAN server through SSH or an authenticated HTTP endpoint, with tightly scoped permissions and clear HAOS limitations.

Home Assistant Automation shell_command LAN-Server
Run your own server scripts from Home Assistant automations

Let Home Assistant start a LAN-server job

MQTT suits continuing state updates, while the REST API suits calls from external programs. An automation reverses the direction: a Home Assistant trigger starts a narrowly defined task on the LAN server. Two practical routes are shell_command over SSH and rest_command to an authenticated HTTP endpoint.

Prerequisites

  • Home Assistant and the server can reach each other over a trusted LAN or VPN.
  • The task already exists as a systemd service.
  • SSH uses a dedicated unprivileged account.
  • Host keys and credentials are verified and kept out of published YAML.

Understand the HAOS execution context

On Home Assistant OS, shell_command runs inside the homeassistant container—not inside the terminal add-on and not on the HAOS host. The official documentation lists tools such as ssh, curl, and sh; the working directory is /config, and commands are terminated after 60 seconds.

The remote command should therefore only start the job. systemd then runs and logs the long task independently.

1. Prepare keys and restricted sudo

Store a dedicated key under /config/.ssh/ and verify the server host key in known_hosts. Do not disable host-key checking. On the LAN server, grant only the exact command in /etc/sudoers.d/homeassistant-backup, verified with visudo -f:


homeassistant ALL=(root) NOPASSWD: /usr/bin/systemctl start backup.service

The service itself must use fixed paths and must not execute unchecked parameters.

2. Define the shell command


shell_command:
  start_lanserver_backup: >-
    ssh -i /config/.ssh/id_ed25519_lanserver
    -o BatchMode=yes
    -o ConnectTimeout=10
    -o UserKnownHostsFile=/config/.ssh/known_hosts
    homeassistant@SERVER-IP
    'sudo /usr/bin/systemctl start backup.service'

Reload Shell Command in Developer tools → YAML or call shell_command.reload.

3. Add the automation


automation:
  - alias: "Start nightly backup on the LAN server"
    triggers:
      - trigger: time
        at: "02:00:00"
    conditions: []
    actions:
      - action: shell_command.start_lanserver_backup
        response_variable: backup_start
      - if:
          - condition: template
            value_template: "{{ backup_start.returncode != 0 }}"
        then:
          - action: notify.notify
            data:
              message: "The backup service could not be started: {{ backup_start.stderr }}"

The response reports the short SSH call, not the eventual backup result. Publish completion separately through MQTT, a status file, or a dedicated endpoint.

REST alternative

An HTTP endpoint can be easier to isolate, but it must authenticate requests, accept only POST, validate all input, and use HTTPS or a trusted network/VPN:


rest_command:
  start_lanserver_backup:
    url: "https://lanserver.example.lan/api/backup"
    method: POST
    headers:
      Authorization: "Bearer {{ token }}"
    content_type: "application/json"
    payload: '{"job":"backup"}'

Do not publish the token or replace this with an unauthenticated HTTP script.

Troubleshooting

1. Test in the actual shell_command runtime environment.

2. Check key and known_hosts permissions.

3. Inspect journalctl -u ssh and journalctl -u backup.service on the server.

4. Remember the 60-second command limit.

5. For REST, inspect the HTTP status, certificate, and server log.

Sources and technical documentation

Links marked with * are affiliate links. As an Amazon Associate I earn from qualifying purchases.

More articles about IoT