I’m setting up a new Home Assistant box as I’m moving from a power-hungry HP ProLiant to a more energy conserving Beelink Mini Series S.

After initially installing Proxmox, like I had on my previous system, ready to install a VM with HA OS, I realised most of what I was running in VMs could run in Docker containers as well. So I decided to install Debian and run Docker with docker-compose instead.

I’ll be documenting my process as I go, turning this is some kind of mini-series. Starting of with Part 1: Install Debian, Docker and Portainer.

Install Debian

We start of installing Debian on the box. This process is the same for just about any system.

  1. Download latest ISO.
    I pick the “Small” image as it includes most files in the image, requiring less to be downloaded during the install process.
  2. Download Balena Etcher, a tool to write ISO images to a USB drive. If you’re on a linux system, you could use dd instead.
  3. Plugin the loaded USB drive in your system and boot from USB.
  4. Follow the installation proces.
    Most of the process is following the defaults and just pressing Continue.
    !! Don’t forget the credentials you entered for the root user and the non-admin user.
    !! Just make sure you do NOT install a graphical user interface (GUI) if you’re not planning on using this as a desktop system, and you DO install the SSH server.
  5. Once the install is completed, SSH into the box using the non-admin credentials.

Install Docker and Docker Compose

Install Docker

Even though the people at Docker are pushing really hard for us to install Docker Desktop, as this requires a GUI interface (which we explicitely didn’t install) we’ll just install Docker Engine instead.

You can read through the documentation, but basically we’ll execute the following commands:

# Install prerequisites
sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \

# Add Docker repository
sudo mkdir -p /etc/apt/keyrings
curl -fsSL | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli docker-compose-plugin

Install Docker Compose

The Docker Compose documentation keeps pushing you to Docker Desktop.

Luckily, we don’t even need to download Docker Compose from GitHub as it actually came included during the installtion of Docker Engine. The only thing we need to do is link to the executable and grant execution permissions.

sudo ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose
sudo chmod u+x /usr/bin/docker-compose

Setting up permissions

Next, to simplify our lives, we allow our non-admin user (I named them sysadmin) to perform root actions using sudo, and to run docker and docker-compose.

su # enter root password
# install sudo
apt install sudo
gpasswd -a sysadmin sudo
# add sysadmin to docker group
gpasswd -a sysadmin docker

Exit SSH session and login as the non-admin user again for changes to apply.

Install Portainer


To install Portainer, we’ll create a docker-compose script which we’ll then launch to set everything up.

cd /opt
sudo nano docker-compose.yaml # or file editor of choice
# Edit file, see below
# Save and Close via Ctrl+O and Ctrl+X

Don’t forget to update the timezone in the config below.

Also, I’m storing all my Docker config and volumes in the /opt folder. This makes it easier to back everything up. These volumes will store data from the Docker image locally so the data isn’t lost when a container is rebuilt (e.g. when upgrading).

Sometimes you’ll be exposing a local file, socket or device to the Docker container so it can access said file/socket/device. Here we expose the file that holds our local time settings so Portainer knows what time it is (for log timestamps) as well as the socket that controls Docker so Container can perform actions in Docker.

version: '3.0'

    container_name: portainer
    image: portainer/portainer-ce:latest
    restart: unless-stopped
      - "9000:9000/tcp"
      - "9443:9443/tcp"
      - TZ=Europe/Brussels
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/portainer/data:/data


We’ll also allow our non-admin user to modify this file. Again, just to make our lives a little bit easier.

sudo chown root:docker docker-compose.yaml
sudo chmod g+w docker-compose.yaml

Check config

Want to make sure you made no errors in your docker-compose.yaml? Run the following command and Docker will output you what it will be running, as well as any erors in your config and warnings that are relevant.

docker-compose -f docker-compose.yaml config


We now run docker-compose up -d and Docker will download the latest Portainer image and set everything up. Once that is done we’re able to open the Portainer web interface by browsing to https://<>:9443 (you’ll get a warning about a self-signed certificate) or http://<>:9000 (non-encrypted connection).

The first time we visit this portal, it’ll ask us to create a user account. Make sure you don’t forget these credentials!

Screenshot of Portainer interface showing a running Portainer container
Portainer up and running

With this behind our back, the next step is to set up Home Assistant Container. I also plan on installing several more Docker images which will replace my old add-ons, such as Mosquitto, Frigate, Node-RED, and more. I’ll probably also install MariaDB and InfluxDB to store the recorder and history data.

Keep an eye out for Part 2 of x ;)