# nixos-infra

Declarative NixOS infrastructure: host configurations, system modules, services, and user environments. Built on **Nix flakes**, **NixOS modules**, and **Home Manager**.

**Design principles:**

- Single source of truth for all systems
- Fully reproducible builds
- Minimal duplication; shared logic in modules and lib
- Modular services with a unified `machine.<service>.*` interface

**Contents:**

- [Machines](#machines)
- [Architecture](#architecture)
- [Repository structure](#repository-structure)
- [Security](#security)
- [System update (nixos-update)](#system-update-nixos-update)
- [Deployment](#deployment)
- [TODO](#todo)
- [License](#license)

---

## Machines

| Host         | Role                                        |
| ------------ | ------------------------------------------- |
| **elaris**   | Personal desktop                            |
| **velarion** | RuJect infrastructure (Forgejo, mail, etc.) |

---

## Architecture

- **hosts/** — per-machine configuration (hardware, disk, common baseline)
- **modules/** — reusable NixOS modules (SSH, security, fonts, nixos-update, etc.)
- **services/** — service definitions with `options.nix` and `service.nix`; enabled via `machine.<name>.enable`, `machine.<name>.domain`, etc.
- **users/** — user accounts and Home Manager configs (`system.nix`, `default.nix`, `hosts/<host>.nix`)
- **lib/** — `mkNixos`, `mkUsers`, `mkHome` for assembling systems and home configs

---

## Repository structure

```plaintext
.
├── flake.nix
├── hosts/
│   ├── common/          # shared baseline (modules, packages, locale)
│   ├── elaris/
│   └── velarion/
├── modules/             # NixOS modules (ssh, security, nixos-update, …)
├── services/             # machine.<name>.* service definitions
├── users/
├── lib/
└── secrets/
```

### Hosts

Per-host config lives under `hosts/<hostname>/` (e.g. `disk.nix`, `machine.nix`, `default.nix`). The `common/` import provides a shared baseline for all hosts (see `hosts/common/default.nix`).

### Lib

- **mkNixos** — builds a `nixosSystem`: flake inputs, host config, Home Manager, users. Entrypoint: `mkNixos { hostname = "velarion"; users = [ "rus07tam" ]; }`.
- **mkUsers** — turns `users/<name>/system.nix` and `users/<name>/default.nix` into system modules and Home Manager config.
- **mkHome** — builds Home Manager config for a user on a given host; supports `users/<name>/hosts/<hostname>.nix` overrides.

### Services

Each service is a module with a unified NixOS option namespace `machine.<service>.*`.

**Typical layout** (see `services/forgejo/`):

| File | Purpose |
|------|---------|
| `default.nix` | Entry point; imports `options.nix`, `service.nix`, and optional submodules |
| `options.nix` | Declares `machine.<service>.*` options (enable, domain, port, database, etc.) |
| `service.nix` | Core service config: enables the service, configures settings, system packages, SSH `AllowUsers` if needed |

**Optional components:**

| File                        | Purpose                                                                                    |
|---------------------------- |------------------------------------------------------------------------------------------- |
| `network.nix` / `nginx.nix` | Firewall (`allowedTCPPorts`), nginx virtualHost with reverse proxy, SSL/ACME               |
| `mail.nix`                  | SMTP/mailer config for the service; mailserver login accounts (when `machine.mail.enable`) |
| `tmpfiles.nix`              | `systemd.tmpfiles.rules` for directories and static assets (e.g. custom themes)            |
| `secrets.nix`               | Sops secrets referenced by the service                                                     |
| `database.nix`              | Database setup (PostgreSQL `ensureDatabases`, `ensureUsers`) when the service needs a DB   |

### Users

Per-user directory: `users/<username>/`.

- **system.nix** — system-level: `users.users.<name>` (groups, `hashedPasswordFile`, `openssh.authorizedKeys`), `services.openssh.settings.AllowUsers`, shared programs (e.g. `programs.fish.enable`). Passwords and sensitive data come from **sops** secrets.
- **default.nix** — Home Manager base: `imports` (variables, modules), `home.packages`, `targets.genericLinux.enable`.
- **hosts/\<hostname\>.nix** — host-specific Home Manager overrides.
- **modules/**, **variables/**, **assets/** — user-local modules and shared variables.

Example layout: `users/rus07tam/{system.nix, default.nix, secrets.nix, variables/, modules/, hosts/}`.

### Secrets

Managed with **sops**. Layout: `secrets/common.yaml`, `secrets/rus07tam.yaml`, etc. Secrets are decrypted at evaluation time and referenced in config (e.g. `config.sops.secrets."rus07tam/hashedPassword".path`).

---

## Security

### Sudo

Configures **sudo** for group `wheel`: NOPASSWD for a fixed set of commands only:

- `nixos-rebuild`
- `nix`
- `systemctl`
- `reboot`
- `poweroff`

All other operations require a password. This keeps privilege escalation explicit and limited.

### OpenSSH

- **services.openssh**: enabled, `openFirewall = true`.
- **Global settings**: Access is key-only; root login is disabled.
- **Per-user access**: each user and each service account that needs SSH (e.g. `forgejo` for git) is added explicitly via `services.openssh.settings.AllowUsers` in the corresponding module (e.g. in `users/rus07tam/system.nix` or `services/forgejo/service.nix`).

---

## System update (nixos-update)

The module **`modules/nixos-update.nix`** (included in the common host baseline) provides a script `nixos-update`, installed as a system package.

It:

1. Clones or updates the flake from `ssh://forgejo@git.ruject.fun/RuJect/nixos-infra.git` into a fixed directory (e.g. `/tmp/nixos-infra-flake`).
2. Prompts for confirmation.
3. Runs `nh os switch` for the current host.

Interactive shell startup reminds the user to use `nixos-update` for system updates. Adjust the flake URL and paths in the module if your setup differs.

---

## Deployment

On a host, apply the configuration for that host:

```bash
sudo nixos-rebuild switch --flake .#<hostname>
```

Alternatively, use the **nixos-update** script (see [System update (nixos-update)](#system-update-nixos-update)) to pull the latest flake from the remote and run `nh os switch`.

---

## TODO

- Decouple service dependencies so that services can run independently (many currently depend on nginx).
- Configure **Synapse** and **Prosody**.

---

## License

See [LICENSE](LICENSE).
