Archived
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a1d6842d7 | ||
|
|
f5ef3194d4 | ||
|
|
90e3397b42 | ||
|
|
be5812d5bb | ||
|
|
84f7e038cb | ||
|
|
91d8f8fab1 | ||
|
|
723212a81f | ||
|
|
75d09d57e3 | ||
|
|
6847a7a6f4 |
Submodule
+1
Submodule .claude/worktrees/proxmox-remote-build added at a5990ccf7d
@@ -7,7 +7,7 @@ servers and workstation.
|
||||
|
||||
The flake exposes NixOS configurations named `<platform>-<buildtype>`
|
||||
(platforms: `linode`, `proxmox`, `lxc`; build types: `minimal`, `nix-cache`,
|
||||
`server`, `docker`, `gui`, `pxe-boot`, `tailscale-exit-node`), generated from `modules/platforms/*`
|
||||
`server`, `docker`, `gui`, `pxe-boot`, `tailscale-exit-node`, `tor-relay`), generated from `modules/platforms/*`
|
||||
and `modules/build-types/*` by the `mkTarget` function in `flake.nix`. Not
|
||||
every combination is built — `pxe-boot` has no `linode` variant. See
|
||||
`README.md` for the full current target list; treat `flake.nix` as the
|
||||
|
||||
@@ -160,9 +160,10 @@ nixosSystem {
|
||||
```
|
||||
|
||||
Platforms: `linode`, `proxmox`, `lxc`. Build types: `minimal`, `nix-cache`,
|
||||
`server`, `docker`, `gui`, `pxe-boot`, `tailscale-exit-node`. Not every
|
||||
combination is built — e.g. `pxe-boot` has no `linode` variant (PXE/DHCP/TFTP
|
||||
need LAN L2 adjacency a Linode VPS doesn't have). Treat `flake.nix`'s
|
||||
`server`, `docker`, `gui`, `pxe-boot`, `tailscale-exit-node`, `tor-relay`. Not
|
||||
every combination is built — e.g. `pxe-boot` has no `linode` variant
|
||||
(PXE/DHCP/TFTP need LAN L2 adjacency a Linode VPS doesn't have), and
|
||||
`tor-relay` currently only exists as `lxc-tor-relay`. Treat `flake.nix`'s
|
||||
`generatedTargets` as the source
|
||||
of truth for which hosts exist — `README.md`, `AGENTS.md`,
|
||||
`docs/flake-lock-automation.md`, and the CI eval workflows
|
||||
@@ -190,7 +191,7 @@ removing a host.
|
||||
`vzdump` backup-archive metadata this doesn't have), no install step —
|
||||
see `docs/auto-installer.md`.
|
||||
- `modules/build-types/*.nix` — what a system is for:
|
||||
minimal/server/docker/gui/pxe-boot/nix-cache/tailscale-exit-node.
|
||||
minimal/server/docker/gui/pxe-boot/nix-cache/tailscale-exit-node/tor-relay.
|
||||
- `modules/common/configuration.nix` — base NixOS config imported by every
|
||||
host: locale, users, nix settings, git.
|
||||
- `modules/common/home.nix` / `hosts/nixos/home.nix` — Home Manager config for
|
||||
@@ -225,7 +226,8 @@ removing a host.
|
||||
and `environmentFile`; used by `hosts/server/host.nix` and
|
||||
`hosts/nix-cache/host.nix` to avoid duplicating that boilerplate.
|
||||
- `modules/tailscale/`, `modules/docker/`, `modules/networking/`,
|
||||
`modules/traefik/`, `modules/services/*` — single-purpose, single-host
|
||||
`modules/traefik/`, `modules/tor/`, `modules/services/*` — single-purpose,
|
||||
single-host
|
||||
feature modules (e.g. `docker/enable-service.nix`,
|
||||
`services/zfs/enable-service.nix`). Grep `modules/build-types/*.nix` for
|
||||
each build type's `imports` list to see which modules apply where.
|
||||
|
||||
@@ -10,11 +10,11 @@ pieces composed in `flake.nix`:
|
||||
|
||||
- **Platforms** (what it runs on): `linode`, `proxmox`, `lxc`
|
||||
- **Build types** (what it's for): `minimal`, `nix-cache`, `server`, `docker`,
|
||||
`gui`, `pxe-boot`, `tailscale-exit-node`
|
||||
`gui`, `pxe-boot`, `tailscale-exit-node`, `tor-relay`
|
||||
|
||||
Not every combination exists — `pxe-boot` has no `linode` variant, since
|
||||
PXE/DHCP/TFTP need LAN L2 adjacency that a Linode VPS doesn't have. The full
|
||||
list:
|
||||
PXE/DHCP/TFTP need LAN L2 adjacency that a Linode VPS doesn't have, and
|
||||
`tor-relay` currently only exists as `lxc-tor-relay`. The full list:
|
||||
|
||||
| Target | Purpose |
|
||||
| --- | --- |
|
||||
@@ -27,6 +27,7 @@ list:
|
||||
| `linode-gui` / `proxmox-gui` / `lxc-gui` | Cinnamon desktop workstation — previously the flat `nixos` target |
|
||||
| `proxmox-pxe-boot` / `lxc-pxe-boot` | HTTP/iPXE boot asset host — previously the flat `pxe-boot` target |
|
||||
| `linode-tailscale-exit-node` / `proxmox-tailscale-exit-node` / `lxc-tailscale-exit-node` | Tailscale exit node |
|
||||
| `lxc-tor-relay` | Tor middle relay |
|
||||
|
||||
Which variant of a given buildtype is actually deployed isn't tracked
|
||||
anywhere in this repo — that's live infrastructure state, not something a
|
||||
|
||||
@@ -19,7 +19,7 @@ see "LXC hosts" immediately below for why those are different.**
|
||||
## LXC hosts
|
||||
|
||||
`lxc-*` targets (`lxc-minimal`, `lxc-nix-cache`, `lxc-server`, `lxc-docker`,
|
||||
`lxc-gui`, `lxc-pxe-boot`, `lxc-tailscale-exit-node`) are **not** installed via `auto-install.sh` — the
|
||||
`lxc-gui`, `lxc-pxe-boot`, `lxc-tailscale-exit-node`, `lxc-tor-relay`) are **not** installed via `auto-install.sh` — the
|
||||
interactive menu deliberately excludes them. Don't try to select one there;
|
||||
`nixos-install` would bind-mount `/` onto `/mnt` (LXC containers have no raw
|
||||
disk to partition) and then refuse to touch the filesystem it's currently
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
# Spec: Refactor Flake Targets into Platform × Build-Type Matrix
|
||||
|
||||
**Status: implemented.** `flake.nix`'s `generatedTargets`/`mkTarget` and
|
||||
`modules/platforms/*`/`modules/build-types/*` are the result of this spec —
|
||||
kept here for historical rationale only (referenced from `CLAUDE.md`'s
|
||||
"Composition pattern" section), not as an active or open plan. The "Open
|
||||
Questions" below were resolved during implementation; don't treat them as
|
||||
outstanding. A `tailscale-exit-node` build type was added later, beyond this
|
||||
spec's original scope.
|
||||
|
||||
## Context
|
||||
|
||||
The flake at `~/nixos` currently defines these output targets (flat, ad-hoc naming):
|
||||
|
||||
- `docker`
|
||||
- `linode-minimal`
|
||||
- `nix-cache`
|
||||
- `nix-minimal`
|
||||
- `nixos`
|
||||
- `server`
|
||||
- `pxe-boot`
|
||||
|
||||
Some already follow a `platform-buildtype` convention (`linode-minimal`), most don't.
|
||||
`~/nix-auto-installer` is a related repo and should be checked for any coupling to
|
||||
these target names (scripts, docs, CI, or install automation that reference them by
|
||||
name) before renaming anything.
|
||||
|
||||
## Goal
|
||||
|
||||
Restructure the flake so targets are generated from two orthogonal concepts:
|
||||
|
||||
**Build types** (what the system is for):
|
||||
- `minimal`
|
||||
- `nix-cache`
|
||||
- `server`
|
||||
- `docker`
|
||||
- `pxe-boot`
|
||||
- `gui`
|
||||
|
||||
**Platforms** (what it's deployed on):
|
||||
- `linode` (Linode VM)
|
||||
- `proxmox` (Proxmox VM)
|
||||
- `lxc` (Proxmox LXC container)
|
||||
|
||||
Final targets should be named consistently as `<platform>-<buildtype>`, e.g.:
|
||||
|
||||
```
|
||||
linode-minimal proxmox-minimal lxc-minimal
|
||||
linode-nix-cache proxmox-nix-cache lxc-nix-cache
|
||||
linode-server proxmox-server lxc-server
|
||||
linode-docker proxmox-docker lxc-docker
|
||||
linode-pxe-boot proxmox-pxe-boot lxc-pxe-boot
|
||||
linode-gui proxmox-gui lxc-gui
|
||||
```
|
||||
|
||||
That's the full matrix (18 targets) if every build type applies to every platform.
|
||||
See **Open Questions** below — some combinations may not make sense and should be
|
||||
confirmed with me before being built out, not silently included or dropped.
|
||||
|
||||
## Migration mapping (old → new)
|
||||
|
||||
| Old target | New target | Notes |
|
||||
|--------------------|------------------------------------------------------|-------|
|
||||
| `linode-minimal` | `linode-minimal` | Already correct, keep as-is |
|
||||
| `nix-minimal` | likely `proxmox-minimal` or a platform-less base module | Ambiguous — see Open Questions |
|
||||
| `nix-cache` | base module consumed by `linode-nix-cache`, `proxmox-nix-cache`, `lxc-nix-cache` | Currently platform-less; needs to become a build-type module, not a standalone target |
|
||||
| `server` | base module consumed by `linode-server`, `proxmox-server`, `lxc-server` | Same as above |
|
||||
| `docker` | base module consumed by `linode-docker`, `proxmox-docker`, `lxc-docker` | Confirm docker actually makes sense as an LXC/VM guest build vs. a standalone container image — see Open Questions |
|
||||
| `pxe-boot` | TBD — may stay a single target rather than a per-platform one | See Open Questions |
|
||||
| `nixos` | TBD — unclear what this maps to in the new scheme | See Open Questions |
|
||||
|
||||
## Open Questions (Claude Code: raise these with me before implementing, don't guess)
|
||||
|
||||
1. **`nixos` target** — what is this currently used for (bare metal install, dev
|
||||
shell, template)? It doesn't obviously map to any of the six build types.
|
||||
2. **`nix-minimal` vs `linode-minimal`** — are these two different things, or is
|
||||
`nix-minimal` a leftover/duplicate?
|
||||
3. **`pxe-boot` and `gui` across all three platforms** — does PXE boot make sense
|
||||
for an LXC container or a cloud VM (Linode), or is it inherently bare-metal/
|
||||
network-boot only and should remain a single non-platform target? Does `gui`
|
||||
make sense inside an LXC container?
|
||||
4. **`docker` as a build type** — is this "a NixOS host configured to run Docker"
|
||||
(which would sensibly have linode/proxmox/lxc variants), or "a Docker container
|
||||
image built by the flake" (which wouldn't take a platform prefix at all, since
|
||||
it doesn't run on Linode/Proxmox/LXC as a guest OS)? These are structurally
|
||||
different and change how it should be wired in.
|
||||
5. Confirm whether all 18 combinations should actually exist, or whether this is
|
||||
meant to produce only the combinations that are genuinely useful (e.g. maybe no
|
||||
one needs `lxc-pxe-boot`).
|
||||
|
||||
## Implementation approach
|
||||
|
||||
1. **Inventory first.** Read the current `flake.nix` and any `nixosConfigurations`/
|
||||
`modules` structure. Map every existing target to what module(s) it actually
|
||||
pulls in. Don't assume — confirm against the real file contents.
|
||||
2. **Separate build-type and platform into their own module directories**, e.g.:
|
||||
```
|
||||
modules/build-types/minimal.nix
|
||||
modules/build-types/nix-cache.nix
|
||||
modules/build-types/server.nix
|
||||
modules/build-types/docker.nix
|
||||
modules/build-types/pxe-boot.nix
|
||||
modules/build-types/gui.nix
|
||||
|
||||
modules/platforms/linode.nix
|
||||
modules/platforms/proxmox.nix
|
||||
modules/platforms/lxc.nix
|
||||
```
|
||||
Build-type modules should contain only what makes a system "minimal" vs
|
||||
"server" vs "gui", etc. Platform modules should contain only what's specific
|
||||
to running as a Linode VM vs Proxmox VM vs LXC container (virtualisation
|
||||
guest tools, boot method, filesystem/image format, LXC-specific constraints
|
||||
like no kernel modules, etc).
|
||||
3. **Generate the target matrix programmatically** in `flake.nix` rather than
|
||||
hand-writing 18 near-identical `nixosConfigurations` entries — e.g. a small
|
||||
function that takes a platform name and build-type name, composes the two
|
||||
modules plus any shared base module, and produces the named output. This
|
||||
keeps future build types/platforms a one-line addition rather than a copy-paste
|
||||
job.
|
||||
4. **Only build combinations we've confirmed make sense** (see Open Questions) —
|
||||
don't emit all 18 by default if some are structurally invalid.
|
||||
5. **Preserve existing working configs during the transition.** Don't delete the
|
||||
old target names until their replacements build successfully — rename/alias
|
||||
at the end, not the start, so there's no window where the flake is broken.
|
||||
|
||||
## Verification
|
||||
|
||||
For every new target produced:
|
||||
```bash
|
||||
nix flake check
|
||||
nix build .#nixosConfigurations.<target>.config.system.build.toplevel
|
||||
```
|
||||
Confirm each builds without evaluation errors before considering it done. If a
|
||||
target fails to build, report which one and why rather than silently skipping it.
|
||||
|
||||
## Deliverables
|
||||
|
||||
- Refactored `flake.nix` using the composed module + generated-matrix approach.
|
||||
- New `modules/build-types/*.nix` and `modules/platforms/*.nix` files.
|
||||
- Old flat target names removed only after their replacements are verified.
|
||||
- A short `README.md` (or section in existing docs) listing the final target
|
||||
names and what each one is for.
|
||||
- A summary at the end of what changed, what was removed, and any of the Open
|
||||
Questions above that got resolved differently than expected.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Don't touch `~/nix-auto-installer` contents beyond checking it for references
|
||||
to the old target names — if changes there are needed, flag them, don't make
|
||||
them without confirming.
|
||||
- Don't add new build types or platforms beyond the ones listed here.
|
||||
@@ -98,6 +98,8 @@
|
||||
linode-tailscale-exit-node = mkTarget { platform = "linode"; buildType = "tailscale-exit-node"; hostPath = ./hosts/tailscale-exit-node/host.nix; };
|
||||
proxmox-tailscale-exit-node = mkTarget { platform = "proxmox"; buildType = "tailscale-exit-node"; hostPath = ./hosts/tailscale-exit-node/host.nix; };
|
||||
lxc-tailscale-exit-node = mkTarget { platform = "lxc"; buildType = "tailscale-exit-node"; hostPath = ./hosts/tailscale-exit-node/host.nix; };
|
||||
|
||||
lxc-tor-relay = mkTarget { platform = "lxc"; buildType = "tor-relay"; hostPath = ./hosts/tor-relay/host.nix; };
|
||||
};
|
||||
|
||||
# Auto-install environments (migrated from the former nix-auto-installer
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
_:
|
||||
|
||||
{
|
||||
networking.hostName = "tor-relay";
|
||||
|
||||
# No networking.hostId: only ZFS-touching hosts (server, docker) need one
|
||||
# for pool-import safety, and this host does neither.
|
||||
|
||||
# A genuinely new host (not a pre-refactor carry-over), so it tracks the
|
||||
# flake's current nixpkgs release rather than being pinned to an older one.
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../tor/enable-relay.nix
|
||||
];
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
{ config, lib, pkgs, vars, ... }:
|
||||
|
||||
let
|
||||
# `x-systemd.automount` never works inside a Linux container (LXC
|
||||
# included, regardless of privilege) -- confirmed live on lxc-docker:
|
||||
# systemd logs "Starting of <unit>.automount unsupported" for every
|
||||
# share and never mounts them. Mount eagerly there instead, with
|
||||
# `nofail` so a boot with the NFS server unreachable doesn't hang
|
||||
# (the VM platforms rely on automount itself to get that same
|
||||
# non-blocking behavior, so they don't need `nofail` too).
|
||||
automountOpts = if config.boot.isContainer then [ "nofail" ] else [ "x-systemd.automount" ];
|
||||
in
|
||||
{
|
||||
fileSystems = {
|
||||
${vars.nfsShares.dockerConfig.mountpoint} = {
|
||||
@@ -9,9 +19,8 @@
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
] ++ automountOpts;
|
||||
};
|
||||
|
||||
${vars.nfsShares.dockerDatabases.mountpoint} = {
|
||||
@@ -21,9 +30,8 @@
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
] ++ automountOpts;
|
||||
};
|
||||
|
||||
${vars.nfsShares.dockerVolumes.mountpoint} = {
|
||||
@@ -33,9 +41,8 @@
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
] ++ automountOpts;
|
||||
};
|
||||
|
||||
${vars.nfsShares.nextcloudData.mountpoint} = {
|
||||
@@ -45,9 +52,8 @@
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
] ++ automountOpts;
|
||||
};
|
||||
|
||||
${vars.nfsShares.raspiVolumes.mountpoint} = {
|
||||
@@ -57,9 +63,8 @@
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
] ++ automountOpts;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ vars, ... }:
|
||||
{ config, lib, vars, ... }:
|
||||
|
||||
{
|
||||
fileSystems.${vars.raspiMountpoint} = {
|
||||
@@ -9,6 +9,15 @@
|
||||
"_netdev"
|
||||
"noatime"
|
||||
|
||||
# Explicitly use NFSv4.2 if supported
|
||||
"nfsvers=4.2"
|
||||
] ++ lib.optionals (!config.boot.isContainer) [
|
||||
# `x-systemd.automount` never works inside a Linux container (LXC
|
||||
# included) -- confirmed live on lxc-docker: systemd logs "Starting
|
||||
# of <unit>.automount unsupported" and never mounts it. `nofail`
|
||||
# above already keeps boot non-blocking there, so plain eager
|
||||
# mounting is fine.
|
||||
|
||||
# Don't mount until first access
|
||||
"x-systemd.automount"
|
||||
|
||||
@@ -17,9 +26,6 @@
|
||||
|
||||
# Give the Pi/Tailscale a little time to appear
|
||||
"x-systemd.device-timeout=10s"
|
||||
|
||||
# Explicitly use NFSv4.2 if supported
|
||||
"nfsvers=4.2"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{ pkgs, vars, ... }:
|
||||
|
||||
{
|
||||
services.tor = {
|
||||
enable = true;
|
||||
|
||||
# Opens settings.ORPort (and DirPort, unset here) in the firewall —
|
||||
# see the nixpkgs tor module's own networking.firewall.mkIf block.
|
||||
openFirewall = true;
|
||||
|
||||
relay = {
|
||||
enable = true;
|
||||
# Plain middle/guard relay, not "exit" — relays onion traffic between
|
||||
# other Tor nodes without ever making requests to the public internet
|
||||
# on a user's behalf, avoiding the abuse complaints and legal exposure
|
||||
# an exit node invites.
|
||||
role = "relay";
|
||||
};
|
||||
|
||||
settings.ORPort = vars.ports.torRelayOrPort;
|
||||
|
||||
# Unix control socket at /run/tor/control (GroupWritable, group "tor")
|
||||
# -- what nyx below actually monitors the relay through. Nyx's own
|
||||
# default control-socket path (/var/run/tor/control) resolves to the
|
||||
# same place, so no extra nyx config is needed.
|
||||
controlSocket.enable = true;
|
||||
};
|
||||
|
||||
# Lets the primary user's shell session read/write the control socket
|
||||
# above without being root -- otherwise nyx fails to authenticate against
|
||||
# it at all.
|
||||
users.users.${vars.primaryUser}.extraGroups = [ "tor" ];
|
||||
|
||||
environment.systemPackages = [ pkgs.nyx ];
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
# Spec: Remove Sensitive Information from NixOS Flake
|
||||
|
||||
## Goal
|
||||
|
||||
Every secret currently readable in plaintext anywhere in this repo (working tree *and* git history) gets removed, replaced with `sops-nix`-managed encrypted references, and rotated. When this is done, the repo should be safe to make public without exposing anything about the systems it configures.
|
||||
|
||||
Treat this as three sequential milestones. Do not start git history rewriting (Milestone 3) until Milestones 1 and 2 are fully verified and the flake still builds. This should be its own branch (`refactor/secrets`) until fully verified, then merged.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 1 — Audit
|
||||
|
||||
Before touching anything, produce a complete inventory. Do not guess at scope — grep the whole tree and the whole history.
|
||||
|
||||
1. Run a secret scanner across the working tree and full history. Use both, since they catch different things:
|
||||
- `gitleaks detect --source . -v --log-opts="--all"` (scans history too)
|
||||
- `trufflehog git file://. --since-commit=$(git rev-list --max-parents=0 HEAD) --only-verified=false`
|
||||
If neither is installed, add them via a temporary `nix-shell -p gitleaks trufflehog` — don't install anything globally on the host.
|
||||
|
||||
2. Manually grep for the categories below, since scanners miss config-specific patterns:
|
||||
- `hashedPassword`, `password`, `initialPassword`, `initialHashedPassword` in any `users.users.*` block
|
||||
- `age.secrets`, `sops.secrets` (if any partial secrets work already exists — check for it)
|
||||
- PSK / `preSharedKey`, `privateKeyFile` inline values (vs. file references) for WireGuard
|
||||
- `authKey`, `apiToken`, `api_key`, `token =`, `secret =` in service modules (Tailscale, Cloudflare, backup tools, etc.)
|
||||
- SSH private key material: search for `BEGIN OPENSSH PRIVATE KEY` / `BEGIN RSA PRIVATE KEY` literals
|
||||
- TLS cert/key pairs committed under e.g. `secrets/`, `certs/`, `pki/`
|
||||
- Real name, personal email, home address, or anything in comments/hostnames that maps a machine to your physical identity or network layout (e.g. hostnames like `wayne-desktop`, static LAN IPs, ISP-identifying info)
|
||||
- `.env` files, `secrets.nix`, `secrets.yaml`, or any file that looks like it was meant to be gitignored but wasn't
|
||||
|
||||
3. Produce `secrets-inventory.md` (temporary, delete before finishing) listing: file path, line, secret type, and which host/service it belongs to. This becomes the checklist for Milestone 2 — every row must be either migrated to sops or deleted, with nothing left unaccounted for.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 2 — Migrate to sops-nix
|
||||
|
||||
### 2.1 Set up sops-nix
|
||||
|
||||
1. Add the flake input:
|
||||
```nix
|
||||
sops-nix.url = "github:Mic92/sops-nix";
|
||||
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
```
|
||||
2. Import `sops-nix.nixosModules.sops` into each host's module list (or into a shared `common.nix` if all hosts use it).
|
||||
3. Generate an age keypair **per host** (not one shared key for everything — a compromised host shouldn't decrypt every other host's secrets):
|
||||
```
|
||||
nix-shell -p age --run "age-keygen -o /var/lib/sops-nix/key.txt"
|
||||
```
|
||||
Print the public key (`age-keygen -y`) for each host — you'll need it for `.sops.yaml`.
|
||||
4. Also generate one age key for yourself (your admin workstation) so you can edit secrets without needing to SSH into a host: store it at `~/.config/sops/age/keys.txt`, back it up somewhere outside this repo (password manager, offline). **If this key is lost, every secret encrypted with it is unrecoverable — losing the age key is equivalent to losing the secrets.**
|
||||
5. Create `.sops.yaml` at the repo root defining creation rules: which age public keys can decrypt which secrets files, keyed by path regex, so e.g. `secrets/hostA.yaml` is decryptable by your admin key + hostA's key, `secrets/hostB.yaml` by your admin key + hostB's key.
|
||||
|
||||
### 2.2 Migrate each secret category from the inventory
|
||||
|
||||
For each row in `secrets-inventory.md`:
|
||||
|
||||
- **Password hashes**: generate hash with `mkpasswd -m sha-512` (or `bcrypt` if your setup wants that), store under `sops.secrets."<name>/hashedPassword"`, reference via `users.users.<name>.hashedPasswordFile = config.sops.secrets."<name>/hashedPassword".path;`. Do not put the *plaintext* password anywhere, only the hash, and only the hash goes into the encrypted sops file.
|
||||
- **API tokens / auth keys**: move the raw value into the per-host sops YAML, reference in the module via `config.sops.secrets."<service>/token".path` — most NixOS service modules that take a token also accept a `*File` variant (e.g. `environmentFile`, `tokenFile`); use that instead of passing the value directly.
|
||||
- **Private keys / certs**: move the PEM/key content wholesale into a sops secret, output as a file with appropriate `sops.secrets.<name>.path`, `owner`, `mode`, `restartUnits` so the depending service (sshd, wireguard, nginx) reloads when the secret changes.
|
||||
- **Personal/identifying info**: this doesn't belong in sops (it's not "secret," it's just information you don't want public). Replace real names/emails with placeholders or move to a small untracked `local.nix` that's `.gitignore`'d and imported conditionally, with a documented template (`local.nix.example`) committed instead.
|
||||
|
||||
### 2.3 Verify before moving on
|
||||
|
||||
- `nixos-rebuild dry-build --flake .#<host>` succeeds for every host.
|
||||
- `sudo nixos-rebuild switch --flake .#<host>` on at least one real machine (or a VM) confirms secrets decrypt and services start.
|
||||
- Confirm decrypted secrets land under `/run/secrets/` (not the Nix store — anything placed in `/nix/store` is world-readable by design, so sops-nix's runtime-only placement is the whole point; double check no module accidentally pulls a secret path into a store-built config file).
|
||||
- Re-run the grep/scanner sweep from Milestone 1 against the *working tree only* (not history yet) — it should now come back clean.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 3 — Scrub git history
|
||||
|
||||
Do this only after Milestone 2 is merged to your main branch and confirmed working, since it rewrites every commit SHA from the point of the earliest offending commit onward.
|
||||
|
||||
**This is destructive and irreversible on your local clone. Back up first:**
|
||||
```
|
||||
cp -r /path/to/nixos-repo /path/to/nixos-repo-backup-$(date +%F)
|
||||
```
|
||||
|
||||
1. Install `git-filter-repo` (not the older `git filter-branch` / BFG — filter-repo is the currently maintained, faster, safer tool):
|
||||
```
|
||||
nix-shell -p git-filter-repo
|
||||
```
|
||||
2. Use the `secrets-inventory.md` list to build a list of literal strings/paths to strip. Two approaches, use both:
|
||||
- Path-based: if whole files were secret (e.g. `secrets.nix`, a `.env`, a private key file), remove them entirely from history:
|
||||
```
|
||||
git filter-repo --path secrets.nix --path .env --invert-paths
|
||||
```
|
||||
- Value-based: for secrets embedded inline in files you're keeping (not deleting the whole file), use `--replace-text` with a file listing each literal secret string to replace with `***REMOVED***`:
|
||||
```
|
||||
git filter-repo --replace-text expressions.txt
|
||||
```
|
||||
3. After filtering, verify: run the Milestone 1 scanners again against full history (`--log-opts="--all"`). They must come back clean.
|
||||
4. Force-push the rewritten history:
|
||||
```
|
||||
git push origin --force --all
|
||||
git push origin --force --tags
|
||||
```
|
||||
5. **Every other clone of this repo (other machines, WSL instances, CI) must be deleted and re-cloned fresh** — a `git pull` against rewritten history will not work cleanly and risks resurrecting the old commits. Don't try to reconcile old clones; throw them away and re-clone.
|
||||
6. If this repo has ever been pushed to a public host (GitHub, etc.) or a fork/mirror exists, treat every secret that was ever in history as **permanently compromised regardless of the rewrite** — caches, forks, and Wayback-style archives can retain old commits indefinitely. History scrubbing prevents *future* exposure via `git clone`; it does not undo past exposure.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 4 — Rotate everything
|
||||
|
||||
Because the secrets were exposed in history (even briefly, even in a private repo), the migration is not complete until every credential in the inventory has been **rotated**, not just re-encrypted. Re-encrypting an already-leaked value protects it going forward but doesn't undo the leak.
|
||||
|
||||
For each row in the original inventory:
|
||||
- Password hashes → change the actual account password, regenerate the hash, update the sops file.
|
||||
- API tokens/auth keys → revoke the old token in the issuing service's dashboard (Cloudflare, Tailscale, backup provider, etc.) and generate a new one.
|
||||
- SSH/WireGuard private keys → generate new keypairs, update the corresponding public key wherever it's trusted (authorized_keys, peer configs, etc.), retire the old ones.
|
||||
- TLS certs → reissue if the private key was exposed.
|
||||
|
||||
Keep `secrets-inventory.md` open during this step and check off each row as rotated. Delete the file only once every row is checked off — it should not be committed.
|
||||
|
||||
---
|
||||
|
||||
## Ongoing prevention
|
||||
|
||||
Add a pre-commit hook (or a `nix flake check` step) running `gitleaks protect --staged` so a secret can't be committed again by accident. Document in the repo README (briefly) that new secrets go through `sops <file>` to edit, never as plaintext in a tracked file.
|
||||
|
||||
---
|
||||
|
||||
## Definition of done
|
||||
|
||||
**Status as of 2026-07-20:** Milestones 1–3 are done — sops-nix is fully
|
||||
wired (`.sops.yaml`, `secrets/*.yaml`, referenced via `hashedPasswordFile`/
|
||||
`*File`/`sops.secrets.*.path` throughout), and history has been scrubbed
|
||||
with `git-filter-repo` + force-push (this removed a GitHub fine-grained PAT
|
||||
that had been committed in plaintext in `flake.nix`/`common/home.nix`
|
||||
between 2025-07-16 and 2026-02-09, later migrated to sops but never scrubbed
|
||||
from history until now). **Milestone 4 is not confirmed** — whether that PAT
|
||||
(or any other historically-plaintext credential) was actually rotated, not
|
||||
just re-encrypted, isn't something this repo can attest to; that's an
|
||||
operator action against the issuing service (GitHub, etc.), not a repo
|
||||
change. Do that before considering this fully closed.
|
||||
|
||||
- [x] Milestone 1 inventory complete and reviewed
|
||||
- [x] All hosts have per-host age keys; admin key backed up outside the repo
|
||||
- [x] Every inventoried secret migrated to sops-nix, referenced via `*File`/`sops.secrets.*.path`, nothing plaintext in the working tree
|
||||
- [x] `nixos-rebuild dry-build` and at least one real `switch` verified per host
|
||||
- [x] Working-tree scanner sweep clean
|
||||
- [x] History rewritten with `git-filter-repo`, force-pushed, full-history scanner sweep clean
|
||||
- [ ] All other clones deleted and re-cloned from the rewritten history — every clone that existed before 2026-07-20's rewrite (any other machine, WSL instance, or CI checkout) needs this
|
||||
- [ ] Every credential in the original inventory rotated (not just re-encrypted) — **the GitHub PAT found in history specifically still needs this**
|
||||
- [x] Pre-commit secret scanning hook added (`.githooks/pre-commit`, `gitleaks protect --staged`)
|
||||
- [x] `secrets-inventory.md` deleted from the working directory (never committed)
|
||||
@@ -41,6 +41,17 @@ warn-dirty = false
|
||||
build-users-group = nixbld
|
||||
EOF
|
||||
|
||||
# The official installer's single-user root path still shells out to
|
||||
# `sudo` to create /nix even though it already knows it's running as
|
||||
# root -- confirmed live against a sudo-less minimal Debian/Proxmox
|
||||
# node, where it fails with "sudo: not found" and prints this exact
|
||||
# mkdir/chown as the manual fix. Pre-create it so that branch of the
|
||||
# installer is skipped entirely.
|
||||
if [ ! -d /nix ]; then
|
||||
mkdir -m 0755 /nix
|
||||
chown root /nix
|
||||
fi
|
||||
|
||||
sh <(curl -L https://nixos.org/nix/install) --no-daemon
|
||||
else
|
||||
sh <(curl -L https://nixos.org/nix/install) --no-daemon
|
||||
|
||||
@@ -22,12 +22,21 @@
|
||||
# refuses to run if the target VMID already exists on the node, or if
|
||||
# a VM/CT identified as --host already exists under any other VMID
|
||||
# (checked live against the node; --allow-duplicate-host overrides).
|
||||
# - --allow-duplicate-host distinguishes an exact match (same --type
|
||||
# *and* --host, e.g. re-running --type lxc --host docker while an
|
||||
# lxc-docker container already exists -- almost always a redeploy of
|
||||
# the same target to pick up a rebuilt image) from a cross-type match
|
||||
# (a different platform sharing the same host identity, e.g. a
|
||||
# proxmox-docker VM coexisting with lxc-docker). Only the exact match
|
||||
# is destroyed and replaced, after typing the hostname back to
|
||||
# confirm (outside --dry-run) -- a cross-type match is always left
|
||||
# untouched, matching-or-not.
|
||||
# - --modify only ever touches a resource you name explicitly via
|
||||
# --vmid, shows exactly what will change first, and (outside
|
||||
# --dry-run) always requires typing that VMID back to confirm before
|
||||
# anything is sent to the node. There is no bulk/implicit modify.
|
||||
# - Neither mode can start/stop/delete a resource. Not implemented on
|
||||
# purpose -- ask before adding it.
|
||||
# - Outside of --allow-duplicate-host's exact-match replace above,
|
||||
# neither mode can start/stop/delete a resource.
|
||||
#
|
||||
# See --help for the full option list.
|
||||
set -euo pipefail
|
||||
@@ -77,7 +86,13 @@ Create mode (default):
|
||||
already exists on the node (checked live via
|
||||
qm/pct, not any file in this repo) --
|
||||
otherwise refused, since it'd share that
|
||||
host's hostName/hostId.
|
||||
host's hostName/hostId. An existing resource
|
||||
of this *same* --type (e.g. re-running --type
|
||||
lxc --host docker over an existing lxc-docker)
|
||||
is destroyed and replaced, after confirming --
|
||||
a different --type sharing the same --host
|
||||
(e.g. a proxmox-docker VM) is always left
|
||||
untouched.
|
||||
|
||||
Modify mode (reconfigure an EXISTING resource -- requires --modify):
|
||||
--modify Switch to modify mode.
|
||||
@@ -319,12 +334,13 @@ fi
|
||||
# this script itself always uses unless --name is overridden) -- a guest
|
||||
# manually renamed on the node afterwards wouldn't match, but nothing here
|
||||
# creates guests that way.
|
||||
if [[ "$allow_duplicate_host" -eq 1 ]]; then
|
||||
echo
|
||||
echo "--allow-duplicate-host: skipping the check for an existing '${host}' on ${node}."
|
||||
elif [[ "$dry_run" -eq 1 ]]; then
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
echo
|
||||
echo "[dry-run] would check ${node} for an existing VM/CT identified as '${host}'"
|
||||
if [[ "$allow_duplicate_host" -eq 1 ]]; then
|
||||
echo "[dry-run] --allow-duplicate-host: an existing ${type} named '${host}' would be" \
|
||||
"destroyed and replaced; a different-type match would be left untouched"
|
||||
fi
|
||||
else
|
||||
echo
|
||||
echo "==> Checking ${node} for an existing VM/CT identified as '${host}'..."
|
||||
@@ -349,17 +365,90 @@ REMOTE_SCRIPT
|
||||
echo "check entirely)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Split into "exact" (same resource kind as --type -- i.e. literally this
|
||||
# same host+platform combo already exists, almost always a redeploy of
|
||||
# the same target to test a rebuilt image) vs "cross-type" (a different
|
||||
# platform sharing this host identity, e.g. a stopped proxmox-docker VM
|
||||
# coexisting with an lxc-docker container -- a deliberate, valid setup
|
||||
# this script has never managed and still won't). Read via a herestring
|
||||
# (not a pipe) so the appends below survive outside the loop.
|
||||
this_kind="$type"
|
||||
exact_matches=""
|
||||
cross_matches=""
|
||||
if [[ -n "$existing" ]]; then
|
||||
echo "ERROR: '${host}' already exists on ${node}:" >&2
|
||||
echo "$existing" | while read -r kind id n; do
|
||||
while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
if [[ "$kind" == "$this_kind" ]]; then
|
||||
exact_matches+="${kind} ${id} ${n}"$'\n'
|
||||
else
|
||||
cross_matches+="${kind} ${id} ${n}"$'\n'
|
||||
fi
|
||||
done <<<"$existing"
|
||||
fi
|
||||
|
||||
if [[ -n "$exact_matches" && "$allow_duplicate_host" -ne 1 ]]; then
|
||||
echo "ERROR: '${host}' already exists on ${node} as this same resource type:" >&2
|
||||
echo "$exact_matches" | while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
echo " - ${kind} VMID ${id} (${n})" >&2
|
||||
done
|
||||
echo "Refusing to create a second ${this_kind} sharing this identity. Pass" >&2
|
||||
echo "--allow-duplicate-host to destroy it and create a fresh one in its place" >&2
|
||||
echo "(after confirming), or use --modify to reconfigure the existing one instead." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$cross_matches" && "$allow_duplicate_host" -ne 1 ]]; then
|
||||
echo "ERROR: '${host}' already exists on ${node} as a different resource type:" >&2
|
||||
echo "$cross_matches" | while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
echo " - ${kind} VMID ${id} (${n})" >&2
|
||||
done
|
||||
echo "Refusing to create a second resource sharing this identity. Pass" >&2
|
||||
echo "--allow-duplicate-host to create one anyway (it gets its own distinct" >&2
|
||||
echo "sops key and VMID -- the existing resource(s) above are left untouched)," >&2
|
||||
echo "sops key and VMID -- the existing resource above is left untouched)," >&2
|
||||
echo "or use --modify to reconfigure the existing one instead." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$cross_matches" ]]; then
|
||||
echo "--allow-duplicate-host: '${host}' also exists on ${node} as a different resource" \
|
||||
"type -- leaving it untouched:"
|
||||
echo "$cross_matches" | while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
echo " - ${kind} VMID ${id} (${n})"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -n "$exact_matches" ]]; then
|
||||
echo "--allow-duplicate-host: '${host}' already exists on ${node} as this same resource" \
|
||||
"type -- it will be destroyed and replaced:"
|
||||
echo "$exact_matches" | while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
echo " - ${kind} VMID ${id} (${n})"
|
||||
done
|
||||
echo
|
||||
read -rp "Type the hostname (${host}) to confirm destroying the above and replacing it: " confirm
|
||||
if [[ "$confirm" != "$host" ]]; then
|
||||
echo "Cancelled -- input didn't match ${host}." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$exact_matches" | while read -r kind id n; do
|
||||
[[ -z "$kind" ]] && continue
|
||||
echo "==> Destroying ${kind} VMID ${id} (${n})..."
|
||||
if [[ "$kind" == "vm" ]]; then
|
||||
# qm destroy has no --force to stop-then-destroy in one call (pct's
|
||||
# does) -- stop explicitly first if it's running.
|
||||
if ssh "$ssh_target" "qm status ${id}" 2>/dev/null | grep -q running; then
|
||||
ssh "$ssh_target" "qm stop ${id}"
|
||||
fi
|
||||
ssh "$ssh_target" "qm destroy ${id} --purge 1"
|
||||
else
|
||||
ssh "$ssh_target" "pct destroy ${id} --force 1 --purge 1"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Target: ${flake_target} (host=${host}, type=${type}) -> Proxmox resource '${name}'"
|
||||
@@ -435,7 +524,7 @@ ensure_remote_repo() {
|
||||
echo
|
||||
echo "==> Ensuring ${remote_repo_dir} exists and is current on ${node}..."
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
echo "[dry-run] would ensure ${remote_repo_dir} exists on ${node} (clone + scripts/codex-setup.sh if missing, git pull if present)"
|
||||
echo "[dry-run] would ensure ${remote_repo_dir} exists on ${node} (clone if missing, git pull if present), and would verify/bootstrap build tooling there (scripts/codex-setup.sh) if \`nix\` isn't already on PATH"
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -453,6 +542,33 @@ ensure_remote_repo() {
|
||||
fi
|
||||
echo "Not present -- cloning from ${origin_url}..."
|
||||
ssh "$ssh_target" "git clone '${origin_url}' '${remote_repo_dir}'"
|
||||
fi
|
||||
|
||||
# Trivial check, run every time (not just right after a fresh clone) --
|
||||
# confirmed live: a first bootstrap can clone the repo successfully and
|
||||
# still leave the node without a working `nix` (e.g. the node had no
|
||||
# `sudo`, which the Nix installer's root path depends on -- see the fix
|
||||
# in scripts/codex-setup.sh), and a later run with the repo already
|
||||
# present would otherwise never retry it. Sources
|
||||
# scripts/lib/nix-bootstrap.sh's ensure_nix_profile first -- a
|
||||
# single-user Nix install typically only gets sourced into login shells,
|
||||
# and ssh's non-interactive command execution is neither, so a
|
||||
# freshly-installed `nix` still wouldn't be on PATH here without it.
|
||||
#
|
||||
# Just `nix` today -- the only thing the remote build commands below
|
||||
# actually invoke -- but a list (not a single hardcoded check) so a
|
||||
# future remote step needing another tool can add itself here instead of
|
||||
# growing a parallel check.
|
||||
local remote_required_cmds=(nix)
|
||||
local tooling_check_cmd="cd '${remote_repo_dir}' && . scripts/lib/nix-bootstrap.sh && ensure_nix_profile"
|
||||
local cmd
|
||||
for cmd in "${remote_required_cmds[@]}"; do
|
||||
tooling_check_cmd="${tooling_check_cmd} && command -v ${cmd}"
|
||||
done
|
||||
|
||||
if ssh "$ssh_target" "$tooling_check_cmd" >/dev/null 2>&1; then
|
||||
echo "Build tooling already present on ${node}."
|
||||
else
|
||||
echo "==> Bootstrapping build tooling on ${node} (scripts/codex-setup.sh)..."
|
||||
ssh "$ssh_target" "cd '${remote_repo_dir}' && bash scripts/codex-setup.sh"
|
||||
fi
|
||||
@@ -536,6 +652,11 @@ repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$
|
||||
declare -a NIX_OPTS=()
|
||||
[[ -n "$nix_extra_opts_str" ]] && eval "NIX_OPTS=(${nix_extra_opts_str})"
|
||||
cd "$repo_dir"
|
||||
# A single-user Nix install only gets sourced into login shells; this ssh
|
||||
# session is neither, so `nix` wouldn't otherwise be on PATH here even
|
||||
# right after a successful install.
|
||||
. scripts/lib/nix-bootstrap.sh
|
||||
ensure_nix_profile
|
||||
NIXOS_HOST_KEYS_DIR="$(pwd)/host-keys" nix build --impure \
|
||||
--no-use-registries --no-accept-flake-config "${NIX_OPTS[@]}" \
|
||||
".#nixosConfigurations.${target}.config.system.build.tarball" \
|
||||
@@ -583,6 +704,8 @@ repo_dir="$1"; target="$2"; dest_dir="$3"; dest_name="$4"; nix_extra_opts_str="$
|
||||
declare -a NIX_OPTS=()
|
||||
[[ -n "$nix_extra_opts_str" ]] && eval "NIX_OPTS=(${nix_extra_opts_str})"
|
||||
cd "$repo_dir"
|
||||
. scripts/lib/nix-bootstrap.sh
|
||||
ensure_nix_profile
|
||||
nix build --no-use-registries --no-accept-flake-config "${NIX_OPTS[@]}" \
|
||||
".#nixosConfigurations.${target}.config.system.build.diskoImagesScript" \
|
||||
--out-link "result-${target}"
|
||||
@@ -642,7 +765,17 @@ if [[ "$type" == "lxc" ]]; then
|
||||
# systemd routinely uses (even plain getty units), and every getty
|
||||
# crash-loops on a denied mount every ~3s (visible as garbage on the
|
||||
# console) while core services like nsncd fail the same way.
|
||||
create_cmd="pct create ${vmid} ${iso_storage}:vztmpl/${remote_filename} --unprivileged 1 --features ${PROXMOX_DEFAULT_LXC_FEATURES} --rootfs ${storage}:${local_disk_size} --hostname ${name} --cores ${cores} --memory ${memory} --swap ${local_swap} --net0 name=eth0,bridge=${bridge},ip=dhcp"
|
||||
#
|
||||
# ...,mount=nfs;nfs4: without it AppArmor blanket-denies the `nfs`/
|
||||
# `rpc_pipefs` mount syscalls any NFS client share needs -- confirmed
|
||||
# live on lxc-docker: `mount: /var/lib/nfs/rpc_pipefs: permission
|
||||
# denied`. The value's `;` (Proxmox's own multi-fstype separator for
|
||||
# this one feature, per PVE::LXC's use of PVE::ParseUtils::split_list)
|
||||
# must stay single-quoted here: create_cmd is sent to `remote()`, which
|
||||
# hands the whole string to `ssh` as a single command for the *remote*
|
||||
# shell to parse -- unquoted, that `;` would be read as a remote
|
||||
# command separator and silently truncate this into two commands.
|
||||
create_cmd="pct create ${vmid} ${iso_storage}:vztmpl/${remote_filename} --unprivileged 1 --features '${PROXMOX_DEFAULT_LXC_FEATURES}' --rootfs ${storage}:${local_disk_size} --hostname ${name} --cores ${cores} --memory ${memory} --swap ${local_swap} --net0 name=eth0,bridge=${bridge},ip=dhcp"
|
||||
remote "$create_cmd"
|
||||
remote "pct start ${vmid}"
|
||||
else
|
||||
|
||||
+9
-1
@@ -53,7 +53,15 @@
|
||||
# crash-loops on a denied `/run/credentials/*` mount every ~3s (visible
|
||||
# as garbage on the console) and core services like nsncd fail the same
|
||||
# way on userns_create; system.build.tarball never finishes activating.
|
||||
: "${PROXMOX_DEFAULT_LXC_FEATURES:=nesting=1,keyctl=1}"
|
||||
#
|
||||
# mount=nfs;nfs4: without it, AppArmor blanket-denies the `nfs`/
|
||||
# `rpc_pipefs` mount syscalls any NFS client share needs -- confirmed
|
||||
# live on lxc-docker (which mounts several, see modules/docker/mount-data.nix
|
||||
# and modules/raspi/mount-data.nix): `mount: /var/lib/nfs/rpc_pipefs:
|
||||
# permission denied`. Harmless to grant on lxc targets that don't mount
|
||||
# NFS at all -- it only widens what the container is *allowed* to mount,
|
||||
# nothing here forces a mount to happen.
|
||||
: "${PROXMOX_DEFAULT_LXC_FEATURES:=nesting=1,keyctl=1,mount=nfs;nfs4}"
|
||||
|
||||
export PROXMOX_HOST PROXMOX_SSH_USER PROXMOX_STORAGE PROXMOX_ISO_STORAGE \
|
||||
PROXMOX_BRIDGE PROXMOX_DEFAULT_CORES PROXMOX_DEFAULT_MEMORY_MB \
|
||||
|
||||
@@ -137,6 +137,14 @@
|
||||
# shortcuts on the gui build type (hosts/nixos/home.nix).
|
||||
pveWeb = 8006;
|
||||
pbsWeb = 8007;
|
||||
|
||||
# Tor relay's ORPort — the port other Tor relays connect to for onion
|
||||
# routing traffic (modules/tor/enable-relay.nix). Tor's own conventional
|
||||
# default; opened via services.tor.openFirewall rather than
|
||||
# networking.firewall.allowedTCPPorts directly, but kept here anyway so
|
||||
# it's not a bare literal duplicated between the relay's settings and
|
||||
# anything else that ever needs to reference it.
|
||||
torRelayOrPort = 9001;
|
||||
};
|
||||
|
||||
# .raw disk image size for every proxmox-* host's standalone Disko image
|
||||
|
||||
Reference in New Issue
Block a user