<h1>Installation<aclass="headerlink"href="#installation"title="Permalink to this headline">¶</a></h1>
<p>This application is written in Python (API) and Javascript (client):</p>
<ulclass="simple">
<li><dlclass="simple">
<dt>API:</dt><dd><ul>
<li><p>Flask</p></li>
<li><p><aclass="reference external"href="https://github.com/tkrajina/gpxpy">gpxpy</a> to parse gpx files</p></li>
<li><p><aclass="reference external"href="https://github.com/komoot/staticmap">staticmap</a> to generate a static map image from gpx coordinates</p></li>
<li><p><aclass="reference external"href="https://github.com/ZeevG/python-forecast.io">python-forecast.io</a> to fetch weather data from <aclass="reference external"href="https://darksky.net">Dark Sky</a> (former forecast.io)</p></li>
<li><p><aclass="reference external"href="https://flask-dramatiq.readthedocs.io/en/latest/">dramatiq</a> for task queue</p></li>
</ul>
</dd>
</dl>
</li>
<li><dlclass="simple">
<dt>Client:</dt><dd><ul>
<li><p>React/Redux</p></li>
<li><p><aclass="reference external"href="https://leafletjs.com/">Leaflet</a> to display map</p></li>
<li><p><aclass="reference external"href="https://github.com/recharts/recharts">Recharts</a> to display charts with elevation and speed</p></li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>Sports and weather icons are made by <aclass="reference external"href="https://www.freepik.com/">Freepik</a> from <aclass="reference external"href="https://www.flaticon.com/">www.flaticon.com</a>.</p>
<divclass="section"id="prerequisites">
<h2>Prerequisites<aclass="headerlink"href="#prerequisites"title="Permalink to this headline">¶</a></h2>
<ulclass="simple">
<li><p>PostgreSQL database (10+)</p></li>
<li><p>Redis for task queue</p></li>
<li><p>Python 3.7+</p></li>
<li><p><aclass="reference external"href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li>
<li><p>API key from <aclass="reference external"href="https://darksky.net/dev">Dark Sky</a> [not mandatory]</p></li>
<li><p>SMTP provider</p></li>
<li><p><aclass="reference external"href="https://yarnpkg.com">Yarn</a> (for development only)</p></li>
<li><p>Docker (for development only, to start <aclass="reference external"href="https://github.com/mailhog/MailHog">MailHog</a>)</p></li>
</ul>
<divclass="admonition note">
<pclass="admonition-title">Note</p>
<divclass="line-block">
<divclass="line">The following steps describe an installation on Linux systems (tested
on Debian and Arch).</div>
<divclass="line">On other OS, some issues can be encountered and adaptations may be
necessary.</div>
</div>
</div>
</div>
<divclass="section"id="environment-variables">
<h2>Environment variables<aclass="headerlink"href="#environment-variables"title="Permalink to this headline">¶</a></h2>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<divclass="line-block">
<divclass="line">Since FitTrackee 0.4.0, <codeclass="docutils literal notranslate"><spanclass="pre">Makefile.custom.config</span></code> is replaced by <codeclass="docutils literal notranslate"><spanclass="pre">.env</span></code></div>
</div>
</div>
<p>The following environment variables are used by <strong>FitTrackee</strong> web application
or the task processing library. They are not all mandatory depending on
deployment method.</p>
<dlclass="std envvar">
<dtid="envvar-FLASK_APP">
<codeclass="sig-name descname">FLASK_APP</code><aclass="headerlink"href="#envvar-FLASK_APP"title="Permalink to this definition">¶</a></dt>
<dd><divclass="line-block">
<divclass="line">Name of the module to import at flask run.</div>
<divclass="line"><codeclass="docutils literal notranslate"><spanclass="pre">FLASK_APP</span></code> should contain <codeclass="docutils literal notranslate"><spanclass="pre">$(PWD)/fittrackee/__main__.py</span></code> with installation from sources, else <codeclass="docutils literal notranslate"><spanclass="pre">fittrackee</span></code>.</div>
</div>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-HOST">
<codeclass="sig-name descname">HOST</code><aclass="headerlink"href="#envvar-HOST"title="Permalink to this definition">¶</a></dt>
<dd><p><strong>FitTrackee</strong> host.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>0.0.0.0</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-PORT">
<codeclass="sig-name descname">PORT</code><aclass="headerlink"href="#envvar-PORT"title="Permalink to this definition">¶</a></dt>
<dd><p><strong>FitTrackee</strong> port.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>5000</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-APP_SETTINGS">
<codeclass="sig-name descname">APP_SETTINGS</code><aclass="headerlink"href="#envvar-APP_SETTINGS"title="Permalink to this definition">¶</a></dt>
<codeclass="sig-name descname">APP_SECRET_KEY</code><aclass="headerlink"href="#envvar-APP_SECRET_KEY"title="Permalink to this definition">¶</a></dt>
<dd><p><strong>FitTrackee</strong> secret key, must be initialized in production environment.</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-APP_WORKERS">
<codeclass="sig-name descname">APP_WORKERS</code><aclass="headerlink"href="#envvar-APP_WORKERS"title="Permalink to this definition">¶</a></dt>
<dd><p>Number of workers spawned by <strong>Gunicorn</strong>.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>1</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-APP_LOG">
<spanid="envvar-APP_LOG 🆕"></span><codeclass="sig-name descname">APP_LOG 🆕</code><aclass="headerlink"href="#envvar-APP_LOG"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
</div>
<p>Path to log file</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-UPLOAD_FOLDER">
<spanid="envvar-UPLOAD_FOLDER 🆕"></span><codeclass="sig-name descname">UPLOAD_FOLDER 🆕</code><aclass="headerlink"href="#envvar-UPLOAD_FOLDER"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
<divclass="line">With installation from PyPI, the directory will be located in
<strong>virtualenv</strong> directory if the variable is not initialized.</div>
</div>
</div>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-DATABASE_URL">
<codeclass="sig-name descname">DATABASE_URL</code><aclass="headerlink"href="#envvar-DATABASE_URL"title="Permalink to this definition">¶</a></dt>
<dd><divclass="line-block">
<divclass="line">Database URL with username and password, must be initialized in production environment.</div>
<divclass="line">For example in dev environment : <codeclass="docutils literal notranslate"><spanclass="pre">postgres://fittrackee:fittrackee@localhost:5432/fittrackee</span></code></div>
</div>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-DATABASE_DISABLE_POOLING">
<spanid="envvar-DATABASE_DISABLE_POOLING 🆕"></span><codeclass="sig-name descname">DATABASE_DISABLE_POOLING 🆕</code><aclass="headerlink"href="#envvar-DATABASE_DISABLE_POOLING"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
</div>
<p>Disable pooling if needed (when starting application with <strong>FitTrackee</strong> entry point and not directly with <strong>Gunicorn</strong>),
see <aclass="reference external"href="https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork">SqlAlchemy documentation</a>.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>false</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-UI_URL">
<codeclass="sig-name descname">UI_URL</code><aclass="headerlink"href="#envvar-UI_URL"title="Permalink to this definition">¶</a></dt>
<dd><p><strong>FitTrackee</strong> URL, needed for links in emails.</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-EMAIL_URL">
<codeclass="sig-name descname">EMAIL_URL</code><aclass="headerlink"href="#envvar-EMAIL_URL"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.3.0.</span></p>
</div>
<p>Email URL with credentials, see <aclass="reference external"href="installation.html#emails">Emails</a>.</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-SENDER_EMAIL">
<codeclass="sig-name descname">SENDER_EMAIL</code><aclass="headerlink"href="#envvar-SENDER_EMAIL"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.3.0.</span></p>
<codeclass="sig-name descname">WORKERS_PROCESSES</code><aclass="headerlink"href="#envvar-WORKERS_PROCESSES"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.3.0.</span></p>
</div>
<p>Number of processes used by <strong>Dramatiq</strong>.</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-TILE_SERVER_URL">
<spanid="envvar-TILE_SERVER_URL 🆕"></span><codeclass="sig-name descname">TILE_SERVER_URL 🆕</code><aclass="headerlink"href="#envvar-TILE_SERVER_URL"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
</div>
<p>Tile server URL (with api key if needed), see <aclass="reference external"href="installation.html#map-tile-server">Map tile server</a>.</p>
<spanid="envvar-MAP_ATTRIBUTION 🆕"></span><codeclass="sig-name descname">MAP_ATTRIBUTION 🆕</code><aclass="headerlink"href="#envvar-MAP_ATTRIBUTION"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
</div>
<p>Map attribution (if using another tile server), see <aclass="reference external"href="installation.html#map-tile-server">Map tile server</a>.</p>
<codeclass="sig-name descname">WEATHER_API_KEY</code><aclass="headerlink"href="#envvar-WEATHER_API_KEY"title="Permalink to this definition">¶</a></dt>
<dd><divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 0.4.0: </span>⚠️ replaces <codeclass="docutils literal notranslate"><spanclass="pre">WEATHER_API</span></code></p>
</div>
<p><strong>Dark Sky</strong> API key for weather data (not mandatory).</p>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_API_URL">
<codeclass="sig-name descname">REACT_APP_API_URL</code><aclass="headerlink"href="#envvar-REACT_APP_API_URL"title="Permalink to this definition">¶</a></dt>
<dd><p><strong>FitTrackee</strong> API URL, only needed in dev environment.</p>
</dd></dl>
<divclass="section"id="deprecated-variables">
<h3>Deprecated variables<aclass="headerlink"href="#deprecated-variables"title="Permalink to this headline">¶</a></h3>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_GPX_LIMIT_IMPORT">
<codeclass="sig-name descname">REACT_APP_GPX_LIMIT_IMPORT</code><aclass="headerlink"href="#envvar-REACT_APP_GPX_LIMIT_IMPORT"title="Permalink to this definition">¶</a></dt>
<dd><divclass="deprecated">
<p><spanclass="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
</div>
<p>Maximum number of gpx file in zip archive.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>10</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_MAX_SINGLE_FILE_SIZE">
<codeclass="sig-name descname">REACT_APP_MAX_SINGLE_FILE_SIZE</code><aclass="headerlink"href="#envvar-REACT_APP_MAX_SINGLE_FILE_SIZE"title="Permalink to this definition">¶</a></dt>
<dd><divclass="deprecated">
<p><spanclass="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
</div>
<p>Maximum size of a gpx or picture file.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>1MB</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_MAX_ZIP_FILE_SIZE">
<codeclass="sig-name descname">REACT_APP_MAX_ZIP_FILE_SIZE</code><aclass="headerlink"href="#envvar-REACT_APP_MAX_ZIP_FILE_SIZE"title="Permalink to this definition">¶</a></dt>
<dd><divclass="deprecated">
<p><spanclass="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
</div>
<p>Maximum size of a zip archive.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>10MB</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_ALLOW_REGISTRATION">
<codeclass="sig-name descname">REACT_APP_ALLOW_REGISTRATION</code><aclass="headerlink"href="#envvar-REACT_APP_ALLOW_REGISTRATION"title="Permalink to this definition">¶</a></dt>
<dd><divclass="deprecated">
<p><spanclass="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
</div>
<p>Allows users to register.</p>
<dlclass="field-list simple">
<dtclass="field-odd">Default</dt>
<ddclass="field-odd"><p>true</p>
</dd>
</dl>
</dd></dl>
<dlclass="std envvar">
<dtid="envvar-REACT_APP_THUNDERFOREST_API_KEY">
<codeclass="sig-name descname">REACT_APP_THUNDERFOREST_API_KEY</code><aclass="headerlink"href="#envvar-REACT_APP_THUNDERFOREST_API_KEY"title="Permalink to this definition">¶</a></dt>
<dd><divclass="deprecated">
<p><spanclass="versionmodified deprecated">Deprecated since version 0.4.0: </span>see <aclass="reference external"href="installation.html#envvar-TILE_SERVER_URL">TILE_SERVER_URL</a></p>
</div>
<p>ThunderForest API key.</p>
</dd></dl>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<divclass="line-block">
<divclass="line">Since FitTrackee 0.3.0, some applications parameters are now stored in database.</div>
<divclass="line">Related environment variables are needed to initialize database when upgrading from version prior 0.3.0.</div>
</div>
</div>
</div>
<divclass="section"id="emails">
<h3>Emails<aclass="headerlink"href="#emails"title="Permalink to this headline">¶</a></h3>
<divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.3.0.</span></p>
</div>
<p>To send emails, a valid <codeclass="docutils literal notranslate"><spanclass="pre">EMAIL_URL</span></code> must be provided:</p>
<ulclass="simple">
<li><p>with an unencrypted SMTP server: <codeclass="docutils literal notranslate"><spanclass="pre">smtp://username:password@smtp.example.com:25</span></code></p></li>
<h3>Map tile server<aclass="headerlink"href="#map-tile-server"title="Permalink to this headline">¶</a></h3>
<divclass="versionadded">
<p><spanclass="versionmodified added">New in version 0.4.0.</span></p>
</div>
<p>Default tile server is now <strong>OpenStreetMap</strong>’s standard tile layer (if environment variables are not initialized).
The tile server can be changed by updating <codeclass="docutils literal notranslate"><spanclass="pre">TILE_SERVER_URL</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">MAP_ATTRIBUTION</span></code> variables (<aclass="reference external"href="https://wiki.openstreetmap.org/wiki/Tile_servers">list of tile servers</a>).</p>
<p>To keep using <strong>ThunderForest Outdoors</strong>, the configuration is:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX</span></code> where <strong>XXXX</strong> is <strong>ThunderForest</strong> API key</p></li>
<li><p>Initialize environment variables, see <aclass="reference external"href="installation.html#environment-variables">Environment variables</a></p></li>
</ul>
<p>For instance, copy and update <codeclass="docutils literal notranslate"><spanclass="pre">.env</span></code> file from <codeclass="docutils literal notranslate"><spanclass="pre">.env.example</span></code> and source the file.</p>
<divclass="line">To start application and workers with <strong>systemd</strong> service, see <aclass="reference external"href="installation.html#deployment">Deployment</a></div>
</div>
</div>
</div>
<divclass="section"id="upgrade">
<h3>Upgrade<aclass="headerlink"href="#upgrade"title="Permalink to this headline">¶</a></h3>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<divclass="line-block">
<divclass="line">Before upgrading, make a backup of all data:</div>
<divclass="line">- database (with <aclass="reference external"href="https://www.postgresql.org/docs/11/app-pgdump.html">pg_dump</a> for instance)</div>
<divclass="line">- upload directory (see <aclass="reference external"href="installation.html#environment-variables">Environment variables</a>)</div>
<li><p>Create <strong>Makefile.custom.config</strong> from example and update it
(see <aclass="reference external"href="installation.html#environment-variables">Environment variables</a>).</p></li>
<li><p>Install Python virtualenv, React and all related packages and
initialize the database:</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make install-dev
$ make install-db
</pre></div>
</div>
<ulclass="simple">
<li><p>Start the server and the client:</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make serve
</pre></div>
</div>
<ulclass="simple">
<li><p>Run dramatiq workers:</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make run-workers
</pre></div>
</div>
<p>Open <aclass="reference external"href="http://localhost:3000">http://localhost:3000</a> and log in (the email is <codeclass="docutils literal notranslate"><spanclass="pre">admin@example.com</span></code>
and the password <codeclass="docutils literal notranslate"><spanclass="pre">mpwoadmin</span></code>) or register</p>
</div>
<divclass="section"id="production-environment">
<h4>Production environment<aclass="headerlink"href="#production-environment"title="Permalink to this headline">¶</a></h4>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<divclass="line-block">
<divclass="line">Note that FitTrackee is under heavy development, some features may be unstable.</div>
</div>
</div>
<ulclass="simple">
<li><p>Download the last release (for now, it is the release v0.4.0):</p></li>
<li><p>Create <strong>Makefile.custom.config</strong> from example and update it
(see <aclass="reference external"href="installation.html#environment-variables">Environment variables</a>).</p></li>
<li><p>Install Python virtualenv and all related packages:</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make install-python
</pre></div>
</div>
<ulclass="simple">
<li><p>Initialize the database (<strong>after updating</strong><codeclass="docutils literal notranslate"><spanclass="pre">db/create.sql</span></code><strong>to change
database credentials</strong>):</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make install-db
</pre></div>
</div>
<ulclass="simple">
<li><p>Start the server and dramatiq workers:</p></li>
</ul>
<divclass="highlight-bash notranslate"><divclass="highlight"><pre><span></span>$ make run
</pre></div>
</div>
<p>Open <aclass="reference external"href="http://localhost:5000">http://localhost:5000</a>, log in as admin (the email is
<codeclass="docutils literal notranslate"><spanclass="pre">admin@example.com</span></code> and the password <codeclass="docutils literal notranslate"><spanclass="pre">mpwoadmin</span></code>) and change the
password</p>
</div>
</div>
<divclass="section"id="id3">
<h3>Upgrade<aclass="headerlink"href="#id3"title="Permalink to this headline">¶</a></h3>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<divclass="line-block">
<divclass="line">Before upgrading, make a backup of all data:</div>
<divclass="line">- database (with <aclass="reference external"href="https://www.postgresql.org/docs/11/app-pgdump.html">pg_dump</a> for instance)</div>
<divclass="line">- upload directory (see <aclass="reference external"href="installation.html#environment-variables">Environment variables</a>)</div>
</div>
</div>
<divclass="section"id="id4">
<h4>Dev environment<aclass="headerlink"href="#id4"title="Permalink to this headline">¶</a></h4>
<ulclass="simple">
<li><p>Stop the application and pull the repository:</p></li>