Timezone Configuration
Get call times right across the stack.
A call that shows up three hours off isn't a small annoyance — it makes shift reports, missed-call windows, and after-hours QA rules wrong everywhere. The good news is that Astervis stores time correctly by design; almost every "wrong time" problem comes down to one or two settings not matching reality. This page walks through the three layers that decide what a timestamp looks like, how to find the right values, and how to apply them.
The default for a fresh install is Asia/Tashkent. The database itself always
stores time in UTC — the settings below only change how that UTC value is
read in from your PBX and displayed back to your users.
The three layers
Astervis handles a timestamp at three distinct points. Each has its own job, and getting time right means getting all three to agree.
Storage — always UTC
The TimescaleDB store keeps every call time in UTC. There's nothing to configure here, and you should never try to change it.
Input — MYSQL_TIMEZONE
Tells Astervis which timezone your PBX used when it wrote calldate, so the value can be normalised to UTC correctly.
Display — TIMEZONE / NEXT_PUBLIC_TIMEZONE
The timezone the backend and admin UI render timestamps in. This is what your team actually sees.
Storage: UTC, always
Your CDR analytics live in TimescaleDB (PostgreSQL 16) as UTC timestamps. This is deliberate: UTC has no daylight-saving jumps and no ambiguity, so historical data stays comparable forever. You don't set a variable for this layer — it's how the data is written, full stop.
Input: MYSQL_TIMEZONE
Asterisk and FreePBX write each call's calldate into MariaDB using the PBX
server's local time, with no timezone marker attached. To turn that bare local
time into UTC, Astervis needs to know which timezone the PBX was in. That's
MYSQL_TIMEZONE.
This is the single most important setting on the page. If it's wrong, every call is shifted by the difference between the real PBX timezone and the one you told Astervis — and because the shift happens at write time, fixing it later doesn't retroactively repair rows that were already stored.
MYSQL_TIMEZONE must match the actual timezone your PBX server runs in, not
the timezone your office is in or the timezone you'd like to display. Find it with
the commands below before you guess.
Display: TIMEZONE and NEXT_PUBLIC_TIMEZONE
Once data is safely in UTC, the display layer converts it back into a human timezone on the way out. Two variables drive this:
TIMEZONE— used by the backend when it formats times (reports, exports, API responses).NEXT_PUBLIC_TIMEZONE— used by the admin UI in the browser.
Astervis shows the same time to everyone based on these server-side settings — it
does not follow each visitor's browser timezone. That's a feature: a supervisor
in one city and an operator in another see identical numbers on the dashboard. Keep
these two values equal to each other, and you'll usually want them equal to
MYSQL_TIMEZONE as well, unless you deliberately want to display a different region.
How a timestamp travels
Here's the full journey of one call's time, from the moment it's written on the PBX to the moment it renders on a dashboard:
1. PBX writes the call
Asterisk/FreePBX → MariaDB cdr.calldate
stored as bare LOCAL time, e.g. 2026-06-13 18:30:00 (no zone attached)
2. litcdc captures the change
MariaDB binlog → litcdc reads calldate
3. Normalise to UTC using MYSQL_TIMEZONE
"18:30 in Asia/Tashkent" → 13:30 UTC
4. Store in TimescaleDB
cdr stored as 2026-06-13 13:30:00 UTC ← always UTC
5. Render for the user using TIMEZONE / NEXT_PUBLIC_TIMEZONE
13:30 UTC → "18:30" shown on the dashboardRead top to bottom, the rule is simple: MYSQL_TIMEZONE must describe step 1, and
TIMEZONE / NEXT_PUBLIC_TIMEZONE decide step 5. When all three name the same
region, what you see in step 5 equals what the PBX wrote in step 1 — exactly what
you want.
Astervis replicates CDR through litcdc, a small Rust service that reads the
MariaDB binlog and streams changes into TimescaleDB. It preserves calldate
byte-for-byte; the timezone normalisation in step 3 is what turns that local value
into UTC. See Sync & CDC for how the pipeline works.
Finding your PBX timezone
Before you set anything, confirm what timezone the PBX server actually uses. Run these on the PBX host (over SSH), not inside a container.
On most FreePBX / Sangoma / Ubuntu / Debian hosts:
timedatectlLook at the Time zone: line, e.g. Time zone: Asia/Tashkent (+05, +0500).
If timedatectl isn't available, fall back to:
cat /etc/timezoneApplying changes
All three settings live in /opt/astervis/.env. The file is owned by root and read
by Docker Compose, so changes only take effect after you restart the stack.
Open the env file as root
sudo nano /opt/astervis/.envSet all three to your PBX region
Use named timezones — never fixed UTC offsets (see the DST note below).
# How the PBX writes calldate — must match the PBX server's real timezone
MYSQL_TIMEZONE=Asia/Tashkent
# How times are displayed to your team (keep these two equal)
TIMEZONE=Asia/Tashkent
NEXT_PUBLIC_TIMEZONE=Asia/TashkentRestart the stack
cd /opt/astervis
docker compose down && docker compose up -dOr use the installer's wrapper, which does the same thing:
sudo astervis-installer restartA timezone change only affects how future times are normalised and how all
times are displayed. Data already in the database is stored in UTC and isn't
rewritten. Changing the display variables is always safe; changing MYSQL_TIMEZONE
only matters for calls captured after the change — see the "wrong historical times"
entry below for the case where past data was captured with the wrong value.
Common timezones
| Region | Timezone |
|---|---|
| Tashkent | Asia/Tashkent |
| Almaty | Asia/Almaty |
| Bishkek | Asia/Bishkek |
| Moscow | Europe/Moscow |
| Kyiv | Europe/Kyiv |
| Minsk | Europe/Minsk |
| Istanbul | Europe/Istanbul |
| London | Europe/London |
| New York | America/New_York |
| Los Angeles | America/Los_Angeles |
The full set of valid names is the IANA tz database. A handy reference is the list of tz database time zones.
DST and best practices
The one trap worth calling out explicitly is daylight saving time. Several of the regions Astervis serves don't observe DST (Uzbekistan, Kazakhstan, Russia), but others do (most of Europe and the Americas) — and the failure mode is subtle: times look correct for half the year and drift by exactly one hour after the clocks change.
Always use named timezones, never fixed offsets. A name like Europe/London
carries the DST rules and switches automatically; a hard-coded +03:00 does not,
so it silently goes an hour wrong on every DST transition.
# Wrong — frozen offset, breaks on DST changes
TIMEZONE=+05:00
# Right — named zone, handles DST automatically
TIMEZONE=Asia/TashkentA short checklist to keep time correct for good:
- Match the PBX exactly.
MYSQL_TIMEZONEis the keystone — verify it againsttimedatectlon the PBX, don't assume. - Keep the three settings consistent. Unless you have a specific reason to
display a different region, set
MYSQL_TIMEZONE,TIMEZONE, andNEXT_PUBLIC_TIMEZONEto the same value. - Use named zones only. This is what makes DST handle itself.
- Settle it during setup. Get the timezone right at install time; changing
MYSQL_TIMEZONEafter data has accumulated won't fix the rows already captured.
Troubleshooting
Last updated on