[Unit] Description=RDM card reader HTTP bridge (serves card taps for web login) Documentation=file:/opt/rdm-card-reader/README.md # The serial device must exist before we start, otherwise the reader opens the # wrong tty or none at all. install.sh rewrites this line for the device given # with --device, since only it knows whether the reader is on the on-board UART # (/dev/serial0, the default) or a USB adapter (/dev/rdm-reader). After=dev-serial0.device network-online.target Wants=network-online.target # Do not restart forever if the reader is genuinely absent. These are [Unit] # options, not [Service] - systemd ignores them in the wrong section. StartLimitIntervalSec=60 StartLimitBurst=5 [Service] Type=simple User=rdmcard Group=dialout WorkingDirectory=/opt/rdm-card-reader # --serve runs the HTTP bridge, which is what makes the reader available as an # API on http://127.0.0.1:8765. --port points at the device the reader is # actually wired to; install.sh rewrites this line from --device, and only it # knows whether that is a USB adapter (/dev/rdm-reader) or the on-board UART # (/dev/serial0). --led-pin is rewritten from --led-pin for the same reason. # Autodetect refuses to guess if more than one USB adapter is present, which is # the safe behaviour: a wrong guess means authenticating the wrong person. # The wheels for rdm6300 and pyserial are bundled inside the package, so no # --wheel-dir is needed here: the install works with no internet. ExecStart=/opt/rdm-card-reader/.venv/bin/rdm-card-reader \ --serve \ --port /dev/serial0 \ --mode login \ --led-pin 23 \ --led-mode presence \ --heartbeat 2.0 Restart=always RestartSec=3 # The bridge reads the serial port, drives the status LED and listens on # loopback. DeviceAllow is rewritten by install.sh alongside --port: with # DevicePolicy=closed a device missing from this list is denied outright, and # omitting the GPIO chip leaves the LED dark while everything else works. NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictNamespaces=true LockPersonality=true MemoryDenyWriteExecute=true DeviceAllow=/dev/serial0 rw DeviceAllow=/dev/gpiochip0 rw DeviceAllow=/dev/gpiochip4 rw DevicePolicy=closed # stdout/stderr go here; watch with: journalctl -u rdm-card-reader -f StandardOutput=journal StandardError=journal SyslogIdentifier=rdm-card-reader [Install] WantedBy=multi-user.target