Skip to content

Portainer

Alexander Elchlepp edited this page Jul 8, 2026 · 7 revisions

Deploying fewohbee with Portainer

This guide describes how to deploy fewohbee using Portainer CE.

Table of Contents


Prerequisites

  • Portainer CE is installed and running
  • A Docker environment is configured in Portainer

Creating the Stack

Step 1 – Add Stack

In Portainer, navigate to Stacks → Add Stack.

  • Name: e.g. fewohbee
  • Build method: Repository

Step 2 – Repository Settings

Field Value
Repository URL https://github.com/developeregrem/fewohbee-dockerized
Repository reference refs/heads/master
Compose path docker-compose.yml (standard, with SSL) or docker-compose.no-ssl.yml (reverse proxy, no SSL)

Which compose file to choose?

  • docker-compose.yml — for servers with direct internet access. Manages SSL certificates automatically (self-signed or Let's Encrypt) via the acme container.
  • docker-compose.no-ssl.yml — for servers behind an external reverse proxy (Traefik, Nginx Proxy Manager, Caddy, etc.) that terminates SSL. The web container only listens on plain HTTP.

Step 3 – Environment Variables

Add all required variables under Environment variables. Use the .env.dist file in the repository as a reference for all available variables and their default values.

Infrastructure variables (required to start the stack):

Variable Description
HOST_NAME Hostname of your server, e.g. fewohbee or yourdomain.tld
TZ Timezone, e.g. Europe/Berlin
MARIADB_ROOT_PASSWORD Database root password (generate randomly)
MARIADB_USER Database user, e.g. fewohbee
MARIADB_PASSWORD Database password (generate randomly)
MARIADB_DATABASE Database name, e.g. fewohbee
MYSQL_BACKUP_USER Backup user name, e.g. backupuser
MYSQL_BACKUP_PASSWORD Backup user password (generate randomly)
DATABASE_URL mysql://fewohbee:<MARIADB_PASSWORD>@db:3306/fewohbee; replace <MARIADB_PASSWORD> with the password in MARIADB_PASSWORD
APP_SECRET Random secret (generate: openssl rand -base64 23)
SELF_SIGNED true to use a self-signed certificate (only for docker-compose.yml)
LETSENCRYPT false unless you want a Let's Encrypt certificate
LETSENCRYPT_DOMAINS Your domain(s) for the certificate
EMAIL Your e-mail for Let's Encrypt expiry notifications
LISTEN_PORT HTTP port exposed by the web container (only for docker-compose.no-ssl.yml), e.g. 80

For all application settings (language, mailer, passkey, salutations, etc.) refer to the Configuration page and .env.dist.

Step 4 – Deploy

Click Deploy the stack. Portainer will clone the repository, pull the referenced images, and start all containers.

Note: The PHP container clones and sets up the fewohbee application on first start. This takes approximately 1–2 minutes. The database container also needs a moment to initialize. Wait until all containers show status running before continuing.

Initialize the Application

Once all containers are running, the application must be initialized once to create the first admin user and load required base data.

Important: The PHP container clones the application and runs database migrations on first start. This takes approximately 1–2 minutes. Before proceeding, check the Logs of the php container and wait until you see ready to handle connections. Running the command below too early will fail.

  1. In Portainer, navigate to Containers and click on the php container.

  2. Open the Exec Console tab.

  3. Configure the console:

    • Command: /bin/sh
    • User: www-data
  4. Click Connect, then run:

    php bin/console app:first-run

    Follow the interactive prompts to create the first admin user.

  5. Open the application in your browser: https://<HOST_NAME>

If SELF_SIGNED=true is set, your browser will show a security warning on first visit. Accept it to proceed to the login page.

Database Backups

Backups created inside the database container are stored in the named Docker volume db-backup-vol. You can browse them directly in Portainer under Volumes → db-backup-vol → Browse.

Database backup user

The backup commands below use the dedicated database backup user (MYSQL_BACKUP_USER) instead of the database root user.

Make sure both MYSQL_BACKUP_USER and MYSQL_BACKUP_PASSWORD are configured in Portainer under Environment variables. See Infrastructure variables.

The backup user is normally created during the first start of the database container. In Portainer CE, this step may be skipped due to a bind-mount limitation. If backups fail with an access error, create the user manually via the db container Exec Console (as root):

mariadb -u root --password="$MARIADB_ROOT_PASSWORD" -e \
  "GRANT LOCK TABLES, SELECT ON *.* TO '$MYSQL_BACKUP_USER'@'%' IDENTIFIED BY '$MYSQL_BACKUP_PASSWORD';"

Restore commands still use the database root user because restoring imports data into the database and requires write permissions.

Running a manual backup

Open the Exec Console of the db container (as root) and run:

mariadb-dump -u "$MYSQL_BACKUP_USER" --password="$MYSQL_BACKUP_PASSWORD" "$MARIADB_DATABASE" | gzip > /dbbackup/manual_backup.sql.gz

Running an automated host backup

For automated backups, run the dump from the Docker host instead of from the Portainer Exec Console.

  1. In Portainer, navigate to Containers and copy the name of the database container. It is usually similar to fewohbee-dockerized-db-1.

  2. On the Docker host, create a directory for the backup files:

    sudo mkdir -p /opt/fewohbee-backups/db
  3. Test the backup command manually. Replace fewohbee-dockerized-db-1 with your actual database container name:

    docker exec fewohbee-dockerized-db-1 /bin/sh -c 'mariadb-dump -u"$MYSQL_BACKUP_USER" --password="$MYSQL_BACKUP_PASSWORD" "$MARIADB_DATABASE" | gzip' > /opt/fewohbee-backups/db/backup_$(date +%F).sql.gz

    The single quotes around the container command are intentional: the environment variables are expanded inside the database container, not on the Docker host.

  4. Add a daily cron job on the Docker host, for example with sudo crontab -e:

    0 3 * * * /usr/bin/docker exec fewohbee-dockerized-db-1 /bin/sh -c 'mariadb-dump -u"$MYSQL_BACKUP_USER" --password="$MYSQL_BACKUP_PASSWORD" "$MARIADB_DATABASE" | gzip' > /opt/fewohbee-backups/db/backup_$(date +\%F).sql.gz 2>> /var/log/fewohbee-db-backup.log

    Adjust /usr/bin/docker if Docker is installed elsewhere. You can check the path with:

    command -v docker

    In cron, the % in date +%F must be escaped as \%.

Optional retention example, keeping 30 days of backups:

30 3 * * * find /opt/fewohbee-backups/db -name 'backup_*.sql.gz' -mtime +30 -delete

Restoring a backup

Restoring imports data into the current database. Create a fresh backup before restoring if the current state might still be needed.

To restore a backup from the Portainer backup volume, open the Exec Console of the db container (as root) and run:

# List available backups
ls /dbbackup

# Decompress and restore
gunzip < /dbbackup/<file>.sql.gz | mariadb -u root --password="$MARIADB_ROOT_PASSWORD" "$MARIADB_DATABASE"

To restore a host backup created by the automated command, run this on the Docker host. Replace the container name and backup file path as needed:

gunzip < /opt/fewohbee-backups/db/backup_YYYY-MM-DD.sql.gz | docker exec -i fewohbee-dockerized-db-1 /bin/sh -c 'mariadb -uroot --password="$MARIADB_ROOT_PASSWORD" "$MARIADB_DATABASE"'

Clone this wiki locally