Introduction
Welcome to autofirma-nix! This project provides a suite of tools to interact with Spain’s public administration, seamlessly integrating into your NixOS and Home Manager setup. It includes:
- AutoFirma for digitally signing documents and authenticating on various Spanish administration websites—because ink and paper are so last century.
- DNIeRemote for using an NFC-based national ID via an Android device—no more digging through drawers for that card reader you haven’t seen since 2010.
- Configurador FNMT-RCM for securely requesting personal certificates from the Spanish Royal Mint—yes, the mint that makes actual coins.
- Integration with Mozilla Firefox (provided on both the NixOS and the Home Manager modules) that allows Firefox to communicate with AutoFirma, as required by some sites—now with automatic setup!
Installation
This project is distributed as a Nix flake for easy integration into your NixOS configuration. It provides both a NixOS module for system-wide configurations and a Home Manager module for user-specific setups. Depending on your preference, you can choose one or the other.
Keep in mind that you should enable either the NixOS module or the Home Manager module—not both simultaneously. Think of it like wearing one hat at a time.
Depending on your Nix channel:
- Use the main branch with
nixpkgs-unstable
. - For stable channels, use the
release-XX.YY
branch corresponding to your NixOS version.
We officially support current releases. If you encounter issues on an older branch, upgrading is recommended, as it might resolve the problem—and let’s face it, newer is usually better.
Here’s an example configuration to include autofirma-nix
as an input:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
autofirma-nix = {
url = "github:nix-community/autofirma-nix"; # For nixpkgs-unstable
# url = "github:nix-community/autofirma-nix/release-24.11"; # For NixOS 24.11
inputs.nixpkgs.follows = "nixpkgs";
};
};
nixConfig = {
extra-substituters = [
"https://nix-community.cachix.org"
];
extra-trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
};
# Further configuration details are provided in the sections below.
}
NixOS module
For those who prefer system-wide configurations, autofirma-nix offers a dedicated NixOS module. Below is an example of how to configure the NixOS module. (The inputs
section is covered in the previous section.)
{
outputs = { self, nixpkgs, autofirma-nix, ... }:
{
nixosConfigurations.myHostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
autofirma-nix.nixosModules.default
{
programs.autofirma.enable = true;
programs.autofirma.firefoxIntegration.enable = true;
programs.dnieremote.enable = true;
programs.configuradorfnmt.enable = true;
programs.configuradorfnmt.firefoxIntegration.enable = true;
programs.firefox.enable = true;
programs.firefox.policies = {
SecurityDevices = {
"OpenSC PKCS#11" = "${pkgs.opensc}/lib/opensc-pkcs11.so";
"DNIeRemote" = "${config.programs.dnieremote.finalPackage}/lib/libdnieremotepkcs11.so";
};
};
}
];
};
};
}
Home Manager module
If you prefer per-user flexibility and customization, the autofirma-nix Home Manager module is the way to go. Here’s how you can set it up in your Home Manager configuration:
{
outputs = { self, home-manager, autofirma-nix, nixpkgs, ... }:
{
homeConfigurations."my-user" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
autofirma-nix.homeManagerModules.default
{
programs.autofirma.enable = true;
programs.autofirma.firefoxIntegration.profiles = {
myprofile = {
enable = true;
};
};
programs.dnieremote.enable = true;
programs.configuradorfnmt.enable = true;
programs.configuradorfnmt.firefoxIntegration.profiles = {
myprofile = {
enable = true;
};
};
programs.firefox = {
enable = true;
policies = {
SecurityDevices = {
"OpenSC PKCS11" = "${pkgs.opensc}/lib/opensc-pkcs11.so";
"DNIeRemote" = "${config.programs.dnieremote.finalPackage}/lib/libdnieremotepkcs11.so";
};
};
profiles.myprofile = {
id = 0;
};
};
}
];
};
};
}
Security
AutoFirma chats with remote servers in a couple of different ways to handle document signing and authentication. Here’s the lowdown on these scenarios and how certificates fit into the bigger picture.
Browser-based scenario
In most cases, your friendly web browser takes care of the heavy lifting for server authentication: it connects to the remote server and confirms the server’s identity with its own certificate store. After that, the browser opens a WebSocket to AutoFirma, relaying commands back and forth. For this communication to work, a SSL certificate is created and added to Firefox; depending on the installation method you chose is located either in /etc/AutoFirma
or in $HOME/.afirma/AutoFirma
.
Direct connection scenario
Sometimes, the browser tells AutoFirma to talk directly to the remote server. In that case, AutoFirma itself must determine which Certificate Authorities (CAs) are valid. This is where certificate management in AutoFirma becomes important.
Managing certificates in autofirma-nix
AutoFirma trusts a certificate only if it meets two conditions:
-
Official Provider
It must come from one of the providers published in the Spanish Government’s authorized list. -
System CA Store
It must also appear in your system’s ca-bundle (or cacerts) on NixOS. If your NixOS configuration blocks or adds a certificate, AutoFirma respects that setting.
If a certificate is missing from the system CA store or explicitly blocked, AutoFirma will ignore it—even if it shows up on the official list.
Relevant NixOS options
-
security.pki.certificateFiles
Adds extra certificates to the global truststore. If a certificate is on the official list, and you include it here, AutoFirma will trust it. -
security.pki.caCertificateBlacklist
Blocks specific certificates. Even if one is on the official list, AutoFirma ignores it if it appears here.
Minimal example
{
security.pki = {
certificateFiles = [
./my-certificate.crt
];
caCertificateBlacklist = [
"Izenpe.com"
];
};
programs.autofirma.enable = true;
}
In this snippet, if ./my-certificate.crt
is on the official list, AutoFirma will trust it, while any certificate from Izenpe.com
is blacklisted, no matter what.
Troubleshooting
Encountering issues? Here are some tips to get you back on track:
Security devices do not seem to update or do not appear
If you have installed AutoFirma and enabled Firefox integration, but Firefox does not
detect the security devices, you may need to remove the pkcs11.txt
file from the
Firefox profile folder. For instance, if you enabled the Home Manager module and the
profile is named myprofile
, the file is located in ~/.mozilla/firefox/myprofile/pkcs11.txt
.
Removing it and restarting Firefox should solve the issue:
$ rm ~/.mozilla/firefox/myprofile/pkcs11.txt
$ firefox
Missing certificates even though the DNIe PIN was requested
If OpenSC PKCS#11 prompts you for a password but no certificates are available for signing, you might see something like the following in the Autofirma logs (when running it from a terminal):
$ autofirma
...
INFO: El almacen externo 'OpenSC PKCS#11' ha podido inicializarse, se anadiran sus entradas y se detiene la carga del resto de almacenes
...
INFO: Se ocultara el certificado por no estar vigente: java.security.cert.CertificateExpiredException: NotAfter: Sat Oct 26 15:03:27 GMT 2024
...
INFO: Se ocultara el certificado por no estar vigente: java.security.cert.CertificateExpiredException: NotAfter: Sat Oct 26 15:03:27 GMT 2024
...
SEVERE: Se genero un error en el dialogo de seleccion de certificados: java.lang.reflect.InvocationTargetException
....
SEVERE: El almacen no contiene ningun certificado que se pueda usar para firmar: es.gob.afirma.keystores.AOCertificatesNotFoundException: No se han encontrado certificados validos en el almacen
This occurs because your certificates have expired, as indicated by the “NotAfter:” date.
If the certificates are not expired because you recently renewed them, but you used AutoFirma before this renewal, it is possible that OpenSC has cached your old certificates. To fix this, you need to delete the OpenSC cache. By default, it is located at $HOME/.cache/opensc.
$ rm -rf $HOME/.cache/opensc
NixOS options
The following options can only be set in a NixOS configuration.
programs.autofirma.enable
Whether to enable AutoFirma.
Type: boolean
Default:
false
Example:
true
programs.autofirma.package
The autofirma package to use.
Type: package
Default:
pkgs.autofirma
programs.autofirma.finalPackage
The AutoFirma package after applying configuration.
Type: package (read only)
Default:
`programs.autofirma.package` with applied configuration
programs.autofirma.firefoxIntegration.enable
Whether to enable Firefox integration.
Type: boolean
Default:
false
Example:
true
programs.autofirma.fixJavaCerts
Whether to enable Fix Java certificates.
Type: boolean
Default:
false
Example:
true
programs.autofirma.truststore.package
The autofirma-truststore package to use.
Type: package
Default:
pkgs.autofirma-truststore
programs.autofirma.truststore.finalPackage
The AutoFirma truststore package after applying configuration.
Type: package (read only)
Default:
`programs.autofirma.truststore.package` with applied configuration
programs.configuradorfnmt.enable
Whether to enable configuradorfnmt.
Type: boolean
Default:
false
Example:
true
programs.configuradorfnmt.package
The configuradorfnmt package to use.
Type: package
Default:
pkgs.configuradorfnmt
programs.configuradorfnmt.finalPackage
The configuradorfnmt package after applying configuration.
Type: package (read only)
Default:
`programs.configuradorfnmt.package` with applied configuration
programs.configuradorfnmt.firefoxIntegration.enable
Whether to enable Firefox integration.
Type: boolean
Default:
false
Example:
true
programs.dnieremote.enable
Whether to enable DNIeRemote.
Type: boolean
Default:
false
Example:
true
programs.dnieremote.package
The dnieremote package to use.
Type: package
Default:
pkgs.dnieremote
programs.dnieremote.finalPackage
The DNIeRemote package after applying configuration.
Type: package (read only)
Default:
`programs.dnieremote.package` with applied configuration
programs.dnieremote.jumpIntro
Skip the intro and jump to a specific screen.
Type: one of “usb”, “wifi”, “no”
Default:
"no"
programs.dnieremote.openFirewall
Open the firewall for the selected port.
Type: boolean
Default:
false
programs.dnieremote.usbPort
The port to use for the USB connection.
Type: signed integer
Default:
9501
programs.dnieremote.wifiPort
The port to use for the Wi-Fi connection.
Type: signed integer
Default:
9501
Home Manager options
The following options can only be set in a Home Manager configuration.
programs.autofirma.enable
Whether to enable AutoFirma.
Type: boolean
Default:
false
Example:
true
programs.autofirma.package
The autofirma package to use.
Type: package
Default:
pkgs.autofirma
programs.autofirma.finalPackage
The AutoFirma package after applying configuration.
Type: package (read only)
Default:
`programs.autofirma.package` with applied configuration
programs.autofirma.firefoxIntegration.profiles
Firefox profiles to integrate AutoFirma with.
Type: attribute set of (submodule)
programs.autofirma.firefoxIntegration.profiles.<name>.enable
Whether to enable Enable AutoFirma in this firefox profile…
Type: boolean
Default:
false
Example:
true
programs.autofirma.firefoxIntegration.profiles.<name>.name
Profile name.
Type: string
Default:
"‹name›"
programs.autofirma.truststore.package
The autofirma-truststore package to use.
Type: package
Default:
pkgs.autofirma-truststore
programs.autofirma.truststore.finalPackage
The AutoFirma truststore package after applying configuration.
Type: package (read only)
Default:
`programs.autofirma.truststore.package` with applied configuration
programs.configuradorfnmt.enable
Whether to enable configuradorfnmt.
Type: boolean
Default:
false
Example:
true
programs.configuradorfnmt.package
The configuradorfnmt package to use.
Type: package
Default:
pkgs.configuradorfnmt
programs.configuradorfnmt.finalPackage
The configuradorfnmt package after applying configuration.
Type: package (read only)
Default:
`programs.configuradorfnmt.package` with applied configuration
programs.configuradorfnmt.firefoxIntegration.profiles
Firefox profiles to integrate configuradorfnmt with.
Type: attribute set of (submodule)
programs.configuradorfnmt.firefoxIntegration.profiles.<name>.enable
Whether to enable Enable configuradorfnmt in this firefox profile…
Type: boolean
Default:
false
Example:
true
programs.configuradorfnmt.firefoxIntegration.profiles.<name>.name
Profile name.
Type: string
Default:
"‹name›"
programs.dnieremote.enable
Whether to enable DNIeRemote.
Type: boolean
Default:
false
Example:
true
programs.dnieremote.package
The dnieremote package to use.
Type: package
Default:
pkgs.dnieremote
programs.dnieremote.finalPackage
The DNIeRemote package after applying configuration.
Type: package (read only)
Default:
`programs.dnieremote.package` with applied configuration
programs.dnieremote.jumpIntro
Skip the intro and jump to a specific screen.
Type: one of “usb”, “wifi”, “no”
Default:
"no"
programs.dnieremote.usbPort
The port to use for the USB connection.
Type: signed integer
Default:
9501
programs.dnieremote.wifiPort
The port to use for the Wi-Fi connection.
Type: signed integer
Default:
9501