feat(deploy): add NixOS live USB ISO for ATM hardware testing
Add NixOS configuration to build a bootable live USB ISO that runs the ATM Electron app in kiosk mode on physical hardware (UpBoard). The ISO boots from squashfs, auto-starts X11/openbox, and launches Electron in production mode. Key changes: - deploy/nixos/live.nix: Live USB module (squashfs+tmpfs, no disk install) - deploy/nixos/flake.nix: Nix flake with ISO build output - deploy/nixos/provision-atm.sh: Auto-provision LP credentials via API - deploy/nixos/build-iso.sh: End-to-end build workflow script - apps/machine: Fix Electron production mode (ELECTRON_FORCE_PROD), Vue Router hash mode for file:// protocol, relative asset paths Build: cd deploy/nixos && bash build-iso.sh Test: qemu-system-x86_64 -enable-kvm -m 2G -cdrom result/iso/*.iso Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c8e5bf9ee1
commit
19d43c2939
13 changed files with 1203 additions and 3 deletions
|
|
@ -40,7 +40,9 @@ function loadEnvFile() {
|
|||
loadEnvFile()
|
||||
|
||||
// Determine if we're in development
|
||||
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged
|
||||
const isDev =
|
||||
process.env.ELECTRON_FORCE_PROD !== '1' &&
|
||||
(process.env.NODE_ENV === 'development' || !app.isPackaged)
|
||||
|
||||
// Window dimensions (vertical ATM display)
|
||||
const WINDOW_WIDTH = 1080
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import App from './App.vue'
|
||||
import './style.css'
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import CashInView from './views/CashInView.vue'
|
|||
|
||||
// Create router
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
history: createWebHashHistory(),
|
||||
routes: [
|
||||
{ path: '/', name: 'idle', component: IdleView },
|
||||
{ path: '/cash-out', name: 'cash-out', component: CashOutView },
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import tailwindcss from '@tailwindcss/vite'
|
|||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
// Use relative paths so assets load correctly with file:// protocol (Electron production)
|
||||
base: './',
|
||||
plugins: [vue(), tailwindcss()],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
|
|
|||
192
deploy/nixos/README.md
Normal file
192
deploy/nixos/README.md
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# Lamassu ATM NixOS Deployment
|
||||
|
||||
NixOS configuration for deploying Lamassu Next ATM software on UP Board hardware.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Build Installation ISO
|
||||
|
||||
```bash
|
||||
cd deploy/nixos
|
||||
nix build .#iso
|
||||
```
|
||||
|
||||
The ISO will be in `result/iso/`.
|
||||
|
||||
### 2. Install on UP Board
|
||||
|
||||
1. Write ISO to USB drive:
|
||||
|
||||
```bash
|
||||
sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress
|
||||
```
|
||||
|
||||
2. Boot UP Board from USB
|
||||
|
||||
3. Run the installer:
|
||||
|
||||
```bash
|
||||
sudo nixos-install --flake .#lamassu-atm
|
||||
```
|
||||
|
||||
4. Reboot and remove USB
|
||||
|
||||
### 3. Post-Install Configuration
|
||||
|
||||
SSH into the machine and configure:
|
||||
|
||||
```bash
|
||||
# Set up the ATM application
|
||||
sudo mkdir -p /opt/lamassu-atm
|
||||
sudo chown lamassu:lamassu /opt/lamassu-atm
|
||||
|
||||
# Copy the built Electron app
|
||||
scp -r apps/machine/dist/* lamassu@<atm-ip>:/opt/lamassu-atm/
|
||||
|
||||
# Configure the ATM
|
||||
sudo nano /etc/lamassu-atm/config.env
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Edit `/etc/nixos/configuration.nix` to customize:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.lamassu-atm = {
|
||||
enable = true;
|
||||
|
||||
# Nostr relay for ATM communication
|
||||
relayUrl = "wss://relay.lamassu.is";
|
||||
|
||||
# Lightning.Pub instance
|
||||
lightningPubUrl = "https://lp.lamassu.is";
|
||||
|
||||
# Hardware configuration
|
||||
billValidator = {
|
||||
enable = true;
|
||||
device = "/dev/ttyUSB0";
|
||||
type = "id003"; # or "mei", "ccnet"
|
||||
};
|
||||
|
||||
billDispenser = {
|
||||
enable = false; # Enable for two-way machines
|
||||
device = "/dev/ttyUSB1";
|
||||
type = "puloon";
|
||||
};
|
||||
|
||||
camera = {
|
||||
enable = true;
|
||||
device = "/dev/video0";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Hardware Support
|
||||
|
||||
### Bill Validators
|
||||
|
||||
- **ID-003** (JCM) - Most common in Lamassu machines
|
||||
- **MEI** (Mars Electronics)
|
||||
- **CCNET** (CashCode)
|
||||
|
||||
### Bill Dispensers
|
||||
|
||||
- **Puloon** - LCDM series
|
||||
- **Genmega**
|
||||
|
||||
### Cameras
|
||||
|
||||
- Any V4L2-compatible USB camera
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
deploy/nixos/
|
||||
├── flake.nix # Nix flake entry point
|
||||
├── configuration.nix # Base system configuration
|
||||
├── lamassu-atm.nix # ATM service module
|
||||
├── hardware/
|
||||
│ └── upboard.nix # UP Board hardware config
|
||||
├── udev/
|
||||
│ └── 99-lamassu-hardware.rules # Hardware device rules
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check ATM service status
|
||||
|
||||
```bash
|
||||
sudo systemctl status lamassu-atm
|
||||
sudo journalctl -u lamassu-atm -f
|
||||
```
|
||||
|
||||
### Check hardware detection
|
||||
|
||||
```bash
|
||||
# List serial devices
|
||||
ls -la /dev/ttyUSB* /dev/ttyACM*
|
||||
|
||||
# Check for bill validator symlink
|
||||
ls -la /dev/bill-validator
|
||||
|
||||
# Test camera
|
||||
v4l2-ctl --list-devices
|
||||
```
|
||||
|
||||
### Manual service control
|
||||
|
||||
```bash
|
||||
sudo systemctl restart lamassu-atm
|
||||
sudo systemctl stop lamassu-atm
|
||||
```
|
||||
|
||||
### Debug mode
|
||||
|
||||
```bash
|
||||
# Run manually with verbose output
|
||||
sudo -u lamassu DISPLAY=:0 LOG_LEVEL=debug electron /opt/lamassu-atm
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
### Update system
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake /etc/nixos#lamassu-atm
|
||||
```
|
||||
|
||||
### Update ATM application
|
||||
|
||||
```bash
|
||||
# Build new version
|
||||
cd lamassu-next/apps/machine
|
||||
pnpm run build
|
||||
|
||||
# Copy to ATM
|
||||
scp -r dist/* lamassu@<atm-ip>:/opt/lamassu-atm/
|
||||
|
||||
# Restart service
|
||||
ssh lamassu@<atm-ip> "sudo systemctl restart lamassu-atm"
|
||||
```
|
||||
|
||||
## Development vs Production
|
||||
|
||||
For development/testing, you can use the regtest docker environment:
|
||||
|
||||
```bash
|
||||
cd lamassu-next
|
||||
./docker/dev.sh up --fund
|
||||
./docker/dev.sh atm
|
||||
```
|
||||
|
||||
For production, deploy this NixOS configuration and point to your production Nostr relay and Lightning.Pub instance.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- The default `lamassu` user has `wheel` access for initial setup
|
||||
- Remove wheel access after configuration: `sudo gpasswd -d lamassu wheel`
|
||||
- SSH is enabled by default - configure key-based auth and disable password auth
|
||||
- Firewall blocks all incoming connections by default
|
||||
64
deploy/nixos/build-iso.sh
Executable file
64
deploy/nixos/build-iso.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build a bootable NixOS Live USB ISO for testing the ATM Electron app
|
||||
# on physical hardware (UpBoard).
|
||||
#
|
||||
# Usage: bash build-iso.sh
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
MACHINE_DIR="$REPO_ROOT/apps/machine"
|
||||
|
||||
echo "=== Building Lamassu ATM Live USB ISO ==="
|
||||
|
||||
# Step 1: Build the Electron app
|
||||
echo ""
|
||||
echo "--- Step 1: Building Electron app ---"
|
||||
cd "$REPO_ROOT"
|
||||
pnpm run build --filter=@lamassu/machine
|
||||
|
||||
# Step 2: Verify build outputs exist
|
||||
echo ""
|
||||
echo "--- Step 2: Verifying build outputs ---"
|
||||
if [ ! -d "$MACHINE_DIR/dist" ]; then
|
||||
echo "ERROR: $MACHINE_DIR/dist not found. Build failed?"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$MACHINE_DIR/dist-electron" ]; then
|
||||
echo "ERROR: $MACHINE_DIR/dist-electron not found. Build failed?"
|
||||
exit 1
|
||||
fi
|
||||
echo "OK: dist/ and dist-electron/ present"
|
||||
|
||||
# Step 3: Build the NixOS ISO
|
||||
echo ""
|
||||
echo "--- Step 3: Building NixOS ISO (this takes a while) ---"
|
||||
cd "$SCRIPT_DIR"
|
||||
export MACHINE_DIR="$MACHINE_DIR"
|
||||
nix build .#iso --impure --show-trace
|
||||
|
||||
# Step 4: Print results
|
||||
ISO_PATH=$(ls result/iso/*.iso 2>/dev/null | head -1)
|
||||
if [ -z "$ISO_PATH" ]; then
|
||||
echo "ERROR: ISO not found in result/iso/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ISO_SIZE=$(du -h "$ISO_PATH" | cut -f1)
|
||||
echo ""
|
||||
echo "=== ISO built successfully ==="
|
||||
echo "File: $ISO_PATH"
|
||||
echo "Size: $ISO_SIZE"
|
||||
echo ""
|
||||
echo "--- Test in QEMU ---"
|
||||
echo "qemu-system-x86_64 -enable-kvm -m 2G \\"
|
||||
echo " -bios /usr/share/edk2-ovmf/OVMF_CODE.fd \\"
|
||||
echo " -cdrom $ISO_PATH -display gtk"
|
||||
echo ""
|
||||
echo "--- Write to USB flash drive ---"
|
||||
echo "sudo dd if=$ISO_PATH of=/dev/sdX bs=4M status=progress oflag=sync"
|
||||
echo ""
|
||||
echo "--- After booting, SSH in and configure ---"
|
||||
echo "ssh lamassu@<atm-ip>"
|
||||
echo "sudo nano /var/lib/lamassu-atm/.env"
|
||||
echo "sudo systemctl restart lamassu-atm"
|
||||
150
deploy/nixos/configuration.nix
Normal file
150
deploy/nixos/configuration.nix
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# Lamassu ATM NixOS Configuration
|
||||
# Base system configuration for ATM kiosk
|
||||
|
||||
{ config, lib, pkgs, pkgs-unstable, ... }:
|
||||
|
||||
{
|
||||
# System basics
|
||||
system.stateVersion = "24.05";
|
||||
|
||||
# Networking
|
||||
networking = {
|
||||
hostName = "lamassu-atm";
|
||||
|
||||
# Use NetworkManager for easy WiFi configuration
|
||||
networkmanager.enable = true;
|
||||
|
||||
# Firewall - minimal exposure
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ ]; # ATM initiates all connections
|
||||
allowedUDPPorts = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
# Timezone - set to your location
|
||||
time.timeZone = "UTC";
|
||||
|
||||
# Locale
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
# Users
|
||||
users.groups.lamassu = { };
|
||||
users.users.lamassu = {
|
||||
isNormalUser = true;
|
||||
group = "lamassu";
|
||||
description = "Lamassu ATM";
|
||||
extraGroups = [
|
||||
"wheel" # For admin access
|
||||
"video" # GPU access
|
||||
"audio" # Sound
|
||||
"dialout" # Serial ports
|
||||
"plugdev" # USB devices
|
||||
"networkmanager" # Network config
|
||||
];
|
||||
# No password - kiosk mode
|
||||
initialPassword = "lamassu";
|
||||
};
|
||||
|
||||
# Kiosk display configuration
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
|
||||
# Display manager - auto-login
|
||||
displayManager = {
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "lamassu";
|
||||
};
|
||||
};
|
||||
|
||||
# No desktop environment - just the ATM app
|
||||
desktopManager.xterm.enable = false;
|
||||
|
||||
# Basic window manager for Electron
|
||||
windowManager.openbox.enable = true;
|
||||
|
||||
# Disable screen blanking
|
||||
serverFlagsSection = ''
|
||||
Option "BlankTime" "0"
|
||||
Option "StandbyTime" "0"
|
||||
Option "SuspendTime" "0"
|
||||
Option "OffTime" "0"
|
||||
'';
|
||||
|
||||
# Intel driver
|
||||
videoDrivers = [ "modesetting" ];
|
||||
};
|
||||
|
||||
# Audio (for transaction sounds)
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
# System packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
# System utilities
|
||||
htop
|
||||
vim
|
||||
git
|
||||
curl
|
||||
wget
|
||||
|
||||
# Hardware debugging
|
||||
usbutils
|
||||
pciutils
|
||||
lsof
|
||||
|
||||
# Serial port tools
|
||||
minicom
|
||||
screen
|
||||
|
||||
# For the Electron app
|
||||
pkgs-unstable.electron
|
||||
|
||||
# Node.js for the application
|
||||
pkgs-unstable.nodejs_22
|
||||
|
||||
# Camera support
|
||||
v4l-utils
|
||||
fswebcam
|
||||
];
|
||||
|
||||
# Enable SSH for remote administration
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
};
|
||||
};
|
||||
|
||||
# Auto-updates (optional - disabled by default for stability)
|
||||
# system.autoUpgrade.enable = false;
|
||||
|
||||
# Journal configuration
|
||||
services.journald = {
|
||||
extraConfig = ''
|
||||
SystemMaxUse=100M
|
||||
MaxRetentionSec=1week
|
||||
'';
|
||||
};
|
||||
|
||||
# Nix settings
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
|
||||
# Garbage collection
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 7d";
|
||||
};
|
||||
};
|
||||
}
|
||||
44
deploy/nixos/flake.lock
generated
Normal file
44
deploy/nixos/flake.lock
generated
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1735563628,
|
||||
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1771177547,
|
||||
"narHash": "sha256-trTtk3WTOHz7hSw89xIIvahkgoFJYQ0G43IlqprFoMA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ac055f38c798b0d87695240c7b761b82fc7e5bc2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
62
deploy/nixos/flake.nix
Normal file
62
deploy/nixos/flake.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
description = "Lamassu Next ATM - NixOS Deployment";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
|
||||
# For Electron/Node.js packaging
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, nixpkgs-unstable }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
|
||||
pkgs-unstable = import nixpkgs-unstable {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
# NixOS configuration for UP Board ATM (installed to disk)
|
||||
nixosConfigurations.lamassu-atm = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
specialArgs = { inherit pkgs-unstable; };
|
||||
|
||||
modules = [
|
||||
./hardware/upboard.nix
|
||||
./configuration.nix
|
||||
./lamassu-atm.nix
|
||||
];
|
||||
};
|
||||
|
||||
# Live USB configuration (boots from USB, no disk install)
|
||||
nixosConfigurations.lamassu-live = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
specialArgs = { inherit pkgs-unstable nixpkgs; };
|
||||
|
||||
modules = [
|
||||
./live.nix
|
||||
];
|
||||
};
|
||||
|
||||
# Standalone module for importing into existing NixOS configs
|
||||
nixosModules.default = import ./lamassu-atm.nix;
|
||||
nixosModules.lamassu-atm = import ./lamassu-atm.nix;
|
||||
|
||||
packages.${system} = {
|
||||
# ISO image for live USB testing
|
||||
iso = self.nixosConfigurations.lamassu-live.config.system.build.isoImage;
|
||||
|
||||
# SD card image (if needed)
|
||||
sdcard = self.nixosConfigurations.lamassu-atm.config.system.build.sdImage;
|
||||
};
|
||||
};
|
||||
}
|
||||
107
deploy/nixos/hardware/upboard.nix
Normal file
107
deploy/nixos/hardware/upboard.nix
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# UP Board Hardware Configuration
|
||||
# Supports UP Board, UP Squared, and similar Intel Atom/Celeron boards
|
||||
# commonly used in Lamassu ATM machines
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Boot configuration for UP Board
|
||||
# UP Board uses 64-bit CPU but some models have 32-bit UEFI
|
||||
boot = {
|
||||
loader = {
|
||||
# Use systemd-boot for UEFI systems
|
||||
systemd-boot.enable = true;
|
||||
efi.canTouchEfiVariables = true;
|
||||
|
||||
# Timeout for boot menu (useful for remote debugging)
|
||||
timeout = 3;
|
||||
};
|
||||
|
||||
# Kernel modules needed for UP Board hardware
|
||||
initrd.availableKernelModules = [
|
||||
"xhci_pci" # USB 3.0
|
||||
"ahci" # SATA
|
||||
"usb_storage" # USB mass storage
|
||||
"sd_mod" # SCSI disk
|
||||
"sdhci_pci" # SD card (eMMC)
|
||||
"i915" # Intel graphics
|
||||
];
|
||||
|
||||
kernelModules = [
|
||||
"kvm-intel" # Virtualization (if needed)
|
||||
"i2c-dev" # I2C for hardware control
|
||||
"spi-dev" # SPI for hardware control
|
||||
];
|
||||
|
||||
# UP Board specific kernel parameters
|
||||
kernelParams = [
|
||||
# Intel graphics
|
||||
"i915.enable_psr=0"
|
||||
|
||||
# Serial console for debugging (UP Board has debug UART)
|
||||
"console=ttyS4,115200n8"
|
||||
"console=tty0"
|
||||
|
||||
# Quiet boot for kiosk mode
|
||||
"quiet"
|
||||
"splash"
|
||||
];
|
||||
};
|
||||
|
||||
# Filesystem configuration
|
||||
# Adjust these to match your actual disk layout
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-label/boot";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
# Hardware-specific packages
|
||||
hardware = {
|
||||
# Intel GPU support
|
||||
graphics = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [
|
||||
intel-media-driver # VAAPI driver for newer Intel
|
||||
vaapiIntel # VAAPI driver (legacy)
|
||||
vaapiVdpau
|
||||
libvdpau-va-gl
|
||||
];
|
||||
};
|
||||
|
||||
# Enable firmware for Intel hardware
|
||||
enableRedistributableFirmware = true;
|
||||
|
||||
# CPU microcode updates
|
||||
cpu.intel.updateMicrocode = true;
|
||||
};
|
||||
|
||||
# Power management
|
||||
powerManagement = {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "performance"; # ATM should be responsive
|
||||
};
|
||||
|
||||
# Disable suspend/hibernate for kiosk
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
|
||||
# Serial port access for bill validator/dispenser
|
||||
# UP Board GPIO/UART pins
|
||||
services.udev.extraRules = ''
|
||||
# UP Board serial ports
|
||||
KERNEL=="ttyS[0-9]*", MODE="0666"
|
||||
|
||||
# USB serial adapters (common for bill validators)
|
||||
KERNEL=="ttyUSB[0-9]*", MODE="0666"
|
||||
KERNEL=="ttyACM[0-9]*", MODE="0666"
|
||||
'';
|
||||
}
|
||||
240
deploy/nixos/lamassu-atm.nix
Normal file
240
deploy/nixos/lamassu-atm.nix
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# Lamassu ATM Service Module
|
||||
# Manages the ATM Electron application and related services
|
||||
|
||||
{ config, lib, pkgs, pkgs-unstable, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.lamassu-atm;
|
||||
in
|
||||
{
|
||||
options.services.lamassu-atm = {
|
||||
enable = mkEnableOption "Lamassu ATM service";
|
||||
|
||||
relayUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "wss://relay.lamassu.is";
|
||||
description = "Nostr relay URL for ATM communication";
|
||||
};
|
||||
|
||||
lightningPubUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "https://lp.lamassu.is";
|
||||
description = "Lightning.Pub instance URL";
|
||||
};
|
||||
|
||||
appDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/opt/lamassu-atm";
|
||||
description = "Directory containing the ATM application";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/lamassu-atm";
|
||||
description = "Directory for ATM data and configuration";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.enum [ "error" "warn" "info" "debug" ];
|
||||
default = "info";
|
||||
description = "Logging level for the ATM application";
|
||||
};
|
||||
|
||||
# Hardware configuration
|
||||
billValidator = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable bill validator support";
|
||||
};
|
||||
|
||||
device = mkOption {
|
||||
type = types.str;
|
||||
default = "/dev/ttyUSB0";
|
||||
description = "Serial device for bill validator";
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "id003" "mei" "ccnet" ];
|
||||
default = "id003";
|
||||
description = "Bill validator protocol type";
|
||||
};
|
||||
};
|
||||
|
||||
billDispenser = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable bill dispenser support (two-way machines)";
|
||||
};
|
||||
|
||||
device = mkOption {
|
||||
type = types.str;
|
||||
default = "/dev/ttyUSB1";
|
||||
description = "Serial device for bill dispenser";
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "puloon" "genmega" ];
|
||||
default = "puloon";
|
||||
description = "Bill dispenser type";
|
||||
};
|
||||
};
|
||||
|
||||
camera = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable camera for QR code scanning";
|
||||
};
|
||||
|
||||
device = mkOption {
|
||||
type = types.str;
|
||||
default = "/dev/video0";
|
||||
description = "Camera device";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Create data directory
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.dataDir} 0750 lamassu lamassu -"
|
||||
"d ${cfg.dataDir}/logs 0750 lamassu lamassu -"
|
||||
];
|
||||
|
||||
# Environment file for ATM configuration
|
||||
environment.etc."lamassu-atm/config.env".text = ''
|
||||
# Lamassu ATM Configuration
|
||||
RELAY_URL=${cfg.relayUrl}
|
||||
LIGHTNING_PUB_URL=${cfg.lightningPubUrl}
|
||||
LOG_LEVEL=${cfg.logLevel}
|
||||
DATA_DIR=${cfg.dataDir}
|
||||
|
||||
# Hardware
|
||||
BILL_VALIDATOR_ENABLED=${boolToString cfg.billValidator.enable}
|
||||
BILL_VALIDATOR_DEVICE=${cfg.billValidator.device}
|
||||
BILL_VALIDATOR_TYPE=${cfg.billValidator.type}
|
||||
|
||||
BILL_DISPENSER_ENABLED=${boolToString cfg.billDispenser.enable}
|
||||
BILL_DISPENSER_DEVICE=${cfg.billDispenser.device}
|
||||
BILL_DISPENSER_TYPE=${cfg.billDispenser.type}
|
||||
|
||||
CAMERA_ENABLED=${boolToString cfg.camera.enable}
|
||||
CAMERA_DEVICE=${cfg.camera.device}
|
||||
|
||||
# Display
|
||||
DISPLAY=:0
|
||||
ELECTRON_DISABLE_GPU=false
|
||||
'';
|
||||
|
||||
# Main ATM service
|
||||
systemd.services.lamassu-atm = {
|
||||
description = "Lamassu ATM Application";
|
||||
wantedBy = [ "graphical.target" ];
|
||||
after = [ "graphical.target" "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "lamassu";
|
||||
Group = "lamassu";
|
||||
WorkingDirectory = cfg.appDir;
|
||||
|
||||
# Environment
|
||||
EnvironmentFile = "/etc/lamassu-atm/config.env";
|
||||
|
||||
# Start the Electron app
|
||||
ExecStart = "${pkgs-unstable.electron}/bin/electron ${cfg.appDir}";
|
||||
|
||||
# Restart policy
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
|
||||
# Resource limits
|
||||
MemoryMax = "1G";
|
||||
CPUQuota = "80%";
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ReadWritePaths = [ cfg.dataDir "/tmp" ];
|
||||
PrivateTmp = true;
|
||||
|
||||
# Allow device access for hardware
|
||||
DeviceAllow = [
|
||||
"/dev/ttyUSB* rw"
|
||||
"/dev/ttyACM* rw"
|
||||
"/dev/ttyS* rw"
|
||||
"/dev/video* rw"
|
||||
];
|
||||
};
|
||||
|
||||
# Pre-start script to verify hardware
|
||||
preStart = ''
|
||||
echo "Lamassu ATM starting..."
|
||||
echo "Relay: ${cfg.relayUrl}"
|
||||
echo "Lightning.Pub: ${cfg.lightningPubUrl}"
|
||||
|
||||
# Check bill validator if enabled
|
||||
if [ "${boolToString cfg.billValidator.enable}" = "true" ]; then
|
||||
if [ ! -c "${cfg.billValidator.device}" ]; then
|
||||
echo "Warning: Bill validator device ${cfg.billValidator.device} not found"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check camera if enabled
|
||||
if [ "${boolToString cfg.camera.enable}" = "true" ]; then
|
||||
if [ ! -c "${cfg.camera.device}" ]; then
|
||||
echo "Warning: Camera device ${cfg.camera.device} not found"
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
# Openbox autostart for kiosk mode
|
||||
environment.etc."xdg/openbox/autostart".text = ''
|
||||
# Disable screen saver and power management
|
||||
xset s off
|
||||
xset -dpms
|
||||
xset s noblank
|
||||
|
||||
# Hide cursor after inactivity
|
||||
unclutter -idle 3 &
|
||||
|
||||
# Start ATM (handled by systemd, but ensure display is ready)
|
||||
sleep 2
|
||||
'';
|
||||
|
||||
# udev rules for ATM hardware
|
||||
services.udev.extraRules = ''
|
||||
# ID-003 Bill Validator (JCM)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="3410", MODE="0666", SYMLINK+="bill-validator"
|
||||
|
||||
# MEI Bill Validator
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0b00", MODE="0666", SYMLINK+="bill-validator"
|
||||
|
||||
# CCNET Bill Validator (CashCode)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0x1b5a", MODE="0666", SYMLINK+="bill-validator"
|
||||
|
||||
# Puloon Bill Dispenser
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", SYMLINK+="bill-dispenser"
|
||||
|
||||
# Generic USB-Serial adapters
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", MODE="0666"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", MODE="0666"
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", MODE="0666"
|
||||
|
||||
# Camera access
|
||||
SUBSYSTEM=="video4linux", MODE="0666"
|
||||
'';
|
||||
|
||||
# Additional packages for hardware support
|
||||
environment.systemPackages = with pkgs; [
|
||||
unclutter # Hide cursor
|
||||
];
|
||||
};
|
||||
}
|
||||
181
deploy/nixos/live.nix
Normal file
181
deploy/nixos/live.nix
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# Lamassu ATM Live USB Configuration
|
||||
# Bootable ISO for testing on physical hardware (UpBoard) without installing to disk.
|
||||
# Builds with: nix build .#iso
|
||||
#
|
||||
# Does NOT import hardware/upboard.nix (its fileSystems conflict with live boot).
|
||||
# Instead, duplicates only the hardware-relevant kernel modules and GPU config.
|
||||
|
||||
{ config, lib, pkgs, pkgs-unstable, nixpkgs, ... }:
|
||||
|
||||
let
|
||||
# Pre-built Electron app copied into the Nix store.
|
||||
# Build first: pnpm run build --filter=@lamassu/machine
|
||||
# Requires --impure: reads MACHINE_DIR env var to find build artifacts (dist/ is gitignored)
|
||||
machineDir = builtins.getEnv "MACHINE_DIR";
|
||||
atm-app = assert machineDir != ""
|
||||
|| throw "MACHINE_DIR env var must be set (use build-iso.sh or: export MACHINE_DIR=/path/to/apps/machine)";
|
||||
pkgs.runCommand "lamassu-atm-app" { } ''
|
||||
mkdir -p $out
|
||||
cp -r ${builtins.path { path = machineDir + "/dist"; name = "dist"; }} $out/dist
|
||||
cp -r ${builtins.path { path = machineDir + "/dist-electron"; name = "dist-electron"; }} $out/dist-electron
|
||||
cp ${builtins.path { path = machineDir + "/package.json"; name = "package.json"; }} $out/package.json
|
||||
'';
|
||||
|
||||
# .env template with regtest defaults pointing to the dev machine
|
||||
envTemplate = pkgs.writeText "lamassu-atm-env" ''
|
||||
# Lamassu ATM Live USB Configuration
|
||||
# Edit this file and restart: sudo systemctl restart lamassu-atm
|
||||
#
|
||||
# Dev machine LAN address (adjust to your network)
|
||||
VITE_RELAY_URL=ws://192.168.1.190:7777
|
||||
VITE_LIGHTNING_PUB_API_URL=http://192.168.1.190:1776
|
||||
VITE_EXTENSION_API_URL=http://192.168.1.190:1777
|
||||
|
||||
# Lightning.Pub credentials (fill in after boot)
|
||||
VITE_LIGHTNING_PUB_PUBKEY=
|
||||
VITE_ATM_PRIVATE_KEY=
|
||||
VITE_ADMIN_TOKEN=
|
||||
VITE_APP_ID=
|
||||
VITE_APP_TOKEN=
|
||||
VITE_LINKING_TOKEN=
|
||||
|
||||
# Machine configuration
|
||||
VITE_LAMASSU_MACHINE_MODEL=sintra
|
||||
VITE_LAMASSU_FIAT_CODE=USD
|
||||
|
||||
# Hardware (uncomment and set for real hardware)
|
||||
# VITE_LAMASSU_VALIDATOR_DEVICE=/dev/ttyUSB0
|
||||
# VITE_LAMASSU_DISPENSER_DEVICE=/dev/ttyUSB1
|
||||
# VITE_LAMASSU_CASSETTES=
|
||||
|
||||
# Force production mode when running via `electron /path`
|
||||
ELECTRON_FORCE_PROD=1
|
||||
|
||||
# Display
|
||||
DISPLAY=:0
|
||||
'';
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# NixOS ISO image builder (nixpkgs path passed via specialArgs from flake.nix)
|
||||
"${nixpkgs}/nixos/modules/installer/cd-dvd/iso-image.nix"
|
||||
"${nixpkgs}/nixos/modules/profiles/all-hardware.nix"
|
||||
|
||||
# Reuse kiosk config (X11, openbox, users, networking)
|
||||
./configuration.nix
|
||||
|
||||
# Reuse ATM systemd service module
|
||||
./lamassu-atm.nix
|
||||
];
|
||||
|
||||
# ISO image settings
|
||||
isoImage = {
|
||||
isoName = "lamassu-atm-live.iso";
|
||||
makeEfiBootable = true;
|
||||
makeBiosBootable = true;
|
||||
squashfsCompression = "zstd -Xcompression-level 6";
|
||||
};
|
||||
|
||||
# No fileSystems override needed — iso-image.nix handles squashfs + tmpfs root.
|
||||
# We don't import hardware/upboard.nix, so there are no conflicting disk mounts.
|
||||
|
||||
# Boot: UpBoard-relevant kernel modules (from hardware/upboard.nix) without disk mounts
|
||||
boot = {
|
||||
initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
"sdhci_pci"
|
||||
"i915"
|
||||
"squashfs"
|
||||
"iso9660"
|
||||
"loop"
|
||||
];
|
||||
|
||||
kernelModules = [
|
||||
"kvm-intel"
|
||||
"i2c-dev"
|
||||
"spi-dev"
|
||||
];
|
||||
|
||||
kernelParams = [
|
||||
"i915.enable_psr=0"
|
||||
"quiet"
|
||||
"splash"
|
||||
];
|
||||
};
|
||||
|
||||
# Intel GPU support (from hardware/upboard.nix)
|
||||
# NB: nixos-24.05 uses hardware.opengl, not hardware.graphics
|
||||
hardware = {
|
||||
opengl = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [
|
||||
intel-media-driver
|
||||
vaapiIntel
|
||||
vaapiVdpau
|
||||
libvdpau-va-gl
|
||||
];
|
||||
};
|
||||
enableRedistributableFirmware = true;
|
||||
cpu.intel.updateMicrocode = true;
|
||||
};
|
||||
|
||||
# Performance governor for responsive kiosk
|
||||
powerManagement = {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "performance";
|
||||
};
|
||||
|
||||
# Disable suspend/hibernate
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
|
||||
# Enable the ATM service with live USB paths
|
||||
services.lamassu-atm = {
|
||||
enable = true;
|
||||
appDir = "${atm-app}";
|
||||
};
|
||||
|
||||
# Allow unprivileged user namespaces (Electron sandbox needs this)
|
||||
boot.kernel.sysctl."kernel.unprivileged_userns_clone" = 1;
|
||||
|
||||
# Override the systemd service for live USB environment
|
||||
systemd.services.lamassu-atm = {
|
||||
serviceConfig = {
|
||||
EnvironmentFile = lib.mkForce "/var/lib/lamassu-atm/.env";
|
||||
# Electron needs --no-sandbox in the live/testing environment
|
||||
ExecStart = lib.mkForce "${pkgs-unstable.electron}/bin/electron --no-sandbox --disable-gpu-sandbox ${atm-app}";
|
||||
# Disable all security hardening that conflicts with Electron
|
||||
NoNewPrivileges = lib.mkForce false;
|
||||
ProtectSystem = lib.mkForce false;
|
||||
ProtectHome = lib.mkForce false;
|
||||
PrivateTmp = lib.mkForce false;
|
||||
};
|
||||
};
|
||||
|
||||
# Install the .env template on first boot
|
||||
system.activationScripts.lamassu-env = ''
|
||||
mkdir -p /var/lib/lamassu-atm
|
||||
if [ ! -f /var/lib/lamassu-atm/.env ]; then
|
||||
cp ${envTemplate} /var/lib/lamassu-atm/.env
|
||||
chmod 600 /var/lib/lamassu-atm/.env
|
||||
chown lamassu:lamassu /var/lib/lamassu-atm/.env
|
||||
fi
|
||||
'';
|
||||
|
||||
# Allow SSH with password for initial setup on the live system
|
||||
services.openssh.settings.PasswordAuthentication = lib.mkForce true;
|
||||
|
||||
# Serial port udev rules (from hardware/upboard.nix)
|
||||
services.udev.extraRules = lib.mkAfter ''
|
||||
KERNEL=="ttyS[0-9]*", MODE="0666"
|
||||
KERNEL=="ttyUSB[0-9]*", MODE="0666"
|
||||
KERNEL=="ttyACM[0-9]*", MODE="0666"
|
||||
'';
|
||||
}
|
||||
99
deploy/nixos/provision-atm.sh
Executable file
99
deploy/nixos/provision-atm.sh
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env bash
|
||||
# Provision a running ATM (live USB or QEMU VM) with Lightning.Pub credentials.
|
||||
# Extracts credentials from the dev docker stack and writes them to the ATM's .env via SSH.
|
||||
#
|
||||
# Usage:
|
||||
# bash provision-atm.sh # defaults: SSH to localhost:2222 (QEMU)
|
||||
# bash provision-atm.sh 192.168.1.50 # SSH to a real ATM on the LAN
|
||||
# bash provision-atm.sh 192.168.1.50 22 # custom SSH port
|
||||
set -euo pipefail
|
||||
|
||||
ATM_HOST="${1:-localhost}"
|
||||
ATM_SSH_PORT="${2:-2222}"
|
||||
ATM_USER="lamassu"
|
||||
LP_API="http://localhost:1776"
|
||||
ADMIN_TOKEN="lamassu-dev-admin-token"
|
||||
ATM_PRIVATE_KEY="f391a2c3fc734f443b0f685688a0441b5fb9805853c0023f570c5a3c6412b136"
|
||||
|
||||
echo "=== Provisioning ATM at $ATM_HOST:$ATM_SSH_PORT ==="
|
||||
|
||||
# Step 1: Extract Lightning.Pub pubkey from docker logs
|
||||
echo ""
|
||||
echo "--- Step 1: Getting Lightning.Pub pubkey ---"
|
||||
PUBKEY=$(docker logs lamassu-lightning-pub 2>&1 | grep -oP 'pubkey:\s*\K[a-f0-9]+' | tail -1)
|
||||
if [ -z "$PUBKEY" ]; then
|
||||
echo "ERROR: Could not extract pubkey from lamassu-lightning-pub logs."
|
||||
echo "Is the docker stack running? Try: docker ps | grep lightning-pub"
|
||||
exit 1
|
||||
fi
|
||||
echo "Pubkey: ${PUBKEY:0:16}..."
|
||||
|
||||
# Step 2: Create ATM app via admin API
|
||||
echo ""
|
||||
echo "--- Step 2: Creating ATM app ---"
|
||||
RESPONSE=$(curl -s -X POST "$LP_API/api/admin/app/add" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $ADMIN_TOKEN" \
|
||||
-d '{"name":"lamassu-atm-live","allow_user_creation":true}' 2>/dev/null)
|
||||
|
||||
if echo "$RESPONSE" | grep -q '"status":"OK"'; then
|
||||
APP_ID=$(echo "$RESPONSE" | grep -oP '"id":"\K[^"]+')
|
||||
APP_TOKEN=$(echo "$RESPONSE" | grep -oP '"auth_token":"\K[^"]+')
|
||||
echo "Created app: ${APP_ID:0:16}..."
|
||||
else
|
||||
echo "WARN: Could not create app (may already exist). Response:"
|
||||
echo "$RESPONSE"
|
||||
echo ""
|
||||
echo "If the app already exists, check docker/dev-state/ for cached credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 3: Determine the host IP as seen from the ATM
|
||||
# For QEMU user-mode networking, the host is at 10.0.2.2
|
||||
# For real hardware on LAN, use the dev machine's LAN IP
|
||||
if [ "$ATM_HOST" = "localhost" ]; then
|
||||
HOST_IP="10.0.2.2"
|
||||
echo ""
|
||||
echo "--- QEMU detected: using $HOST_IP as host gateway ---"
|
||||
else
|
||||
HOST_IP=$(hostname -I | awk '{print $1}')
|
||||
echo ""
|
||||
echo "--- LAN ATM: using $HOST_IP as dev machine address ---"
|
||||
fi
|
||||
|
||||
# Step 4: Write .env to the ATM via SSH
|
||||
echo ""
|
||||
echo "--- Step 3: Writing .env to ATM ---"
|
||||
ENV_CONTENT="# Lamassu ATM Configuration
|
||||
# Auto-generated by provision-atm.sh on $(date -Iseconds)
|
||||
|
||||
# Lightning.Pub connection
|
||||
VITE_RELAY_URL=ws://$HOST_IP:7777
|
||||
VITE_LIGHTNING_PUB_PUBKEY=$PUBKEY
|
||||
VITE_LIGHTNING_PUB_API_URL=http://$HOST_IP:1776
|
||||
VITE_EXTENSION_API_URL=http://$HOST_IP:1777
|
||||
|
||||
# Credentials
|
||||
VITE_ADMIN_TOKEN=$ADMIN_TOKEN
|
||||
VITE_ATM_PRIVATE_KEY=$ATM_PRIVATE_KEY
|
||||
VITE_APP_ID=$APP_ID
|
||||
VITE_APP_TOKEN=$APP_TOKEN
|
||||
|
||||
# Machine configuration
|
||||
VITE_LAMASSU_MACHINE_MODEL=sintra
|
||||
VITE_LAMASSU_FIAT_CODE=USD
|
||||
|
||||
# Force production mode
|
||||
ELECTRON_FORCE_PROD=1
|
||||
DISPLAY=:0"
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -p "$ATM_SSH_PORT" "$ATM_USER@$ATM_HOST" \
|
||||
"echo '$ENV_CONTENT' | sudo tee /var/lib/lamassu-atm/.env > /dev/null && sudo systemctl restart lamassu-atm"
|
||||
|
||||
echo ""
|
||||
echo "=== ATM provisioned successfully ==="
|
||||
echo ""
|
||||
echo "Credentials written to /var/lib/lamassu-atm/.env"
|
||||
echo "ATM service restarted. It should connect to Lightning.Pub at $HOST_IP."
|
||||
echo ""
|
||||
echo "To check status: ssh -p $ATM_SSH_PORT $ATM_USER@$ATM_HOST 'sudo journalctl -u lamassu-atm -f'"
|
||||
57
deploy/nixos/udev/99-lamassu-hardware.rules
Normal file
57
deploy/nixos/udev/99-lamassu-hardware.rules
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Lamassu ATM Hardware udev Rules
|
||||
# Place in /etc/udev/rules.d/ or use services.udev.extraRules in NixOS
|
||||
|
||||
# ============================================
|
||||
# Bill Validators
|
||||
# ============================================
|
||||
|
||||
# ID-003 Bill Validator (JCM/Japan Cash Machine)
|
||||
# Uses TI USB-Serial chip
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="3410", MODE="0666", GROUP="dialout", SYMLINK+="bill-validator"
|
||||
|
||||
# MEI Bill Validator (Mars Electronics)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0b00", MODE="0666", GROUP="dialout", SYMLINK+="bill-validator"
|
||||
|
||||
# CCNET Bill Validator (CashCode)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1b5a", MODE="0666", GROUP="dialout", SYMLINK+="bill-validator"
|
||||
|
||||
# ============================================
|
||||
# Bill Dispensers
|
||||
# ============================================
|
||||
|
||||
# Puloon Bill Dispenser (uses FTDI chip)
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", GROUP="dialout", SYMLINK+="bill-dispenser"
|
||||
|
||||
# Genmega Bill Dispenser
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", MODE="0666", GROUP="dialout", SYMLINK+="bill-dispenser"
|
||||
|
||||
# ============================================
|
||||
# Generic USB-Serial Adapters
|
||||
# ============================================
|
||||
|
||||
# Prolific PL2303
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", MODE="0666", GROUP="dialout"
|
||||
|
||||
# FTDI
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", MODE="0666", GROUP="dialout"
|
||||
|
||||
# Silicon Labs CP210x
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", MODE="0666", GROUP="dialout"
|
||||
|
||||
# CH340/CH341
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", MODE="0666", GROUP="dialout"
|
||||
|
||||
# ============================================
|
||||
# Camera
|
||||
# ============================================
|
||||
|
||||
# Allow access to all video4linux devices (cameras)
|
||||
SUBSYSTEM=="video4linux", MODE="0666", GROUP="video"
|
||||
|
||||
# ============================================
|
||||
# Printers
|
||||
# ============================================
|
||||
|
||||
# Common thermal receipt printers
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="04b8", MODE="0666", GROUP="lp" # Epson
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0519", MODE="0666", GROUP="lp" # Star Micronics
|
||||
Loading…
Add table
Add a link
Reference in a new issue