Install the Box IO Docker server on CentOS
These steps install the prebuilt image ghcr.io/someone275/box_io-docker-server on CentOS Stream 9 or CentOS Stream 10. Docker runs two containers: boxio (the hub and the dashboard API) and nginx (HTTP and HTTPS). Arduino boards use HTTP port 5923. Ubuntu is on the Ubuntu page. Red Hat Enterprise Linux is on the Red Hat page. A BlueOnyx panel already owns ports 80 and 443, so use the BlueOnyx page there.
Replace boxio.example.com with the dashboard name, and user with the SSH account. Do not put the SSH password, the JWT secret, SMTP passwords, or Twilio tokens in git.
1. Point DNS and forward the ports
- Add an A record for
boxio.example.com. The value is the router’s public WAN address. - From a phone with Wi-Fi off,
ping boxio.example.commust answer from that WAN address. - Forward TCP
80,443, and5923from the router to this CentOS machine. UDP is not required.
2. Sign in and update CentOS
ssh user@boxio.example.com
sudo dnf -y upgrade
3. Install Docker Engine
This installs Docker Engine and the Compose plugin from Docker’s CentOS repository. CentOS Stream uses dnf.
sudo dnf -y install dnf-plugins-core git
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker user
The docker group applies on the next login. Sign out and back in, then check both version commands:
exit
ssh user@boxio.example.com
docker version
docker compose version
4. Open firewalld
Leave SSH reachable. firewall-cmd adds the dashboard ports and the Arduino hub. If firewalld is not running, the host firewall still has to allow these ports.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=5923/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
SELinux can stay enforcing. The compose file labels the nginx files so the container can read them.
5. Copy Box IO onto the server
cd ~
git clone https://github.com/Someone275/Box_IO-Docker-server.git
cd ~/Box_IO-Docker-server
The clone holds the compose file and the HTTPS proxy. docker load installs the prebuilt image. This machine does not compile Node.
6. Create the secret file
cd ~/Box_IO-Docker-server
cp .env.example .env
openssl rand -hex 48
Open .env and set JWT_SECRET to that hex string. One line, no quotes:
JWT_SECRET=paste_the_hex_here
Save the file. Never commit .env. Projects, users, and device keys are stored in the Docker volume boxio-data.
7. Start the containers
cd ~/Box_IO-Docker-server
curl -fL -o box_io-docker-server.tar.gz https://github.com/Someone275/Box_IO-Docker-server/releases/download/v1.0.0/box_io-docker-server.tar.gz
docker load -i box_io-docker-server.tar.gz
docker compose up -d --no-build
docker compose ps
docker compose logs -f --tail=50
boxio and nginx should both say Up. The health URL on the LAN returns JSON with ok set to true. The first certificate is self-signed, so a browser warning is expected until the next step.
http://127.0.0.1:5923/health
https://boxio.example.com
8. Issue the HTTPS certificate
Let’s Encrypt has to see the public name. On the server, curl -sS http://127.0.0.1/http-ok must print boxio-http-ok. From a phone on cellular, http://boxio.example.com/http-ok must show the same text.
cd ~/Box_IO-Docker-server
chmod +x nginx/init-letsencrypt.sh nginx/ensure-certs.sh nginx/issue-cert-dns.sh
DOMAIN=boxio.example.com EMAIL=you@example.com ./nginx/init-letsencrypt.sh
If that times out, port 80 is not reachable from the internet. Use the DNS method. It prints a TXT name and value. Create that record, wait until dig shows it, then press Enter:
cd ~/Box_IO-Docker-server
EMAIL=you@example.com ./nginx/issue-cert-dns.sh
dig +short TXT _acme-challenge.boxio.example.com
9. Create the admin account
- Open
https://boxio.example.comand create the admin username and password. - Generate a device key. It starts with
bx_. Copy it into the sketch asBOXIO_AUTH. - Create a project, add widgets, Save layout, then switch to Live.
- Open License and install a trial or a paid year before pin values will show.
10. Update
cd ~/Box_IO-Docker-server
git checkout main
git pull origin main
curl -fL -o box_io-docker-server.tar.gz https://github.com/Someone275/Box_IO-Docker-server/releases/download/v1.0.0/box_io-docker-server.tar.gz
docker load -i box_io-docker-server.tar.gz
docker compose up -d --no-build
docker compose ps
git pull updates the proxy files. docker load updates the image. The volume boxio-data stays. From this directory, docker compose restart restarts the containers, and docker compose down stops them without deleting the volume. After the image is on Docker Hub, set BOXIO_IMAGE in .env and use docker compose pull instead of curl and docker load.