Upgrading
Upgrades require a brief restart. No data is lost.
Take a complete VM snapshot before every upgrade. Back up .env separately
and keep it off the server — it holds ENCRYPTION_KEY, without which no
stored PBX or accounting credential can be decrypted.
Back the server up on a schedule as well, not only before upgrades.
Standard upgrade
cd /opt/vodia-billing && test -f docker-compose.yml && test -f .env && \
UPD=".vodia-billing-upd.$(date +%s)" && \
wget https://cdn.vodia.net/vodia-billing/vodia-billing.zip -O vodia-billing-update.zip && \
unzip -oq vodia-billing-update.zip -d "./$UPD" && \
test -d "./$UPD/vodia-billing" && \
cp .env .env.bak.$(date +%s) && \
cp .env /tmp/.env.vodia-billing.bak && \
cp -rf "./$UPD/vodia-billing/"* . && \
cp /tmp/.env.vodia-billing.bak .env && \
rm -rf "./$UPD" && \
rm -f vodia-billing-update.zip && \
docker compose up -d --build
.env is preserved and a timestamped copy is left beside it. Database
migrations run automatically when the API starts.
Why --build and not restart
docker compose restart reuses the previously baked image. The new source
would be on disk but not running, and everything would report healthy. Always
up -d --build.
First start after an upgrade
New database indexes are built when the API starts. On a large database this can take a few minutes, during which the web interface and CDR ingestion are unavailable.
docker compose up -d may print dependency api failed to start while this
happens. That is expected — do not interrupt it.
Watch progress:
docker compose logs -f api
Wait for the API to report that it is listening.
Verify after upgrading
curl https://your-domain/api/health
Check that version is what you expected, mongo is up, and the version
shown in the bottom-left corner of the web interface matches.
Then check one finalized invoice from the previous period and confirm its totals are unchanged. Frozen detail means they should be, and confirming it takes a minute.
Do not re-run install.sh
install.sh is first-install only and refuses to run when .env exists. If
it were forced, it would generate a new ENCRYPTION_KEY and every stored PBX
and accounting credential would stop decrypting.
Rolling back
Restore the VM snapshot. There is no in-place downgrade, because migrations run forward only.
Manual database backup
cd /opt/vodia-billing
docker compose exec -T mongo mongodump \
--db vodia_billing --archive > billing-$(date +%Y%m%d).archive
cp .env env-$(date +%Y%m%d).bak
Keep the archive and the .env copy together and off the server. Either alone
is insufficient: the database without the key cannot decrypt its stored
credentials.
Restore:
docker compose exec -T mongo mongorestore --archive --drop < billing-YYYYMMDD.archive
Migrations run forward only and are designed to be idempotent, but an issued invoice's totals are the thing worth checking.
Open a finalized invoice from the previous period and confirm its totals are unchanged. Frozen detail means they should be, and confirming it takes a minute.