Expanded the DEPLOYMENT-GUIDE.md to include a comprehensive section on managing encrypted secrets using Passage and Pass. Detailed steps for setting up, creating, and deploying machine-specific secrets, along with security notes. Updated krops.nix and config/lnbits.nix to include configurations for deploying custom LNBits extensions, enhancing the flexibility and security of the NixOS deployment process.
7.8 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
.
├── web-app/ # Shared web-app source code
│ ├── package.json
│ ├── index.html
│ └── public/ # Base public folder
├── machine-specific/
│ ├── machine1/
│ │ ├── env/.env # Machine1's environment file
│ │ └── images/ # Machine1's images
│ │ ├── logo.png
│ │ └── banner.jpg
│ └── machine2/
│ ├── env/.env # Machine2's environment file
│ └── images/ # Machine2's images
│ ├── logo.png
│ └── banner.jpg
├── build/ # Generated locally (gitignored)
│ ├── machine1/dist/ # Built files for machine1
│ └── machine2/dist/ # Built files for machine2
├── 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
- Create directories:
machine-specific/machine3/env/andmachine-specific/machine3/images/ - Add
.envfile and images for machine3 - Create
config/machine3/configuration.nix - Add machine3 to
build-local.nixandkrops.nix
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