The linuxcnc-grpc server runs on your LinuxCNC machine and exposes both LinuxCNCService and HalService over gRPC.
Requirements#
- Linux with LinuxCNC installed and running
- Python 3.9+
- Network access to the machine (for remote clients)
Installation#
pip install linuxcnc-grpc
# or with uv
uv pip install linuxcnc-grpcBasic Usage#
Start LinuxCNC first, then start the gRPC server:
linuxcnc-grpc --host 0.0.0.0 --port 50051Or run as a Python module:
python -m linuxcnc_grpc.server --host 0.0.0.0 --port 50051Command Line Options#
| Option | Default | Description |
|---|---|---|
--host | 0.0.0.0 | Address to bind to. Use 127.0.0.1 for local-only access |
--port | 50051 | Port number to listen on |
--nc-files | /home/linuxcnc/linuxcnc/nc_files | Directory for G-code file operations |
--debug | off | Enable debug logging |
Auto-Start with LinuxCNC#
Method 1: HAL File#
Add to your machine’s HAL file (e.g., your_machine.hal):
# Start gRPC server
loadusr linuxcnc-grpc --host 0.0.0.0 --port 50051Method 2: Dedicated HAL File#
Create a separate grpc-server.hal file:
# grpc-server.hal
loadusr linuxcnc-grpc --host 0.0.0.0 --port 50051Reference it in your INI file:
[HAL]
POSTGUI_HALFILE = grpc-server.halUsing POSTGUI_HALFILE ensures the server starts after the GUI, which is useful for certain configurations.
Method 3: systemd Service#
Create /etc/systemd/system/linuxcnc-grpc.service:
[Unit]
Description=LinuxCNC gRPC Server
After=linuxcnc.service
[Service]
Type=simple
ExecStart=/usr/local/bin/linuxcnc-grpc --host 0.0.0.0 --port 50051
Restart=on-failure
User=your-username
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl daemon-reload
sudo systemctl enable linuxcnc-grpc
sudo systemctl start linuxcnc-grpcNetwork Configuration#
Firewall#
Allow incoming connections on the gRPC port:
# UFW (Ubuntu)
sudo ufw allow 50051/tcp
# firewalld (Fedora/CentOS)
sudo firewall-cmd --permanent --add-port=50051/tcp
sudo firewall-cmd --reload
# iptables
sudo iptables -A INPUT -p tcp --dport 50051 -j ACCEPTBinding to Specific Interface#
To bind to a specific network interface:
# Bind to localhost only (no remote access)
linuxcnc-grpc --host 127.0.0.1
# Bind to specific IP
linuxcnc-grpc --host 192.168.1.100Environment Variables#
| Variable | Default | Description |
|---|---|---|
LINUXCNC_NC_FILES | /home/linuxcnc/linuxcnc/nc_files | Directory for G-code file operations (UploadFile, ListFiles, DeleteFile, program open) |
NC Files Directory#
All file management RPCs (UploadFile, ListFiles, DeleteFile) and the program open command operate within a single allowed directory. By default this is /home/linuxcnc/linuxcnc/nc_files.
To change it, use the --nc-files flag:
linuxcnc-grpc --host 0.0.0.0 --nc-files /home/user/nc_programsOr set the LINUXCNC_NC_FILES environment variable:
export LINUXCNC_NC_FILES=/home/user/nc_programs
linuxcnc-grpc --host 0.0.0.0Priority: --nc-files flag > LINUXCNC_NC_FILES env var > default.
Or in a systemd service file:
[Service]
Environment=LINUXCNC_NC_FILES=/home/user/nc_programs
ExecStart=/usr/local/bin/linuxcnc-grpc --host 0.0.0.0 --port 50051Path traversal outside this directory is rejected — filenames like ../../etc/passwd will return INVALID_ARGUMENT. The server resolves symlinks and validates the canonical path stays within the allowed directory.
Security Considerations#
The default configuration uses insecure (unencrypted) connections. This is suitable for:
- Local development
- Trusted private networks
- Testing and evaluation
Production Security#
For production use on untrusted networks:
- Use TLS - gRPC supports TLS encryption. Configure your server with certificates.
- Use a VPN - Run LinuxCNC on a private network accessible only via VPN.
- Firewall rules - Restrict access to known client IPs.
- Authentication - Implement gRPC interceptors for authentication.
TLS Configuration (Advanced)#
To enable TLS, modify the server code or use a gRPC proxy like Envoy:
# Example TLS configuration (requires code modification)
import grpc
with open('server.key', 'rb') as f:
private_key = f.read()
with open('server.crt', 'rb') as f:
certificate_chain = f.read()
server_credentials = grpc.ssl_server_credentials(
[(private_key, certificate_chain)]
)
server.add_secure_port('[::]:50051', server_credentials)Logging#
Log Levels#
- INFO (default) - Normal operation, connection events
- DEBUG - Detailed request/response logging
Enable debug logging:
linuxcnc-grpc --debugLog Format#
2024-01-15 10:30:45 [INFO] linuxcnc_grpc.server: Server configured on 0.0.0.0:50051
2024-01-15 10:30:45 [INFO] linuxcnc_grpc.server: LinuxCNC + HAL gRPC ServerConnection Handling#
Reconnection#
The server automatically handles LinuxCNC connection issues:
- Detects when LinuxCNC disconnects
- Returns
UNAVAILABLEstatus to clients during disconnection - Automatically reconnects when LinuxCNC becomes available
Thread Pool#
The server uses a thread pool for handling concurrent requests:
- Default: 10 worker threads
- Sufficient for most use cases
- Can be customized in code if needed
Troubleshooting#
“LinuxCNC not running”#
The server requires LinuxCNC to be running first:
# Start LinuxCNC
linuxcnc /path/to/your/machine.ini
# Then start the gRPC server
linuxcnc-grpc“Address already in use”#
Another process is using the port:
# Find what's using port 50051
sudo lsof -i :50051
# Use a different port
linuxcnc-grpc --port 50052“Connection refused” from client#
- Verify the server is running
- Check firewall rules
- Verify the host/port match
- Check network connectivity:
nc -zv hostname 50051
Debug Mode#
Enable debug logging to see detailed information:
linuxcnc-grpc --debugThis shows:
- All incoming requests
- Response details
- Connection events
- Internal state changes
Performance Tuning#
Streaming Intervals#
Status streaming defaults to 100ms intervals. Adjust based on your needs:
- 10-50ms - High-frequency updates (UI animation)
- 100ms - Standard monitoring
- 500ms-1000ms - Low-bandwidth connections
Clients specify the interval when calling StreamStatus:
request = linuxcnc_pb2.StreamStatusRequest(interval_ms=50)Network Latency#
gRPC performs well over high-latency connections. For best results:
- Use streaming instead of polling for real-time data
- Batch multiple queries when possible
- Consider compression for slow connections