Install with Docker
Run Epilykos with Docker Compose on any system that runs Docker.
Install on a Raspberry Pi
Flash EpilykosOS to a microSD card and finish setup in your browser.
First-run setup
The setup wizard, the admin password and the pages you'll use.
Epilykos comes as a ready-made Docker image, irunmole/epilykos:latest, built for 64-bit x86 and ARM
(amd64 and arm64). If a computer runs Docker and stays switched on, it can run Epilykos: Windows
or macOS with Docker Desktop, a Linux PC or server, a NAS, or a Raspberry Pi with a 64-bit OS.
What you need
- Docker with Compose: Docker Desktop on Windows and macOS, or Docker Engine with the Compose plugin on Linux.
- For Bluetooth batteries or inverter modules, a Linux host with a Bluetooth adapter and BlueZ running.
- For RS232 or RS-485 equipment, a USB serial adapter.
On Docker Desktop (Windows, macOS), hardware takes extra steps
Docker Desktop runs containers inside a virtual machine. Anything Epilykos reaches over the network (Wi-Fi dongles, Modbus-TCP, Home Assistant, MQTT, REST APIs, and Tuya devices you add by hand) works as normal. USB serial adapters can be passed through with USB/IP, Bluetooth needs a Linux host, and Tuya discovery may not work. The details are in Docker Desktop on Windows and macOS.
Install
Get the compose file
Make a folder for Epilykos and download the compose file into it:
mkdir epilykos && cd epilykos
curl -fsSLO https://raw.githubusercontent.com/ashipaek0/Epilykos/main/docker-compose.yamlEverything Epilykos stores ends up in a data folder next to this file.
Decide how the admin password is set (optional)
Normally, whoever opens the setup wizard first chooses the admin password. That's fine if you're the
first one there. If other people can reach this computer before you've finished setup, set the
password in the compose file instead: uncomment the environment: line and the SETTINGS_PASSWORD=
line under it, and type your password after the =.
environment:
- SETTINGS_PASSWORD=choose-a-long-passwordA .env file won't work
This compose file doesn't pass a .env file into the container, so a SETTINGS_PASSWORD written
in .env is simply ignored. Put it under environment: as shown above.
Make it at least 12 characters long, because remote access won't accept a shorter admin password. If
the password contains a $, write it as $$: Compose treats a single $ as the start of a
variable, so pa$word would arrive as pa, and a password that starts with $ would arrive empty.
A password set this way can't be changed from Settings. To change it, edit the compose file and run
docker compose up -d again.
Start Epilykos
docker compose up -dRun the setup wizard
Open http://localhost:3000/setup in a browser on the same computer, or
http://<this-computer>:3000/setup from another device on your network, for example
http://192.168.1.10:3000/setup. The setup wizard walks you
through the password, your equipment and a first dashboard.
The compose file
services:
epilykos:
image: irunmole/epilykos:latest
container_name: epilykos
restart: unless-stopped
ports:
- "3000:3000" # Ignored with network_mode: host (the app then listens on host port 3000)
# - "5279:5279" # Growatt SPF stick (Growatt dongle profile): it pushes its data to this port. Not needed with network_mode: host.
volumes:
- ./data:/app/data
- /etc/localtime:/etc/localtime:ro # The container follows this computer's time zone.
- /run/dbus:/run/dbus:ro # Bluetooth BMS / inverter Bluetooth modules: talk to the host's BlueZ over D-Bus.
# "Update now" in Settings → Updates. This gives Epilykos full control of Docker on
# this computer (it could start any container), so only keep it if you want one-click
# updates. Without it, update with: docker compose pull && docker compose up -d
- /var/run/docker.sock:/var/run/docker.sock
security_opt:
- "apparmor=unconfined" # Lets the container reach the host's Bluetooth service on Ubuntu; harmless elsewhere.
# ── Option: USB serial adapter (RS232 / RS485 inverter or wired BMS) and/or the Bluetooth group.
# Uncomment `group_add:` and only the lines you need (at least one), and `devices:` with its line.
# Add one line to `devices` per adapter. Docker refuses to start if a listed device does not exist.
# devices:
# - "/dev/ttyUSB0:/dev/ttyUSB0"
# group_add:
# - "dialout" # Serial port permission.
# - "108" # The host's bluetooth group ID, from `getent group bluetooth`; only if Settings says "D-Bus denied access to BlueZ".
# ── Option: the admin password and/or a time zone other than this computer's.
# Uncomment `environment:` and only the lines you need (at least one). A .env file is not passed
# to the container, so environment variables go here. Write a "$" in a value as "$$".
# environment:
# - SETTINGS_PASSWORD= # Admin password, typed after the "=". The setup wizard then asks for it; only this file can change it.
# - TZ=Europe/London
# ── Option: host networking, only for Tuya LAN broadcast discovery (then `ports` above is ignored).
# network_mode: "host"Lines that start with # are options that are switched off. To switch one on, remove the # from
every line of its block (the key and the items under it) and leave the indentation exactly as it
is. A key with nothing under it, such as devices: on its own, is an error. If you're not sure you got
it right, docker compose config either prints the file back or tells you what's wrong. Then run
docker compose up -d.
USB serial adapters
To connect an RS232 or RS-485 inverter, or a wired BMS, switch on devices: with one line per adapter,
and group_add: with dialout so Epilykos is allowed to use them. These lines start out switched off
because Docker refuses to start the container if a listed device doesn't exist.
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
group_add:
- "dialout"Adapters can change names when you unplug and replug them. ls /dev/serial/by-id/ shows names that
stay the same; you can use one of those on the left-hand side instead.
On Docker Desktop, the adapter first has to be handed to Docker; see USB adapters on Docker Desktop.
Bluetooth
Bluetooth batteries and inverter modules work out of the box on a Linux host (not on Docker Desktop).
Epilykos uses the computer's own Bluetooth adapter through BlueZ, over the /run/dbus line that's
already switched on.
- BlueZ has to be running with the adapter powered on:
systemctl status bluetoothshould say active, andbluetoothctl showshould sayPowered: yes. - If Settings reports D-Bus denied access to BlueZ, switch on
group_add:and add the host'sbluetoothgroup ID, whichgetent group bluetoothtells you. - On Ubuntu, the
security_opt: apparmor=unconfinedline that's already in the file lets the container reach Bluetooth.
Time zone
Daily totals roll over at midnight in the container's time zone, which by default follows the
computer's (that's the /etc/localtime line). To use a different one, switch on environment: with a
TZ= line. The first lines of the log show which time zone is active.
On Docker Desktop, set TZ anyway; see Time zone on Docker Desktop.
One-click updates
The docker.sock line lets Settings → Updates → Update now download a new image and restart
Epilykos on it. It also gives Epilykos full control over Docker on this computer. If you'd rather not
allow that, remove the line and update with the commands under Updating.
Tuya discovery
Tuya devices announce themselves with broadcasts on your local network. Those only reach the container
when it uses host networking on a Linux host, so switch on network_mode: "host" if you want
discovery. The dashboard is then on port 3000 of the computer, and the ports: lines are ignored. On
Docker Desktop, see Tuya discovery on Docker Desktop.
Docker Desktop on Windows and macOS
Docker Desktop runs your containers inside a small virtual machine, so the computer's own hardware doesn't reach Epilykos directly. Anything Epilykos talks to over the network (Wi-Fi dongles, Modbus-TCP, Home Assistant, MQTT, REST APIs, and Tuya devices with known addresses) works without any extra steps. Hardware plugged into the computer needs a little more.
USB adapters on Docker Desktop
You can pass a USB serial adapter through with USB/IP, which hands the device over to Docker's virtual machine:
- Windows with the WSL 2 backend (Docker Desktop's default): install
usbipd-win. In an administrator PowerShell,
run
usbipd listto find the adapter's bus ID,usbipd bind --busid <id>once to share it, andusbipd attach --wsl --busid <id>to attach it. It then shows up as a Linux device such as/dev/ttyUSB0, which you add underdevices:just like on Linux. - macOS, and Windows with the Hyper-V backend: follow Docker's guide, Using USB/IP with Docker Desktop. You run a USB/IP server on the computer and a privileged helper container that attaches the device, and the helper has to keep running.
Either way, the attachment doesn't survive a restart of the computer or of Docker Desktop; you'll need
to attach it again. On Windows, usbipd attach --wsl --busid <id> --auto-attach keeps reattaching for
as long as it runs. The common adapter chips (CH340, CP210x, FTDI) usually work, but neither Docker
nor Microsoft promises that every device will.
For a Modbus inverter on RS-485, there's a simpler route: an RS-485 to Ethernet gateway avoids USB altogether and works with any Docker host. See Modbus.
Bluetooth on Docker Desktop
This isn't possible on Docker Desktop. Epilykos talks to the computer's Bluetooth service (BlueZ), and Docker Desktop's virtual machine doesn't have one. For Bluetooth batteries and inverter modules, run Docker on Linux or use EpilykosOS.
Tuya discovery on Docker Desktop
Docker Desktop 4.34 and later can use host networking if you switch it on (Settings → Resources → Network → Enable host networking). It passes TCP and UDP connections through rather than putting the container on your network, though, so Tuya's broadcast announcements may still not arrive. If discovery finds nothing, enter each device's IP address yourself; see Tuya.
Time zone on Docker Desktop
Set TZ under environment:. The /etc/localtime line may not carry your computer's time zone into
the container on Docker Desktop.
Updating
docker compose pull && docker compose up -dIf you kept the Docker socket line, Settings → Updates can do this for you. See Updates and system.
The latest tag follows releases. If you'd like to try what's coming next, irunmole/epilykos:dev
follows the development builds.
Environment variables
Any of these can go under environment: in the compose file.
| Variable | Default | What it does |
|---|---|---|
SETTINGS_PASSWORD | not set | The admin password; use at least 12 characters and write $ as $$. While it's set, the password can't be changed in Settings. |
TZ | the computer's | The time zone for daily totals, for example Africa/Lagos. |
PORT | 3000 | The port Epilykos listens on inside the container. |
LOG_LEVEL | info | How much to log at start: debug, info, warn or error. A level chosen in Settings → Logs takes over. |
LOG_TO_FILE | true | Set to false to log only to the container's output, for read-only setups. |
LOG_DIR | logs/ | Where log files go when file logging is on. |
SQLITE_SYNCHRONOUS | NORMAL | How carefully the database writes: NORMAL, FULL or EXTRA (OFF isn't allowed). |
TMPDIR | /tmp | Temporary folder for uploads, such as restoring a backup or importing a layout. |
BLUETOOTH | on | Set to off to switch Bluetooth off even when /run/dbus is mounted. |
BLE_KEEP_ALIVE | true | Keeps Bluetooth connections open between reads. false reconnects every time: slower, but frees up the adapter. |
BLE_MAX_LINKS | 1 | How many Bluetooth devices stay connected at once. Raise it if your adapter copes well with several. |
BLE_LOG_LEVEL | WARNING | How much the Bluetooth helper logs; use INFO or DEBUG when chasing a problem with a device. |
UPDATE_CHECK | on | Set to off to never check for updates. |
SESSION_SECRET | generated | The secret for sign-in sessions. If it isn't set, one is generated and kept in data/session-secret. |
RESET_TWO_STEP | not set | true switches two-step sign-in off every time Epilykos starts. Remove it and run docker compose up -d again once you're back in. See Security. |
Health check
GET /healthz works without signing in. It answers 200 {"status":"ok",…} once Epilykos is running
and its database has opened properly, and 503 if not. It doesn't depend on the internet, so a box
without a connection still counts as healthy. Docker uses it as the image's HEALTHCHECK.
What's in the data folder
| Path | What it is |
|---|---|
data/energy.db | The database: your settings, layouts and history. |
data/snapshots/ | The automatic daily snapshots of the database (the two newest are kept). |
data/settings-password | The admin password, hashed (not used when SETTINGS_PASSWORD is set). |
data/encryption-key | The key that encrypts your saved passwords and tokens. |
data/two-step.json | Two-step sign-in, when it's switched on. |
data/session-secret | The secret for sign-in sessions. |
data/tailscale/ | Tailscale's state, when remote access is on. |
A backup downloaded from Settings contains only the database. To move an installation with its saved
passwords intact, keep a copy of the whole data folder as well; see
Backup and restore.
Last updated on