3 Commits

Author SHA1 Message Date
5b776288bd [nix] add module.nix 2026-07-11 12:23:08 +02:00
1883662b5f Update README 2026-07-04 01:04:26 +02:00
a91bda16c2 [nix] nix run now possible 2026-07-04 01:04:15 +02:00
3 changed files with 91 additions and 9 deletions

View File

@@ -1,17 +1,39 @@
## Gatekeeper - Door access system ## Gatekeeper - Door access system
Status: WIP - not prod ready #### Status: WIP - getting there o.o
Dev with `nix develop` Start prod server `nix run`<br>
sync python deps with `uv sync` Start dev server `nix run .#dev` or `nix run .#dev -- {args}`<br>
start dev server `uv run fastapi dev` Interactive dev with `nix develop`, then sync deps with `uv sync`<br>
Swagger UI @ http://127.0.0.1:8000/docs Swagger UI @ http://127.0.0.1:8000/api/v1/docs<br>
start prod server `uv run fastapi run` OpenApi @ http://127.0.0.1:8000/api/v1/openapi.json<br>
You need to set services.pcscd.enable = true; for the smartcard reader to work #### Config:
Issues: Nixos config for the card reader:
```
services.pcscd = {
enable = true;
plugins = [ pkgs.acsccid ]; #<-- Needed for the ACE1552U
};
```
This application is configured using env vars. You can use `cp .env.example .env` and then edit `.env` to change the keys to something else.
### A note on keycard scanners
I have tried two scanners while developing this project, the TWN4 MultiTech 2 from elatec and the ACR1552U from acs.<br>
##### TWN4
From the factory the TWN4 comes with firmware that emulates a HID and just inputs the serial of any scanned card. To be usable with pcscd it had to be flashed with the `TWN4_xPx520_S1SC161_Multi_CCID_1Slot_Standard.bix` firmware found in the `TWN4DevPack520` which can be downloaded under https://www.elatec-rfid.com/int/elatec-software (They send you a download link via email).
This software seems to not work under wine. I had to setup a win10 vm and pass the usb to be able to flash.<br>
Range: In my testing the TWN4 has a range of about 22mm when interfacing with our Mifare DESFire v2 cards. This is not enough for our idea of mounting the scanner on the inside of a glass window.
#### ACR1552U
The ACR1552U comes preloaded with PC/SC firmware. You need to install the acsccid package with your package-manager of choice (Nixos user see above) for the scanner to work but after that I had no problems with the hardware interfacing.<br>
Range: The range of the ACR1552U was much better at over 60mm (almost 70mm if you take of the face plate)
#### Issues:
- documentation missing - documentation missing
- `nix run` currently broken
- raspberry pi image not working - raspberry pi image not working
- no door state - no door state
- no door operations - no door operations

View File

@@ -25,6 +25,7 @@
outputs = outputs =
{ {
self,
nixpkgs, nixpkgs,
pyproject-nix, pyproject-nix,
uv2nix, uv2nix,
@@ -105,5 +106,23 @@
packages = forAllSystems (system: { packages = forAllSystems (system: {
default = pythonSets.${system}.mkVirtualEnv "gatekeeper" workspace.deps.default; default = pythonSets.${system}.mkVirtualEnv "gatekeeper" workspace.deps.default;
}); });
apps = forAllSystems (system: {
default = {
type = "app";
program = toString (nixpkgs.legacyPackages.${system}.writeShellScript "gatekeeper" ''
export LD_LIBRARY_PATH="${lib.getLib nixpkgs.legacyPackages.${system}.pcsclite}/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec ${self.packages.${system}.default}/bin/fastapi run ${self}/app/main.py "$@";
'');
};
dev = {
type = "app";
program = toString (nixpkgs.legacyPackages.${system}.writeShellScript "gatekeeper" ''
export LD_LIBRARY_PATH="${lib.getLib nixpkgs.legacyPackages.${system}.pcsclite}/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec ${self.packages.${system}.default}/bin/fastapi dev ${self}/app/main.py "$@";
'');
};
});
nixosModules = { gatekeeper = import ./module.nix; };
}; };
} }

41
module.nix Normal file
View File

@@ -0,0 +1,41 @@
{config, pkgs, lib, self, system, ... }:
let
cfg = config.services.gatekeeper;
in
{
options = {
services.gatekeeper = {
enable = lib.mkEnableOption "Enable the gatekeeper api service.";
dotenv = lib.mkOption {
type = lib.types.path;
default = null;
description = "The path to a .env file with the keys";
};
db = {
type = lib.types.path;
default = null;
description = "Where to save the database.";
};
};
};
config = lib.mkIf cfg.enable {
users.extraGroups.gatekeeper = {};
users.extraUsers.gatekeeper = {
description = "gatekeeper user";
group = "gatekeeper";
isSystemUser = true;
};
#environment.systemPackages = [self.packages.${system}.default];
systemd.services.gatekeeper = {
script = ''
export LD_LIBRARY_PATH="${lib.getLib pkgs.pcsclite}/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec ${pkgs.python3.pkgs.uvicorn}/bin/uvicorn run ${self}/app/main.py
'';
wantedBy = ["multi-user.target"];
serviceConfig = {
User = "gatekeeper";
Restart = "on-failure";
};
};
};
}