This guide explains how to run TeamPass using Docker and Docker Compose.
- Prerequisites
- Quick Start
- Installation Wizard
- Configuration
- SSL/HTTPS Setup
- Upgrading
- Backup and Restore
- Troubleshooting
- Advanced Usage
- Docker Engine 20.10+ or Docker Desktop
- Docker Compose 2.0+
- At least 2 GB of free disk space
Add your user to the docker group before any operation:
sudo usermod -aG docker $USER
newgrp docker # or close/re-open the terminalWithout this, all Docker commands will fail with "permission denied".
git clone https://github.com/nilsteampassnet/TeamPass.git
cd TeamPass/docker/docker-composecp .env.example .envEdit .env and set your passwords:
nano .envMinimum required changes:
DB_PASSWORD=YourSecureDBPassword
MARIADB_ROOT_PASSWORD=YourSecureRootPassworddocker compose up -dThe first run downloads images (~300 MB) and initializes the database. Wait ~30 seconds.
TeamPass needs a directory to store its master encryption key. This directory must exist
and be writable by the PHP-FPM process (nginx user inside the container).
docker exec teampass-app sh -c "mkdir -p /var/TeampassSecurity && chown nginx:nginx /var/TeampassSecurity && chmod 750 /var/TeampassSecurity"Persistence warning: This directory is inside the container and will be lost if the container is recreated (
docker compose down -v). For production, mount it as a volume (see Advanced Usage).
Open your browser: http://localhost:8080/install/install.php
See Installation Wizard for field values.
docker compose restart teampassFill in the installation form with these values:
| Field | Value |
|---|---|
| Absolute path of the application | /var/www/html |
| URL of the application | http://localhost:8080 |
| Absolute path to secure key | /var/TeampassSecurity |
| Saltkey absolute path | /var/www/html/sk |
| Database host | db |
| Database port | 3306 |
| Database name | teampass (or DB_NAME from .env) |
| Database login | teampass (or DB_USER from .env) |
| Database password | value of DB_PASSWORD from .env |
| Table prefix | teampass_ |
The database host must be
db(Docker service name), notlocalhost.
All configuration is managed via the .env file in docker/docker-compose/.
DB_NAME=teampass # Database name
DB_USER=teampass # Database user
DB_PASSWORD=YourSecurePassword! # Database password
DB_PREFIX=teampass_ # Table prefix
MARIADB_ROOT_PASSWORD=YourRootPassword! # MariaDB root password
MARIADB_VERSION=11.2 # MariaDB image versionTEAMPASS_PORT=8080 # External port
TEAMPASS_URL=http://localhost:8080 # Public URL (used in installer)PHP_MEMORY_LIMIT=512M
PHP_UPLOAD_MAX_FILESIZE=100M
PHP_MAX_EXECUTION_TIME=120INSTALL_MODE=manual # manual (default) or autoDocker Hub (teampass/teampass) provides:
| Tag | Description |
|---|---|
latest |
Latest build from master branch |
master |
Same as latest |
develop |
Development branch |
sha-xxxxxxx |
Specific commit build |
3.1.5.2, 3.1.6.x |
Versioned releases (published on GitHub Release only) |
For testing, use latest. Versioned tags only appear after a GitHub Release is published.
| Volume | Container path | Purpose |
|---|---|---|
teampass-sk |
/var/www/html/storage/sk |
Saltkey file |
teampass-files |
/var/www/html/storage/files |
Uploaded files |
teampass-upload |
/var/www/html/storage/upload |
Temporary uploads |
teampass-config |
/var/www/html/storage/config |
Install state (settings.php, csrfp.config.php) |
teampass-secrets |
/var/www/html/secrets |
Defuse master key |
teampass-db |
/var/lib/mysql |
Database data |
teampass-configandteampass-secretsare required: without them TeamPass loses its install state and master key on container recreation and tries to reinstall itself on every restart.
- Edit
.env:
VIRTUAL_HOST=teampass.example.com
LETSENCRYPT_HOST=teampass.example.com
LETSENCRYPT_EMAIL=admin@example.com
TEAMPASS_URL=https://teampass.example.com- Start with the proxy configuration:
docker compose -f docker-compose.with-proxy.yml up -dRequirements: domain pointing to your server, ports 80 and 443 open.
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}-
Backup your data first (see Backup and Restore)
-
Pull the new image and restart:
docker compose pull
docker compose down
docker compose up -d
downwithout-vpreserves your data volumes.
Database:
docker exec teampass-db mariadb-dump \
-u root -pYourRootPassword \
teampass > teampass-backup-$(date +%Y%m%d).sqlFiles:
docker run --rm \
-v docker-compose_teampass-sk:/sk:ro \
-v docker-compose_teampass-files:/files:ro \
-v $(pwd):/backup \
alpine tar czf /backup/teampass-files-$(date +%Y%m%d).tar.gz /sk /filesDatabase:
docker exec -i teampass-db mariadb \
-u root -pYourRootPassword \
teampass < teampass-backup-20240315.sqlFiles:
docker run --rm \
-v docker-compose_teampass-sk:/sk \
-v docker-compose_teampass-files:/files \
-v $(pwd):/backup \
alpine tar xzf /backup/teampass-files-20240315.tar.gzpermission denied while trying to connect to the Docker daemon socket
Fix:
sudo usermod -aG docker $USER
newgrp dockerThis error occurs when the installer sets an empty SSL array, which causes mysqli to fail over TCP connections (required in Docker). It does not occur on traditional (non-Docker) installations because PHP uses Unix sockets there.
Workaround (already applied in latest image): The installer files run.step3.php
through run.step6.php must have DB::$ssl = null instead of an empty SSL array.
If you encounter this on an older image, patch the files manually:
for f in run.step3.php run.step4.php run.step5.php run.step6.php; do
docker exec teampass-app sed -i \
'/DB::\$ssl = array(/,/);/c\ DB::$ssl = null;' \
/var/www/html/install/install-steps/$f
doneAfter changing DB_PASSWORD in .env, you must destroy the database volume to force
MariaDB to reinitialize with the new password:
docker compose down -v # destroys all volumes including database
docker compose up -dIf you don't use
-v, MariaDB ignores the new password (existing data files take precedence).
WSL2 does not support O_DIRECT for InnoDB. The docker/mariadb/custom.cnf is already
configured with innodb_flush_method = fsync to work around this. If you see:
InnoDB: liburing disabled: falling back to innodb_use_native_aio=OFF
This is normal on WSL2 and does not affect functionality.
# All services
docker compose logs -f
# TeamPass only
docker compose logs -f teampass
# MariaDB only
docker compose logs -f db
# PHP errors
docker exec teampass-app cat /var/log/php_errors.log
# Nginx errors
docker exec teampass-app cat /var/log/nginx/teampass-error.logdocker compose ps
curl http://localhost:8080/healthdocker compose down -v
docker compose up -dTeamPass 3.2 stores its install state and master key under:
/var/www/html/secrets— Defuse master key (saltkey)/var/www/html/storage/config—settings.phpandcsrfp.config.php
The provided docker-compose.yml already mounts teampass-secrets and
teampass-config for these paths, so the installation survives container
recreation out of the box. If you maintain your own compose file, make sure
both volumes are present:
services:
teampass:
volumes:
- teampass-sk:/var/www/html/storage/sk
- teampass-files:/var/www/html/storage/files
- teampass-upload:/var/www/html/storage/upload
- teampass-config:/var/www/html/storage/config
- teampass-secrets:/var/www/html/secrets
volumes:
teampass-config:
driver: local
teampass-secrets:
driver: localWithout these volumes TeamPass loses its configuration on docker compose down
and shows the installer again on the next start.
Create docker/php/custom.ini and mount it:
volumes:
- ../../docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini:roRemove the db service from docker-compose.yml and update:
DB_HOST=mysql.example.com
DB_PORT=3306# TeamPass container
docker exec -it teampass-app sh
# Database container
docker exec -it teampass-db mariadb -u root -pYourRootPassword# Start
docker compose -f docker/docker-compose/docker-compose.yml --env-file docker/docker-compose/.env up -d
# Stop (keep data)
docker compose -f docker/docker-compose/docker-compose.yml down
# Stop and destroy all data
docker compose -f docker/docker-compose/docker-compose.yml down -v
# Restart TeamPass only
docker compose -f docker/docker-compose/docker-compose.yml restart teampass
# Pull latest image
docker compose -f docker/docker-compose/docker-compose.yml pull
# Container stats
docker stats teampass-app teampass-db- Documentation: https://documentation.teampass.net
- Docker Hub: https://hub.docker.com/r/teampass/teampass
- GitHub: https://github.com/nilsteampassnet/TeamPass
- Issues: https://github.com/nilsteampassnet/TeamPass/issues
Last updated: 2026-03-11 Tested with: TeamPass 3.1.6+ / Docker Compose 2.x / MariaDB 11.2