# Instalador ISO do Appliance NVR

Este documento descreve a ISO personalizada para instalar Debian/Ubuntu e provisionar o NVR como appliance de producao.

## Conteudo

- Autoinstall/cloud-init em `scripts/appliance/iso/autoinstall/`.
- ZIP final do projeto embutido em `/nvr-appliance/`.
- Script de primeiro boot `first-boot-nvr-install.sh`.
- Unidade systemd `nvr-first-boot-install.service`.
- Configuracao segura `nvr-appliance.env.example`.

O primeiro boot extrai o ZIP, protege `/etc/nvr-appliance/nvr-appliance.env` como `0600 root:root` e executa `scripts/appliance/install-nvr-appliance.sh`.

A geracao/validacao tambem cria arquivos auxiliares de producao:

- `*.iso.sha256`: SHA-256 da ISO final.
- `*.iso.build.log`: log da geracao.
- `*.iso.check.log`: log da validacao.

Use `SHA256_FILE`, `BUILD_LOG` e `CHECK_LOG` para gravar esses artefatos em outro diretorio de release.

## Configuracao Segura

Por padrao, `DB_PASSWORD` e `LOCAL_WEB_ADMIN_TOKEN` ficam vazios para serem gerados automaticamente. O fluxo normal de producao nao cria admin local inicial: primeiro deve ocorrer ativacao por serial/licenca do portal e depois login autorizado pelo portal. Os valores sensiveis ficam em:

```bash
/var/lib/nvr/secrets/appliance.env
/var/lib/nvr/secrets/initial-admin.env # somente modo tecnico explicito
```

Ambos devem permanecer `0600 root:root`. `initial-admin.env` so deve existir quando um tecnico presencial habilitar contingencia com `CREATE_INITIAL_ADMIN=1` e `ALLOW_TECHNICAL_INITIAL_ADMIN=1`.

Variaveis principais aceitas pelo ISO:

```bash
PUBLIC_BASE_URL=
PUBLIC_SCHEME=http
PUBLIC_HOST=
PORTAL_HOST=_
HTTP_PORT=80
CENTRAL_APP_URL=
CENTRAL_API_URL=
NVR_CENTRAL_ACTIVATION_ENDPOINT=/gateways/activate
LOCAL_WEB_PORT=9080
LOCAL_WEB_BIND=
LOCAL_WEB_EXPOSE_LAN=0
LOCAL_WEB_ALLOWED_CIDRS=
LOCAL_WEB_ADMIN_EXPOSE_LAN=0
LOCAL_WEB_ADMIN_ALLOWED_CIDRS=
LOCAL_WEB_ADMIN_TOKEN=
ENABLE_HDMI_KIOSK=0
ENABLE_DEV_SEEDS=0
CREATE_INITIAL_ADMIN=0
ALLOW_TECHNICAL_INITIAL_ADMIN=0
REBOOT_AFTER_FIRST_BOOT=1
```

Use `PUBLIC_BASE_URL` quando ja houver DNS/HTTPS definido. Sem ele, o instalador deriva a URL a partir de host, porta, IP local e hostname.

Use `CENTRAL_APP_URL`/`CENTRAL_API_URL` para apontar para o portal principal externo que emite e valida o serial do appliance. Se esses valores ficarem vazios, o appliance instala normalmente, mas a tela de ativacao falha fechada ate a URL central real ser configurada; ela nao usa `127.0.0.1` como autoridade de producao.

Validacoes aplicadas no primeiro boot:

- portas `HTTP_PORT` e `LOCAL_WEB_PORT` numericas, de 1 a 65535 e sem conflito;
- caminhos `INSTALL_ROOT` e `RECORDINGS_ROOT` absolutos;
- flags booleanas somente como `0` ou `1`;
- `PUBLIC_SCHEME` restrito a `http`/`https`;
- `PUBLIC_BASE_URL` vazio ou iniciado por `http://`/`https://`;
- `CENTRAL_APP_URL` e `CENTRAL_API_URL` vazios ou iniciados por `http://`/`https://`, nunca como loopback para ativacao de producao;
- listas de CIDRs sem caracteres fora do formato esperado;
- `ALLOW_PARTIAL_INSTALL=1` bloqueado no fluxo ISO de producao;
- exposicao administrativa LAN exige `LOCAL_WEB_ADMIN_TOKEN` provisionado.
- `CREATE_INITIAL_ADMIN=1` bloqueado em producao salvo modo tecnico/contingencia explicito.

`/etc/nvr-appliance/nvr-appliance.env` e `/var/log/nvr/first-boot-install.log` devem permanecer `0600 root:root`. O check da ISO confirma que o autoinstall aplica essa permissao e que o script de primeiro boot reforca a permissao antes de carregar variaveis.

## SSH e Usuario Local

O perfil final deixa SSH por senha desativado (`allow-pw: false`). A conta local `nvr-setup` fica habilitada para console fisico com senha inicial temporaria `Nvr-Setup-2026!`, troca obrigatoria no primeiro login e permissao sudo local. Essa senha nao libera SSH por senha.

Para homologacao ou administracao controlada por rede, injete uma chave publica na geracao da ISO usando `ISO_SSH_AUTHORIZED_KEY`; a chave privada nunca deve ser incluida no artefato. Quando uma chave e injetada, a conta tambem recebe uma regra sudo local para administracao por chave.

O sistema instalado grava orientacoes em:

```bash
/etc/issue.d/90-nvr-appliance.issue
/etc/update-motd.d/90-nvr-appliance
/etc/nvr-appliance/ACESSO_LOCAL.txt
/etc/nvr-appliance/STATUS_REDE.txt
/usr/local/sbin/nvr-status-local
```

## Rede E Instalacao Offline

A ISO configura DHCP persistente para rede cabeada no sistema instalado:

- `/etc/netplan/01-nvr-wired-dhcp.yaml` cobre interfaces `en*`, como `enp2s0` em Realtek RTL8111/8168/8411;
- `/etc/systemd/network/20-nvr-wired.network` cobre `en*` e `eth*`;
- NetworkManager fica disponivel para Wi-Fi, mas `en*` e `eth*` permanecem nao gerenciadas por ele;
- `systemd-networkd-wait-online` usa `--any --timeout=20`;
- `nvr-first-boot-install.service` inicia depois de `network.target`, sem depender de `network-online.target`.

Se nao houver rede, o boot segue em modo local e registra:

```text
Rede nao detectada. Verifique o cabo. A ativacao do serial exigira internet.
```

O comando local `sudo nvr-wifi-configure` abre a tela simples de Wi-Fi, lista redes e permite DHCP ou IPv4 fixo. A credencial fica persistida pelo NetworkManager em arquivo `0600 root:root` e nao deve aparecer em logs ou evidencias.

O instalador usa o repositorio APT offline embutido em `/nvr-appliance/offline-apt`, copiado para `/opt/nvr-appliance-installer/offline-apt`. Quando esse repositorio existe, as fontes HTTP/HTTPS do sistema alvo sao desabilitadas para evitar download acidental de pacotes como `unzip`. A ISO inclui offline `network-manager`, `wpasupplicant`, `iw` e `rfkill`.

## Decisao Segura De Disco

O `scripts/appliance/iso/autoinstall/user-data` roda um guard em `early-commands`, antes do particionamento:

- disco interno unico, gravavel e sem particoes/assinaturas: instala automaticamente;
- disco com particoes, Windows, Linux, assinaturas ou dados: bloqueia ate confirmacao explicita;
- multiplos discos internos: bloqueia ate selecao explicita do disco por caminho ou serial;
- toda decisao e registrada em `/var/log/installer/nvr-storage-decision.log` e copiada para `/var/log/nvr/storage-decision.log`.

Confirmacao avancada no boot da ISO:

```text
nvr_wipe_confirm=APAGAR nvr_install_disk=/dev/sdX
```

ou por serial:

```text
nvr_wipe_confirm=APAGAR nvr_install_disk_serial=SERIAL_DO_DISCO
```

A ISO continua usando storage `direct`, mas o layout e limitado ao disco alvo detectado pelo guard. Se a confirmacao estiver ausente ou ambigua, a instalacao falha antes de apagar qualquer disco.

Antes de usar em producao:

- mantenha `ssh.allow-pw=false` e provisione acesso por chave SSH, console local ou outro fluxo administrado;
- troque a senha temporaria da conta `nvr-setup` no primeiro login local;
- teste em VM limpa, em VM com disco pre-particionado e em hardware equivalente antes de usar em producao.

Para injetar chave publica de homologacao:

```bash
ISO_SSH_AUTHORIZED_KEY="$(cat ~/.ssh/nvr_iso_test.pub)" \
bash scripts/appliance/iso/build-nvr-iso.sh ISO_BASE nvr_monorepo_complete_final.zip nvr-appliance-installer.iso
```

## Gerar a ISO

```bash
sudo apt-get update
sudo apt-get install -y xorriso python3

cd /caminho/do/nvr
bash scripts/appliance/iso/build-nvr-iso.sh \
  /caminho/ubuntu-live-server.iso \
  /caminho/nvr_monorepo_complete_final.zip \
  ./nvr-appliance-installer.iso
```

Valide o bundle:

```bash
bash scripts/appliance/iso/check-iso-bundle.sh \
  /caminho/ubuntu-live-server.iso \
  /caminho/nvr_monorepo_complete_final.zip \
  ./nvr-appliance-installer.iso
```

A validacao confirma a presenca do ZIP, autoinstall, unidade systemd e script de primeiro boot dentro da ISO; confirma `autoinstall ds=nocloud` nos carregadores de boot conhecidos; confirma o contrato de permissao `0600`; confirma protecao por marcador `FIRST_BOOT_DONE`; e atualiza o arquivo SHA-256.

## Instalacao Iniciada Pelo Windows

Use `scripts/windows/Start-NvrApplianceInstall.ps1` somente para preparar o boot/USB gravavel da ISO e registrar a confirmacao destrutiva. O iniciador Windows:

- mostra discos detectados no Windows;
- bloqueia o disco de boot/sistema do Windows;
- exige selecionar o disco alvo;
- exige digitar `APAGAR`;
- grava `nvr-appliance/wipe-confirm.conf` e auditoria JSON na midia de boot;
- injeta `nvr_wipe_confirm=APAGAR` e, quando seguro, `nvr_install_disk_serial=...` no bootloader;
- pode reiniciar a maquina.

Ele nao formata, particiona nem apaga discos no Windows ativo. O apagamento so ocorre depois da reinicializacao, dentro do instalador Linux/NVR, e ainda passa pelo guard de disco da ISO.

Exemplo:

```powershell
Set-ExecutionPolicy -Scope Process Bypass
.\scripts\windows\Start-NvrApplianceInstall.ps1 -BootMediaRoot E:\ -TargetDiskNumber 1 -Restart
```

## Testar em VM

Use VM limpa com 2 vCPUs, 4 GB RAM, disco de 40 GB e rede NAT ou bridge. Acompanhe:

```bash
sudo journalctl -u nvr-first-boot-install.service -f
sudo tail -f /var/log/nvr/first-boot-install.log
```

Valide apos instalar e apos reinicializar:

```bash
test -f /var/lib/nvr/FIRST_BOOT_DONE
sudo REQUIRE_FIRST_BOOT_MARKER=1 bash /opt/nvr/scripts/appliance/healthcheck.sh
systemctl is-enabled nvr-stack.target platform-scheduler.timer nvr-log-rotate.timer
systemctl status nginx php*-fpm mariadb redis-server gateway-bootstrap gateway-daemon gateway-local-web platform-queue nvr-stack.target nvr-platform.target nvr-gateway.target --no-pager
systemctl status platform-scheduler.timer nvr-log-rotate.timer --no-pager
ss -ltnp | grep -E ':80|:9080'
sudo find /var/lib/nvr/secrets -maxdepth 1 -type f -exec stat -c '%a %U:%G %n' {} +
sudo stat -c '%a %U:%G %n' /etc/nvr-appliance/nvr-appliance.env /var/log/nvr/first-boot-install.log
```

Se `ENABLE_HDMI_KIOSK=1`, valide tambem:

```bash
systemctl status gateway-hdmi-kiosk.service --no-pager
curl -fsS http://127.0.0.1:9080/hdmi/healthz
```

URLs:

- Portal: `http://IP_DO_NVR/`
- NVR: `http://IP_DO_NVR/nvr/`
- Gateway publico de midia: `http://IP_DO_NVR/nvr/gateway/api/media/...`

O painel administrativo local do gateway permanece protegido por token e restrito a loopback, salvo se LAN for liberada explicitamente.

## HTTPS e LAN

Habilite HTTPS definindo `PUBLIC_BASE_URL` com `https://...` e instalando certificado no proxy frontal. `SESSION_SECURE_COOKIE` e redirects que exigem HTTPS so devem bloquear HTTP quando HTTPS real estiver ativo.

Para liberar o gateway local na LAN, defina `LOCAL_WEB_EXPOSE_LAN=1`, ajuste CIDRs e mantenha `LOCAL_WEB_ADMIN_TOKEN` forte. Rotas administrativas como `/metrics` e `/ui/operations` nao sao expostas por `/nvr/gateway`.

## Reinstalacao

Em teste, reinstale pela ISO. Para repetir somente o primeiro boot em ambiente descartavel:

```bash
sudo systemctl enable nvr-first-boot-install.service
sudo rm -f /var/lib/nvr/FIRST_BOOT_DONE
sudo reboot
```

Nao repita em producao sem backup e sem preservar os segredos.

## Primeiro Boot E Reinicializacao

`nvr-first-boot-install.service` e habilitado pelo autoinstall e roda somente se `/var/lib/nvr/FIRST_BOOT_DONE` ainda nao existir. O script cria log restrito, valida variaveis, extrai o bundle, chama o instalador, executa a verificacao de saude, grava o marcador e desabilita a unidade.

Por padrao, `REBOOT_AFTER_FIRST_BOOT=1` agenda reinicializacao apos a conclusao para subir o sistema ja pelo estado definitivo. Defina `REBOOT_AFTER_FIRST_BOOT=0` apenas durante diagnostico presencial ou laboratorio, e reinicie manualmente depois de validar logs e verificacao de saude.
