Install Monica CRM with Docker-Compose, Apache Proxy and Let’s encrypt certificate on Ubuntu 18.04

Table of Contents


    Heads Up! This article might be heavily outdated and will most probably not be updated anymore!

    This is a step-to step instruction for getting Monica CRM up and running.

    Monica CRM is a self-hosted OpenSource solution to keep track of your personal relationships and great for keeping a personal Journal or Diary. It denotes itself as “PRM” or “Personal Relationship Management“. You can try it out for free on the hosted version of Monica.

    Despite using the official documentation and Docker-Container for Monica installing it behind an Apache Proxy was not that straight forward. The official documentation leaves some blanks.

    Target audience of this guide

    This guide is meant for people who already have a server with DNS, Docker, Docker-Compose, an Apache Webserver as Reverse Proxy and Certbot installed and configured.


    [Edit: 2021-08-06]

    Check this gitlab repository for up-to-date ressources of this tutorial.

    pipeline status

    Especially to get Monica’s notification E-Mails working I hat to build a Docker image using Supervisord. The Image extends the official Monica Docker image and is built automatically every week.

    Need help?

    If you need help/support hosting your own instance of monica, or you want me to host an instance for you, don’t hesitate to contact me via E-Mail, or leave a comment here.

    Step 1: DNS entries

    Make sure, you have your DNS server configured to resolve the final Domain Name of your Monica installation and point to your Apache reverse Proxy. In this guide we will use the DNS-Name “” . This is always the first step for me since DNS-Propagation might take some time, depending on your setup.

    Step 2: Create Apache Virtual Host Config

    This is the apache config file /etc/apache2/sites-available/ . Let’s encrypt will add some stuff in the next step. You might want to modify the port 8123. This port-number will be used later on in the docker-compose.yml File.

    File (Apache Config)

    <VirtualHost *:80>
        ProxyPreserveHost On
        ProxyRequests Off
        ProxyPass / http://localhost:8123/ retry=1
        ProxyPassReverse / http://localhost:8123/
        RequestHeader add X-Forwarded-Proto https

    The configuration RequestHeader add X-Forwarded-Proto https is important for Monica to work properly.

    Heads up! You might add some lines to the Apache config-file for Let’s Encrypt’s ACME-Challenge to work. I have a dedicated Virtual Host for the /.well-known/acme-challenge folder which handles that for me. Let me know in the comments if you are interested in that solution.

    Run the fololowing commands on the host machine to enable the Virtual host:

    sudo a2ensite
    sudo systemctl restart apache2

    Step 3: Enable HTTPS with Let’s Encrypt’s Certbot

    Run certbot to enable HTTPS for your Domain Make sure you select the option to “redirect all requests to HTTPS” when asked by certbot.

    sudo certbot --apache -d

    After that step there should be a new Apache Config file. Here how both of the files might look like:


    <VirtualHost *:80>
        ProxyPreserveHost On
        ProxyRequests Off
        ProxyPass / http://localhost:8123/ retry=1
        ProxyPassReverse / http://localhost:8123/
        RequestHeader add X-Forwarded-Proto https
    RewriteEngine on
    RewriteCond %{SERVER_NAME}
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]


    This file is generated by certbot

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
        ProxyPreserveHost On
        ProxyRequests Off
        ProxyPass / http://localhost:8123/ retry=1
        ProxyPassReverse / http://localhost:8123/
        RequestHeader add X-Forwarded-Proto https
    SSLCertificateFile /etc/letsencrypt/live/
    SSLCertificateKeyFile /etc/letsencrypt/live/
    Include /etc/letsencrypt/options-ssl-apache.conf

    Step 4: Create Docker ressources

    You might change the folder /dockers/monica/ in the following chapters to wherever you like to keep your Docker ressources.

    File docker-compose.yml

    Make sure the port 8123 corresponds with the port in your Apache Config. I prefer to use MariaDB instead of mysql. You might want to change mariadb:10.6 to mysql:5.7.

    For the sake of simplicity I keep the databasename monica and database username usermonica in it’s default settings. The variables for ${MYSQL_ROOT_PASSWORD} and ${MYSQL_PASSWORD} are taken from the file .env. See below.

    Monica Notification E-Mails: See this Gitlab Repository for an Docker image which enables sending Monica’s notification E-Mails

    version: "3.4"
        image: monica
        env_file: .env-monica
          - db 
          - db
          - ""
          - ./mydata/storage:/var/www/html/storage
        restart: always
        image: mariadb:10.6
          - MYSQL_DATABASE=monica
          - MYSQL_USER=usermonica
          - ./mydata/mysql:/var/lib/mysql
        restart: always

    File .env

    In the file /dockers/monica/.env we keep our databse secrets. Replace the strings [REPLACE_THIS_WITH_A_SECURE_PASSWORD] with secure passwords. You might want to use an Online Password Generator to create secure passwords.


    File .env-monica

    This is the config file for the Container named “app“. It’s referencd in docker-compose.yml (see above).

    Replace the value of APP_URL with the domainname you set up before..
    Replace the strings [REPLACE_THIS_WITH_A_SECURE_PASSWORD] with secure passwords. (Online Password Generator). The password for APP_KEY must be 32 characters long.
    Keep an eye on the variable APP_TRUSTED_PROXIES. I figured that many people forget to set this properly.

    # Welcome, friend. Thanks for trying out Monica. We hope you'll have fun.
    # Two choices: local|production. Use local if you want to install Monica as a
    # development version. Use production otherwise.
    # true if you want to show debug information on errors. For production, put this
    # to false.
    # The encryption key. This is the most important part of the application. Keep
    # this secure otherwise, everyone will be able to access your application.
    # Must be 32 characters long exactly.
    # Use `php artisan key:generate` or `echo -n 'base64:'; openssl rand -base64 32` to generate a random key.
    # Prevent information leakage by referring to IDs with hashIds instead of
    # the actual IDs used in the database.
    # The URL of your application.
    # Force using APP_URL as base url of your application.
    # You should not need this, unless you are using subdirectory config.
    # Database information
    # To keep this information secure, we urge you to change the default password
    # Currently only "mysql" compatible servers are working
    # You can use mysql unix socket if available, it overrides DB_HOST and DB_PORT values.
    # Use utf8mb4 database charset format to support emoji characters
    # ⚠ be sure your DBMS supports utf8mb4 format
    # Mail credentials used to send emails from the application.
    # Outgoing emails will be sent with these identity
    MAIL_FROM_NAME="Monica Example"
    # New registration notification sent to this email
    # Ability to disable signups on your instance.
    # Can be true or false. Default to false.
    # Enable user email verification.
    # Set trusted proxy IP addresses.
    # To trust all proxies that connect directly to your server, use a "*".
    # To trust one or more specific proxies that connect directly to your server,
    # use a comma separated list of IP addresses.
    # Enable automatic cloudflare trusted proxy discover
    # Frequency of creation of new log files. Logs are written when an error occurs.
    # Refer to config/logging.php for the possible values.
    # Error tracking. Specific to hosted version on .com. You probably don't need
    # those.
    # Send a daily ping to to check if a new version
    # is available. When a new version is detected, you will have a message in the
    # UI, as well as the release notes for the new changes. Can be true or false.
    # Default to true.
    # Cache, session, and queue parameters
    # ⚠ Change this only if you know what you are doing
    #. Cache: database, file, memcached, redis, dynamodb
    #. Session: file, cookie, database, apc, memcached, redis, array
    #. Queue: sync, database, beanstalkd, sqs, redis
    #  If Queue is not set to 'sync', you'll have to set a queue worker
    #  See
    # If you use redis, set the redis host or ip, like:
    # Maximum allowed size for uploaded files, in kilobytes.
    # Make sure this is an integer, without commas or spaces.
    # Maximum allowed storage size per account, in megabytes.
    # Make sure this is an integer, without commas or spaces.
    # Default filesystem to store uploaded files.
    # Possible values: public|s3
    # AWS keys for S3 when using this storage method
    # Set to true if you use S3 and need path style URL support for bucket access
    # The default is to use virtual-hosted style URLs which may not work everywhere
    # Allow Two Factor Authentication feature on your instance
    # Enable DAV support
    # CLIENT ID and SECRET used for OAuth authentication
    # Allow to access general statistics about your instance through a public API
    # call
    # Indicates that each user in the instance must comply to international policies
    # like CASL or GDPR
    # Enable geolocation services
    # This is used to translate addresses to GPS coordinates.
    # API key for geolocation services
    # We use LocationIQ ( to translate addresses to
    # latitude/longitude coo0rdinates. We could use Google instead but we don't
    # want to give anything to Google, ever.
    # LocationIQ offers 10,000 free requests per day.
    # Enable weather on contact profile page
    # Weather can only be fetched if we know longitude/latitude - this is why
    # you also need to activate the geolocation service above to make it work
    # Access to weather data from darksky api
    # Darksky provides an api with 1000 free API calls per day
    # You need to enable the weather above if you provide an API key here.

    Create data-directory

    Run the following command in the folder /dockers/monica/ to create the data directory. This must be the same as in the docker-compose.yml file.

    mkdir mydata

    Step 5: First startup and setup

    Start containers with docker-compose

    So let’s start the containers and attach to the logs.

    docker-compose up -d && docker-compose logs -f

    Be patient! Wait a few minutes(!) when first booting up the containers. Ignore the “Can’t connect to database…” errors. The database needs some time to ramp-up. Give it a few minutes!

    Now you can quit the log-tail by pressing Ctrl+C

    Run the setup script once

    Now run the setup with the following command. You have to confirm to start the setup procedure by pressing the key y.

    docker-compose exec app php artisan setup:production

    Clear cache

    It’s important to clear the cache after you run the setup! It seems many user ran into this, left alone with an unworking installation.

    docker-compose exec app php artisan config:cache

    Step 6: Create first user and make it an admin

    Now it’s time to open your Domain in the browser and you should see an Login/Registration form. Create a user. After that make that user an admin by executing the following command

    docker-compose exec app php artisan monica:admin

    There is no admin interface implemented yet, but once it’s here, your user is already prepared. But it’s a planned feature (see this Github Issue)

    Step 7: Something went wrong

    Stop the containers and delete the data directory. To begin with a fresh start.

    docker-compose down
    sudo rm -rf ./mydata
    mkdir data

    After that Repeat Step 5: First startup and setup.

    Your opinion

    Please let me know in the comments below if this tutorial helped you, to get Monica PRM up and running, or if you’re missing some information which should be added in your opinion.


    Georg Abenthung

    Working in IT since 2004.

    Leave a Reply

    Your email address will not be published. Required fields are marked *