Updated the .gitignore to include machine-specific configurations and secrets handling. Expanded the DEPLOYMENT-GUIDE.md to provide detailed instructions for adding new machines using a template, along with steps for managing encrypted secrets. Introduced example configuration files for boot settings and a sample WireGuard service, improving modularity and flexibility in the NixOS deployment process. Adjusted krops.nix to reference the correct path for machine-specific configurations.
8.9 KiB
Web-App Deployment Guide
Overview
This setup builds the web-app locally with machine-specific configuration, then deploys the built artifacts to each target machine. Each machine gets its own customized build with:
- Machine-specific
.envfiles - Machine-specific images in the
publicfolder
Structure
.
├── config/ # NixOS configuration files
│ ├── shared.nix # Shared config for all machines
│ ├── nginx.nix # Nginx configuration
│ ├── lnbits.nix # LNBits configuration
│ ├── pict-rs.nix # Pict-rs configuration
│ └── machines/ # Machine-specific configs (gitignored)
│ ├── example-machine/ # Template (committed to git)
│ │ ├── configuration.nix # Main config entry point
│ │ ├── boot.nix # Bootloader settings
│ │ └── example-service.nix # Service examples
│ ├── machine1/ # Your machines (gitignored)
│ └── machine2/ # Your machines (gitignored)
├── web-app/ # Shared web-app source (symlink)
├── machine-specific/ # Machine-specific web-app assets (symlink)
├── lnbits/ # LNBits source (symlink)
├── secrets/ # Encrypted secrets
│ ├── example-machine/
│ │ └── README.md # Secrets usage guide
│ ├── machine1/ # Machine-specific secrets
│ │ └── *.age # Encrypted with age
│ └── machine2/
├── build/ # Generated locally (gitignored)
├── build-local.nix # Local build scripts
└── krops.nix # Deployment configuration
How It Works
1. Build Locally
First, build the web-app for each machine on your local machine:
# Build for a specific machine
nix-build ./build-local.nix -A machine1 && ./result/bin/build-machine1
# Or build for all machines
nix-build ./build-local.nix -A all && ./result/bin/build-all
This:
- Copies web-app source to
./build/{machine}/ - Copies machine-specific
.envfile - Copies machine-specific images to
public/ - Runs
npm run build - Creates
./build/{machine}/dist/with the built app
2. Deploy Built Artifacts
After building, deploy to target machines:
# Deploy to specific machine
nix-build ./krops.nix -A machine1 && ./result
# Deploy to all machines
nix-build ./krops.nix -A all && ./result
The built files from ./build/{machine}/dist/ are copied to /var/src/web-app-dist/ on each target machine.
Complete Workflow
# 1. Build locally for all machines
nix-build ./build-local.nix -A all && ./result/bin/build-all
# 2. Deploy to all machines
nix-build ./krops.nix -A all && ./result
Customization
Add a new machine
-
Copy the example template:
cp -r config/machines/example-machine config/machines/my-new-machine -
Edit the configuration:
- Open
config/machines/my-new-machine/configuration.nix - Change
domain = "example.com"to your domain - Add your
hardware-configuration.nix(fromnixos-generate-config)
- Open
-
Create machine-specific web-app assets (if using web-app):
mkdir -p machine-specific/my-new-machine/env mkdir -p machine-specific/my-new-machine/images # Add .env file and images -
Add to krops.nix and build-local.nix:
- Add
my-new-machineconfiguration to both files
- Add
-
Build and deploy:
nix-build ./build-local.nix -A my-new-machine && ./result/bin/build-my-new-machine nix-build ./krops.nix -A my-new-machine && ./result
Update environment variables
Edit .env in machine-specific/{machine-name}/env/.env, then rebuild locally
Update images
Replace files in machine-specific/{machine-name}/images/, then rebuild locally
Update web-app code
Edit files in web-app/, then rebuild locally
After any changes: rebuild locally, then redeploy.
Adding Machine-Specific Services
Sometimes you need services that only run on certain machines (e.g., WireGuard on machine1 but not machine2).
Using the Example Template
A complete example machine configuration is provided in config/example-machine/:
config/example-machine/
├── configuration.nix # Template with domain parameter
├── boot.nix # Bootloader configuration examples
└── example-service.nix # WireGuard and other service examples
To use the template:
- Copy the
example-machinedirectory to your new machine name:cp -r config/example-machine config/my-new-machine - Edit
configuration.nixto set your domain - Copy your
hardware-configuration.nixfromnixos-generate-config - Customize
boot.nixfor your bootloader (UEFI or BIOS) - Modify or remove
example-service.nixas needed - Add the machine to
build-local.nixandkrops.nix
Example: Machine1 has WireGuard
Structure:
config/
├── shared.nix # Shared config for all machines
├── machine1/
│ ├── configuration.nix # Imports shared.nix + machine-specific modules
│ ├── wireguard.nix # Machine1-specific service
│ ├── hardware-configuration.nix
│ └── boot.nix
└── machine2/
├── configuration.nix # Only imports shared.nix
├── hardware-configuration.nix
└── boot.nix
Steps to Add a Machine-Specific Service
-
Create a service configuration file in the machine's directory:
# Example: config/machine1/wireguard.nix { config, lib, pkgs, ... }: { networking.wireguard.interfaces = { wg0 = { privateKeyFile = "/etc/wireguard/privatekey"; ips = [ "10.0.0.2/24" ]; peers = [ ... ]; }; }; } -
Import it in the machine's configuration.nix:
# config/machine1/configuration.nix { config, pkgs, ... }: { imports = [ (import /var/src/config-shared { inherit config pkgs; domain = "4lpaca.io"; }) ./hardware-configuration.nix ./boot.nix ./wireguard.nix # ← Add your service here ]; } -
Deploy - the service will only be deployed to that specific machine:
nix-build ./krops.nix -A machine1 && ./result
Common Machine-Specific Services
- WireGuard VPN - Only on machines that need VPN access
- Backup services - Different backup targets per machine
- Development tools - Extra packages for staging vs production
- Custom hardware drivers - GPU drivers, specific hardware support
The key is that each machine's configuration.nix can import different modules while still sharing common configuration through shared.nix.
Deploying LNBits Extensions
You can deploy custom LNBits extensions to /var/lib/lnbits/extensions on your target machines.
Setup
1. Create extensions directory:
mkdir -p lnbits-extensions
2. Add your custom extensions:
# Example: Clone a custom extension
git clone https://github.com/your-org/custom-extension lnbits-extensions/custom-extension
3. Enable in krops.nix: Uncomment the lnbits-extensions line:
lnbits-extensions.file = toString ./lnbits-extensions;
4. Enable in config/lnbits.nix:
Choose one of two options:
Option 1: Replace extensions directory (use if you manage ALL extensions via deployment)
systemd.tmpfiles.rules = [
"L+ /var/lib/lnbits/extensions - - - - /var/src/lnbits-extensions"
];
⚠️ Warning: This will DELETE any extensions installed via the LNBits UI!
Option 2: Merge deployed extensions (safer - keeps UI-installed extensions)
systemd.services.lnbits-copy-extensions = {
description = "Copy deployed LNBits extensions";
before = [ "lnbits.service" ];
wantedBy = [ "lnbits.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.rsync}/bin/rsync -av /var/src/lnbits-extensions/ /var/lib/lnbits/extensions/";
};
};
5. Deploy:
nix-build ./krops.nix -A machine1 && ./result
How It Works
Option 1 (Symlink):
- Your
./lnbits-extensionsdirectory is deployed to/var/src/lnbits-extensions - A symlink replaces
/var/lib/lnbits/extensions→/var/src/lnbits-extensions - Any existing extensions directory is deleted
- All extensions must be managed via deployment
Option 2 (Copy/Merge):
- Your
./lnbits-extensionsdirectory is deployed to/var/src/lnbits-extensions - Deployed extensions are copied into
/var/lib/lnbits/extensions/ - Existing UI-installed extensions are preserved
- You can mix deployed extensions with UI-installed ones