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

Table of Contents

    Introduction

    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.

    Ressources

    [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 “monica.example.com” . 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/monica.example.com.conf . 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 monica.example.com.conf (Apache Config)

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

    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 monica.example.com.conf
    sudo systemctl restart apache2

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

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

    sudo certbot --apache -d monica.example.com

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

    File monica.example.com.conf

    <VirtualHost *:80>
        ServerName monica.example.com
        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} =monica.example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>

    File monica.example.com-le-ssl.conf

    This file is generated by certbot

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

    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"
    
    services:
      app:
        image: monica
        env_file: .env-monica
        depends_on:
          - db 
        links:
          - db
        ports:
          - "127.0.0.1:8123:80"
        volumes:
          - ./mydata/storage:/var/www/html/storage
        restart: always
      db:
        image: mariadb:10.6
        environment:
          - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
          - MYSQL_DATABASE=monica
          - MYSQL_USER=usermonica
          - MYSQL_PASSWORD=${MYSQL_PASSWORD}
        volumes:
          - ./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.

    MYSQL_PASSWORD=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]
    MYSQL_ROOT_PASSWORD=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]

    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.
    APP_ENV=production
    
    # true if you want to show debug information on errors. For production, put this
    # to false.
    APP_DEBUG=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.
    APP_KEY=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]
    
    # Prevent information leakage by referring to IDs with hashIds instead of
    # the actual IDs used in the database.
    HASH_SALT=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]
    HASH_LENGTH=18
    
    # The URL of your application.
    APP_URL=https://monica.example.com
    
    # Force using APP_URL as base url of your application.
    # You should not need this, unless you are using subdirectory config.
    APP_FORCE_URL=false
    
    # Database information
    # To keep this information secure, we urge you to change the default password
    # Currently only "mysql" compatible servers are working
    DB_CONNECTION=mysql
    DB_HOST=db
    DB_PORT=3306
    # You can use mysql unix socket if available, it overrides DB_HOST and DB_PORT values.
    #DB_UNIX_SOCKET=/var/run/mysqld/mysqld.sock
    DB_DATABASE=monica
    DB_USERNAME=usermonica
    DB_PASSWORD=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]
    DB_PREFIX=
    
    # Use utf8mb4 database charset format to support emoji characters
    # ⚠ be sure your DBMS supports utf8mb4 format
    DB_USE_UTF8MB4=true
    
    # Mail credentials used to send emails from the application.
    MAIL_MAILER=smtp
    MAIL_HOST=smtp.example.it
    MAIL_PORT=587
    MAIL_USERNAME=noreply@example.com
    MAIL_PASSWORD=[REPLACE_THIS_WITH_A_SECURE_PASSWORD]
    MAIL_ENCRYPTION=TLS
    # Outgoing emails will be sent with these identity
    MAIL_FROM_ADDRESS=noreply@example.com
    MAIL_FROM_NAME="Monica Example"
    # New registration notification sent to this email
    APP_EMAIL_NEW_USERS_NOTIFICATION=someaddress@example.com
    
    # Ability to disable signups on your instance.
    # Can be true or false. Default to false.
    APP_DISABLE_SIGNUP=false
    
    # Enable user email verification.
    APP_SIGNUP_DOUBLE_OPTIN=false
    
    # 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.
    APP_TRUSTED_PROXIES=*
    
    # Enable automatic cloudflare trusted proxy discover
    APP_TRUSTED_CLOUDFLARE=false
    
    # Frequency of creation of new log files. Logs are written when an error occurs.
    # Refer to config/logging.php for the possible values.
    LOG_CHANNEL=daily
    
    # Error tracking. Specific to hosted version on .com. You probably don't need
    # those.
    SENTRY_SUPPORT=false
    SENTRY_LARAVEL_DSN=
    
    # Send a daily ping to https://version.monicahq.com 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.
    CHECK_VERSION=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 https://laravel.com/docs/5.7/queues#running-the-queue-worker
    CACHE_DRIVER=database
    SESSION_DRIVER=file
    SESSION_LIFETIME=15
    QUEUE_CONNECTION=sync
    
    # If you use redis, set the redis host or ip, like:
    #REDIS_HOST=redis
    
    # Maximum allowed size for uploaded files, in kilobytes.
    # Make sure this is an integer, without commas or spaces.
    DEFAULT_MAX_UPLOAD_SIZE=10240
    
    # Maximum allowed storage size per account, in megabytes.
    # Make sure this is an integer, without commas or spaces.
    DEFAULT_MAX_STORAGE_SIZE=512
    
    # Default filesystem to store uploaded files.
    # Possible values: public|s3
    DEFAULT_FILESYSTEM=public
    
    # AWS keys for S3 when using this storage method
    AWS_KEY=
    AWS_SECRET=
    AWS_REGION=us-east-1
    AWS_BUCKET=
    AWS_SERVER=
    
    # 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
    S3_PATH_STYLE=
    
    # Allow Two Factor Authentication feature on your instance
    MFA_ENABLED=true
    
    # Enable DAV support
    DAV_ENABLED=true
    
    # CLIENT ID and SECRET used for OAuth authentication
    PASSPORT_PASSWORD_GRANT_CLIENT_ID=
    PASSPORT_PASSWORD_GRANT_CLIENT_SECRET=
    
    # Allow to access general statistics about your instance through a public API
    # call
    ALLOW_STATISTICS_THROUGH_PUBLIC_API_ACCESS=false
    
    # Indicates that each user in the instance must comply to international policies
    # like CASL or GDPR
    POLICY_COMPLIANT=false
    
    # Enable geolocation services
    # This is used to translate addresses to GPS coordinates.
    ENABLE_GEOLOCATION=false
    
    # API key for geolocation services
    # We use LocationIQ (https://locationiq.com/) 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.
    LOCATION_IQ_API_KEY=
    
    # 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
    ENABLE_WEATHER=false
    
    # Access to weather data from darksky api
    # https://darksky.net/dev/register
    # 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.
    DARKSKY_API_KEY=
    

    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 https://monica.example.com/ 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 *