This guide provides a full Ansible playbook to deploy Homebox with Docker Compose on Debian 10+, Ubuntu LTS, and RHEL 9+ compatible hosts.
---
- name: Deploy Homebox
hosts: homebox
become: true
vars:
app_root: /opt/homebox
app_port: 3100
timezone: "America/New_York"
homebox_image: "ghcr.io/sysadminsmedia/homebox:latest"
tasks:
- name: Install Docker on Debian/Ubuntu
apt:
name:
- docker.io
- docker-compose-plugin
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Docker on RHEL family
package:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: Add docker group
group:
name: docker
state: present
- name: Add ansible user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
when: ansible_user is defined
- name: Enable and start Docker
systemd:
name: docker
state: started
enabled: yes
- name: Create application directory
file:
path: "{{ app_root }}"
state: directory
mode: "0755"
owner: "{{ ansible_user | default('root') }}"
group: "{{ ansible_user | default('root') }}"
- name: Create data directory
file:
path: "{{ app_root }}/data"
state: directory
mode: "0755"
owner: "65532" # For rootless image
group: "65532"
- name: Write Docker Compose file
template:
src: docker-compose.yml.j2
dest: "{{ app_root }}/docker-compose.yml"
mode: "0644"
notify: restart homebox
- name: Start application stack
command: docker compose up -d
args:
chdir: "{{ app_root }}"
register: docker_up_result
- name: Wait for Homebox to be ready
wait_for:
port: "{{ app_port }}"
delay: 10
timeout: 60
delegate_to: localhost
handlers:
- name: restart homebox
command: docker compose restart
args:
chdir: "{{ app_root }}"
Create a template file at templates/docker-compose.yml.j2:
version: '3.8'
services:
homebox:
image: {{ homebox_image }}
container_name: homebox
restart: unless-stopped
ports:
- "{{ app_port }}:7745"
environment:
- TZ={{ timezone }}
- HBOX_MODE=production
- HBOX_SERVER_PUBLIC_URL={{ public_url }}
- HBOX_DB_TYPE=sqlite
- HBOX_DB_SQLITE_FILE=/data/data.db
- HBOX_OPTIONS_ALLOW_REGISTRATION=true # Set to false after initial setup
- HBOX_OPTIONS_DEFAULT_ROLE=user
- HBOX_WEB_MAX_UPLOAD_SIZE=10 # Max upload size in MB
- HBOX_LOG_LEVEL=info
- HBOX_RATE_LIMIT_GENERAL=100 # General request rate limit
- HBOX_RATE_LIMIT_AUTHENTICATION=5 # Auth rate limit
volumes:
- ./data:/data
networks:
- homebox-net
networks:
homebox-net:
driver: bridge
For production deployments with additional security and configuration:
---
- name: Deploy Homebox with Security Hardening
hosts: homebox
become: true
vars:
app_root: /opt/homebox
app_port: 3100
timezone: "America/New_York"
homebox_image: "ghcr.io/sysadminsmedia/homebox:latest-rootless" # Use rootless image
public_url: "https://homebox.example.com"
tasks:
- name: Install Docker on Debian/Ubuntu
apt:
name:
- docker.io
- docker-compose-plugin
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Docker on RHEL family
package:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start Docker
systemd:
name: docker
state: started
enabled: yes
- name: Create application directory
file:
path: "{{ app_root }}"
state: directory
mode: "0755"
- name: Create data directory with proper permissions
file:
path: "{{ app_root }}/data"
state: directory
mode: "0755"
owner: "65532" # Non-root user for rootless image
group: "65532"
- name: Write secure Docker Compose file
template:
src: docker-compose-secure.yml.j2
dest: "{{ app_root }}/docker-compose.yml"
mode: "0644"
notify: restart homebox
- name: Start application stack
command: docker compose up -d
args:
chdir: "{{ app_root }}"
- name: Wait for Homebox to be ready
wait_for:
port: "{{ app_port }}"
delay: 10
timeout: 60
delegate_to: localhost
handlers:
- name: restart homebox
command: docker compose restart
args:
chdir: "{{ app_root }}"
version: '3.8'
services:
homebox:
image: {{ homebox_image }}
container_name: homebox
restart: unless-stopped
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /run
ports:
- "{{ app_port }}:7745"
environment:
- TZ={{ timezone }}
- HBOX_MODE=production
- HBOX_SERVER_PUBLIC_URL={{ public_url }}
- HBOX_DB_TYPE=sqlite
- HBOX_DB_SQLITE_FILE=/data/data.db
- HBOX_OPTIONS_ALLOW_REGISTRATION=false # Disabled after initial setup
- HBOX_LOG_LEVEL=info
- HBOX_SESSION_SECRET=very-long-random-string-here # Required for production
- HBOX_SESSION_SECURE_COOKIE=true # Required when using HTTPS reverse proxy
- HBOX_RATE_LIMIT_GENERAL=100 # General request rate limit
- HBOX_RATE_LIMIT_AUTHENTICATION=5 # Auth rate limit
volumes:
- ./data:/data:rw # Only data directory is writable
- /etc/localtime:/etc/localtime:ro # Read-only system time
networks:
- homebox-net
# Drop all capabilities for additional security
cap_drop:
- ALL
networks:
homebox-net:
driver: bridge
After running the playbook:
http://your-server-ip:3100 (or your configured port)HBOX_OPTIONS_ALLOW_REGISTRATION=false in your configurationghcr.io/sysadminsmedia/homebox:latest-rootless) for enhanced security.Any questions?
Feel free to contact us. Find all contact information on our contact page.