Files
endurain/getting-started/advanced-started/index.html
2025-12-23 12:09:59 +00:00

1658 lines
50 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="prev" href="../getting-started/">
<link rel="next" href="../bare-metal/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.22">
<title>Getting started advanced - Endurain documentation</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.84d31ad4.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
<style>:root{--md-admonition-icon--alert:url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M13%2014h-2V9h2m0%209h-2v-2h2M1%2021h22L12%202z%22/%3E%3C/svg%3E');--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M13%209h-2V7h2m0%2010h-2v-6h2m-1-9A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10A10%2010%200%200%200%2012%202%22/%3E%3C/svg%3E');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%206a6%206%200%200%201%206%206c0%202.22-1.21%204.16-3%205.2V19a1%201%200%200%201-1%201h-4a1%201%200%200%201-1-1v-1.8c-1.79-1.04-3-2.98-3-5.2a6%206%200%200%201%206-6m2%2015v1a1%201%200%200%201-1%201h-2a1%201%200%200%201-1-1v-1zm6-10h3v2h-3zM1%2011h3v2H1zM13%201v3h-2V1zM4.92%203.5l2.13%202.14-1.42%201.41L3.5%204.93zm12.03%202.13%202.12-2.13%201.43%201.43-2.13%202.12z%22/%3E%3C/svg%3E');}</style>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#default-credentials" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="Endurain documentation" class="md-header__button md-logo" aria-label="Endurain documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Endurain documentation
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Getting started advanced
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/endurain-project/endurain" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="Endurain documentation" class="md-nav__button md-logo" aria-label="Endurain documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
Endurain documentation
</label>
<div class="md-nav__source">
<a href="https://github.com/endurain-project/endurain" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Hosting Guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Hosting Guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting started easy
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Getting started advanced
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Getting started advanced
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#default-credentials" class="md-nav__link">
<span class="md-ellipsis">
Default Credentials
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#docker-deployment" class="md-nav__link">
<span class="md-ellipsis">
Docker Deployment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#supported-environment-variables" class="md-nav__link">
<span class="md-ellipsis">
Supported Environment Variables
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#session-timeout-configuration-optional" class="md-nav__link">
<span class="md-ellipsis">
Session Timeout Configuration (Optional)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#docker-secrets-support" class="md-nav__link">
<span class="md-ellipsis">
Docker Secrets Support
</span>
</a>
<nav class="md-nav" aria-label="Docker Secrets Support">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-file-based-secrets" class="md-nav__link">
<span class="md-ellipsis">
Using File-Based Secrets
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#volumes" class="md-nav__link">
<span class="md-ellipsis">
Volumes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bulk-import-and-file-upload" class="md-nav__link">
<span class="md-ellipsis">
Bulk import and file upload
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#importing-information-from-a-strava-bulk-export-beta" class="md-nav__link">
<span class="md-ellipsis">
Importing information from a Strava bulk export (BETA)
</span>
</a>
<nav class="md-nav" aria-label="Importing information from a Strava bulk export (BETA)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#importing-gear-from-a-strava-bulk-export" class="md-nav__link">
<span class="md-ellipsis">
Importing gear from a Strava bulk export
</span>
</a>
<nav class="md-nav" aria-label="Importing gear from a Strava bulk export">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#bike-import" class="md-nav__link">
<span class="md-ellipsis">
Bike import
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#shoe-import" class="md-nav__link">
<span class="md-ellipsis">
Shoe import
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#notes-on-importing-gear" class="md-nav__link">
<span class="md-ellipsis">
Notes on importing gear
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#importing-other-items-from-a-strava-bulk-import" class="md-nav__link">
<span class="md-ellipsis">
Importing other items from a Strava bulk import
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#image-personalization" class="md-nav__link">
<span class="md-ellipsis">
Image personalization
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../bare-metal/" class="md-nav__link">
<span class="md-ellipsis">
Bare-Metal installation guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://community-scripts.github.io/ProxmoxVE/scripts?id=endurain&category=Gaming+%26+Leisure" class="md-nav__link">
<span class="md-ellipsis">
Proxmox community script
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../maria-to-postgres-migration/" class="md-nav__link">
<span class="md-ellipsis">
MariaDB to Postgres migration
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
Features
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Features
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../features/single-sign-on/" class="md-nav__link">
<span class="md-ellipsis">
Single Sign-On (SSO)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../features/sleep-scoring/" class="md-nav__link">
<span class="md-ellipsis">
Sleep Scoring
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Integrations
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Integrations
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../integrations/3rd-party-apps/" class="md-nav__link">
<span class="md-ellipsis">
3rd party apps
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../integrations/3rd-party-services/" class="md-nav__link">
<span class="md-ellipsis">
3rd party services
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Developer guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Developer guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../developer-guide/setup-dev-env/" class="md-nav__link">
<span class="md-ellipsis">
Setup a development environment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../developer-guide/authentication/" class="md-nav__link">
<span class="md-ellipsis">
Authentication
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../developer-guide/supported-types/" class="md-nav__link">
<span class="md-ellipsis">
Supported types
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../gallery/" class="md-nav__link">
<span class="md-ellipsis">
Gallery
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#default-credentials" class="md-nav__link">
<span class="md-ellipsis">
Default Credentials
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#docker-deployment" class="md-nav__link">
<span class="md-ellipsis">
Docker Deployment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#supported-environment-variables" class="md-nav__link">
<span class="md-ellipsis">
Supported Environment Variables
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#session-timeout-configuration-optional" class="md-nav__link">
<span class="md-ellipsis">
Session Timeout Configuration (Optional)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#docker-secrets-support" class="md-nav__link">
<span class="md-ellipsis">
Docker Secrets Support
</span>
</a>
<nav class="md-nav" aria-label="Docker Secrets Support">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-file-based-secrets" class="md-nav__link">
<span class="md-ellipsis">
Using File-Based Secrets
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#volumes" class="md-nav__link">
<span class="md-ellipsis">
Volumes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bulk-import-and-file-upload" class="md-nav__link">
<span class="md-ellipsis">
Bulk import and file upload
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#importing-information-from-a-strava-bulk-export-beta" class="md-nav__link">
<span class="md-ellipsis">
Importing information from a Strava bulk export (BETA)
</span>
</a>
<nav class="md-nav" aria-label="Importing information from a Strava bulk export (BETA)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#importing-gear-from-a-strava-bulk-export" class="md-nav__link">
<span class="md-ellipsis">
Importing gear from a Strava bulk export
</span>
</a>
<nav class="md-nav" aria-label="Importing gear from a Strava bulk export">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#bike-import" class="md-nav__link">
<span class="md-ellipsis">
Bike import
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#shoe-import" class="md-nav__link">
<span class="md-ellipsis">
Shoe import
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#notes-on-importing-gear" class="md-nav__link">
<span class="md-ellipsis">
Notes on importing gear
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#importing-other-items-from-a-strava-bulk-import" class="md-nav__link">
<span class="md-ellipsis">
Importing other items from a Strava bulk import
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#image-personalization" class="md-nav__link">
<span class="md-ellipsis">
Image personalization
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1>Getting started advanced</h1>
<h2 id="default-credentials">Default Credentials</h2>
<ul>
<li><strong>Username:</strong> admin </li>
<li><strong>Password:</strong> admin</li>
</ul>
<h2 id="docker-deployment">Docker Deployment</h2>
<p>Endurain provides a Docker image for simplified deployment. To get started, check out the <code>docker-compose.yml.example</code> file in the project repository and adjust it according to your setup. Supported tags are:</p>
<ul>
<li><strong>latest:</strong> contains the latest released version;</li>
<li><strong>version, example "v0.3.0":</strong> contains the app state available at the time of the version specified;</li>
<li><strong>development version, example "dev_06092024":</strong> contains a development version of the app at the date specified. This is not a stable released and may contain issues and bugs. Please do not open issues if using a version like this unless asked by me.</li>
</ul>
<h2 id="supported-environment-variables">Supported Environment Variables</h2>
<p>Table below shows supported environment variables. Variables marked with optional "No" should be set to avoid errors.</p>
<table>
<thead>
<tr>
<th>Environment variable</th>
<th>Default value</th>
<th>Optional</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>UID</td>
<td>1000</td>
<td>Yes</td>
<td>User ID for mounted volumes. Default is 1000</td>
</tr>
<tr>
<td>GID</td>
<td>1000</td>
<td>Yes</td>
<td>Group ID for mounted volumes. Default is 1000</td>
</tr>
<tr>
<td>TZ</td>
<td>UTC</td>
<td>Yes</td>
<td>Timezone definition. Useful for TZ calculation for activities that do not have coordinates associated, like indoor swim or weight training. If not specified UTC will be used. List of available time zones <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">here</a>. Format <code>Europe/Lisbon</code> expected</td>
</tr>
<tr>
<td>FRONTEND_DIR</td>
<td><code>/app/frontend/dist</code></td>
<td>Yes</td>
<td>You will only need to change this value if installing using bare metal method</td>
</tr>
<tr>
<td>BACKEND_DIR</td>
<td><code>/app/backend</code></td>
<td>Yes</td>
<td>You will only need to change this value if installing using bare metal method</td>
</tr>
<tr>
<td>DATA_DIR</td>
<td><code>/app/backend/data</code></td>
<td>Yes</td>
<td>You will only need to change this value if installing using bare metal method</td>
</tr>
<tr>
<td>LOGS_DIR</td>
<td><code>/app/backend/logs</code></td>
<td>Yes</td>
<td>You will only need to change this value if installing using bare metal method</td>
</tr>
<tr>
<td>ENDURAIN_HOST</td>
<td>No default set</td>
<td><code>No</code></td>
<td>Required for internal communication and Strava. For Strava https must be used. Host or local ip (example: http://192.168.1.10:8080 or https://endurain.com)</td>
</tr>
<tr>
<td>REVERSE_GEO_PROVIDER</td>
<td>nominatim</td>
<td>Yes</td>
<td>Defines reverse geo provider. Expects <a href="https://geocode.maps.co/">geocode</a>, photon or nominatim. photon can be the <a href="https://photon.komoot.io">SaaS by komoot</a> or a self hosted version like a <a href="https://github.com/rtuszik/photon-docker">self hosted version</a>. Like photon, Nominatim can be the <a href="https://nominatim.openstreetmap.org/">SaaS</a> or a self hosted version</td>
</tr>
<tr>
<td>PHOTON_API_HOST</td>
<td>photon.komoot.io</td>
<td>Yes</td>
<td>API host for photon. By default it uses the <a href="https://photon.komoot.io">SaaS by komoot</a></td>
</tr>
<tr>
<td>PHOTON_API_USE_HTTPS</td>
<td>true</td>
<td>Yes</td>
<td>Protocol used by photon. By default uses HTTPS to be inline with what <a href="https://photon.komoot.io">SaaS by komoot</a> expects</td>
</tr>
<tr>
<td>NOMINATIM_API_HOST</td>
<td>nominatim.openstreetmap.org</td>
<td>Yes</td>
<td>API host for Nominatim. By default it uses the <a href="https://nominatim.openstreetmap.org">SaaS</a></td>
</tr>
<tr>
<td>NOMINATIM_API_USE_HTTPS</td>
<td>true</td>
<td>Yes</td>
<td>Protocol used by Nominatim. By default uses HTTPS to be inline with what <a href="https://nominatim.openstreetmap.org">SaaS</a> expects</td>
</tr>
<tr>
<td>GEOCODES_MAPS_API</td>
<td>changeme</td>
<td>Yes</td>
<td><a href="https://geocode.maps.co/">Geocode maps</a> offers a free plan consisting of 1 Request/Second. Registration necessary.</td>
</tr>
<tr>
<td>REVERSE_GEO_RATE_LIMIT</td>
<td>1</td>
<td>Yes</td>
<td>Change this if you have a paid Geocode maps tier. Other providers also use this variable. Keep it as is if you use photon or Nominatim to keep 1 request per second</td>
</tr>
<tr>
<td>DB_HOST</td>
<td>postgres</td>
<td>Yes</td>
<td>postgres</td>
</tr>
<tr>
<td>DB_PORT</td>
<td>5432</td>
<td>Yes</td>
<td>3306 or 5432</td>
</tr>
<tr>
<td>DB_USER</td>
<td>endurain</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>DB_PASSWORD</td>
<td>No default set</td>
<td><code>No</code></td>
<td>Database password. Alternatively, use <code>DB_PASSWORD_FILE</code> for Docker secrets</td>
</tr>
<tr>
<td>DB_DATABASE</td>
<td>endurain</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>SECRET_KEY</td>
<td>No default set</td>
<td><code>No</code></td>
<td>Run <code>openssl rand -hex 32</code> on a terminal to get a secret. Alternatively, use <code>SECRET_KEY_FILE</code> for Docker secrets</td>
</tr>
<tr>
<td>FERNET_KEY</td>
<td>No default set</td>
<td><code>No</code></td>
<td>Run <code>python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"</code> on a terminal to get a secret or go to <a href="https://fernetkeygen.com">https://fernetkeygen.com</a>. Example output is <code>7NfMMRSCWcoNDSjqBX8WoYH9nTFk1VdQOdZY13po53Y=</code>. Alternatively, use <code>FERNET_KEY_FILE</code> for Docker secrets</td>
</tr>
<tr>
<td>ALGORITHM</td>
<td>HS256</td>
<td>Yes</td>
<td>Currently only HS256 is supported</td>
</tr>
<tr>
<td>ACCESS_TOKEN_EXPIRE_MINUTES</td>
<td>15</td>
<td>Yes</td>
<td>Time in minutes</td>
</tr>
<tr>
<td>REFRESH_TOKEN_EXPIRE_DAYS</td>
<td>7</td>
<td>Yes</td>
<td>Time in days</td>
</tr>
<tr>
<td>SESSION_IDLE_TIMEOUT_ENABLED</td>
<td>false</td>
<td>Yes</td>
<td>Enforce idle timeouts (supported values are <code>true</code> and <code>false</code>)</td>
</tr>
<tr>
<td>SESSION_IDLE_TIMEOUT_HOURS</td>
<td>1</td>
<td>Yes</td>
<td>Time in hours</td>
</tr>
<tr>
<td>SESSION_ABSOLUTE_TIMEOUT_HOURS</td>
<td>24</td>
<td>Yes</td>
<td>Time in hours</td>
</tr>
<tr>
<td>JAEGER_ENABLED</td>
<td>false</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>JAEGER_PROTOCOL</td>
<td>http</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>JAEGER_HOST</td>
<td>jaeger</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>JAEGER_PORT</td>
<td>4317</td>
<td>Yes</td>
<td>N/A</td>
</tr>
<tr>
<td>BEHIND_PROXY</td>
<td>false</td>
<td>Yes</td>
<td>Change to true if behind reverse proxy</td>
</tr>
<tr>
<td>ENVIRONMENT</td>
<td>production</td>
<td>Yes</td>
<td><code>production</code>, <code>demo</code> and <code>development</code> allowed. <code>development</code> allows connections from localhost:8080 and localhost:5173 at the CORS level. <code>demo</code> equals to <code>production</code> except it does not return user sessions</td>
</tr>
<tr>
<td>SMTP_HOST</td>
<td>No default set</td>
<td>Yes</td>
<td>The SMTP host of your email provider. Example <code>smtp.protonmail.ch</code></td>
</tr>
<tr>
<td>SMTP_PORT</td>
<td>587</td>
<td>Yes</td>
<td>The SMTP port of your email provider. Default is 587</td>
</tr>
<tr>
<td>SMTP_USERNAME</td>
<td>No default set</td>
<td>Yes</td>
<td>The username of your SMTP email provider, probably your email address</td>
</tr>
<tr>
<td>SMTP_PASSWORD</td>
<td>No default set</td>
<td>Yes</td>
<td>The password of your SMTP email provider. Some providers allow the use of your account password, others require the creation of an app password. Please refer to your provider documentation. Alternatively, use <code>SMTP_PASSWORD_FILE</code> for Docker secrets</td>
</tr>
<tr>
<td>SMTP_SECURE</td>
<td>true</td>
<td>Yes</td>
<td>By default it uses secure communications. Accepted values are <code>true</code> and <code>false</code></td>
</tr>
<tr>
<td>SMTP_SECURE_TYPE</td>
<td>starttls</td>
<td>Yes</td>
<td>If SMTP_SECURE is set you can set the communication type. Accepted values are <code>starttls</code> and <code>ssl</code></td>
</tr>
</tbody>
</table>
<p>Table below shows the obligatory environment variables for postgres container. You should set them based on what was also set for the Endurain container.</p>
<table>
<thead>
<tr>
<th>Environemnt variable</th>
<th>Default value</th>
<th>Optional</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>POSTGRES_PASSWORD</td>
<td>changeme</td>
<td><code>No</code></td>
<td>N/A</td>
</tr>
<tr>
<td>POSTGRES_DB</td>
<td>endurain</td>
<td><code>No</code></td>
<td>N/A</td>
</tr>
<tr>
<td>POSTGRES_USER</td>
<td>endurain</td>
<td><code>No</code></td>
<td>N/A</td>
</tr>
<tr>
<td>PGDATA</td>
<td>/var/lib/postgresql/data/pgdata</td>
<td><code>No</code></td>
<td>N/A</td>
</tr>
</tbody>
</table>
<p>To check Python backend dependencies used, use poetry file (pyproject.toml).</p>
<p>Frontend dependencies:</p>
<ul>
<li>To check npm dependencies used, use npm file (package.json)</li>
<li>Logo created on Canva</li>
</ul>
<h2 id="session-timeout-configuration-optional">Session Timeout Configuration (Optional)</h2>
<p>By default, Endurain sessions last 7 days without enforcing idle timeouts.
For enhanced security, you can enable automatic session expiration:</p>
<p><strong>Environment Variables:</strong></p>
<ul>
<li><code>SESSION_IDLE_TIMEOUT_ENABLED</code>: Enable timeout enforcement (default: <code>false</code>)</li>
<li><code>SESSION_IDLE_TIMEOUT_HOURS</code>: Logout after inactivity (default: <code>1</code>)</li>
<li><code>SESSION_ABSOLUTE_TIMEOUT_HOURS</code>: Force re-login after duration (default: <code>24</code>)</li>
</ul>
<p><strong>Example:</strong></p>
<div class="highlight"><pre><span></span><code><span class="nt">environment</span><span class="p">:</span>
<span class="w"> </span><span class="nt">SESSION_IDLE_TIMEOUT_ENABLED</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;true&quot;</span>
<span class="w"> </span><span class="nt">SESSION_IDLE_TIMEOUT_HOURS</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;2&quot;</span>
<span class="w"> </span><span class="nt">SESSION_ABSOLUTE_TIMEOUT_HOURS</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;48&quot;</span>
</code></pre></div>
<h2 id="docker-secrets-support">Docker Secrets Support</h2>
<p>Endurain supports <a href="https://docs.docker.com/compose/how-tos/use-secrets/">Docker secrets</a> for securely managing sensitive environment variables. For the following environment variables, you can use <code>_FILE</code> variants that read the secret from a file instead of storing it directly in environment variables:</p>
<ul>
<li><code>DB_PASSWORD</code><code>DB_PASSWORD_FILE</code></li>
<li><code>SECRET_KEY</code><code>SECRET_KEY_FILE</code></li>
<li><code>FERNET_KEY</code><code>FERNET_KEY_FILE</code></li>
<li><code>SMTP_PASSWORD</code><code>SMTP_PASSWORD_FILE</code></li>
</ul>
<h3 id="using-file-based-secrets">Using File-Based Secrets</h3>
<p>Use file-based secrets to securely manage sensitive environment variables:</p>
<ol>
<li><strong>Create a secrets directory with proper permissions:</strong></li>
</ol>
<div class="highlight"><pre><span></span><code>mkdir<span class="w"> </span>-p<span class="w"> </span>secrets
chmod<span class="w"> </span><span class="m">700</span><span class="w"> </span>secrets
</code></pre></div>
<ol>
<li><strong>Create secret files with strong passwords:</strong></li>
</ol>
<div class="highlight"><pre><span></span><code><span class="c1"># Use randomly generated passwords, not hardcoded ones</span>
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;</span><span class="k">$(</span>openssl<span class="w"> </span>rand<span class="w"> </span>-base64<span class="w"> </span><span class="m">32</span><span class="k">)</span><span class="s2">&quot;</span><span class="w"> </span>&gt;<span class="w"> </span>secrets/db_password.txt
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;</span><span class="k">$(</span>openssl<span class="w"> </span>rand<span class="w"> </span>-hex<span class="w"> </span><span class="m">32</span><span class="k">)</span><span class="s2">&quot;</span><span class="w"> </span>&gt;<span class="w"> </span>secrets/secret_key.txt
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;</span><span class="k">$(</span>python3<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())&quot;</span><span class="k">)</span><span class="s2">&quot;</span><span class="w"> </span>&gt;<span class="w"> </span>secrets/fernet_key.txt
<span class="c1"># Set secure file permissions</span>
chmod<span class="w"> </span><span class="m">600</span><span class="w"> </span>secrets/*.txt
chown<span class="w"> </span><span class="k">$(</span>id<span class="w"> </span>-u<span class="k">)</span>:<span class="k">$(</span>id<span class="w"> </span>-g<span class="k">)</span><span class="w"> </span>secrets/*.txt
</code></pre></div>
<ol>
<li><strong>Configure docker-compose.yml:</strong></li>
</ol>
<div class="highlight"><pre><span></span><code><span class="nt">services</span><span class="p">:</span>
<span class="w"> </span><span class="nt">endurain</span><span class="p">:</span>
<span class="w"> </span><span class="nt">environment</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DB_PASSWORD_FILE=/run/secrets/db_password</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SECRET_KEY_FILE=/run/secrets/secret_key</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">FERNET_KEY_FILE=/run/secrets/fernet_key</span>
<span class="w"> </span><span class="nt">secrets</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">db_password</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">secret_key</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">fernet_key</span>
<span class="nt">secrets</span><span class="p">:</span>
<span class="w"> </span><span class="nt">db_password</span><span class="p">:</span>
<span class="w"> </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">./secrets/db_password.txt</span>
<span class="w"> </span><span class="nt">secret_key</span><span class="p">:</span>
<span class="w"> </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">./secrets/secret_key.txt</span>
<span class="w"> </span><span class="nt">fernet_key</span><span class="p">:</span>
<span class="w"> </span><span class="nt">file</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">./secrets/fernet_key.txt</span>
</code></pre></div>
<p><strong>Note</strong>: When using <code>_FILE</code> variants, the original environment variables (e.g., <code>DB_PASSWORD</code>) are not needed. The application will automatically read from the file specified by the <code>_FILE</code> environment variable.</p>
<h2 id="volumes">Volumes</h2>
<p>Docker image uses a non-root user, so ensure target folders are not owned by root. Non-root user should use UID and GID 1000. It is recommended to configure the following volumes for data persistence:</p>
<table>
<thead>
<tr>
<th>Volume</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>&lt;local_path&gt;/endurain/backend/logs:/app/backend/logs</code></td>
<td>Log files for the backend</td>
</tr>
<tr>
<td><code>&lt;local_path&gt;/endurain/backend/data:/app/backend/data</code></td>
<td>Necessary for image and activity files persistence on docker image update</td>
</tr>
</tbody>
</table>
<h2 id="bulk-import-and-file-upload">Bulk import and file upload</h2>
<p>To perform a bulk import:
- Place .fit, .tcx, .gz and/or .gpx files into the data/activity_files/bulk_import folder. Create the folder if needed.
- In the "Settings" menu select "Import".
- Click "Import" next to "Bulk Import".</p>
<p>.fit files are preferred. I noticed that Strava/Garmin Connect process of converting .fit to .gpx introduces additional data to the activity file leading to minor variances in the data, like for example additional
meters in distance and elevation gain. Some notes:</p>
<ul>
<li>After the files are processed, the files are moved to the processed folder</li>
<li>GEOCODES API has a limit of 1 Request/Second on the free plan, so if you have a large number of files, it might not be possible to import all in the same action</li>
<li>The bulk import currently only imports data present in the .fit, .tcx or .gpx files - no metadata or other media are imported.</li>
</ul>
<h2 id="importing-information-from-a-strava-bulk-export-beta">Importing information from a Strava bulk export (BETA)</h2>
<p>Strava allows users to create a bulk export of their historical activity on the site. This information is stored in a zip file, primarily as .csv files, GPS recording files (e.g., .gpx, .fit), and media files (e.g., .jpg, .png).</p>
<h3 id="importing-gear-from-a-strava-bulk-export">Importing gear from a Strava bulk export</h3>
<h4 id="bike-import">Bike import</h4>
<p>At the present time, importing bikes from a Strava bulk export is implemented as a beta feature - use with caution. Components of bikes are not imported - just the bikes themselves. There is no mechanism present to undo an import.</p>
<p>To perform an import of bikes:
- Place the bikes.csv file from a Strava bulk export into the data/activity_files/bulk_import folder. Create the folder if needed;
- In the <code>Settings</code> menu select <code>Import</code>;
- Click <code>Import Strava Bikes</code> next to <code>Strava gear import</code>;
- Upon successful import, the bikes.csv file is moved to /data/activity_files/processed folder;
- Status messages about the import, including why any gear was not imported, can be found in the logs.</p>
<p>Ensure the file is named <code>bikes.csv</code> and has a header row with at least the fields 'Bike Name', 'Bike Brand', and 'Bike Model'.</p>
<h4 id="shoe-import">Shoe import</h4>
<p>At the present time, importing shoes from a Strava bulk export is implemented as a beta feature - use with caution. Components of shooes are not imported - just the shoes themselves. </p>
<p>To perform an import of shoes:
- Place the shoes.csv file from a Strava bulk export into the data/activity_files/bulk_import folder. Create the folder if needed;
- In the <code>Settings</code> menu select <code>Import</code>;
- Click <code>Shoes import</code> next to <code>Strava gear import</code>;
- Upon successful import, the shoes.csv file is moved to /data/activity_files/processed folder;
- Status messages about the import, including why any gear was not imported, can be found in the logs.</p>
<p>Ensure the file is named <code>shoes.csv</code> and has a header row with at least the fields 'Shoe Name', 'Shoe Brand', and 'Shoe Model'.</p>
<p>Note that Strava allows blank shoe names, but Endurain does not. Shoes with a blank name will thus be given a default name of <code>Unnamed Shoe #</code> on import.</p>
<h4 id="notes-on-importing-gear">Notes on importing gear</h4>
<p>NOTE: There is currently no mechanism to undo a gear import.</p>
<p>All gear will be imported as active, as Strava does not export the active/inactive status of the gear.</p>
<p>Note that Endurain does not allow the <code>+</code> character in gear field names, and thus +'s will removed from all fields and replaced with spaces (" ") on import. All beginning and ending space characters (" ") will be removed on import as well.</p>
<p>Endurain does not allow duplicate gear nicknames, case insensitively (e.g., <code>Ilves</code> and <code>ilves</code> would not be allowed) and regardless of gear type (e.g., <code>Ilves</code> the bike and <code>ilves</code> the shoe would not be allowed). Gear with duplicate nicknames will not be imported (i.e., only the first item with a given nickname will be imported).</p>
<p>The import routine checks for duplicate items, and should not import duplicates. Thus it should be safe to re-import the same file mulitple times. However, due to the renaming of un-named shoes, repeated imports of the same shoe file will create duplicate entries of any unnamed shoes present. </p>
<p>Gear that is already present in Endurain due to having an active link with Strava will not be imported via the manual import process.</p>
<h3 id="importing-other-items-from-a-strava-bulk-import">Importing other items from a Strava bulk import</h3>
<p>Importing activity metadata and media is under development in October 2025.</p>
<h2 id="image-personalization">Image personalization</h2>
<p>It is possible (v0.10.0 or higher) to personalize the login image in the login page. To do that, map the data/server_images directory for image persistence on container updates and:
- Set the image in the server settings zone of the settings page
- A square image is expected. Default one uses 1000px vs 1000px</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>