# Modules

> FeatherWings modules are optional daemon features. AlwaysMOTD answers Minecraft server list pings while a server is offline, suspended, installing or starting.

Source: https://featherpanel.com/docs/wings/modules/

Modules are optional features built into the FeatherWings binary. They are off until you enable them. FeatherWings
ships one module, AlwaysMOTD.

Module state is stored in `wings.db` in `system.root_directory` (default `/var/lib/featherpanel`). On start Wings
enables every module that was enabled before, with its saved configuration.

## Managing modules

In the admin area open Nodes, edit the node and go to the Wings Modules tab. The tab is shown when the node runs
FeatherWings. Each module has an Enabled or Disabled badge, a switch, and a Configure button that opens its
configuration as JSON. You can only change the configuration while the module is disabled. Viewing needs
`admin.nodes.view`, changing needs `admin.nodes.edit`.

The panel calls these Wings endpoints, which you can also use directly with the node token from `token` in
`/etc/featherpanel/config.yml`:

```bash
TOKEN='<token from config.yml>'
WINGS='https://node.example.com:8080'

curl -s -H "Authorization: Bearer $TOKEN" "$WINGS/api/modules"
curl -s -H "Authorization: Bearer $TOKEN" "$WINGS/api/modules/AlwaysMOTD/config"
curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"config": { ... }}' "$WINGS/api/modules/AlwaysMOTD/config"
curl -s -X POST -H "Authorization: Bearer $TOKEN" "$WINGS/api/modules/AlwaysMOTD/enable"
curl -s -X POST -H "Authorization: Bearer $TOKEN" "$WINGS/api/modules/AlwaysMOTD/disable"
```

A new configuration is validated before it is applied, and saved to `wings.db`.

## AlwaysMOTD

Without this module, a Minecraft server that is stopped simply does not answer, and players see "Can't connect to
server" in their list. AlwaysMOTD answers the server list ping for the server instead, with a message that depends on
its state: `offline`, `suspended`, `installing` or `starting`. When the server is running again, the module steps
aside.

How it works:

- Every `monitoring.checkInterval` milliseconds (default 10000) it checks the allocations whose port lies in
  `portRange` (default 25565 to 25800).
- It runs one Java listener per state on `motd.port + offset` (offsets 0 to 3, so 25560 to 25563 by default) and
  adds an iptables NAT rule, tagged `featherwings-alwaysmotd`, that sends Java pings for a stopped server's port to the
  listener for its state.
- For Bedrock it binds the server's UDP port directly while the server is down, because RakNet pings do not survive
  NAT well.
- Players who try to join get disconnected with the state message.

### Configuration

| Key | Default | Meaning |
|-----|---------|---------|
| `portRange.start`, `portRange.end` | `25565`, `25800` | Ports to watch |
| `motd.port` | `25560` | Base port for the Java listeners |
| `motd.javaEnabled`, `motd.bedrockEnabled` | `true`, `true` | Answer Java or Bedrock pings |
| `motd.states.<state>` | built in | `version`, `protocol`, `maxPlayers`, `onlinePlayers`, `description`, and optional `javaDescription` and `bedrockDescription` |
| `motd.java.*` | | Disconnect message format, prefix and suffix, delays, protocol version, favicon, `showAsUnhealthy` |
| `motd.bedrock.*` | | Disconnect message format, prefix and suffix, wait times, protocol and version |
| `monitoring.checkInterval` | `10000` | Milliseconds between state checks |
| `logging.level` | `info` | `error`, `warn`, `info` or `debug` |

All four states must be present in `motd.states`, or the configuration is rejected. Descriptions accept a plain string
with `§` color codes or a Minecraft JSON text component.

The module needs `iptables` on the node and the ports in `motd.port` to `motd.port + 3` free. Disabling it removes its
NAT rules and closes the listeners.

## Frequently asked questions

### Why can I not save the configuration of a module?

The panel only lets you edit the configuration of a disabled module. Disable it, save the new JSON, then enable it again.

### Do modules stay enabled after a restart?

Yes. The enabled flag and the configuration are saved in wings.db and restored when Wings starts. A module that fails to start is marked disabled.
