Ctrl K
ComunidadGuías…

docs/installation.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Installation

## Development

Docker and Compose are the only requirements. The compose file carries working
defaults for everything, including a development JWT secret, so no `.env` is
needed to get started.

```bash
npm run dev          # docker compose up --build
```

| Service    | URL                   | Notes                          |
| ---------- | --------------------- | ------------------------------ |
| Dashboard  | http://localhost:4200 | Angular dev server, hot reload |
| Player     | http://localhost:4300 | the app a display opens        |
| API        | http://localhost:3000 | NestJS, hot reload             |
| Mailpit    | http://localhost:8025 | catches every outgoing mail    |
| PostgreSQL | `127.0.0.1:5432`      | loopback only                  |
| Redis      | `127.0.0.1:6379`      | loopback only                  |

Migrations run at boot, so the schema is there by the time the API answers.

### First run

The dashboard has no seeded account. On a fresh database it shows a one-time
setup screen that creates the initial super-admin; that route stops working the
moment a user exists. Super-admins always use a second factor, so the setup
continues straight into pairing an authenticator app — have one at hand, and
keep the recovery codes it shows you somewhere safe.

After that:

1. Create an organisation.
2. Open the player at http://localhost:4300 — it shows a six-digit code.
3. In the dashboard, **Screens → Add a screen**, and enter that code.

Emails (verification, invitations, password resets) never leave the machine:
they land in Mailpit at http://localhost:8025.

### Starting over

```bash
docker compose down -v      # also drops the database volume
rm -rf test-data/media/*    # and the uploaded media
```

## Without Docker

You need PostgreSQL 16+, Redis 7+ and FFmpeg on `PATH`, plus Node.js 26.

```bash
npm ci                                   # root only — one lockfile for the monorepo
cp .env.example .env                     # then set JWT_ACCESS_SECRET + SECRETS_ENCRYPTION_KEY
npx nx run backend:db-migrate            # create the schema

npx nx serve backend                     # :3000
npx nx serve frontend                    # :4200
npx nx serve player                      # :4300
```

> The lockfile is written by npm 11. npm 10, which ships with Node 22, cannot
> install it — run `npm i -g npm@12.2.0` first.

## Production

Images are built by CI and published to GHCR:

```
ghcr.io/flo-schilli/mynextscreen/backend
ghcr.io/flo-schilli/mynextscreen/frontend
ghcr.io/flo-schilli/mynextscreen/player
```

The shipped deployment is Ansible driving rootless Podman quadlets behind Caddy.
It builds nothing on the host — it pulls the images above.

```bash
cd ansible
cp hosts.ini.example hosts.ini     # fill in your host and domain
ansible-playbook deploy.yml --ask-vault-pass
```

What the playbook sets up:

- a `mynextscreen` system user running rootless Podman
- quadlet units for backend, frontend, player, PostgreSQL and Redis on their own
  container network
- Caddy as the only public listener, with automatic TLS, SSE pass-through and a
  fail2ban jail
- all application ports bound to loopback, reachable only through Caddy

Required before the first run:

- `vault_mynextscreen_postgres_password` in your vault — the playbook refuses to
  run without it rather than falling back to a default
- `JWT_ACCESS_SECRET` of at least 32 characters (`openssl rand -base64 48`)
- `secrets_encryption_key` in your vault (`openssl rand -base64 32`) — the playbook
  and the backend refuse to run without it. Back it up apart from database dumps.
- `PUBLIC_BASE_URL`, and `PLAYER_BASE_URL` if the player has its own hostname

Pin a version with `signage_image_tag=0.10.1`; the default is `latest`.

### Backup and restore

```bash
ansible-playbook download_db.yml     # dump to your machine
ansible-playbook upload_db.yml       # restore a dump into the instance
```

Media lives on the host under the service user's `app/media` and is not part of
the database dump — back it up separately.

## Database migrations

The Drizzle schema in `apps/backend/src/db/` is the source of truth. Change it,
then generate a migration; never edit the database by hand.

```bash
npx nx run backend:db-generate    # diff the schema into a new SQL migration
npx nx run backend:db-migrate     # apply pending migrations
npx nx run backend:db-studio      # browse the data
```

Migrations are applied automatically when the backend starts, so a deployment
does not need a separate step.