# Configuration

## Configuration file

You can use the [default
`config.yaml`](https://git.platypush.tech/platypush/platypush/src/branch/master/platypush/config/config.yaml)
as a template/reference.

The location of the `config.yaml` to be used by the application is determined
in the following way:

1. It can be passed through the command-line `-c`/`--config` argument.
2. If not specified via `-c`, it will be read from the `PLATYPUSH_CONFIG`
   environment variable.
3. If not specified, use `./config.yaml` if available.
4. If not available, and you are running Platypush within a Docker container,
   or as a privileged user (and usually you shouldn't), or as a systemd service
   created by a supported package manager, then `/etc/platypush/config.yaml`
   will be used if available.
5. Otherwise, if you are running Platypush as a non-privileged user or in a
   virtual environment, `$XDG_CONFIG_HOME/platypush/config.yaml` will be used
   (defaults to `~/.config/platypush/config.yaml`).

### Scripts directory

By default, any custom Python scripts will be searched under
`<CONFDIR>/scripts`, where `<CONFDIR>` is the path to your `config.yaml`.

You can override it in your `config.yaml`:

```yaml
scripts_dir: /path/to/custom/scripts
```

Since everything under the scripts directory will be imported as a submodule,
you can create your own libraries of scripts that can import other scripts:

```python
# Content of scripts/music.py

from platypush import run

def music_play(plugin='music.mopidy', resource=None):
  run(f'{plugin}.play', resource)

# Content of scripts/lights.py

from platypush import run

def lights_toggle(plugin='light.hue', groups=('Living Room',)):
  run(f'{plugin}.toggle', groups=groups)

# Content of scripts/home.py

from platypush import procedure

from scripts.music import music_play
from scripts.lights import lights_toggle

@procedure
def at_home():
  music_play()
  lights_toggle()
```

### Splitting configuration on multiple files

The `config.yaml` file can become very complex, especially if you embed many
hooks and procedures in it in YAML format.

To make the configuration more maintainable, and also to isolate modules that
you can reuse across multiple instances, you can leverage the `include`
directive:

```yaml
# All paths are relative to config.yaml, or to the location of the current file
include:
  - assistant.yaml
  - db.yaml
  - media.yaml
  - mqtt.yaml
  - sensors.yaml
  # ...
```

## Working directory

This is where the application will store its data and integration plugins will
store their data. The order of precedence is:

* `-w`/`--workdir` command line argument.
* The `PLATYPUSH_WORKDIR` environment variable.
* The `workdir` field in the configuration file.
* `$XDG_DATA_HOME/platypush` (default: `~/.local/share/platypush`) if launched
  with a non-privileged user, `/var/lib/platypush` if launched as root or with
  a system user.

## Database

The application stores entities, variables, users, integrations state and more
on a database. The engine configuration supports the [SQLAlchemy engine
syntax](https://docs.sqlalchemy.org/en/20/core/engines.html).

**Note**: The application uses a local SQLite database by default, which is
natively supported by SQLAlchemy. The application has also been tested against
MySQL/MariaDB and Postgres, and should work fine with any modern relational
database supported by SQLAlchemy. However, any backend other than SQLite may
require an additional Python dependency for the SQLAlchemy driver (for example
[`pg8000`](https://pypi.org/project/pg8000/) for PostgreSQL).

Order of precedence for the engine:

* `--main-db`/`--db` command line argument.
* The `PLATYPUSH_DB` environment variable.
* The `main.db` field in the configuration file.
* `sqlite:///<WORKDIR>/main.db`

## Device ID

The device ID is a unique identifier for a Platypush instance on a network and
is used to reliably dispatch messages when multiple instances use a shared
backend.

The order of precedence is:

* `--device-id` command line argument.
* The `PLATYPUSH_DEVICE_ID` environment variable.
* The `device_id` field in the configuration file.
* The hostname of the machine.

## systemd service

If you installed Platypush from a system package manager then you'll also have
a `systemd` service installed for it.

You can start/enable Platypush like any other `systemd` service:

```
# systemctl start platypush
# systemctl enable platypush
```

Or, if you want to run the Platypush service as a generic user:

```bash
❯ systemctl --user start platypush
❯ systemctl --user enable platypush
```

Otherwise, you can create your own `systemd` service copying the [provided
`.service`
file](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/systemd/platypush.service)
to e.g. `~/.config/systemd/user` or `/etc/systemd/system`.

## Redis

Platypush uses Redis as a in-memory queue to deliver messages and as a pub/sub
bus for inter-process communication.

If you installed Platypush through a package manager, then the Redis service
will automatically be installed and started if you launch the Platypush service
as a privileged user.

If you run Platypush in a container then by default it'll start its own Redis
instance through the `--start-redis` command-line option.

You can customize the Redis configuration through the:

1. `--redis-host`, `--redis-port` and `--redis-queue` command-line options.
2. `PLATYPUSH_REDIS_HOST`, `PLATYPUSH_REDIS_PORT` and `PLATYPUSH_REDIS_QUEUE`
   environment variables.
3. Through your `config.yaml`:

```yaml
# See https://redis-py.readthedocs.io/en/latest/connections.html#redis.Redis
# for the full list of supported parameters
redis:
  host: redis-host
  port: 6379
  username: redis-user
  password: redis-pass
```

## nginx

If you want to access your Platypush web panel outside your home network, it may
be a good idea to use an nginx/Apache reverse proxy with a valid SSL certificate
(e.g. managed by certbot). A [sample an nginx
configuration](https://git.platypush.tech/platypush/platypush/src/branch/master/examples/nginx/nginx.sample.conf)
is provided in the repository.
