How to install Akeneo product inventory management software

Dick de Leeuw
5 min readJan 30, 2018

--

At Travelteq, I installed Akeneo product inventory management (PIM) on a DigitalOcean LAMP stack droplet to help us with our product management.

The current e-commerce website runs on the Magento monolith, which is not suited for today’s e-commerce challenges and is cumbersome in creating and configuring products.

A Product Information Management (PIM) system centralizes and harmonizes all your marketing and technical information for product listings and catalogs. — akeneo.com

Akeneo interface.

In our IT topology, Akeneo bridges our e-commerce platform, an ERP, our business intelligence (BI) software and our POS software.

Prerequisites

Setup a DigitalOcean ‘LAMP on 16.04 droplet’. It exists off a preinstalled and preconfigured Linux OS, Apache HTTP server, MySQL database and PHP programming language.

Akeneo requires a relatively large amount of memory, so I opted for a Droplet with ≥8GB of memory. To be precise, Elasticsearch and Java require a lot of memory.

Technical setup

See my gist or:

# date: january 2018
# author: Dick de Leeuw (dick@leeuw.studio, @leeuwd)
# prerequisites: LAMP droplet (>= 8GB RAM)
# environment: Ubuntu 16.04.3 LTS xenial, Apache/2.4.29 (Ubuntu), MySQL 5.7.21 & PHP 7.1

# create droplet

# login as root from local
ssh root@[IP]

# update
apt update
apt upgrade
apt dist-upgrade

# akeneo dependencies
apt install apt-transport-https
add-apt-repository ppa:ondrej/php
add-apt-repository ppa:ondrej/apache2
apt update
apt-get install upstart composer php7.1 php7.1-cli php7.1-common php7.1-json php7.1-opcache php7.1-mysql php7.1-mbstring php7.1-mcrypt php7.1-zip unzip php7.1-fpm php7.1-bcmath php7.1-curl php7.1-gd php7.1-intl php7.1-soap php7.1-xml php-xml php7.1-exif php7.1-imagick supervisor openjdk-8-jre-headless

# enable php 7.1
a2enmod proxy_fcgi setenvif
a2enconf php7.1-fpm
service apache2 restart

# elasticsearch (use v5, v6 won't work with akeneo!)
wget -O - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | tee -a /etc/apt/sources.list.d/elastic-5.x.list
apt update
apt install elasticsearch
sudo systemctl enable elasticsearch

# elasticsearch config
nano /etc/elasticsearch/elasticsearch.yml
# uncomment and set: cluster.name: akeneo
# uncomment and set: node.name: node-1
# save and close
sudo systemctl start elasticsearch

# test elasticsearch (wait 1 min before running this, give it time to start)
curl -X GET 'http://localhost:9200'

# java heap count
sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" | tee /etc/sysctl.d/elasticsearch.conf
systemctl restart elasticsearch

# prevent updates, those will break akeneo
apt-mark hold php7.1
apt-mark hold elasticsearch
apt-add-repository --remove ppa:ondrej/php
apt-add-repository --remove ppa:ondrej/apache2

# firewall
sudo ufw allow in "Apache Full"

# enable apache proxy modules
a2enmod rewrite proxy_fcgi

# apache config (add line)
nano /etc/apache2/apache2.conf
ServerName [HOSTNAME]

# apache php mod
nano /etc/apache2/mods-enabled/dir.conf
# move index.php to front of line
# so: DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm

# restart and check apache
systemctl restart apache2
systemctl status apache2

# set hostname
hostnamectl set-hostname '[HOSTNAME]'
# e.g. hostnamectl set-hostname 'akeneo.domain.com'

# set timezone
dpkg-reconfigure tzdata

# nodejs
curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
apt-get install -y nodejs
apt-get install -y build-essential

# yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn

# php cli config
nano /etc/php/7.1/cli/php.ini
date.timezone = [TIMEZONE]
# e.g. date.timezone = Europe/Amsterdam
# see http://php.net/manual/en/timezones.php

# php fpm config (modify lines)
nano /etc/php/7.1/fpm/php.ini
date.timezone = [TIMEZONE]
memory_limit = 1024M
post_max_size = 64M
upload_max_filesize = 64M

# swap file
sudo fallocate -l 1G /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# auto ban IPs that hack (http://denyhosts.sourceforge.net)
apt-get install denyhosts
# sudo nano /etc/denyhosts.conf for optional config

# fail2ban
sudo apt-get install fail2ban
nano /etc/fail2ban/jail.conf
# find [sshd] section
# add/set enabled = true

# htop process viewer (http://hisham.hm/htop/)
apt-get install htop
# open/test with 'htop' command

# mysql root password
cat /root/.digitalocean_password
mysql_secure_installation
# paste password in
# run installation wizard

# mysql table and user
mysql -u root -p
CREATE DATABASE akeneo_production DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE USER 'pim_usr_prod'@'localhost' IDENTIFIED BY '[PASSWORD]';
GRANT ALL PRIVILEGES ON akeneo_production.* TO 'pim_usr_prod'@'localhost';
GRANT ALL PRIVILEGES ON *.* TO root@'%' IDENTIFIED BY '[ROOT_MYSQL_PASSWORD]';
FLUSH PRIVILEGES;
quit

# allow remote mysql access (comment lines)
# decide this for youself, it's a risk but eases sysops
nano /etc/mysql/mysql.conf.d/mysqld.cnf
#skip-external-locking
#bind-address=127.0.0.1
service mysql restart

# firewall whitelist mysql
sudo ufw allow 3306/tcp
sudo service ufw restart

# final upgrades & cleanup
sudo apt upgrade
rm -rf /etc/update-motd.d/99-one-click
rm -rf /root/.digitalocean_password
apt autoremove
apt autoclean

# non-root user
adduser [USERNAME]
usermod -aG sudo [USERNAME]
su - [USERNAME]
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
ssh-keygen -t rsa -C "[EMAIL_ADDRESS]" -b 4096
cat ~/.ssh/id_rsa.pub
# save this public key somewhere, you can use it as deploy key in Github/Gitlab
exit

# now add public key auth: https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04#step-four-%E2%80%94-add-public-key-authentication-(recommended)
# e.g. from macOS: cat ~/.ssh/id_rsa.pub | ssh [USERNAME]@[IP] "cat >> ~/.ssh/authorized_keys"
# the latter only works when creating the droplet with ssh password access allowed (i.e. key not set when creating droplet)
# otherwise, on local, cat ~/.ssh/id_rsa.pub and copy key, paste into /home/[USERNAME]/.ssh/authorized_keys

# reboot (just to be sure all works fine)
reboot

# login as non-root
ssh [USERNAME]@[IP]

# filesystem
sudo mkdir -p /var/www/html/akeneo
sudo chown [USERNAME]:[USERNAME] /var/www/html/akeneo
chmod 775 /var/www/html/akeneo

# apache virtual host file
sudo rm -f /etc/apache2/sites-enabled/000-default.conf
sudo touch /etc/apache2/sites-available/akeneo_production.conf
sudo nano /etc/apache2/sites-available/akeneo_production.conf
# paste virtual host config in (see below), save and close
sudo a2enmod rewrite
sudo service apache2 restart
sudo apache2ctl configtest
sudo a2ensite akeneo_production
sudo systemctl reload apache2

# host file (add line)
sudo nano /etc/hosts
127.0.0.1 [HOSTNAME]

# akeneo source
cd /var/www/html/akeneo/web
wget https://download.akeneo.com/pim-community-standard-v2.1-latest.tar.gz
tar --strip-components=1 -zxvf pim-community-standard-v2.1-latest.tar.gz
rm -f pim-community-standard-v2.1-latest.tar.gz
mkdir -p /app/file_storage
mkdir -p /app/uploads
mkdir -p /var/media
chmod -R 777 ./app/file_storage/
chmod -R 777 ./app/uploads/
chmod -R 777 ./var/logs/
chmod -R 777 ./var/cache/
chmod -R 777 ./var/media/
composer install --optimize-autoloader --prefer-dist
yarn install

# set db credentials
sudo nano app/config/parameters.yml

# github token (https://github.com/settings/tokens)
composer config --global github-oauth.github.com "[GITHUB_TOKEN]"

# install
php bin/console cache:clear --no-warmup --env=prod
php bin/console pim:installer:assets --symlink --clean --env=prod
bin/console pim:install --force --symlink --clean --env=prod
yarn run webpack

# cron
*/15 * * * * php /var/www/html/akeneo/bin/console pim:completeness:calculate --env=prod > /var/www/html/akeneo/bin/console/var/logs/calculate_completeness.log 2>&1
*/15 * * * * php /var/www/html/akeneo/bin/console pim:versioning:refresh --env=prod > /var/www/html/akeneo/bin/console/var/logs/refresh_versioning.log 2>&1

# supervisor task runner
sudo touch /etc/supervisor/conf.d/akeneo_production.conf
sudo nano /etc/supervisor/conf.d/akeneo_production.conf
# paste supervisor config (see below) in it
supervisorctl reread
supervisorctl update
supervisorctl start akeneo_production

Apache virtual host config

# apache virtual host config file
# /etc/apache2/sites-available/akeneo_production.conf
# after change, restart apache with 'systemctl restart apache2'

<VirtualHost *:80>
ServerName [HOSTNAME]
DocumentRoot /var/www/html/akeneo/web

<Directory /var/www/html/akeneo/web>
AllowOverride None
Require all granted

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</Directory>

<Directory /var/www/html/akeneo>
Options FollowSymlinks
</Directory>

<Directory /var/www/html/akeneo/web/bundles>
RewriteEngine Off
</Directory>

<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php7.1-fpm.sock|fcgi://localhost/"
</FilesMatch>

SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
</VirtualHost>

Supervisor config

[program:akeneo_production]
command=/usr/bin/php /var/www/html/akeneo/bin/console akeneo:batch:job-queue-consumer-daemon --env=prod
autostart=false
autorestart=true
stderr_logfile=/var/log/akeneo_daemon.err.log
stdout_logfile=/var/log/akeneo_daemon.out.log
user=[USERNAME]

Deploying

I’ve setup Deployer for atomic deploys of our Akeneo software.

--

--

Dick de Leeuw

CTO @ Tellow | Previously CPO @ Bloqhouse, Head of E-commerce @ Travelteq and Lead Developer @ Ace & Tate. Passionate about disruptive digital innovation.