This guide provides a full Ansible playbook to deploy Umami with Docker Compose on Debian 10+, Ubuntu LTS, and RHEL 9+ compatible hosts. With Umami v3 (released December 2024), note that PostgreSQL is now the only supported database - MySQL support has been removed.
- name: Deploy Umami
hosts: umami
become: true
vars:
app_root: /opt/umami
app_port: 3000 # Umami v3 default port
umami_version: "postgresql-v3.0.3" # Specify version for production
postgres_host: "localhost" # Update with your PostgreSQL host
postgres_user: "umami"
postgres_db: "umami"
postgres_password: "your_secure_password" # Use Ansible Vault for production
app_secret: "generate_a_secure_app_secret" # Use Ansible Vault for production
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
dnf:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Add ansible user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
notify: restart ssh
- name: Create application directory
file:
path: "{{ app_root }}"
state: directory
mode: "0755"
- name: Create environment file
template:
src: umami.env.j2
dest: "{{ app_root }}/.env"
mode: "0600" # Restrictive permissions for secrets
notify: restart_umami
- name: Write Docker Compose file
template:
src: docker-compose.yml.j2
dest: "{{ app_root }}/docker-compose.yml"
mode: "0644"
notify: restart_umami
- name: Initialize database schema
command: docker compose run --rm app npx prisma migrate deploy
args:
chdir: "{{ app_root }}"
register: db_init
retries: 5
delay: 10
until: db_init.rc == 0
notify: restart_umami
- name: Start application stack
command: docker compose up -d
args:
chdir: "{{ app_root }}"
handlers:
- name: restart_umami
command: docker compose restart
args:
chdir: "{{ app_root }}"
- name: restart ssh
service:
name: ssh
state: restarted
Create this template file at templates/umami.env.j2:
# Database Configuration (PostgreSQL only in Umami v3)
UMAMI_DB_TYPE=postgresql
UMAMI_DB_HOST={{ postgres_host }}
UMAMI_DB_PORT=5432
UMAMI_DB_USER={{ postgres_user }}
UMAMI_DB_NAME={{ postgres_db }}
UMAMI_DB_PASSWORD={{ postgres_password }}
# Application Settings
UMAMI_APP_SECRET={{ app_secret }}
UMAMI_URL={{ inventory_hostname }}
# Additional Configuration
UMAMI_RESET_TIMEZONE=UTC
UMAMI_DISABLE_COOKIE=true
Create this template file at templates/docker-compose.yml.j2:
version: '3.8'
services:
app:
image: ghcr.io/umami/umami:{{ umami_version }}
restart: unless-stopped
ports:
- "{{ app_port }}:3000"
environment:
- DATABASE_URL=postgresql://{{ postgres_user }}:{{ postgres_password }}@{{ postgres_host }}:5432/{{ postgres_db }}
- APP_SECRET={{ app_secret }}
depends_on:
- db
volumes:
- ./config.json:/app/config/config.json:ro
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/api/website"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:15-alpine
restart: unless-stopped
environment:
- POSTGRES_DB={{ postgres_db }}
- POSTGRES_USER={{ postgres_user }}
- POSTGRES_PASSWORD={{ postgres_password }}
volumes:
- umami-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U {{ postgres_user }} -d {{ postgres_db }}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
umami-db-data:
For production deployments, store sensitive information using Ansible Vault:
# Create encrypted variables file
ansible-vault create group_vars/umami/vault.yml
# Add sensitive variables
vault_postgres_password: "your_secure_password"
vault_app_secret: "generate_a_secure_app_secret"
Then reference these in your playbook:
vars:
postgres_password: "{{ vault_postgres_password }}"
app_secret: "{{ vault_app_secret }}"
Example inventory file (inventory.ini):
[umami]
analytics-server ansible_host=192.168.1.100 ansible_user=ubuntu
[umami:vars]
postgres_host=localhost
postgres_user=umami
postgres_db=umami
# Run with vault password prompt
ansible-playbook -i inventory.ini umami-playbook.yml --ask-vault-pass
# Or if using a vault password file
ansible-playbook -i inventory.ini umami-playbook.yml --vault-password-file ~/.vault_pass
postgresql-v3.0.3)Common issues and solutions:
Any questions?
Feel free to contact us. Find all contact information on our contact page.